RuNetBSD


Руководство

Глава 21. Практическая настройка TCP/IP в NetBSD

Русский перевод Михаил Сгибнев
Содержание

21.1. Проверка конфигурации ядра
21.2. Обзор конфигурационных файлов
21.3. Подключение к Internet с помощью модема
21.3.1. Получение информации о соединении
21.3.2. resolv.conf и nsswitch.conf
21.3.3. Создание каталогов для pppd
21.3.4. Сценарий соединения и файл конфигурации chat
21.3.5. Аутентификация
21.3.6. Опции pppd
21.3.7. Проверка модема
21.3.8. Установка соединения
21.3.9. Использование сценария для подключения и отключения
21.3.10. Выполнение команд после дозвона
21.4. Создание маленькой домашней сети
21.5. Настройка Internet шлюза с IPNAT
21.5.1. Настройка шлюза/межсетевого экрана
21.5.2. Конфигурирование клиентской машины
21.5.3. Некоторые полезные команды
21.6. Общая настройка LAN
21.7. Соединение двух компьютеров через последовательный кабель
21.7.1. Соединение NetBSD с BSD или Linux
21.7.2. Соединение NetBSD и Windows NT
21.7.3. Соединение NetBSD и Windows 95

21.1. Проверка конфигурации ядра

Прежде, чем мы начнем конфигурировать различные аспекты работы сети, нам необходимо проверить наличие некоторых необходимых параметров в ядре. Обратитесь к главе Глава 28, Компиляция ядра для получения дополнительной информации о конфигурации, компиляции и установке ядра. Здесь мы рассмотрим процесс конфирурирования ядра, касательно параметров сети. В качестве примера мы будем использовать файл конфигурации i386/GENERIC. Конфигурационный файл для других платформ содержат подробные комментарии и подсказки. Помимо представленной здесь информации, каждая опция содержит страницу руководства options(4) , так же как и драйверы устройств, например tlp(4).
Читать дальше

Глава 20. Введение в сети TCP/IP

Русский перевод Вадим Лопатюк

Содержание
20.1. Читателям
20.2. Поддерживаемые сетевые протоколы
20.3. Поддерживаемые носители
20.3.1. Последовательная линия
20.3.2. Ethernet
20.4. Формат адреса TCP/IP
20.5. Подсети и маршрутизация
20.6. Концепция сервиса имен
20.6.1. /etc/hosts
20.6.2. Сервис доменных имен (DNS)
20.6.3. Сервис сетевой информации (NIS/YP)
20.6.4. Другое
20.7. Интернет протокол следующего поколения – IPv6
20.7.1. Будещее интернет
20.7.2. Чем хорош IPv6?
20.7.3. Отличия от IPv4

20.1. Читателям

Эта глава разъясняет различные аспекты работы сети. Что предполагает помощь начинающим людям с небольшими познаниями сети. Она соотоит из трех больших частей. Мы начнем с рассмотрения главной части работы сети и основных концепций. Затем, во второй части, мы рассмотрим в деталях настройки различных типов сети и в третьей части раздела работы сети изучим некоторые «продвинутые» аспекты, для углубления познаний, полученных в первых двух разделах.
Читать дальше

Глава 19. Различные полезные мелочи

Русский перевод Михаил Сгибнев

Содержание

19.1. Создание установочной/загрузочной дискеты i386
19.2. Создание CD-ROM
19.2.1. Создание образа ISO
19.2.2. Запись образа CD
19.2.3. Копирование CD
19.2.4. Создание загрузочного CD
19.3. Синхронизация системных часов
19.4. Установка менеджера загрузки
19.5. Удаление раздела
19.6. Спикер
19.7. Забыли пароль root?
19.8. Добавление нового жесткого диска
19.9. Файл паролей занят?
19.10. Как восстановить файлы устройств в /dev
В этой главе собраны в единое целое различные полезные советы, которым не нашлось места в предыдущих главах.

19.1. Создание установочной/загрузочной дискеты i386

Возможно, Вы захотите изготовить собственные загрузочные дискеты для платформы i386, вместо того, чтобы использовать уже прекомпилированные.
Читать дальше

Настройка клиента PPPoE в NetBSD

Перевод: Сгибнев Михаил


Примечание: оригинал документа находится здесь: http://www.netbsd.org/Documentation/network/pppoe/, в документе очень много лишнего, что и было убрано.

Поддержка в ядре

Необходимо убедиться, что PPPoE поддерживается ядром. Для этого выполните команду:

    
    -bash-3.00$ ifconfig -C
    bridge vlan gif gre tun tap strip sl pppoe ppp lo
    

Если в строке вывода не обнаружится упоминания о pppoe, то необходимо перекомпилировать ядро, добавив туда строку:

    
    pseudo-device pppoe
    

Проверка соединения

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

    
    ifconfig pppoe0 create
    ifconfig pppoe0 inet 0.0.0.0 0.0.0.1 down
    

Сейчас привяжем интерфейс pppoe к соответствующей сетевой карте, например к той, к которой подключен DSL модем, или которая смотрит в сеть провайдера.

    
    ifconfig rtk0 up
    pppoectl -e rtk0 pppoe0
    

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

    
    pppoectl pppoe0 myauthproto=pap 'myauthname=XXX' 'myauthsecret=YYY' hisauthproto=none
    

В данном случае, XXX это имя пользователя, а YYY – его пароль. Параметр hisauthproto=none указывает PPP, что нет необходимости подтверждать подлинность провайдера, так как большинство из них не предоставляют такой возможности. Если провайдер осуществляет авторизацию по протоколу CHAP, то необходимо установить параметр myauthproto=chap.
Мы готовы к подключению. Так как что-то может пойти неправильно, мы ограничим количество повторных попыток установить соединение:

    
    pppoectl pppoe0 max-auth-failure=1
    

И активируем интерфейс:

    
    ifconfig pppoe0 up
    

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

    
    # pppoectl -d pppoe0
    pppoe0: state = session
            Session ID: 0x254f
            PADI retries: 0
            PADR retries: 0
    

В этом примере у нас отображается рабочая сессия PPPoE (state = session). Если у вас указано другое состояние, то проверьте правильность указания регистрационных данных или доступность сервера. Ошибки будут отображаться как увеличение значения счетчиков PADI или PADR. Попробуйте указать service name (через опцию -s в pppoectl) или access concentrator name (через опцию -a в pppoectl), если эти данные необходимы, то провайдер должен вам их предоставить. Для получения дополнительной информации, обратитесь к странице руководства man pppoectl(8).
После того как сессия PPPoE была установлена, проверим правильность выделения IP адреса сервисом PPP:

    
    # ifconfig pppoe0
    pppoe0: flags=8851 mtu 1492
            inet 117.80.111.85 -> 118.5.113.169 netmask 0xff000000
    

Как мы видим, подключение установлено правильно, поскольку мы видим свой адрес и адрес удаленного хоста (естесственно, у вас будут другие адреса). Если вы не видите подобной картины, то скорее всего, вы неверно указали аутентификационные данные PPP.

Установка постоянного соединения

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

Независимо от тарифного плана, провайдер должен вам предоставить адреса DNS серверов, которые необходимо внести в /etc/resolv.conf.

Постоянное соединение

В этом случае мы устанавливаем соединение и оставляем его открытым сколь угодно долго, восстанавливая связь при обрыве.
Создадим файл /etc/ifconfig.pppoe0 следующего содержания:

    
    create
    # Mark the physical interface used by this PPPoE interface up
    ! /sbin/ifconfig rtk0 up
    # Let $int use rtk0 as its Ethernet interface
    ! /sbin/pppoectl -e rtk0 $int
    # Configure authentication
    ! /sbin/pppoectl $int myauthproto=pap 'myauthname=XXX' 'myauthsecret=YYY' hisauthproto=none
    # Configure the PPPoE interface itself. These addresses are magic
    # meaning we don't care about either address and let the remote
    # ppp choose them.
    0.0.0.0 0.0.0.1 up
    

Выставьте права доступа таким образом, чтобы прочитать этот файл мог только пользователь root.
В файл /etc/ppp/ip-up внесите:

    
    #! /bin/sh
    /sbin/route add default $5
    

В файл /etc/ppp/ip-down внесите:

    
    #! /bin/sh
    /sbin/route delete default $5
    

Также убедитесь, что прочитать эти файлы может только пользователь root.
В заключение, добавим следущую строку в /etc/rc.conf:

    
    ifwatchd=YES
    

Дело сделано. Обратите внимание, что загружается демон ifwatchd (выполняющий сценарии ip-up и ip-down). Проблема может заключаться в том, что маршрут по умолчанию может быть установлен после старта сетевых демонов, что приведет к некорректной их работе. Для устранения этой досадной ошибки рекомендую использовать подобный сценарий ip-up:

    
    #! /bin/sh
    /sbin/route add default $5
    /etc/rc.d/ntpd restart
    /etc/rc.d/named restart
    

Соединение по требованию

В данном примере мы устанавливаем соединение при необходимости передать данные и разрываем его при простое.
Главные отличия от постоянного соединения заключаются в следующем:

  • Флаг link1 на интерфейсе pppoe0
  • Лимит бездействия (в данном примере 60 секунд)
  • Конфигурация маршрутизации, когда первый пакет идет на интерфейс pppoe0, в то время, как соединение еще не установлено

Создадим файл /etc/ifconfig.pppoe0:

    
    create
    # Mark the physical interface used by this PPPoE interface up
    ! /sbin/ifconfig ne0 up
    # Let $int use ne0 as its Ethernet interface
    ! /sbin/pppoectl -e ne0 $int
    # Configure authentication
    ! /sbin/pppoectl $int idle-timeout=60 myauthproto=pap 'myauthname=XXX' 'myauthsecret=YYY' hisauthproto=none
    # Configure the PPPoE interface itself. These addresses are magic
    # meaning we don't care about either address and let the remote
    # ppp choose them.
    0.0.0.0 0.0.0.1 link1 up
    ! /sbin/route add default -iface 0.0.0.1
    

Использовать ifwatchd в этой конфигурации нет необходимости, поскольку мы уже задаем маршрут по умолчанию. Если вам необходимо получать уведомления о изменениях IP адресов или состояния соединения, то вы можете сконфигурировать ifwatchd и использовать/etc/ppp/ip-up и/etc/ppp/ip-down.

Установка NAT с MSS-clamping

Некоторые машины с ненастроенной системой фильтрации пакетов пытаются использовать Path-MTU-Discovery, в то время как пакетный фильтр отбрасывает все ICMP пакеты. Вполне вероятно, что вам придется общаться с такими системами, при необходимости получить от них данные.
В связи с этим, предать большие обьемы данных машине, подключенной через PPPoE, будет затруднительно. Для решения этого вопроса мы пошлем маленькое значение MSS (maximum segment size) во время установки сессии TCP. Для этого нам необходимо установить sysctl переменную net.inet.tcp.mss_ifmtu, добавив в /etc/sysctl.conf следущую строку:

    
    # Obey interface MTUs when calculating MSS
    net.inet.tcp.mss_ifmtu=1
    

В этом случае, в правилах NAT вашего маршрутизатора, имеющего связь с миром через PPPoE необходимо указать следущие строки:

    
    map pppoe0 192.168.1.0/24 -> 0/32 portmap tcp/udp 44000:49999 mssclamp 1440
    map pppoe0 192.168.1.0/24 -> 0/32 mssclamp 1440
    

Если вы не используете NAT, то добавьте такое правило:

    
    map pppoe0 x.x.x.x/24 -> 0/0 mssclamp 1440
    

В вышеприведенных примерах MTU принимается равным 1492 байтам. Учитывая смещение в 52 байта, укажите свое MTU, например 1408 для MTU 1460 байта. Обратите внимание: теоретически правильное значение для вышеупомянутого примера было бы 1452 байта (минимальное значение PPPoE MTU, заголовок TCP и максимум 0×40 байтов опций TCP).

Введение в Common Address Redundancy Protocol

Перевод: Сгибнев Михаил

Аббревиатура CARP расшифровывается как Common Address Redundancy Protocol. Основной целью этого протокола является использование одного IP адреса в пределах одного сегмента сети несколькими машинами. CARP является свободной, безопасной альтернативой протоколам Virtual Router Redundancy Protocol и Hot Standby Router Protocol.

CARP позволяет выделить группу хостов в сегменте сети и назначить ей один IP адрес. Такая группа называется «redundancy group» (группа избыточности). В пределах этой группы, один из хостов становится «главным», а остальные обозначаются как «резервные». В каждый момент времени мастер-хост отвечает на ARP-запросы к назначенному IP адресу и обрабатывает трафик, идущий к этому адресу. Каждый хост одновременно может принадлежать к нескольким группам.

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

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

Однако, есть ситуации, когда CARP не может помочь. Дизайн CARP требует, чтобы члены одной группы физически находились в одной подсети с одним статическим IP адресом, хотя с введением директивы carpdev необходимости назначать адрес на физический интерфейс нет. Сервисы, требующие постоянного соединения с сервером (такие как SSH и IRC) не могут быть прозрачно переброшены в случае отказа и потребуют переподключения. CARP не может синхронизировать данные между приложениями.

CARP поддерживает IPv4 и IPv6.

Читать дальше

Глава 18. Подсистема Veriexec NetBSD

Русский перевод: Михаил Сгибнев

Содержание

18.1. Как это работает
18.2. Файл сигнатур
18.3. Генерирование контрольной суммы
18.4. Уровни доступа
18.5. Конфигурация ядра

Veriexec является системой проверки целостности файлов NetBSD.
Она входит в состав ядра, поэтому может обеспечить защиту даже
в случае компрометации учетной записи пользователя root.
Эта глава применима только к версии NetBSD 3.0 и выше.

18.1. Как это работает

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

В настоящий момент поддерживаются следующие алгоритмы Veriexec:
MD5,
SHA1,
SHA256,
SHA384,
SHA512, and
RMD160.

18.2. Файл сигнатур

Запись в фале сигнатур выглядит следующим образом:

	/path/to/file algorithm fingerprint flags

Где первое поле представляетс собой абсолютный путь до файла,
далее указан алгоритм и ASCII отпечаток (контрольная сумма).

18.3. Генерирование контрольной суммы

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

Таблица 18.1. Veriexec fingerprints tools

Алгоритм Утилита
MD5 /usr/bin/md5
SHA1 /usr/bin/sha1
SHA256 digest sha256 (из
pkgsrc)
SHA384 digest sha384 (из
pkgsrc)
SHA512 digest sha512 (из
pkgsrc)
RMD160 /usr/bin/rmd160

Для примера, создадим контрольную сумму MD5 для
/bin/ls:

	% md5 < /bin/ls
	a8b525da46e758778564308ed9b1e493

Добавим контрольную сумму SHA512 для
/bin/ps:

	% digest sha512 < /bin/ps
	381d4ad64fd47800897446a2026eca42151e03adeae158db5a34d12c529559113d928a9fef9a7c4615d257688d1da4645db004081030d7f080bb7198067eb890

С каждой записью может ассоциироваться несколько флагов.
В настоящее время флаги описывают метод обращения к файлу, которому
соответствует запись. Обратите внимание, что этот тип доступа
применим только в 2 уровне доступа (режим IPS) и выше.

Типы доступа могут быть «DIRECT»,
«INDIRECT» и «FILE».

  • Метод DIRECT
    указывает на прямое выполнение и не вызывается как интерпретатор
    для некоего сценария или открываемого текстовым редактором.
    К большинству используемых вами файлов стоит обращаться именно
    так:

    	% ls /tmp
    	% cp ~/foo /tmp/bar
    	% rm ~/foo
  • Метод INDIRECT
    означает косвенное выполнение файла, например, для интерпретации
    сценария. Это происходит, когда сценарий в первой строке
    содержит #!. Для примера, у нас усть скрипт, в первой строке
    содержащий:

    	#!/bin/sh

    И вы запускаете его:

    	% ./script.sh

    В этом случае происходит косвенный вызов
    /bin/sh для интерпретации
    скрипта.

  • Запись FILE
    указывает на невыполняемый (или, который не должен быть выполняемым)
    файл. Это могут быть библиотеки, файлы конфигурации и т.д.

    Вот несколько примеров записей в файле сигнатур Veriexec:

    	/bin/ls         MD5 dc2e14dc84bdefff4bf9777958c1b20b DIRECT
    	/usr/bin/perl   MD5 914aa8aa47ebd79ccd7909a09ed61f81 INDIRECT
    	/etc/pf.conf    MD5 950e1dd6fcb3f27df1bf6accf7029f7d  FILE
  • Veriexec позволят вам определить несколько вариантов доступа к файлу.
    Для примера, /usr/bin/perl может быть вызван
    как интерпретатор, так и в качестве самостоятельной программы.
    Для этого мы должны указать:

    	/usr/bin/perl MD5 914aa8aa47ebd79ccd7909a09ed61f81 DIRECT, INDIRECT

    Сценарии оболочки, использующие #! для «выполнения»
    также требуют указания двух типов доступа: «DIRECT» для
    выполнения и «FILE» для того, чтобы ядро могло подать
    содержимое скрипта интерпретатору:

    	/usr/src/build.sh MD5 e80dbb4c047ecc1d84053174c1e9264a DIRECT, FILE

    Для облегчения создания фала сигнатур и повышения читабельности,
    Veriexec может понимать следующие псевдонимы:

    Таблица 18.2. Псевдонимы типов Veriexec

    Alias Expansion
    PROGRAM DIRECT
    INTERPRETER INDIRECT
    SCRIPT DIRECT, FILE
    LIBRARY FILE

    Примерный сценарий для генерации контрольных сумм доступен в
    /usr/share/examples/veriexecctl. После
    генерации файла сигнатур, который сохраняется в
    /etc/signatures, а включение Veriexec
    осучествляется через rc.conf:

    	veriexec=YES

    18.4. Уровни доступа

    С тех пор, как люди заинтересовались использованием
    Veriexec для различных целей, мы определили четыре уровня
    доступа, называемые режимами «learning»,
    «IDS», «IPS» и «lockdown».

    На уровне доступа 0,
    режиме learning, Veriexec будет действовать пассивно и только предупреждать
    о любых аномалиях. При обьединении с уровнем 1, может оказаться
    полезным при отладке файла сигнатур. На этом уровне, в отличие от
    остальных, вы можете загружать новые записи в ядро.

    На уровне доступа 1,
    режиме IDS, будет запрещаться доступ к файлам с несоответствующей
    контрольной суммой. Этот режим больше всего подходит пользователям,
    которые предпочитают просто запретить доступ к файлам, которые
    могут быть модифицированы злоумышленником.

    Уровень доступа 2, режим IPS,
    предпринимает шаги по защите файлов. В дополнение к предотвращению
    доступа к файлам с несоответствующей контрольной суммой,
    закроется доступ на запись и удаление защищаемых файлов и
    будет организовано ведение журналов доступа к этим файлам.

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

    Мы рекомендуем выполнить первый запуск Veriexec в режиме 0 и
    отлаживать в режиме 1, для точной подстройки файла сигнатур,
    удостовериться в правильной работе приложений и только после этого
    повышать уровень. Для автоматической установки уровня доступа
    после перезагрузки вы можете использовать
    /etc/sysctl.conf:

    	kern.veriexec.strict=1

    18.5. Конфигурация ядра

    Для использования Veriexec необходимо, кроме создания файла сигнатур,
    обеспечить поддержку в файле конфигурации ядра: (например
    /usr/src/sys/arch/i386/conf/GENERIC.local):

    	options VERIFIED_EXEC

    Затем, нам необходимо установить поддреживаемые алгоритмы
    хэширования:

    	options VERIFIED_EXEC_FP_MD5
    	options VERIFIED_EXEC_FP_SHA1
    	options VERIFIED_EXEC_FP_RMD160
    	options VERIFIED_EXEC_FP_SHA512
    	options VERIFIED_EXEC_FP_SHA384
    	options VERIFIED_EXEC_FP_SHA256

    В заключение добавим псевдо-устройство Veriexec:

    	pseudo-device veriexec 1

    Далее, как обычно, компилируем, устанавливаем новое ядро и
    перезагружаемя.

    Глава 17. Точная настройка NetBSD

    Русский перевод: Михаил Сгибнев

    Содержание

    17.1. Введение
    17.1.1. Краткий обзор
    17.2. Общие вопросы настройки
    17.2.1. Конфигурация системы
    17.2.2. Системные сервисы
    17.2.3. Ядро NetBSD
    17.3. Visual Monitoring Tools
    17.3.1. Программа мониторинга процессов top
    17.3.2. Утилита sysstat
    17.4. Утилиты мониторинга
    17.4.1. fstat
    17.4.2. iostat
    17.4.3. ps
    17.4.4. vmstat
    17.5. Сетевые утилиты
    17.5.1. ping
    17.5.2. traceroute
    17.5.3. netstat
    17.5.4. tcpdump
    17.6. Аккаунтинг
    17.6.1. Accounting
    17.6.2. Чтение информации аккаунтинга
    17.6.3. Как исполдьзовать аккаунтинг
    17.7. Профили ядра
    17.7.1. С чего начать
    17.7.2. Расшифровка вывода kgmon
    17.7.3. Использование
    17.7.4. Резюме:
    17.8. Оптимизация системы
    17.8.1. Использование sysctl
    17.8.2. memfs & softdeps
    17.9. Оптимизация ядра
    17.9.1. Подготовка к компиляции ядра
    17.9.2. Конфигурирование ядра
    17.9.3. Building the New Kernel

    17.1. Введение

    17.1.1. Краткий обзор

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

    17.1.1.1. Что такое оптимизация производительности?

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

    Самым распространенным мнением является то, что
    «настройка» – это уменьшение размера ядра или увеличение
    скорости. На самом деле, это только некоторые из аспектов,
    которые нам придется рассмотреть, для того, чтобы
    привести NetBSD в оптимальное
    состояние.

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

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

    17.1.1.2. Когда делать настройку?

    Настраивать систему необходимо довольно небольшой
    группе пользователей. GENERIC ядро работает прекрасно
    и конфигурация позволяет использовать его для самых
    разнообразных задач. Если же точная настройка все-таки
    необходима, то необходимо четко себе представлять, что
    вы будете делать. Настройка обычно делается после
    внезапной потери или постепенного снижения производительности,
    когда неприятные последствия уже наступают. Давайте не
    будем учиться на своих ошибках и рассмотрим основные
    методы настройки.

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

    17.1.1.3. Что не рассматривается в этом документе

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

    17.1.1.4. Используемые примеры

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

    17.2. Общие вопросы настройки

    Тонкая настройка системы не является таким уж сложным
    делом, просто заняться этим стоит до того, как
    «началось». Настроить сервер до его ввода в
    строй проще, чем во время простоя.

    17.2.1. Конфигурация системы

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

    17.2.1.1. Файловая система и диски

    Размещение файловых систем на дисках – очень важный
    вопрос. На системах с аппаратным RAID это не так критично,
    но большое число пользователей NetBSD работают с устаревшим
    оборудованием, где просто нет RAID. Хорошей идеей будет
    размещение / в начале диска, но если
    дисков несколько? Стоит ли выделить в отдельный раздел
    /usr? Будет ли интенсивно использоваться
    /usr/pkgsrc? Подумайте перед началом
    установки над этими вопросами.

    17.2.1.2. Конфигурация раздела подкачки

    Есть три теории вычисления размера раздела подкачки
    и около пятидесяти о разбиении файла подкачки с расстановкой
    приоритетов. Каждая теория имеет свои собственные формулы
    расчета, например для HP-UX с установленной на нем Oracle
    использует формулу:

    2.5 GB * Number_of_processor
    

    На самом деле, здесь все зависит от размера и
    интенсивности использования баз данных, для примера, если
    база данных распределенная, то форма будет не верна.

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

    1. Посчитайте общее количество необходимой памяти
      при одновременном запуске всего, что вам может
      потребоваться. Это базы данных, web серверы и так
      далее.
    2. Добавьте несколько мегабайт про запас.
    3. Вычтите значение RAM из результата.

    Если получившийся остаток превышает размер RAM в три
    и более раза, то рассмотрите возможность увеличения RAM.
    Конечно, есть проблема в определении того, что может
    потребоваться и сколько памяти это займет, Другой недостаток
    этого метода – возможные ошибки в программном обеспечении.
    Например браузер Netscape, который в некоторых своих
    версиях имел тенденцию к разрастанию. Поэтому – чем больше
    резерва, тем больше времени на убийство процесса.

    Не на последнем месте стоит и старый, испытанный
    метод PHYSICAL_RAM * 2. На старых машинах он работает
    лучше всего, хотя на современных, с большим количеством
    RAM начал терять свою актуальность.

    в целом, довольно сложно сказать, когда начнется
    активный своппинг. Даже на машинах с 16MB RAM (и даже
    меньше) с установленной NetBSD все работает достаточно
    хорошо, пока не будет запущено

    17.2.2. Системные сервисы

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

    Другим хорошим примером может служить старый вопрос:
    «Использовать или нет inetd?». Рассмотрим
    pop3. Вызов его через inetd быстро сможет исчерпать ресурсы
    системы, что приведет к замедлению работы системы в целом.
    Установка демона pop3, не связанного с inetd может помочь
    решить ситуацию.

    17.2.3. Ядро NetBSD

    От ядра системы очень сильно зависит производительность
    системы и хотя оптимизация ядра описана несколько ниже по
    тексту, вкратце коснемся этой темы и здесь.

    Оптимизация ядра NetBSD возможна в следующих направлениях:

    1. удаление лишних драйверов
    2. опции конфигурации
    3. системные установки

    17.2.3.1. Удаление лишних драйверов

    Удаление лишних драйверов из состава ядра приносит
    следущие результаты: быстрее происходит загрузка системы,
    занимается меньше памяти, вследствии уменьшения размера
    ядра, быстрее происходит отклик ядра.

    17.2.3.2. Опции конфигурации

    Опции конфигурации позволяют нам задействовать или
    отключать некоторые подсистемы, специфичные аппаратные
    средства и файловые системы. Отключение неиспользуемых
    функций также может дать прирост производительности.
    Самый простой пример – сервер FTP, на котором не запущено
    ничего более. В этом случае нет необходимости в поддержке
    ядром лишних файловых систем, типа NTFS. В случае же
    наличия рабочей станции, возможно, такая необходимость
    есть, для обеспечения совместного доступа к файлам.

    17.2.3.3. Системные установки

    System wide settings are controlled by the kernel,
    a few examples are filesystem settings, network settings
    and core kernel settings such as the maximum number of
    processes. Almost all system settings can be at least
    looked at or modified via the sysctl facility. Examples
    using the sysctl facility are given later on.

    17.3. Visual Monitoring Tools

    NetBSD ships a variety of performance monitoring tools with
    the system. Most of these tools are common on all UNIX systems.
    In this section some example usage of the tools is given with
    interpretation of the output.

    17.3.1. Программа мониторинга процессов top

    Эта программа выводит на экран список процессов с
    ранжированием их по потребляемым ресурсам. Будучи запущеным
    без параметров выглядит так:

    load averages:  0.09,  0.12,  0.08                                     20:23:41
    21 processes:  20 sleeping, 1 on processor
    CPU states:  0.0% user,  0.0% nice,  0.0% system,  0.0% interrupt,  100% idle
    Memory: 15M Act, 1104K Inact, 208K Wired, 22M Free, 129M Swap free
    
      PID USERNAME PRI NICE   SIZE   RES STATE     TIME   WCPU    CPU COMMAND
    13663 root       2    0  1552K 1836K sleep     0:08  0.00%  0.00% httpd
      127 root      10    0   129M 4464K sleep     0:01  0.00%  0.00% mount_mfs
    22591 root       2    0   388K 1156K sleep     0:01  0.00%  0.00% sshd
      108 root       2    0   132K  472K sleep     0:01  0.00%  0.00% syslogd
    22597 jrf       28    0   156K  616K onproc    0:00  0.00%  0.00% top
    22592 jrf       18    0   828K 1128K sleep     0:00  0.00%  0.00% tcsh
      203 root      10    0   220K  424K sleep     0:00  0.00%  0.00% cron
        1 root      10    0   312K  192K sleep     0:00  0.00%  0.00% init
      205 root       3    0    48K  432K sleep     0:00  0.00%  0.00% getty
      206 root       3    0    48K  424K sleep     0:00  0.00%  0.00% getty
      208 root       3    0    48K  424K sleep     0:00  0.00%  0.00% getty
      207 root       3    0    48K  424K sleep     0:00  0.00%  0.00% getty
    13667 nobody     2    0  1660K 1508K sleep     0:00  0.00%  0.00% httpd
     9926 root       2    0   336K  588K sleep     0:00  0.00%  0.00% sshd
      200 root       2    0    76K  456K sleep     0:00  0.00%  0.00% inetd
      182 root       2    0    92K  436K sleep     0:00  0.00%  0.00% portsentry
      180 root       2    0    92K  436K sleep     0:00  0.00%  0.00% portsentry
    13666 nobody    -4    0  1600K 1260K sleep     0:00  0.00%  0.00% httpd
    

    Утилита показывает наиболее «прожорливое» приложение,
    зависшие процессы или группы процессов, которые могут
    вызывать проблемы. Приведенный выше пример – ненагруженая,
    спокойная система. Ниже – совсем другой результат:

    load averages:  0.34,  0.16,  0.13                                     21:13:47
    25 processes:  24 sleeping, 1 on processor
    CPU states:  0.5% user,  0.0% nice,  9.0% system,  1.0% interrupt, 89.6% idle
    Memory: 20M Act, 1712K Inact, 240K Wired, 30M Free, 129M Swap free
    
      PID USERNAME PRI NICE   SIZE   RES STATE     TIME   WCPU    CPU COMMAND
     5304 jrf       -5    0    56K  336K sleep     0:04 66.07% 19.53% bonnie
     5294 root       2    0   412K 1176K sleep     0:02  1.01%  0.93% sshd
      108 root       2    0   132K  472K sleep     1:23  0.00%  0.00% syslogd
      187 root       2    0  1552K 1824K sleep     0:07  0.00%  0.00% httpd
     5288 root       2    0   412K 1176K sleep     0:02  0.00%  0.00% sshd
     5302 jrf       28    0   160K  620K onproc    0:00  0.00%  0.00% top
     5295 jrf       18    0   828K 1116K sleep     0:00  0.00%  0.00% tcsh
     5289 jrf       18    0   828K 1112K sleep     0:00  0.00%  0.00% tcsh
      127 root      10    0   129M 8388K sleep     0:00  0.00%  0.00% mount_mfs
      204 root      10    0   220K  424K sleep     0:00  0.00%  0.00% cron
        1 root      10    0   312K  192K sleep     0:00  0.00%  0.00% init
      208 root       3    0    48K  432K sleep     0:00  0.00%  0.00% getty
      210 root       3    0    48K  424K sleep     0:00  0.00%  0.00% getty
      209 root       3    0    48K  424K sleep     0:00  0.00%  0.00% getty
      211 root       3    0    48K  424K sleep     0:00  0.00%  0.00% getty
      217 nobody     2    0  1616K 1272K sleep     0:00  0.00%  0.00% httpd
      184 root       2    0   336K  580K sleep     0:00  0.00%  0.00% sshd
      201 root       2    0    76K  456K sleep     0:00  0.00%  0.00% inetd
    

    Кажется очевидным, какой процесс наиболее грузит систему,
    но попробуем выяснить почему. bonnie – это утилита для
    определения производительности диска и может записывать
    файлы, варьируя пути и размеры. Так что, top указал нам на
    самую ресурсопотребляющую программу, но не сказал почему
    она так себя ведет.

    17.3.1.1. Другие подобные программы

    Изучая man команды top(1), можно узнать, что с
    помощью этой команды можно менять приоритет и уничтожать
    процессы, также можно установить дополнительные
    фильтры.

    17.3.2. Утилита sysstat

    Man sysstat(1) указывает нам, что systat отображает
    разнообразную системную статистику и основана на библиотеке
    curses. Во время работы экран разделен на две части, верхнее
    окно показывает текущее среднее число загрузки, в то время
    как нижний экран зависит от директив пользователя.

    		   /0   /1   /2   /3   /4   /5   /6   /7   /8   /9   /10
         Load Average   |
    
    			 /0   /10  /20  /30  /40  /50  /60  /70  /80  /90  /100
    		  <idle> XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    

    В простейшем случае, эта утилита нам покажет загрузку
    некоторого компонента системы, в этом примере, команда
    sysstat inet.tcp отобразит:

    		    /0   /1   /2   /3   /4   /5   /6   /7   /8   /9   /10
         Load Average   |
    
    	0 connections initiated           19 total TCP packets sent
    	0 connections accepted            11   data
    	0 connections established          0   data (retransmit)
    					   8   ack-only
    	0 connections dropped              0   window probes
    	0   in embryonic state             0   window updates
    	0   on retransmit timeout          0   urgent data only
    	0   by keepalive                   0   control
    	0   by persist
    					  29 total TCP packets received
           11 potential rtt updates           17   in sequence
           11 successful rtt updates           0   completely duplicate
    	9 delayed acks sent                0   with some duplicate data
    	0 retransmit timeouts              4   out of order
    	0 persist timeouts                 0   duplicate acks
    	0 keepalive probes                11   acks
    	0 keepalive timeouts               0   window probes
    					   0   window updates
    

    Теперь более информативно. Счетчики накапливаются,
    можно видеть много дополнительной информации. Теперь обратим
    внимание на буферный кэш и просмотрим его с помощью systat
    bufcache:

    		    /0   /1   /2   /3   /4   /5   /6   /7   /8   /9   /10
         Load Average
    
    There are 1642 buffers using 6568 kBytes of memory.
    
    File System          Bufs used   %   kB in use   %  Bufsize kB   %  Util %
    /                          877  53        6171  93        6516  99      94
    /var/tmp                     5   0          17   0          28   0      60
    
    Total:                     882  53        6188  94        6544  99
    

    Ну что, снова довольно скучная система, но имеется в
    наличии много информации. Раз у нас так все замечательно,
    введем в систему ложную нагрузку, чтобы увидеть, как systat
    можно использовать в качестве средства диагностики:

    		    /0   /1   /2   /3   /4   /5   /6   /7   /8   /9   /10
         Load Average   |||
    
    There are 1642 buffers using 6568 kBytes of memory.
    
    File System          Bufs used   %   kB in use   %  Bufsize kB   %  Util %
    /                          811  49        6422  97        6444  98      99
    
    Total:                     811  49        6422  97        6444  98
    

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

    17.4. Утилиты мониторинга

    В дополнение к экранно-ориентированным утилитам мониторига
    в NetBSD присутствуют текстовые утилиты. Эти утилиты присутствуют
    во всех UNIX и UNIX-like системах.

    17.4.1. fstat

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

    Приведем пример вывода fstat:

    USER     CMD          PID   FD MOUNT      INUM MODE         SZ|DV R/W
    jrf      tcsh       21607   wd /         29772 drwxr-xr-x     512 r
    jrf      tcsh       21607    3* unix stream c057acc0<-> c0553280
    jrf      tcsh       21607    4* unix stream c0553280 <-> c057acc0
    root     sshd       21597   wd /             2 drwxr-xr-x     512 r
    root     sshd       21597    0 /         11921 crw-rw-rw-    null rw
    nobody   httpd       5032   wd /             2 drwxr-xr-x     512 r
    nobody   httpd       5032    0 /         11921 crw-rw-rw-    null r
    nobody   httpd       5032    1 /         11921 crw-rw-rw-    null w
    nobody   httpd       5032    2 /         15890 -rw-r--r--  353533 rw
    ...
    

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

    17.4.2. iostat

    iostat(8) – утилита, имя которой соответстует
    выполняемой задаче. Она сообщает о состоянии подсистем
    ввода – вывода в системе. Когда эта утилита выполняется,
    пользователь, с некоторой дискретностью, может наблюдать
    примерно следующее:

    $ iostat 5 5
          tty            wd0             cd0             fd0             md0             cpu
     tin tout  KB/t t/s MB/s   KB/t t/s MB/s   KB/t t/s MB/s   KB/t t/s MB/s  us ni sy in id
       0    1  5.13   1 0.00   0.00   0 0.00   0.00   0 0.00   0.00   0 0.00   0  0  0  0 100
       0   54  0.00   0 0.00   0.00   0 0.00   0.00   0 0.00   0.00   0 0.00   0  0  0  0 100
       0   18  0.00   0 0.00   0.00   0 0.00   0.00   0 0.00   0.00   0 0.00   0  0  0  0 100
       0   18  8.00   0 0.00   0.00   0 0.00   0.00   0 0.00   0.00   0 0.00   0  0  0  0 100
       0   28  0.00   0 0.00   0.00   0 0.00   0.00   0 0.00   0.00   0 0.00   0  0  0  0 100

    Вышеупомянутый вывод – от ненагруженного сервера, поля
    представляют различные устройства ввода/вывода – HDD,
    CD-ROM, FDD, память и CPU.

    Теперь попробуем нагрузить систему. будем использовать
    все тот же bonnie++(утилита тестирования дисков) и передавать
    tarball netbsd.

    $ iostat 5 5
          tty            wd0             cd0             fd0             md0             cpu
     tin tout  KB/t t/s MB/s   KB/t t/s MB/s   KB/t t/s MB/s   KB/t t/s MB/s  us ni sy in id
       0    1  5.68   1 0.00   0.00   0 0.00   0.00   0 0.00   0.00   0 0.00   0  0  0  0 100
       0   54 61.03 150 8.92   0.00   0 0.00   0.00   0 0.00   0.00   0 0.00   1  0 18  4 78
       0   26 63.14 157 9.71   0.00   0 0.00   0.00   0 0.00   0.00   0 0.00   1  0 20  4 75
       0   20 43.58  26 1.12   0.00   0 0.00   0.00   0 0.00   0.00   0 0.00   0  0  9  2 88
       0   28 19.49  82 1.55   0.00   0 0.00   0.00   0 0.00   0.00   0 0.00   1  0  7  3 89

    Как и следовало ожидать, wd0 очень активен, загрузка
    процессора повышается в некоторой зависимости от wd0. Малая
    загрузка процессора свидетельствует о том, что сервер ftp
    едва используется и это связано с усиленной работой bonnie++.
    В данном случае с помощью одного инструмента сложно
    локализовать проблему и необходимо проанализировать список
    процессов, допустим с помощью утилиты systat bufcache.

    17.4.3. ps

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

    $ ps
      PID TT STAT    TIME COMMAND
    21560 p0 Is   0:00.04 -tcsh
    21564 p0 I+   0:00.37 ssh jrf.odpn.net
    21598 p1 Ss   0:00.12 -tcsh
    21673 p1 R+   0:00.00 ps
    21638 p2 Is+  0:00.06 -tcsh

    Не впечатляет… Поля довольно понятны, за исключением
    STAT, в котором отображается статус процесса. I – простой,
    S бездействует, R – runnable, + означает, что процесс
    находится в приоритетном состоянии, и s означает, что
    процесс – лидер сеанса. Это все очень просто, например
    процесс 21560 – tcsh, простой процесс, следовательно tcsh
    является и лидером.

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

    # ps aux
    USER     PID %CPU %MEM    VSZ  RSS TT STAT STARTED    TIME COMMAND
    root       0  0.0  9.6      0 6260 ?? DLs  16Jul02 0:01.00 (swapper)
    root   23362  0.0  0.8    144  488 ?? S    12:38PM 0:00.01 ftpd -l
    root   23328  0.0  0.4    428  280 p1 S    12:34PM 0:00.04 -csh
    jrf    23312  0.0  1.8    828 1132 p1 Is   12:32PM 0:00.06 -tcsh
    root   23311  0.0  1.8    388 1156 ?? S    12:32PM 0:01.60 sshd: jrf@ttyp1
    jrf    21951  0.0  1.7    244 1124 p0 S+    4:22PM 0:02.90 ssh jrf.odpn.net
    jrf    21947  0.0  1.7    828 1128 p0 Is    4:21PM 0:00.04 -tcsh
    root   21946  0.0  1.8    388 1156 ?? S     4:21PM 0:04.94 sshd: jrf@ttyp0
    nobody  5032  0.0  2.0   1616 1300 ?? I    19Jul02 0:00.02 /usr/pkg/sbin/httpd
    ...

    Снова, большинство полей понятно, за исключением VSZ
    и RSS. RSS – реальный размер процесса в 1024-байтовых
    модулях, а SZ – виртуальный размер. Это все здорово, но
    как ps может нам помочь? Хорошо, смотрите на эту измененную
    версию того же самого вывода:

    # ps aux
    USER     PID %CPU %MEM    VSZ  RSS TT STAT STARTED    TIME COMMAND
    root       0  0.0  9.6      0 6260 ?? DLs  16Jul02 0:01.00 (swapper)
    root   23362  0.0  0.8    144  488 ?? S    12:38PM 0:00.01 ftpd -l
    root   23328  0.0  0.4    428  280 p1 S    12:34PM 0:00.04 -csh
    jrf    23312  0.0  1.8    828 1132 p1 Is   12:32PM 0:00.06 -tcsh
    root   23311  0.0  1.8    388 1156 ?? S    12:32PM 0:01.60 sshd: jrf@ttyp1
    jrf    21951  0.0  1.7    244 1124 p0 S+    4:22PM 0:02.90 ssh jrf.odpn.net
    jrf    21947  0.0  1.7    828 1128 p0 Is    4:21PM 0:00.04 -tcsh
    root   21946  0.0  1.8    388 1156 ?? S     4:21PM 0:04.94 sshd: jrf@ttyp0
    nobody  5032  9.0  2.0   1616 1300 ?? I    19Jul02 0:00.02 /usr/pkg/sbin/httpd
    ...

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

    17.4.4. vmstat

    Используя vmstat(1) можно получить информацию, касающуюся состояния виртуальной памяти. Мало чем отличаясь
    от iostat, vmstat может быть вызван с указанием дискретности.
    Следующее – некоторый типовой вывод, используя дискретность
    5 и выводя 5 результатов:

    # vmstat 5 5
     procs   memory     page                       disks         faults      cpu
     r b w   avm   fre  flt  re  pi   po   fr   sr w0 c0 f0 m0   in   sy  cs us sy id
     0 7 0 17716 33160    2   0   0    0    0    0  1  0  0  0  105   15   4  0  0 100
     0 7 0 17724 33156    2   0   0    0    0    0  1  0  0  0  109    6   3  0  0 100
     0 7 0 17724 33156    1   0   0    0    0    0  1  0  0  0  105    6   3  0  0 100
     0 7 0 17724 33156    1   0   0    0    0    0  0  0  0  0  107    6   3  0  0 100
     0 7 0 17724 33156    1   0   0    0    0    0  0  0  0  0  105    6   3  0  0 100

    Снова проводим испытания на нагрузку. Условия – те же
    самые: bonny++ и файл большого размера.

    # vmstat 5 5
     procs   memory     page                       disks         faults      cpu
     r b w   avm   fre  flt  re  pi   po   fr   sr w0 c0 f0 m0   in   sy  cs us sy id
     1 8 0 18880 31968    2   0   0    0    0    0  1  0  0  0  105   15   4  0  0 100
     0 8 0 18888 31964    2   0   0    0    0    0 130  0  0  0 1804 5539 1094 31 22 47
     1 7 0 18888 31964    1   0   0    0    0    0 130  0  0  0 1802 5500 1060 36 16 49
     1 8 0 18888 31964    1   0   0    0    0    0 160  0  0  0 1849 5905 1107 21 22 57
     1 7 0 18888 31964    1   0   0    0    0    0 175  0  0  0 1893 6167 1082  1 25 75

    Не очень много различий. Обратите внимание, так как
    большинство работы производила система ввода/вывода,
    фактически виртуальная память не очень расходовалась
    вследствии использования для /tmp файловой системы mfs.
    Это соотношение может быть нарушено:

    # vmstat 5 5
     procs   memory     page                       disks         faults      cpu
     r b w   avm   fre  flt  re  pi   po   fr   sr w0 c0 f0 m0   in   sy  cs us sy id
     0 2 0 99188   500    2   0   0    0    0    0  1  0  0  0  105   16   4  0  0 100
     0 2 0111596   436  592   0 587  624  586 1210 624  0  0  0  741  883 1088  0 11 89
     0 3 0123976   784  666   0 662  643  683 1326 702  0  0  0  828  993 1237  0 12 88
     0 2 0134692  1236  581   0 571  563  595 1158 599  0  0  0  722  863 1066  0  9 90
     2 0 0142860   912  433   0 406  403  405  808 429  0  0  0  552  602 768  0  7 93

    Довольно страшно выглядит. Такой результат мы получили
    используя bonny в системе, где /tmp использует файловую
    систему mfs для хранения своих данных. Обратите внимание,
    на то, что хоть и виртуальная память была очень нагружена,
    процессор был свободен.

    17.5. Сетевые утилиты

    Иногда, проблемы возникают не в работе какой-то отдельно
    взятой машины, а в сети – с кабельной разводкой или сетеыми
    устройствами. То, как взаимодествуют другие машины в сети с
    нашей NetBSD-машиной, может оказывать сильное влияние на
    функционирование сервисов непосредственно на машине или
    оказывать влияние на работу пользователей с этой машиной.
    Реальный пример – когда в сети становится недступен DNS
    сервер. Разрешение имени тогда идет долго и в конце концов
    терпят неудачу, и тогда начинаютя обвинения в адрес NetBSD-машины,
    раздаются крики пользователей что «сломался Интернет»
    и т.д. Независимо от того, что произошло, NetBSD имеет
    средства для поиска неисправности как на локальной машине,
    так и в сети.

    17.5.1. ping

    Классическая утилита ping(8) показывает наличие
    связи с удаленной машиной. В качестве параметра можно
    указать IP адрес целевой машины или ее имя (если настроен
    nsswitch.conf). Вот ее вывод:

    # ping -c 3 marie
    PING marie (172.16.14.12): 56 data bytes
    64 bytes from 172.16.14.12: icmp_seq=0 ttl=255 time=0.571 ms
    64 bytes from 172.16.14.12: icmp_seq=1 ttl=255 time=0.361 ms
    64 bytes from 172.16.14.12: icmp_seq=2 ttl=255 time=0.371 ms
    
    ----marie PING Statistics----
    3 packets transmitted, 3 packets received, 0.0% packet loss
    round-trip min/avg/max/stddev = 0.361/0.434/0.571/0.118 ms

    Этот вывод покажет нам, что не только есть связь, но
    и количество прошедших пакетов, их размер, время прохождения
    до удаленной машины. Также указывется соответствие IP
    адреса к имени машины. Если не использовать сервер имен,
    то можно воспользоваться только IP адресом.

    # ping -c 1 172.16.20.5
    PING ash (172.16.20.5): 56 data bytes
    64 bytes from 172.16.20.5: icmp_seq=0 ttl=64 time=0.452 ms
    
    ----ash PING Statistics----
    1 packets transmitted, 1 packets received, 0.0% packet loss
    round-trip min/avg/max/stddev = 0.452/0.452/0.452/0.000 ms

    Время доступа к машине весьма субьективный параметр.
    Например для получения хорошего времени досупа мы можем
    пинговать localhost:

    # ping -c 4 localhost
    PING localhost (127.0.0.1): 56 data bytes
    64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=0.091 ms
    64 bytes from 127.0.0.1: icmp_seq=1 ttl=255 time=0.129 ms
    64 bytes from 127.0.0.1: icmp_seq=2 ttl=255 time=0.120 ms
    64 bytes from 127.0.0.1: icmp_seq=3 ttl=255 time=0.122 ms
    
    ----localhost PING Statistics----
    4 packets transmitted, 4 packets received, 0.0% packet loss
    round-trip min/avg/max/stddev = 0.091/0.115/0.129/0.017 ms

    Это время намного меньше, потому что запрос никогда не
    покидал машину. Утилита ping может использоваться для
    определения состояния сети и измерения времени доступа к
    различным хостам сети. Также она может быть использована
    для некоторой локализации проблемы в сети – если есть три
    машины под управлением NetBSD и с одной из них очень плохая
    связь, можно предположить, что на ней что-либо неправильно
    настроено.

    17.5.2. traceroute

    Утилита traceroute(8) служит для определения пути
    пакета от одного хоста к другому. Например – путь пакета
    между нашим ftp сервером и ftp. NetBSD.org:

    # traceroute ftp.NetBSD.org
    traceroute to ftp.NetBSD.org (204.152.184.75), 30 hops max, 40 byte packets
     1  208.44.95.1 (208.44.95.1)  1.646 ms  1.492 ms  1.456 ms
     2  63.144.65.170 (63.144.65.170)  7.318 ms  3.249 ms  3.854 ms
     3  chcg01-edge18.il.inet.qwest.net (65.113.85.229)  35.982 ms  28.667 ms  21.971 ms
     4  chcg01-core01.il.inet.qwest.net (205.171.20.1)  22.607 ms  26.242 ms  19.631 ms
     5  snva01-core01.ca.inet.qwest.net (205.171.8.50)  78.586 ms  70.585 ms  84.779 ms
     6  snva01-core03.ca.inet.qwest.net (205.171.14.122)  69.222 ms  85.739 ms  75.979 ms
     7  paix01-brdr02.ca.inet.qwest.net (205.171.205.30)  83.882 ms  67.739 ms  69.937 ms
     8  198.32.175.3 (198.32.175.3)  72.782 ms  67.687 ms  73.320 ms
     9  so-1-0-0.orpa8.pf.isc.org (192.5.4.231)  78.007 ms  81.860 ms  77.069 ms
    10  tun0.orrc5.pf.isc.org (192.5.4.165)  70.808 ms  75.151 ms  81.485 ms
    11  ftp.NetBSD.org (204.152.184.75)  69.700 ms  69.528 ms  77.788 ms

    В целом, не плохо. Пакет пошел с главного компьютера
    на местный маршрутизатор, потом в сеть провайдера, затем
    в Интернет и наконец к адресату. Показания traceroute также
    являются субьективными, но повышенне время доступа на каком
    либо участке сети может указать на проблему сетевого
    оборудования. Утилита traceroute мало чем отличается от
    утилиты ping по принципу действия. Теперь пример проблем
    в сети:

    # traceroute www.microsoft.com
    traceroute: Warning: www.microsoft.com has multiple addresses; using 207.46.230.220
    traceroute to www.microsoft.akadns.net (207.46.230.220), 30 hops max, 40 byte packets
     1  208.44.95.1 (208.44.95.1)  2.517 ms  4.922 ms  5.987 ms
     2  63.144.65.170 (63.144.65.170)  10.981 ms  3.374 ms  3.249 ms
     3  chcg01-edge18.il.inet.qwest.net (65.113.85.229)  37.810 ms  37.505 ms  20.795 ms
     4  chcg01-core03.il.inet.qwest.net (205.171.20.21)  36.987 ms  32.320 ms  22.430 ms
     5  chcg01-brdr03.il.inet.qwest.net (205.171.20.142)  33.155 ms  32.859 ms  33.462 ms
     6  205.171.1.162 (205.171.1.162)  39.265 ms  20.482 ms  26.084 ms
     7  sl-bb24-chi-13-0.sprintlink.net (144.232.26.85)  26.681 ms  24.000 ms  28.975 ms
     8  sl-bb21-sea-10-0.sprintlink.net (144.232.20.30)  65.329 ms  69.694 ms  76.704 ms
     9  sl-bb21-tac-9-1.sprintlink.net (144.232.9.221)  65.659 ms  66.797 ms  74.408 ms
    10  144.232.187.194 (144.232.187.194)  104.657 ms  89.958 ms  91.754 ms
    11  207.46.154.1 (207.46.154.1)  89.197 ms  84.527 ms  81.629 ms
    12  207.46.155.10 (207.46.155.10)  78.090 ms  91.550 ms  89.480 ms
    13  * * *
    .......

    В данном случае сервер microsoft не может быть найден
    или из-за большого числа переходов, или из-за блокирования
    ICMP – пакетов межсетевым экраном, или из-за потерь пакетов
    в канале. Если попробовать применить утилиту ping, то она
    не будет работать, так что можно селать вывод о том, что
    скорее всего заблокированы ICMP – пакеты на сеть
    microsoft.

    17.5.3. netstat

    Другая проблема, которая мжет возникнуть, проблема
    маршрутизации. Эти проблемы не всегда появляются вследствие
    неправильной настройки. Команды route(8) and
    netstat(1) команды могут показать информацю о маршрутах
    и сетевых подключениях соответственно.

    Команда route может использоваться, чтобы смотреть и
    изменять таблицы маршрутизации, в то время как netstat
    может отобразит информацию о сетевых подключениях и маршрутах.
    Вот вывод команды route:

    # route show
    Routing tables
    
    Internet:
    Destination      Gateway            Flags
    default          208.44.95.1        UG
    loopback         127.0.0.1          UG
    localhost        127.0.0.1          UH
    172.15.13.0      172.16.14.37       UG
    172.16.0.0       link#2             U
    172.16.14.8      0:80:d3:cc:2c:0    UH
    172.16.14.10     link#2             UH
    marie            0:10:83:f9:6f:2c   UH
    172.16.14.37     0:5:32:8f:d2:35    UH
    172.16.16.15     link#2             UH
    loghost          8:0:20:a7:f0:75    UH
    artemus          8:0:20:a8:d:7e     UH
    ash              0:b0:d0:de:49:df   UH
    208.44.95.0      link#1             U
    208.44.95.1      0:4:27:3:94:20     UH
    208.44.95.2      0:5:32:8f:d2:34    UH
    208.44.95.25     0:c0:4f:10:79:92   UH
    
    Internet6:
    Destination      Gateway            Flags
    default          localhost          UG
    default          localhost          UG
    localhost        localhost          UH
    ::127.0.0.0      localhost          UG
    ::224.0.0.0      localhost          UG
    ::255.0.0.0      localhost          UG
    ::ffff:0.0.0.0   localhost          UG
    2002::           localhost          UG
    2002:7f00::      localhost          UG
    2002:e000::      localhost          UG
    2002:ff00::      localhost          UG
    fe80::           localhost          UG
    fe80::%ex0       link#1             U
    fe80::%ex1       link#2             U
    fe80::%lo0       fe80::1%lo0        U
    fec0::           localhost          UG
    ff01::           localhost          U
    ff02::%ex0       link#1             U
    ff02::%ex1       link#2             U
    ff02::%lo0       fe80::1%lo0        U

    Значение флагов: U – действует, H – хост, G – шлюз.
    О значении других флагов, читайте руководство man.

    Теперь вывод netstat с параметрами r(маршруты) и n(не
    использовать DNS):

    Routing tables
    
    Internet:
    Destination        Gateway            Flags     Refs     Use    Mtu  Interface
    default            208.44.95.1        UGS         0   330309   1500  ex0
    127                127.0.0.1          UGRS        0        0  33228  lo0
    127.0.0.1          127.0.0.1          UH          1     1624  33228  lo0
    172.15.13/24       172.16.14.37       UGS         0        0   1500  ex1
    172.16             link#2             UC         13        0   1500  ex1
    ...
    Internet6:
    Destination                   Gateway                   Flags     Refs     Use
      Mtu  Interface
    ::/104                        ::1                       UGRS        0        0
    33228  lo0 =>
    ::/96                         ::1                       UGRS        0        0
    

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

    17.5.4. tcpdump

    Последний по списку, но определенно не по значению,
    tcpdump(8), сетевой анализатор, с помощью которого
    можно собрать очень много информации. Сейчас мы рассмотрим
    вывод утилиты и объясненим некоторые из наиболее полезных
    параметров tcpdump.

    Следующее – маленький отрывок вывода tcpdump:

    # tcpdump
    tcpdump: listening on ex0
    14:07:29.920651 mail.ssh > 208.44.95.231.3551: P 2951836801:2951836845(44) ack 2
    476972923 win 17520 <nop,nop,timestamp 1219259 128519450> [tos 0x10]
    14:07:29.950594 12.125.61.34 >  208.44.95.16: ESP(spi=2548773187,seq=0x3e8c) (DF)
    14:07:29.983117 smtp.somecorp.com.smtp > 208.44.95.30.42828: . ack 420285166 win
    16500 (DF)
    14:07:29.984406 208.44.95.30.42828 > smtp.somecorp.com.smtp: . 1:1376(1375) ack 0
     win 7431 (DF)
    ...

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

    # tcpdump > tcpdump.out
    tcpdump: listening on ex0

    Так, что точно мы ищем? Это могут быть неправильные
    пакеты, пакеты с определенного адреса или пределенного
    типа, в общем, что угодно. С помощью tcpdump возможна
    диагностика большого количества проблем в сети.

    17.5.4.1. Использование tcpdump

    Вот несколько примеров использования tcpdump:

    Наличие двойных IP адресов:

    tcpdump -e host ip-address

    Для примера:

    tcpdump -e host 192.168.0.2

    Проблемы маршрутизации:

    tcpdump icmp

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

    17.6. Аккаунтинг

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

    17.6.1. Accounting

    В то время как аккаунтинг используется на уровне
    окружения пользователя, профилирование ядра с gprof
    обеспечивает явное использование системного вызова.

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

    Использование очень простое, необходимо выполнить с
    правами пользователя root команду accton(8):
    accton filename

    И вся информация будет добавляться в конец файла
    filename. Команда lastcomm позволит просмотреть этот файл.
    По умолчанию будет просмотрен файл
    /var/account/acct. Также может быть
    указан любой другой файл.

    Для остановки аккаунтинга достаточно ввести accton без
    параметров.

    17.6.2. Чтение информации аккаунтинга

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

    17.6.2.1. lastcomm

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

    $ lastcomm jrf
    last       -       jrf      ttyp3      0.00 secs Tue Sep  3 14:39 (0:00:00.02)
    man        -       jrf      ttyp3      0.00 secs Tue Sep  3 14:38 (0:01:49.03)
    sh         -       jrf      ttyp3      0.00 secs Tue Sep  3 14:38 (0:01:49.03)
    less       -       jrf      ttyp3      0.00 secs Tue Sep  3 14:38 (0:01:49.03)
    lastcomm   -       jrf      ttyp3      0.02 secs Tue Sep  3 14:38 (0:00:00.02)
    stty       -       jrf      ttyp3      0.00 secs Tue Sep  3 14:38 (0:00:00.02)
    tset       -       jrf      ttyp3      0.00 secs Tue Sep  3 14:38 (0:00:01.05)
    hostname   -       jrf      ttyp3      0.00 secs Tue Sep  3 14:38 (0:00:00.02)
    ls         -       jrf      ttyp0      0.00 secs Tue Sep  3 14:36 (0:00:00.00)
    ...

    По умолчанию чтение производится из файла /var/account/acct,
    но с помощью опции -f можно переопределить файл.

    Очевидно, что использовать lastcomm в системе с
    большим количеством пользователей достаточно тяжело. Тут
    может помоч утилита sa.

    17.6.2.2. sa

    Утилита sa(расшифровывается как «печатать статистику
    системного аккаунтинга») может использоваться для обработки
    информации аккаунтинга. Также применяется для создания
    интерактивных отчетов. Вот пример вывода этой команды:

    $ sa
          77       18.62re        0.02cp        8avio        0k
           3        4.27re        0.01cp       45avio        0k   ispell
           2        0.68re        0.00cp       33avio        0k   mutt
           2        1.09re        0.00cp       23avio        0k   vi
          10        0.61re        0.00cp        7avio        0k   ***other
           2        0.01re        0.00cp       29avio        0k   exim
           4        0.00re        0.00cp        8avio        0k   lastcomm
           2        0.00re        0.00cp        3avio        0k   atrun
           3        0.03re        0.00cp        1avio        0k   cron*
           5        0.02re        0.00cp       10avio        0k   exim*
          10        3.98re        0.00cp        2avio        0k   less
          11        0.00re        0.00cp        0avio        0k   ls
           9        3.95re        0.00cp       12avio        0k   man
           2        0.00re        0.00cp        4avio        0k   sa
          12        3.97re        0.00cp        1avio        0k   sh
    ...

    Слева направо: полное время вызова, реальное время
    в минутах, число пользователей, системное время в минутах,
    среднее количество операций ввода/вывода, и имя
    команды.

    Команда sa может также использоваться для создания
    файлов отчета или сообщений, основанных на шаблонах.
    Например, вот – вывод процессов, отсортированных по
    среднему использованию CPU:

    $ sa -k
          86       30.81re        0.02cp        8avio        0k
          10        0.61re        0.00cp        7avio        0k   ***other
           2        0.00re        0.00cp        3avio        0k   atrun
           3        0.03re        0.00cp        1avio        0k   cron*
           2        0.01re        0.00cp       29avio        0k   exim
           5        0.02re        0.00cp       10avio        0k   exim*
           3        4.27re        0.01cp       45avio        0k   ispell
           4        0.00re        0.00cp        8avio        0k   lastcomm
          12        8.04re        0.00cp        2avio        0k   less
          13        0.00re        0.00cp        0avio        0k   ls
          11        8.01re        0.00cp       12avio        0k   man
           2        0.68re        0.00cp       33avio        0k   mutt
           3        0.00re        0.00cp        4avio        0k   sa
          14        8.03re        0.00cp        1avio        0k   sh
           2        1.09re        0.00cp       23avio        0k   vi

    Утилита sa весьма полезна на загруженных системах.

    17.6.3. Как исполдьзовать аккаунтинг

    Аккаунтинг, при его ведении и регулярном анализе, может
    помочь предсказать появление проблем производительности,
    после пары месяцев сбора статистики позволит понять, какие
    изменения надо сделать, чтобы сохранить или повысить
    производительность. Другой хороший пример – использование
    сервера сети. Если нагрузка начинает увеличиваться, возможно
    стоит предпринять некоторые действия, до того как она станет
    реальной проблемой. Так что, вывод однозначный – как
    здорово, что в NetBSD есть такие замечательные средства
    контроля и все проблемы можно предсказать заранее!

    17.7. Профили ядра

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

    17.7.1. С чего начать

    Для начала просмотрите разделы Раздел 17.9, «Оптимизация ядра»
    и Глава 28, Компиляция ядра настоящего руководства.
    Единственное различие в процедуре установки ядра с
    профилированием заключается в необходимости добавить в
    config опцию -p. Находясь в каталоге исходных текстов ядра
    ../compile/<KERNEL_NAME>.PROF,
    в то время как GENERIC-ядро в
    ../compile/GENERIC.PROF.

    Ниже следует краткая инструкция по тому, как скомпилировать
    ядро с поддержкой профилирования для i386. Считаем, что
    исходники доступны в /usr/src и
    используется ядро GENERIC, что не всегда соответствует
    действительности.

    1. cd
      /usr/src/sys/arch/i386/conf
    2. config -p GENERIC
    3. cd ../compile/GENERIC.PROF
    4. make depend && make
    5. cp /netbsd /netbsd.old
    6. cp netbsd /
    7. reboot

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

    17.7.1.1. Использование kgmon

    Запускаем kgmon:

    $ kgmon -b
    kgmon: kernel profiling is running.

    Затем посылаем данные в файл
    gmon.out:

    $ kgmon -p

    Делаем читаемый вывод:

    $ gprof /netbsd > gprof.out

    В текущем каталоге gmon начинает искать файл
    gmon.out.

    Выполняя только kgmon, вы не можете получить всей
    информации, в которой вы нуждаетесь, однако, если Вы
    можете получить данные для ядра GENERIC, для последующего
    сравнения со своими ядрами.

    17.7.2. Расшифровка вывода kgmon

    Теперь, когда kgmon может собирать и анализировать
    информацию, пришло время посмотреть на работу системы. В
    нашем примере ядро GENERIC выполняется с профилированием
    в течение приблизительно часа с только системными процессами,
    дополнительной нагрузки нет, ошибок нет.

    17.7.2.1. Flat Profile

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

    Flat profile:
    
    Each sample counts as 0.01 seconds.
      %   cumulative   self              self     total
     time   seconds   seconds    calls  ns/call  ns/call  name
     99.77    163.87   163.87                             idle
      0.03    163.92     0.05      219 228310.50 228354.34  _wdc_ata_bio_start
      0.02    163.96     0.04      219 182648.40 391184.96  wdc_ata_bio_intr
      0.01    163.98     0.02     3412  5861.66  6463.02  pmap_enter
      0.01    164.00     0.02      548 36496.35 36496.35  pmap_zero_page
      0.01    164.02     0.02                             Xspllower
      0.01    164.03     0.01   481968    20.75    20.75  gettick
      0.01    164.04     0.01     6695  1493.65  1493.65  VOP_LOCK
      0.01    164.05     0.01     3251  3075.98 21013.45  syscall_plain
    ...
    

    Как и ожидалось, основную часть времени система
    простаивала, но некоторые процессы всеже работали,
    например, функция vn_lock:

    ...
      0.00    164.14     0.00     6711     0.00     0.00  VOP_UNLOCK
      0.00    164.14     0.00     6677     0.00  1493.65  vn_lock
      0.00    164.14     0.00     6441     0.00     0.00  genfs_unlock
    

    Это закономерно и ожидаемо.

    17.7.2.2. Call Graph Profile

    Это расширенная версия конфигурации, представленной
    выше, показывающая последующие запросы от перечисленных
    функций. Вот пример ее вывода:

    		     Call graph (explanation follows)
    
    granularity: each sample hit covers 4 byte(s) for 0.01% of 164.14 seconds
    
    index % time    self  children    called     name
    						 <spontaneous>
    [1]     99.8  163.87    0.00                 idle [1]
    -----------------------------------------------
    						 <spontaneous>
    [2]      0.1    0.01    0.08                 syscall1 [2]
    		0.01    0.06    3251/3251        syscall_plain [7]
    		0.00    0.01     414/1660        trap [9]
    -----------------------------------------------
    		0.00    0.09     219/219         Xintr14 [6]
    [3]      0.1    0.00    0.09     219         pciide_compat_intr [3]
    		0.00    0.09     219/219         wdcintr [5]
    -----------------------------------------------
    ...
    

    Все выглядит немного запутанно. Индексный номер
    отображается в конце строки, для примера:

    ...
    		0.00    0.01      85/85          dofilewrite [68]
    [72]     0.0    0.00    0.01      85         soo_write [72]
    		0.00    0.01      85/89          sosend [71]
    ...
    

    Здесь мы видим, что сначала был вызван dofilewrite,
    теперь мы можем смотреть на индексный номер для 64 и
    посмотреть то, что случилось там:

    ...
    		0.00    0.01     101/103         ffs_full_fsync <cycle 6> [58]
    [64]     0.0    0.00    0.01     103         bawrite [64]
    		0.00    0.01     103/105         VOP_BWRITE [60]
    ...
    

    Таким образом можно установить «визуальный путь»
    процесса.

    В конце вывода идет индекс имен функций, который
    может помочь разобраться с картой индексов.

    17.7.3. Использование

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

    Рассмотрим верхнюю часть Flat profile после часа работы
    системы не слишком нагруженной пользовательскими задачами:

    Flat profile:
    
    Each sample counts as 0.01 seconds.
      %   cumulative   self              self     total
     time   seconds   seconds    calls  us/call  us/call  name
     93.97    139.13   139.13                             idle
      5.87    147.82     8.69       23 377826.09 377842.52  check_exec
      0.01    147.84     0.02      243    82.30    82.30  pmap_copy_page
      0.01    147.86     0.02      131   152.67   152.67  _wdc_ata_bio_start
      0.01    147.88     0.02      131   152.67   271.85  wdc_ata_bio_intr
      0.01    147.89     0.01     4428     2.26     2.66  uvn_findpage
      0.01    147.90     0.01     4145     2.41     2.41  uvm_pageactivate
      0.01    147.91     0.01     2473     4.04  3532.40  syscall_plain
      0.01    147.92     0.01     1717     5.82     5.82  i486_copyout
      0.01    147.93     0.01     1430     6.99    56.52  uvm_fault
      0.01    147.94     0.01     1309     7.64     7.64  pool_get
      0.01    147.95     0.01      673    14.86    38.43  genfs_getpages
      0.01    147.96     0.01      498    20.08    20.08  pmap_zero_page
      0.01    147.97     0.01      219    45.66    46.28  uvm_unmap_remove
      0.01    147.98     0.01      111    90.09    90.09  selscan
    ...
    

    Как видно из результата вывода, имеется большое различие
    в работе. Сначительно сократилось время простоя системы.
    Основное различие состоит в том, что одна специфическая
    функция имеет большое время работы с очень небольшим
    количеством запросов. Эта функция – check_exec. Сначала
    это может не показаться странным, но после выполнения
    большого числа команд расхождение с Flat profile первого
    измерения оказаться значительным:

    ...
      0.00    164.14     0.00       37     0.00 62747.49  check_exec
    ...
    

    Запрос в первом измерении сделан 37 раз и имеет большое
    время работы. Очевидно, что работа этой функции неправильна.
    Чтобы выявить другие функции, нам необходим график запросов,
    вот – первая зависимость check_exec:

    ...
    -----------------------------------------------
    		0.00    8.69      23/23          syscall_plain [3]
    [4]      5.9    0.00    8.69      23         sys_execve [4]
    		8.69    0.00      23/23          check_exec [5]
    		0.00    0.00      20/20          elf32_copyargs [67]
    ...
    

    Обратите внимание, как время 8.69, кажется, затрагивает
    две предыдущих функции. Возможно, что – то не так с ними,
    однако, следующий образец check_exec доказывает иное:

    ...
    -----------------------------------------------
    		8.69    0.00      23/23          sys_execve [4]
    [5]      5.9    8.69    0.00      23         check_exec [5]
    ...
    

    Теперь мы можем видеть, что проблема, наиболее вероятно,
    постоянно находится в check_exec.
    Конечно, проблемы не всегда настолько просты и очевидны,
    вот – простой код, который был вставлен в
    check_exec (функция находится в
    sys/kern/kern_exec.c):

    ...
    	/* A Cheap fault insertion */
    	for (x = 0; x < 100000000; x++) {
    		y = x;
    	}
    ..
    

    Не очень красиво, но достаточно для показа работы
    системы с профилированием.

    17.7.4. Резюме:

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

    17.8. Оптимизация системы

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

    17.8.1. Использование sysctl

    Данная утилита используется для просмотра и установки
    системных параметров. Так как параметров очень много,
    рассмотреть здесь их все не представляется возможным. Но
    приведем несколько примеров, например вывод переменной
    PATH:

    $ sysctl user.cs_path
    user.cs_path = /usr/bin:/bin:/usr/sbin:/sbin:/usr/pkg/bin:/usr/pkg/sbin:/usr/local/bin:/usr/local/sbin

    Довольно просто. Теперь кое-что, что фактически связано
    с работой. Посмотрим параметр kern.maxfiles – он определяет
    сколько одновременно может быть открыто файлов. На сильно
    нагруженных системах, говорят, что могут появиться проблемы
    из-за невозможности открыть файл.

    $ sysctl kern.maxfiles
    kern.maxfiles = 1772

    Отлично. Теперь изменим этот параметр. Мы должны владеть
    правами пользователя root и использовать параметр -w:

    # sysctl -w kern.maxfiles=1972
    kern.maxfiles: 1772 -> 1972

    Помните, что после перезагрузки изменения пропадут.
    Есть два пути сохранения изменений – это внести изменения
    в ядро и прекомпилировать его или внести изменения в файл
    /etc/sysctl.conf:

    kern.maxfiles=1972
    

    17.8.2. memfs & softdeps

    Работа операционной системы может быть улучшена изменением
    сразу нескольких прараметров (также она может быть и
    ухудшена). Этими параметрами является использование
    файловых систем в памяти и/или soft updates.

    17.8.2.1. Использование memfs

    Когда использовать memfs, а когда нет – дело сугубо
    субьективное. Использование на сервере с большим
    количеством пользователей не рекомендуется. Однако на
    персональной машине это выглядит довольно симпатично и
    каталог obj и некоторые из tmp каталогов можно было бы
    перенести в память. Смысл это имеет при соответствующем
    размере памяти. С другой стороны, если система только
    имеет 16 МБ оперативной памяти и /var/tmp
    использует memfs, могут возникнуть большие проблемы с
    приложениями, использующих /var/tmp.

    В GENERIC – ядре memfs установлен по умолчанию. Чтобы
    использовать memfs необходимо сначала определить раздел
    файла подкачки. Быстрый взгляд на /etc/fstab
    говорит, что им является /dev/wd0b.

    mail% cat /etc/fstab
    /dev/wd0a / ffs rw 1 1
    /dev/wd0b none swap sw 0 0
    /kern /kern kernfs rw
    

    Эта система – почтовый сервер, так что я хочу
    использовать только /tmp с memfs.
    Также на этой системе я связал /tmp
    с /var/tmp для экономии дискового
    пространства.

    /dev/wd0b /var/tmp mfs rw 0 0
    

    Удостоверьтесь, что каталоги пусты и никто не использует
    их! Потом можно примонтировать этот раздел командой
    mount -a или перезагрузить систему.

    17.8.2.2. Использование softdeps

    Этот механизм позволяет не записывать мета-данные
    немедленно на диск, что позволяет оптимизировать операции
    ввода/вывода. soft updates не установлена по умолчанию
    из-за особенностей лицензирования и потому, что эта
    функция все еще считается экспериментальной. Да включения
    этой функции обратитесь к главе Раздел 4.9, «Включение FFS soft-dependencies» руководства.
    Однако, практика подтверждает, что работает это дело
    хорошо. softdeps заставляет систему работать значительно
    быстрее, например rm -f в обычном случае требует некоторое
    время на выполнение, с softdeps все происходит практически
    мгновенно. Много подробной информации о возможностях
    softdep может быть найдено на странице
    автора
    .

    17.9. Оптимизация ядра

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

    17.9.1. Подготовка к компиляции ядра

    Сперва получите исходные тексты ядра. Для получения
    подробной информации обратитесь к главам Глава 26, Obtaining sources by CVS и Глава 28, Компиляция ядра руководства. Внимание
    - этот документ применим к -current ветке ядра. Также
    прочитайте статью Трэкинг
    -current
    на официальном сайте.

    17.9.2. Конфигурирование ядра

    Конфигурирование ядра в NetBSD довольно непростое
    занятие. Связано это с много численными зависимостями в
    пределах файла конфигурации, единственный плюс – для
    конфигурирования можно обойтись выводом dmesg и ascii
    редактором. Ядро находится в
    src/sys/arch/ARCH/conf, где ARCH -
    ваша архитектура. (например, на sparc это было бы под
    src/sys/arch/sparc/conf).

    Конфигурирование ядра заключается в создании копии
    файла конфигурации ядра и удаления(комментирования) всего
    лишнего. Сейчас именно тот случай, когда dmesg(8)
    становится вашим другом. dmesg(8) покажет все устройства,
    обнаруженным ядром во время загрузки. Используя вывод
    dmesg(8) могут быть определены опции имеющихся устройств.
    Для автоматизации действий может быть использован пакет
    «adjustkernel».

    17.9.2.1. Пример конфигурации

    В данном примере мы конфигурируем ядро для ftp сервера,
    убирая все лишние драйвера и сервисы – все, что может
    замедлить работу. Копируем файл
    /usr/src/sys/arch/i386/conf/GENERIC
    в файл FTP и приступаем к его редактированию.

    В начале файла есть набор опций, включая maxuser,
    которые мы оставим в покое, однако на много пользовательских
    системах этот параметр можно и поправить. Далее идет тип
    процессора. Руководствуясь выводом dmesg определяем:

    cpu0: Intel Pentium II/Celeron (Deschutes) (686-class), 400.93 MHz
    

    Нам требуется только опция I686_CPU. В следущей секции
    тоже все оставляем в покое за исключением PIC_DELAY – ее
    рекомендуется выставить, если это не старая машина (не
    ниже 686).

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

    Следущая секция содержит в себе строки поддержки
    файловых систем.

    # File systems
    file-system     FFS             # UFS
    file-system     LFS             # log-structured file system
    file-system     MFS             # memory file system
    file-system     CD9660          # ISO 9660 + Rock Ridge file system
    file-system     FDESC           # /dev/fd
    file-system     KERNFS          # /kern
    file-system     NULLFS          # loopback file system
    file-system     PROCFS          # /proc
    file-system     UMAPFS          # NULLFS + uid and gid remapping
    ...
    options         SOFTDEP         # FFS soft updates support.
    ...
    

    Сетевые опции:

    options         INET            # IP + ICMP + TCP + UDP
    options         INET6           # IPV6
    options         IPFILTER_LOG    # ipmon(8) log support
    

    Опцию IPFILTER_LOG мы оставим, та как планируем
    использовать ipf.

    Следующий раздел – подробные отладочные сообщения
    для различных подсистем, так как эта машина уже работала
    и не имела никаких проблем, все они прокомментированы.

    17.9.2.2. Драйверы устройств

    Элементы конфигурации указанные выше – дело простое
    и обьяснимое. Драйверы устройство – совсем наоборот.
    Вот маленький пример с CD-ROM.

    ...
    cd0 at atapibus0 drive 0: <CD-540E, , 1.0A> type 5 cdrom removable
    cd0: 32-bit data port
    cd0: drive supports PIO mode 4, DMA mode 2, Ultra-DMA mode 2
    pciide0: secondary channel interrupting at irq 15
    cd0(pciide0:1:0): using PIO mode 4, Ultra-DMA mode 2 (using DMA data transfer
    ...
    

    Теперь пришло время разыскивать этот раздел в файле
    конфигурации. Обратите внимание, что CD находится на
    atapibus и требует поддержки pciide. Раздел, который
    представляет интерес в этом случае – раздел «IDE and
    related devices». Также рядом лежат разделы ISA, PCMCIA
    и т.д. На этой машине нет PCMCIA устройств, поэтому всю
    секцию комментируем.

    Всекции IDE ищем строку:

    ...
    wd*     at atabus? drive ? flags 0x0000
    ...
    atapibus* at atapi?
    ...
    

    Хорошо, довольно очевидно, что те строки должны быть
    сохранены. Затем:

    ...
    # ATAPI devices
    # flags have the same meaning as for IDE drives.
    cd*     at atapibus? drive ? flags 0x0000       # ATAPI CD-ROM drives
    sd*     at atapibus? drive ? flags 0x0000       # ATAPI disk drives
    st*     at atapibus? drive ? flags 0x0000       # ATAPI tape drives
    uk*     at atapibus? drive ? flags 0x0000       # ATAPI unknown
    ...
    

    Единственный тип устройства, который был в выводе
    dmesg(8) – это CD, остальное может быть
    закомментировано.

    Следующий пример чуть сложнее – сетевые интерфейсы.
    В этой машине их два.

    ...
    ex0 at pci0 dev 17 function 0: 3Com 3c905B-TX 10/100 Ethernet (rev. 0x64)
    ex0: interrupting at irq 10
    ex0: MAC address 00:50:04:83:ff:b7
    UI 0x001018 model 0x0012 rev 0 at ex0 phy 24 not configured
    ex1 at pci0 dev 19 function 0: 3Com 3c905B-TX 10/100 Ethernet (rev. 0x30)
    ex1: interrupting at irq 11
    ex1: MAC address 00:50:da:63:91:2e
    exphy0 at ex1 phy 24: 3Com internal media interface
    exphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
    ...
    

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

    exphy0 at ex1 phy 24: 3Com internal media interface
    

    Мы имеем только две сетевые карты, поэтому, как и в
    случае с CDROM, просто удаляем все, что мы не увидели в
    выводе dmesg. Переходим в начало секции сетевых
    интерфейсов:

    ...
    # Network Interfaces
    
    # PCI network interfaces
    an*     at pci? dev ? function ?        # Aironet PC4500/PC4800 (802.11)
    bge*    at pci? dev ? function ?        # Broadcom 570x gigabit Ethernet
    en*     at pci? dev ? function ?        # ENI/Adaptec ATM
    ep*     at pci? dev ? function ?        # 3Com 3c59x
    epic*   at pci? dev ? function ?        # SMC EPIC/100 Ethernet
    esh*    at pci? dev ? function ?        # Essential HIPPI card
    ex*     at pci? dev ? function ?        # 3Com 90x[BC]
    ...
    

    У нас есть устройство ex. Все остальное в разделе
    PCI может быть заккоментировано, кроме строки:

    exphy*  at mii? phy ?                   # 3Com internal PHYs
    

    Которая может быть как закомментирована, так и
    сохранена.

    17.9.2.3. Multi Pass

    Когда я настраиваю ядро, я люблю сделать это дистанционно
    в сеансе X, в одном окне вывод dmesg, в другом файл
    конфигурации. Может иногда потребоваться выполнить
    несколько проходов, чтобы восстановить черезчур урезанное
    ядро, так как легко случайно удалить зависимости.

    17.9.3. Building the New Kernel

    Теперь пришло время компилировать и устанавливать ядро.
    В каталоге conf нашего ftp сервера выполним следующую
    команду:

    $ config FTP

    Когда на экране появится предупреждение не забыть
    сделать make depend:

    $ cd ../compile/FTP
    $ make depend && make

    Когда это сделано, сохраняем старое ядро и ставим
    новое:

    # cp /netbsd /netbsd.orig
    # cp netbsd /

    Теперь перезагрузка. Если ядро не загружается, то
    остановите процесс загрузки и введите boot
    netbsd.orig
    для загрузки предыдущего ядра.

    Глава 16. Pluggable Authentication Modules (PAM)

    Русский перевод: Михаил Сгибнев

    Содержание

    16.1. Краткое содержание
    16.2. Introduction
    16.3. Термины и соглашения
    16.3.1. Определения
    16.3.2. Примеры
    16.4. Основное в PAM
    16.4.1. Средства и примитивы
    16.4.2. Модули
    16.4.3. Цепочки и правила
    16.4.4. Транзакции
    16.5. Конфигурирование PAM
    16.5.1. Файл политик PAM
    16.5.2. Разбор строки конфигурации
    16.5.3. Политики
    16.6. Модули PAM
    16.6.1. Общие модули
    16.6.2. Специфичные для FreeBSD модули PAM
    16.6.3. Модули PAM, специфичные для NetBSD
    16.7. Программирование приложений PAM
    16.8. Программирование модулей PAM
    16.9. Пример приложения PAM
    16.10. Пример модуля PAM
    16.11. Простая функция сеанса связи PAM
    16.12. Для дополнительного прочтения

    16.1. Краткое содержание

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

    16.2. Introduction

    Библиотеки Pluggable Authentication Modules (PAM)являются обьединенным API для сервисов, требующих аутентификацию и позволяет системным администраторам добавлять новые методы аутентификации просто инсталировав новый модуль PAM и модифицировав правила аутентификации в файле конфигурации.

    Впервые PAM был описан и разработан в 1995 Vipin Samar и Charlie Lai из Sun Microsystems и с тех пор не сильно изменился. В 1997 году Open Group опубликовала предварительную спецификацию X/Open Single Sign-on (XSSO), которая стандартизировала PAM API и добавляла расширения для единственной (или, скорее, интегрированной) подписи. В то время, когда писалась эта глава, стандарт еще не был утвержден.

    Хотя эта глава больше применима к FreeBSD 5.x и NetBSD 3.x, которые используют OpenPAM, она может использоваться и при работе с FreeBSD 4.x, которая использует Linux-PAM и другими ОС, такими как Linux и Solaris™.

    16.3. Термины и соглашения

    16.3.1. Определения

    Терминология в PAM довольно запутанная. Ни Neither Samar и Lai’s ни спецификация XSSO не делали попыток первоначального определения терминов и обьектов, входящих в PAM, поэтому с течением времени возникла неоднозначность и путанница. Первая попытка установления непротиворечивой и однозначной терминологии была предпринята в подробном докладе, написанным Эндрю Г. Морган (автор Linux-PAM) в 1999 году. Хотя это и был огромный шаг вперед, по мнению самого Моргана, терминология еще далека от совершенства. Поэтому начнем мы с точного определения всех акторов и обьектов, включенных в PAM.

    аккаунт
    Привилегии, которые претендент запрашивает у арбитра.

    претендент
    Пользователь или обьект, запрашивающий аутентификацию.

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

    цепочка
    Последовательность модулей, которые будут вызваны в ответ на запрос PAM. Цепочка включает информацию о порядке вызова модулей, передаваемых параметрах, и методе интерпретации результатов.

    клиент
    Приложение, ответственное за инициализацию запроса на аутентификацию и готовое получить от него необходимую аутентификационную информацию.

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

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

    политика
    Законченный набор инструкций, описывающих как PAM обрабатывает запросы на обслуживание. Политика обычно состоит из четырех цепочек, по одной на каждое средство, хотя некоторые сервисы не используют все четыре средства.

    сервер
    Приложение, действующее от имени арбитра, для общения с клиентом, получения аутентификационной информации, проверки полномочий претендента и предоставления доступа.

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

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

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

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

    16.3.2. Примеры

    В этом разделе мы проиллюстрируем значения некоторых терминов на простых примерах.

    16.3.2.1. Одна программа в роли и клиента и сервера

    В этом примере, пользователь alice использует su(1) для использования учетной записи root.

    $ whoami
    alice
    $ ls -l `which su`
    -r-sr-xr-x  1 root  wheel  10744 Dec  6 19:06 /usr/bin/su
    $ su -
    Password: xi3kiune
    # whoami
    root
    • Здесь претендентом будет alice.
    • Аккаунтом будет root.
    • Процесс su(1) выступает в роли и клиента и сервера.
    • Ключом аутентификации будет xi3kiune.
    • Арбитром является root, поскольку у su(1) выставлен setuid root.

    16.3.2.2. Разделенный клиент и сервер

    В этом примере показано, как eve инициирует соединение ssh(1) с login.example.com, и логинится под именем bob. Боб должен был выбрать лучший пароль!

    $ whoami
    eve
    $ ssh bob@login.example.com
    bob@login.example.com's password: god
    Last login: Thu Oct 11 09:52:57 2001 from 192.168.0.1
    NetBSD 3.0 (LOGIN) #1: Thu Mar 10 18:22:36 WET 2005
    
    Welcome to NetBSD!
    $
    • Претендентом является eve.
    • Клиентом будет процесс ssh(1), выполняемый eve.
    • В роли сервера выступит процесс sshd(8) на login.example.com
    • Аккаунтом является bob.
    • Ключ аутентификации – god.
    • Хотя это и не показано в нашем примере, арбитром является root.

    16.3.2.3. Простая политика

    Вот политика по умолчанию для FreeBSD sshd:

    sshd	auth		required	pam_nologin.so	no_warn
    sshd	auth		required	pam_unix.so	no_warn try_first_pass
    sshd	account		required	pam_login_access.so
    sshd	account		required	pam_unix.so
    sshd	session		required	pam_lastlog.so	no_fail
    sshd	password	required	pam_permit.so
    • Эта политика обращается к сервису sshd, (который может состоять не только из сервера sshd(8)).
    • auth, account, session и password будут средствами.
    • pam_nologin.so, pam_unix.so, pam_login_access.so, pam_lastlog.so и pam_permit.so являются модулями. Из этого примера ясно, что pam_unix.so предоставляет не менее двух средств (аутентификация и управление аккаунтом).

    Есть несколько отличий между политиками PAM на FreeBSD и NetBSD:

    • По умолчанию, каждая конфигурация сделана для /etc/pam.d.
    • Если конфигурации не существует, то вы не получите доступа в систему, в отличие от FreeBSD, где имеется политика по умолчанию, принимающая аутентификацию.
    • Для аутентификации в NetBSD необходимо наличие не менее одного модуля required, requisite или binding.

    16.4. Основное в PAM

    16.4.1. Средства и примитивы

    API PAM предлагает шесть различных примитивов аутентификации, сгруппированных в четырех средствах, которые описаны ниже.

    auth
    Аутентификация. Это средство занимается подтверждением претендента и установлением данных аккаунта. Оно предоставляет два примитива:

    • pam_authenticate(3) подтверждает подлинность претендента, обычно запрашивая ключ аутентификации и сравнивая это со значением, сохраненным в базе данных или полученный от сервера аутентификации.
    • pam_setcred(3) утанавливает данные аккаунта, такие как ID пользователя, членство в группах и лимит ресурсов.
    account
    Управление аккаунтом. Это средство проверяет доступность аккаунта, опираясь на такие данные, как время суток или загрузку сервера. Оно предоставляет единственный примитив:

    • pam_acct_mgmt(3) проверяет, что запрашиваемый аккаунт доступен.
    session
    Управление сессией. Это средство обрабатывает задачи, связанные с установкой и окончанием сеанса, типа учета входа в систему. Оно обеспечивает два примитива:

    • pam_open_session(3) исполняет задачи, связанные с установкой сеанса: добавляет запись в базах данных utmp и wtmp, запускает агента SSH и т.д.
    • pam_close_session(3) отвечает за разрыв сеанса: добавляет записи в базы данных utmp и wtmp, останавливает агента SSH и т.д.
    password
    Управление паролями. Это средство используется для смены аутентификационного ключа, связанного с аккаунтом, по запросу пользователя или по истечению срока действия. Предоставляется один примитив:

    • pam_chauthtok(3) изменяет ключ аутентификации, дополнительно проверяя его стойкость и не использовался ли он ранее.

    16.4.2. Модули

    Модули – это очень важная часть концепции PAM, в конце концов, они «M» в слове «PAM». Модуль PAM – самостоятельная программа, которая реализует примитивы в одном или более средствах для одного специфического механизма, например для базы паролей UNIX®, NIS, LDAP и Radius.

    16.4.2.1. Именование модулей

    FreeBSD и NetBSD реализуют каждый механизм в одном модуле, называемом pam_mechanism.so (для примера, pam_unix.so для механизма UNIX®). Другие реализации могут включать в себя отдельные модули для разных средств и содержать имя средства как имя механизма, например в Solaris™ имеется модуль pam_dial_auth.so.1, используемый для аутентификации dialup пользователей. Так же, почти каждый модуль имеет страницу руководства man, тем же именем, например pam_unix(8) описывает работу модуля pam_unix.so.

    16.4.2.2. Нумерация версий модулей

    Оригинальная реализация PAM в FreeBSD, базирующаяся на Linux-PAM не использовала номера версий для модулей. Обычно это вызывало проблемы с приложениями, которые были слинкованы с более старыми версиями системных библиотек, так как нет возможности загружать соответствующую версию, требуемую модулем.

    OpenPAM, с другой стороны, ищет модули, которые имеют тот же самый номер версии как и библиотека PAM (в настоящее время 2 в FreeBSD и 0 в NetBSD) и загружает модуль , не соответствующий версии, только в случае, если нет подходящего модуля. Таким образом унаследованные модули могут быть обеспечены для унаследованных приложений, при этом обеспечивается работа приложений, завязанных на новые версии модулей.

    Хотя модули PAM в Solaris™ и имеют номер версии, но он входит в имя модуля и должен быть включен в конфигурацию.

    16.4.2.3. Путь к модулям

    Нет общего каталога для чтобы хранить модули PAM. В FreeBSD, они расположены в /usr/lib, в NetBSD вы можете найти их в /usr/lib/security.

    16.4.3. Цепочки и правила

    Когда сервер инициирует транзакцию PAM, библиотека пытается загрузить правила для сервиса, указанного в вызове pam_start(3). Политика описывает метод обработки аутентификационного запроса и определяется в конфигурационном файле. Это и есть другая основная концепция PAM: администратор имеет возможность настраивать правила безопасности системы (в глобальном смысле), просто редактируя текстовый файл.

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

    Понимание контрольных флагов является основным в понимании конфигурационных файлов PAM. Есть множество различных флагов:

    binding
    Если модуль был выполнен и небыло ошибок в предыдущих модулях, то цепочка немедленно заканчивается и принимается положительное решение о предоставлении доступа. Если модуль выдал ошибку, остальная часть цепочки выполнится, но запрос будет отклонен.

    Этот флаг был введен Sun в Solaris™ 9 (SunOS™ 5.9)и поддерживается в OpenPAM.

    required
    Если модуль выполнен и выполнена остальная часть цепочки, то доступ предоставляется. Если модуль выдал ошибку, то цепочка продолжит выполняться, но запрос будет отклонен.

    requisite
    Если модуль выполнен и выполнена остальная часть цепочки, то доступ предоставляется. Если поизошла ошибка модуля, цепочка немедленно заканчивается, и запрос отклоняется.

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

    Поскольку семантика этого флага несколько запутанна, мы рекомендуем использовать binding, там где это возможно.

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

    Когда сервер вызывает один из шести примитивов PAM, PAM отыскивает цепочку для средства, к которой примитив принадлежит и вызывает каждый из модулей, перечисленный в цепочке в порядке следования, пока не достигает конца, или не будет принято решение об окончании обработки (в случае выполнения с флагами binding или sufficient или ошибки с флагом requisite).

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

    16.4.4. Транзакции

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

    1. В случае необходимости, сервер получает привилегии арбитра через механизм, независимый от PAM— в общем случае он стартует как root или имеет setuid root.
    2. Сервер вызывает pam_start(3) для инициализации библиотеки PAM, указания имени сервиса и аккаунта, регистрации и поддержания связи.
    3. Сервер получает различную информацию, касающуюся транзакции (такую как имя претендента и имя хоста, на котором выполняется клиент) и посылает его PAM, используя pam_set_item(3).
    4. Сервер вызывает pam_authenticate(3) для аутентификации претендента.
    5. Сервер вызывает pam_acct_mgmt(3) для проверки доступности и валидности запрашиваемого аккаунта. Если пароль корретен но устарел, man.pam.acct.mgmt.3; вернет PAM_NEW_AUTHTOK_REQD вместо PAM_SUCCESS.
    6. Если предыдущий шаг вернул PAM_NEW_AUTHTOK_REQD, сервер вызовет pam_chauthtok(3) для смены клиентом ключа аутентификации аккаунта.
    7. Теперь, когда претендент был должным образом заверен, сервер вызывает pam_setcred(3), чтобы установить полномочия требуемой учетной записи. Это возможно, потому что все действия осуществляются от имени арбитра и подтверждаются его полномочиями.
    8. Как только полномочия будут утановлены, сервер вызовет pam_open_session(3) для открытия сессии.
    9. Теперь сервер может предоставить клиенту сервис, например, запустить оболочку.
    10. Для разрыва сеанса вызывается pam_close_session(3).
    11. В заключение, сервер вызывает pam_end(3) для уведомления библиотеки PAM, что сессия закончена и используемые ресурсы могут быть освобождены.

    16.5. Конфигурирование PAM

    16.5.1. Файл политик PAM

    16.5.1.1. Файл /etc/pam.conf

    Традиционно, файл политик PAM называется /etc/pam.conf. Каждая строка этого файла один шаг в цепочке, как показано ниже:

    login   auth    required        pam_nologin.so  no_warn

    Поля, по порядку: имя сервиса, имя средства, контрольный флаг, имя модуля и аргументы модуля. Все дополнительные поля интерпретируются как аргументы модуля.

    Отдельная цепочка создается для каждой пары сервис/средство. Для пары сервис/средство важен порядок следования строк, для отдельных сервисов или средств проядок следования не важен. Примеры в оригинальной документации сгруппированы по средствам и Solaris™ продолжает придерживаться этого в pam.conf, а FreeBSD группирует строки по сервисам. Оба эти подхода имеют место быть.

    16.5.1.2. Каталог /etc/pam.d

    OpenPAM и Linux-PAM поддерживают дополнительный механизм конфигурации, который является предпочтительным в FreeBSD и NetBSD. В этой схеме, каждая политика содержится в отдельном файле, именуемом по имени службы, к которому она обращается. Эти файлы находятся в /etc/pam.d/.

    Файлы, содержащие по одной политике на сервер, имеют только четыре поля, вместо пяти у pam.conf: опускается имя сервиса. Таким образом, вместо строки в pam.conf мы получаем файл /etc/pam.d/login следующего содержания:

    auth    required        pam_nologin.so  no_warn

    Как следствие этого упрощенного синтаксиса, появляется возможность использовать ту же самую политику для нескольких услуг, привязывая разные имена сервисов к одному файлу. Например, чтобы использовать одинаковую политику для su и sudo, можно сделать следующим образом:

    # cd /etc/pam.d
    # ln -s su sudo

    Эта конструкция будет работать, так как имя сервиса определяется не в файле конфигурации, а в его названии. Только поэтому один файл можно использовать для нескольких сервисов.

    Так как политика кдля каждой службы сохраняется в отдельном файле, механизм pam.d позволяет сильно упростить установку политик для сторонних программых продуктов.

    16.5.1.3. Порядок поиска политик

    Как мы видели выше, политики PAM могут находиться в в множестве мест. Если для указанной службы не было найдено ни одного файла конфигурации, будет использоваться /etc/pam.d/other, в случае, если этот файл не существует, будет искаться соответствующая запись в файле /etc/pam.conf или использоваться сервис «other».

    Главное, что необходимо понять, это то, что конфигурирование PAM основано на цепочках.

    16.5.2. Разбор строки конфигурации

    Как указывалось в главе Файл политик PAM, какдая строка файла конфигурации /etc/pam.conf состоит из четырех или более полей: имя службы, имя средства, контрольный флаг, имя модуля и необязательные аргументы модуля.

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

    Обратите внимание, что если вы используете /etc/pam.d/ вместо /etc/pam.conf, имя сервиса определяется именем файла политики и не присутствует в файле конфигурации.

    Средство — одно из ключевых слов, описанных в разделе Средства и примитивы section.

    Аналогично, управляющий флаг – одно из четырех ключевых слов, описанных в разделе Цепочки и правила и указывает, как как интерпретировать код возврата от модуля. Linux-PAM поддерживает дополнительный синтаксис, который позволяет вам определить действие, связанное с кодом возврата, но этого стоит избегать, так как это не является стандартным поведением и пересекается с фукциями запросов вызовов сервисов (и очень отличается от пути Solaris™ и OpenPAM).

    16.5.3. Политики

    Для правильного конфигурирования PAM нужно понимание порядка интерпретации политик.

    Когда приложение вызывает pam_start(3), библиотека PAM загружает политику для указанного сервиса и создает четыре цепочки модулей (по одной на каждое средство). Если одна или более этих цепочек пусты, то они заменяются соответствующими цепочками из политики для сервиса other.

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

    Таблица 16.1. Выполнение цепочек PAM

    PAM_SUCCESS PAM_IGNORE other
    binding if (!fail) break; - fail = true;
    required - - fail = true;
    requisite - - fail = true; break;
    sufficient if (!fail) break; - -
    optional - - -

    Если в конце цепочки fail – истина, или когда выполняется «break», диспетчер возвращает код ошибки, выданный первым модулем, но котором произошел сбой. В противном случае, возвращается PAM_SUCCESS.

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

    Второе исключение состоит в том, что pam_setcred(3) обрабатывает модули binding и sufficient как будто они required.

    Третье и последнее исключение состоит в том, что pam_chauthtok(3) выполняет цепочку дважды (один раз предварительный и второй раз с новым паролем) и на предварительной стадии модули binding и sufficient обрабатываются, как будто они required.

    16.6. Модули PAM

    16.6.1. Общие модули

    16.6.1.1. pam_deny(8)

    Модуль pam_deny(8) является одним из самых простых доступных модулей, на любой запрос он отвечает PAM_AUTH_ERR. Это бывает полезно для быстрого отключения сервиса (добавьте в начало каждой цепочки) или для завершения цепочки sufficient модулей.

    16.6.1.2. pam_echo(8)

    Модуль pam_echo(8) просто возвращает аргумент как сообщение PAM_TEXT_INFO. Этот модуль может быть полезен при отладке или вывода перед началом аутентификации сообщения «Unauthorized access will be prosecuted».

    16.6.1.3. pam_exec(8)

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

    16.6.1.4. pam_ftpusers(8)

    Модуль pam_ftpusers(8) отработает правильно только в том случае, если пользователь перечислен в /etc/ftpusers. В настоящее время в NetBSD этот модуль не понимает расширенный синтаксис ftpd(8), но это будет исправлено в более поздных версиях.

    16.6.1.5. pam_group(8)

    Модуль pam_group(8) принимает или отклоняет претендента на основе членства его в определенной группе (обычно, wheel для su(1)). Это, в первую очередь, предназначено для сохранения традиционного стиля работы BSD su(1), но может применяться для ограничения доступа определенных групп пользователей к сервисам.

    В NetBSD есть аргумент authenticate, с помощью которого пользователя просят подтвердить подлинность использования его собственного пароля.

    16.6.1.6. pam_guest(8)

    Модуль pam_guest(8) позволяет входить в систему по заранее установленному гостевому имени. В качестве пароля могут быть введены любые данные, аутентификация проходит только имени. pam_guest(8) может применяться для предоставления анонимного доступа на FTP

    16.6.1.7. pam_krb5(8)

    Модуль pam_krb5(8) предоставляет функции идентификации пользователя с помощью Kerberos 5. У пользователя запрашивается пароль и получается новый Kerberos TGT. TGT проверяется, получая тикет для локального хоста. Полученные ключи сохраняются в кэше, соответствующим образом устанавливается переменная KRB5CCNAME. Кэш должен быть разрушен при выходе пользователя из системы kdestroy(1).

    16.6.1.8. pam_ksu(8)

    Модуль pam_ksu(8) обеспечивает только сервис аутентификации для Kerberos 5, чтобы определить, действительно ли претендент уполномочен получить привилегии аккаунта.

    16.6.1.9. pam_lastlog(8)

    Модуль pam_lastlog(8) обеспечивает услуги управления сеанса. Он делает запись в базе данных utmp(5), utmpx(5), wtmp(5), wtmpx(5), lastlog(5) и lastlogx(5).

    16.6.1.10. pam_login_access(8)

    Модуль pam_login_access(8) обеспечивает выполнение примитива управления учетной записью, который предписывает ограничения входа в систему, указанные в таблице login.access(5).

    16.6.1.11. pam_nologin(8)

    Модуль pam_nologin(8) отклоняет не-root запросы на аутентификацию, в случае, если существует файл /var/run/nologin. Этот файл обычно создается shutdown(8) за пять минут до выключения системы.

    16.6.1.12. pam_permit(8)

    Модуль pam_permit(8) — один из простейших доступных. На каждый запрос он возвращает PAM_SUCCESS. Этот модуль бывает полезен в качестве метки или для предотвращения появления пустой цепочки.

    16.6.1.13. pam_radius(8)

    Модуль pam_radius(8) предоставляет сервис аутентификации через протокол RADIUS (Remote Authentication Dial In User Service) protocol.

    16.6.1.14. pam_rhosts(8)

    Модуль pam_rhosts(8) предоставляет только сервис аутентификации. Он выполняется без сообщения от ошибке если идентификатор целевого пользователя не 0 и удаленный хост и пользователь имеются в /etc/hosts.equiv или ~/.rhosts.

    16.6.1.15. pam_rootok(8)

    Модуль pam_rootok(8) сообщает об успехе, если и только если реальный пользовательский идентификатор процесса, вызывающий его – 0. Это полезно для несетевых услуг типа su(1) или passwd(1), к которым root должен иметь автоматический доступ.

    16.6.1.16. pam_securetty(8)

    Модуль pam_securetty(8) предоставляет только сервис учетной записи. Он применяется когда претендент запрашивает полномочия суперпользователя или процесс присоединяется к insecure TTY.

    16.6.1.17. pam_self(8)

    Модуль pam_self(8) сообщает об успехе если имена претендента и целевой учетной записи совпадают. Это наиболее полезно для несетевых услуг типа su(1), где тождество претендента может быть легко проверено.

    16.6.1.18. pam_ssh(8)

    Модуль pam_ssh(8) обеспечивает услуги и сеанса и идентификации. Сервис аутентификации позволяет пользователям, защитившим свои секретные ключи в каталоге ~/.ssh кодовыми фразами, ввести кодовую фразу для подтверждения своей подлинности. Сервис сеанса запускает ssh-agent(1) и производит предварительную загрузку ключей, которые расшифровываются в фазе аутентификации. Эта особенность особенно полезна для входа на консоль локальной машины или входа в X (используя xdm(1) or или другой понимающий PAM X менеджер).

    Этот модуль осуществляет фундаментальнуюо схему аутентификации пароля. Необходимо принять все меры, по обеспечению работы модуля только по безопасному соединению, в противном случае, кодовая фраза SSH может быть скомпрометирована.

    Рассмотрим еще один аспект использования pam_ssh(8). Пользователи часто предполагают, что установленные права доступа будут надежной защитой для ключей и указывают простую кодовую фразу или не указывают ее вовсе. Так как администратор системы не имеет никаких эффективных средств для контроля качества кодовых фраз, то есть риск компрометации системы.

    16.6.1.19. pam_unix(8)

    Модуль pam_unix(8) реализует традиционную аутентификацию UNIX® по паролю, используя getpwnam(3) в FreeBSD или getpwnam_r(3) в NetBSD для получения доступа к целевой учетной записи для сравнения пароля учетной записи и пароля, введенного претендентом. Также, этот модуль предоставляет сервис управления учетной записью (смена пароля при истечении его срока действия) и сервис смены пароля. Это, вероятно, самый полезный модуль, так как большинство администраторов хотело бы придерживаться исторически сложившейся методики аутентификации.

    16.6.2. Специфичные для FreeBSD модули PAM

    16.6.2.1. pam_opie(8)

    Модуль pam_opie(8) реализует метод аутентификации opie(4). Система opie(4) построена на механизме вопрос-ответ, где ответ на каждый вопрос является прямой функцией от вопроса и кодовой фразы, так что ответ может быть легко вычислен «на лету» тем, кому известна кодовая фраза, при этом исчезает потребность в списках пользователей. Кроме того, opie(4) никогда не использует вопрос, на который был дан корректный ответ, что позволяет избежать уязвимости «replay attacks».

    16.6.2.2. pam_opieaccess(8)

    pam_opieaccess(8) — это модуль-компаньон к pam_opie(8). Его цель состоит в том, чтобы установить ограничения, описанные в opieaccess(5), которые регулируют условия, при которых пользователю, который обычно подтверждал подлинность себя, используя opie(4), разрешают использовать дополнительные методы. Это наиболее часто используется, чтобы запретить использование аутентификации по паролю от недоверенных хостов.

    Для эффективной работы, модуль pam_opieaccess(8) должен быть указан как requisite сразу после записи sufficient для pam_opie(8), и перед любыми другими модулями в цепочке auth .

    16.6.2.3. pam_passwdqc(8)

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

    16.6.2.4. pam_tacplus(8)

    Модуль pam_tacplus(8) предоставляет аутентификацию с помощью протокола TACACS+.

    16.6.3. Модули PAM, специфичные для NetBSD

    16.6.3.1. pam_skey(8)

    Модуль pam_skey(8) реализует метод аутентификации по одноразовым паролям (S/Key One Time Password (OTP)), используя базу данных /etc/skeykeys.

    16.7. Программирование приложений PAM

    Этот раздел еще не написан.

    16.8. Программирование модулей PAM

    Этот раздел еще не написан.

    16.9. Пример приложения PAM

    Ниже представлена простейшая реализация su(1) для использования PAM. Обратите внимание на то, что используется специфичная для OpenPAM функция сеанса связи openpam_ttyconv(3), прототипом которой является security/openpam.h. Если вы хотите реализовать это приложение на системе, использующей другую реализацию библиотек PAM, то должны использовать другую функцию сеанса связи. Стабильную функцию сеанса связи удивительно сложно реализовать, представленная в Простая функция сеанса связи PAM хороша для примера, но не должна использоваться в реальных приложениях.

    #include <sys/param.h>
    #include <sys/wait.h>
    
    #include <err.h>
    #include <pwd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <syslog.h>
    #include <unistd.h>
    
    #include <security/pam_appl.h>
    #include <security/openpam.h>	/* for openpam_ttyconv() */
    
    extern char **environ;
    
    static pam_handle_t *pamh;
    static struct pam_conv pamc;
    
    static void
    usage(void)
    {
    
    	fprintf(stderr, "Usage: su [login [args]]\n");
    	exit(1);
    }
    
    int
    main(int argc, char *argv[])
    {
    	char hostname[MAXHOSTNAMELEN];
    	const char *user, *tty;
    	char **args, **pam_envlist, **pam_env;
    	struct passwd *pwd;
    	int o, pam_err, status;
    	pid_t pid;
    
    	while ((o = getopt(argc, argv, "h")) != -1)
    		switch (o) {
    		case 'h':
    		default:
    			usage();
    		}
    
    	argc -= optind;
    	argv += optind;
    
    	if (argc > 0) {
    		user = *argv;
    		--argc;
    		++argv;
    	} else {
    		user = "root";
    	}
    
    	/* initialize PAM */
    	pamc.conv = &openpam_ttyconv;
    	pam_start("su", user, &pamc, &pamh);
    
    	/* set some items */
    	gethostname(hostname, sizeof(hostname));
    	if ((pam_err = pam_set_item(pamh, PAM_RHOST, hostname)) != PAM_SUCCESS)
    		goto pamerr;
    	user = getlogin();
    	if ((pam_err = pam_set_item(pamh, PAM_RUSER, user)) != PAM_SUCCESS)
    		goto pamerr;
    	tty = ttyname(STDERR_FILENO);
    	if ((pam_err = pam_set_item(pamh, PAM_TTY, tty)) != PAM_SUCCESS)
    		goto pamerr;
    
    	/* authenticate the applicant */
    	if ((pam_err = pam_authenticate(pamh, 0)) != PAM_SUCCESS)
    		goto pamerr;
    	if ((pam_err = pam_acct_mgmt(pamh, 0)) == PAM_NEW_AUTHTOK_REQD)
    		pam_err = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
    	if (pam_err != PAM_SUCCESS)
    		goto pamerr;
    
    	/* establish the requested credentials */
    	if ((pam_err = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS)
    		goto pamerr;
    
    	/* authentication succeeded; open a session */
    	if ((pam_err = pam_open_session(pamh, 0)) != PAM_SUCCESS)
    		goto pamerr;
    
    	/* get mapped user name; PAM may have changed it */
    	pam_err = pam_get_item(pamh, PAM_USER, (const void **)&user);
    	if (pam_err != PAM_SUCCESS || (pwd = getpwnam(user)) == NULL)
    		goto pamerr;
    
    	/* export PAM environment */
    	if ((pam_envlist = pam_getenvlist(pamh)) != NULL) {
    		for (pam_env = pam_envlist; *pam_env != NULL; ++pam_env) {
    			putenv(*pam_env);
    			free(*pam_env);
    		}
    		free(pam_envlist);
    	}
    
    	/* build argument list */
    	if ((args = calloc(argc + 2, sizeof *args)) == NULL) {
    		warn("calloc()");
    		goto err;
    	}
    	*args = pwd->pw_shell;
    	memcpy(args + 1, argv, argc * sizeof *args);
    
    	/* fork and exec */
    	switch ((pid = fork())) {
    	case -1:
    		warn("fork()");
    		goto err;
    	case 0:
    		/* child: give up privs and start a shell */
    
    		/* set uid and groups */
    		if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {
    			warn("initgroups()");
    			_exit(1);
    		}
    		if (setgid(pwd->pw_gid) == -1) {
    			warn("setgid()");
    			_exit(1);
    		}
    		if (setuid(pwd->pw_uid) == -1) {
    			warn("setuid()");
    			_exit(1);
    		}
    		execve(*args, args, environ);
    		warn("execve()");
    		_exit(1);
    	default:
    		/* parent: wait for child to exit */
    		waitpid(pid, &status, 0);
    
    		/* close the session and release PAM resources */
    		pam_err = pam_close_session(pamh, 0);
    		pam_end(pamh, pam_err);
    
    		exit(WEXITSTATUS(status));
    	}
    
    pamerr:
    	fprintf(stderr, "Sorry\n");
    err:
    	pam_end(pamh, pam_err);
    	exit(1);
    }
    

    16.10. Пример модуля PAM

    Ниже представлена минимальная реализация pam_unix(8), предоставляющая только сервис аутентификации. Этот модуль должен работать со всеми реализациями PAM, но применяет расширения OpenPAM: обратите внимание на использование pam_get_authtok(3), который черезвычайно упрощает реализацию подсказки пользователю на ввод пароля..

    #include <sys/param.h>
    
    #include <pwd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    
    #include <security/pam_modules.h>
    #include <security/pam_appl.h>
    
    #ifndef _OPENPAM
    static char password_prompt[] = "Password:";
    #endif
    
    #ifndef PAM_EXTERN
    #define PAM_EXTERN
    #endif
    
    PAM_EXTERN int
    pam_sm_authenticate(pam_handle_t *pamh, int flags,
    	int argc, const char *argv[])
    {
    #ifndef _OPENPAM
    	struct pam_conv *conv;
    	struct pam_message msg;
    	const struct pam_message *msgp;
    	struct pam_response *resp;
    #endif
    	struct passwd *pwd;
    	const char *user;
    	char *crypt_password, *password;
    	int pam_err, retry;
    
    	/* identify user */
    	if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
    		return (pam_err);
    	if ((pwd = getpwnam(user)) == NULL)
    		return (PAM_USER_UNKNOWN);
    
    	/* get password */
    #ifndef _OPENPAM
    	pam_err = pam_get_item(pamh, PAM_CONV, (const void **)&conv);
    	if (pam_err != PAM_SUCCESS)
    		return (PAM_SYSTEM_ERR);
    	msg.msg_style = PAM_PROMPT_ECHO_OFF;
    	msg.msg = password_prompt;
    	msgp = &msg;
    #endif
    	for (retry = 0; retry < 3; ++retry) {
    #ifdef _OPENPAM
    		pam_err = pam_get_authtok(pamh, PAM_AUTHTOK,
    		    (const char **)&password, NULL);
    #else
    		resp = NULL;
    		pam_err = (*conv->conv)(1, &msgp, &resp, conv->appdata_ptr);
    		if (resp != NULL) {
    			if (pam_err == PAM_SUCCESS)
    				password = resp->resp;
    			else
    				free(resp->resp);
    			free(resp);
    		}
    #endif
    		if (pam_err == PAM_SUCCESS)
    			break;
    	}
    	if (pam_err == PAM_CONV_ERR)
    		return (pam_err);
    	if (pam_err != PAM_SUCCESS)
    		return (PAM_AUTH_ERR);
    
    	/* compare passwords */
    	if ((!pwd->pw_passwd[0] && (flags & PAM_DISALLOW_NULL_AUTHTOK)) ||
    	    (crypt_password = crypt(password, pwd->pw_passwd)) == NULL ||
    	    strcmp(crypt_password, pwd->pw_passwd) != 0)
    		pam_err = PAM_AUTH_ERR;
    	else
    		pam_err = PAM_SUCCESS;
    #ifndef _OPENPAM
    	free(password);
    #endif
    	return (pam_err);
    }
    
    PAM_EXTERN int
    pam_sm_setcred(pam_handle_t *pamh, int flags,
    	int argc, const char *argv[])
    {
    
    	return (PAM_SUCCESS);
    }
    
    PAM_EXTERN int
    pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
    	int argc, const char *argv[])
    {
    
    	return (PAM_SUCCESS);
    }
    
    PAM_EXTERN int
    pam_sm_open_session(pam_handle_t *pamh, int flags,
    	int argc, const char *argv[])
    {
    
    	return (PAM_SUCCESS);
    }
    
    PAM_EXTERN int
    pam_sm_close_session(pam_handle_t *pamh, int flags,
    	int argc, const char *argv[])
    {
    
    	return (PAM_SUCCESS);
    }
    
    PAM_EXTERN int
    pam_sm_chauthtok(pam_handle_t *pamh, int flags,
    	int argc, const char *argv[])
    {
    
    	return (PAM_SERVICE_ERR);
    }
    
    #ifdef PAM_MODULE_ENTRY
    PAM_MODULE_ENTRY("pam_unix");
    #endif
    

    16.11. Простая функция сеанса связи PAM

    Функция сеанса связи, представленная ниже – очень упрощенная версия openpam_ttyconv(3) из OpenPAM. Она полностью функциональна, и должна дать читателю хорошую базу относительно того, как функция сеанса связи должна себя вести, но она слишком проста для реального использования. Даже если вы не используете OpenPAM, не стесняйтесь изучать исходный текст и приспосабливать openpam_ttyconv(3) к вашим требованиям. Мы полагаем, что она будет столь же стабильна, как ориентированная на tty функция сеанса связи.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    
    #include <security/pam_appl.h>
    
    int
    converse(int n, const struct pam_message **msg,
    	struct pam_response **resp, void *data)
    {
    	struct pam_response *aresp;
    	char buf[PAM_MAX_RESP_SIZE];
    	int i;
    
    	data = data;
    	if (n <= 0 || n > PAM_MAX_NUM_MSG)
    		return (PAM_CONV_ERR);
    	if ((aresp = calloc(n, sizeof *aresp)) == NULL)
    		return (PAM_BUF_ERR);
    	for (i = 0; i < n; ++i) {
    		aresp[i].resp_retcode = 0;
    		aresp[i].resp = NULL;
    		switch (msg[i]->msg_style) {
    		case PAM_PROMPT_ECHO_OFF:
    			aresp[i].resp = strdup(getpass(msg[i]->msg));
    			if (aresp[i].resp == NULL)
    				goto fail;
    			break;
    		case PAM_PROMPT_ECHO_ON:
    			fputs(msg[i]->msg, stderr);
    			if (fgets(buf, sizeof buf, stdin) == NULL)
    				goto fail;
    			aresp[i].resp = strdup(buf);
    			if (aresp[i].resp == NULL)
    				goto fail;
    			break;
    		case PAM_ERROR_MSG:
    			fputs(msg[i]->msg, stderr);
    			if (strlen(msg[i]->msg) > 0 &&
    			    msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
    				fputc('\n', stderr);
    			break;
    		case PAM_TEXT_INFO:
    			fputs(msg[i]->msg, stdout);
    			if (strlen(msg[i]->msg) > 0 &&
    			    msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
    				fputc('\n', stdout);
    			break;
    		default:
    			goto fail;
    		}
    	}
    	*resp = aresp;
    	return (PAM_SUCCESS);
     fail:
            for (i = 0; i < n; ++i) {
                    if (aresp[i].resp != NULL) {
                            memset(aresp[i].resp, 0, strlen(aresp[i].resp));
                            free(aresp[i].resp);
                    }
            }
            memset(aresp, 0, n * sizeof *aresp);
    	*resp = NULL;
    	return (PAM_CONV_ERR);
    }
    

    16.12. Для дополнительного прочтения

    Литература

    Документация

    Making Login Services Independent of Authentication Technologies. Vipin Samar Charlie Lai. Sun Microsystems.

    X/Open Single Sign-on Preliminary Specification. The Open Group. 1-85912-144-6. June 1997.

    Pluggable Authentication Modules. Andrew G. Morgan. October 6, 1999.

    Руководство пользователя

    PAM Administration. Sun Microsystems.

    Related Web pages

    Домашняя страница OpenPAM. Dag-Erling Sm?rgrav. ThinkSec AS.
    Домашняя страница Linux-PAM. Andrew G. Morgan.

    Домашняя страница Solaris PAM. Sun Microsystems.

    Глава 15. NetBSD RAIDframe

    Русский перевод: Михаил Сгибнев

    Содержание

    15.1. Введение в RAIDframe
    15.1.1. Общие сведения о RAIDframe
    15.1.2. Предупреждение о целостности данных, резервных копиях и высокой доступности
    15.1.3. Получение помощи
    15.2. Установка поддержки RAIDframe
    15.2.1. Поддержка в ядре
    15.2.2. Избыточность питания и кэширование дисков:
    15.3. Пример: реализация RAID-1
    15.3.1. Схема псевдо-процессов
    15.3.2. Обзор аппаратного обеспечения
    15.3.3. Начальная установка на Disk0/wd0
    15.3.4. Подготовка Disk1/wd1
    15.3.5. Инициализация устройства RAID
    15.3.6. Установка файловой системы
    15.3.7. Перенос системы на RAID
    15.3.8. Первая загрузка с RAID
    15.3.9. Добавление Disk0/wd0 в RAID
    15.3.10. Тестирование загрузочной области

    15.1. Введение в RAIDframe

    15.1.1. Общие сведения о RAIDframe

    NetBSD использует подсистему CMU RAIDframe. RAIDframe впервые появился именно в NetBSD и впоследствии был перенесен в OpenBSD и FreeBSD. NetBSD в составе ядра имеет еще несколько RAID систем называемых Vinum и Глава 14, Конфигурация Concatenated Disk Device (CCD), которые здесь не рассматриваются. Возможно. вам стоит посмотреть начальную информацию для получения начальных знаний о терминологии и концепции RAID. Как минимум вы должны быть знакомы с уровнями RAID. RAID – Adaptec предоставляет превосходное руководство, некоторый обьем информации содержится в raid(4)

    15.1.2. Предупреждение о целостности данных, резервных копиях и высокой доступности

    Во-первых, потому что RAIDframe является программной реализацией RAID, в отличие от аппаратной реализации, нуждающейся в специальном контроллере, системные администраторы должны обратить пристальное внимание к работе «критических» приложений. Для таких проектов стоит рассмотреть возможность использования поддерживаемых NetBSD RAID устройств. В этом случае вы самостоятельно принимаетет решение о выборе модели, но я рекомендую вам обратить внимание на такие факторы как управляемость, поддержка производителем, балансировка нагрузки и отказоустойчивость.

    Во-вторых, в зависимости от используемого уровня RAID, RAIDframe обеспечивает некоторую избыточность в случае аппаратного сбоя. Однако это не является заменой резервному копированию! Программные и пользовательские ошибки все еще могут привести к потере данных. RAIDframe может использоваться как механизм облегчающий резервное копирование при отсутствии соответствующих аппаратных средств. И наконец, «высокая доступность» RAID является только малым компонентом обеспечения доступности данных в целом.

    Дадим хороший совет: Резервируйте ваши данные!

    15.1.3. Получение помощи

    Если вы столкнулись с проблемами при использовании RAIDframe, то у вас есть несколько путей получения помощи.

    1. Чтение страниц руководства по RAIDframe: raid(4) и raidctl(8).
    2. Поиск в архивах списков рассылки. К сожалению, нет списка рассылки NetBSD, непосредственно посвященному RAIDframe. В связи с этим, разные темы могут начинаться и заканчиваться в разных списках. Как минимум, просмотрите netbsd-help@NetBSD.org, netbsd-users@NetBSD.org, current-users@NetBSD.org. Также стоит обратить на список рассылки используемой платформы: port-${ARCH}@NetBSD.org.

      Предостережение

      Поскольку RAIDframe постоянно развивается, имеющаяся в списках рассылки информация может быть уже неактуальной и неверной.

    3. Поиск в Базе данных сообщений о проблемах.
    4. Если в не смогли решить проблему, то сделайте следующее: пошлите сообщение в список рассылки, содержащее наиболее полное описание проблемы, сопроводив его всей доступной вам отладочной информацией и сообщениями об ошибках, включая выводом dmesg(8) из файла /var/run/dmesg.boot, файл конфигурации ядра config(8), /etc/raid[0-9].conf, /var/log/messages или stdout/stderr raidctl(8). Также включите описание предпринятых вами шагов для решения проблемы. Будьте терпеливы в ожидании ответа.

    15.2. Установка поддержки RAIDframe

    Для использования RAID требуется внесение изменений в программную и аппаратную конфигурацию.

    15.2.1. Поддержка в ядре

    Мы должны удостовериться, что имеется поддержка RAID в текущем ядре, в ядре GENERIC необходимые опции уже включены. Если вы используете собственное ядро, то удостоверьтесь, что оно содержит следущие опции:

    pseudo-device   raid            8       # RAIDframe disk driver
    options         RAID_AUTOCONFIG         # auto-configuration of RAID components
    

    Поддержка RAID должна быть обнаружена ядром NetBSD, что может быть проверено с помощью команды dmesg(8).

    # dmesg|grep -i raid
    Kernelized RAIDframe activated
    

    Ядро также должно содержать статическую привязку адресов шины и устройств в /dev. Это позволит гарантировать правильное размещение дисков в RAID в случае сбоя после перезагрузки. Обратитесь к главе Глава 28, Компиляция ядра для настройки, сборки и установки нового ядра.

    В случае SCSI привязка будет выглядеть примерно таким образом:

    sd0 at scsibus0 target 0 lun ?  # SCSI disk drives
    sd1 at scsibus0 target 1 lun ?  # SCSI disk drives
    sd2 at scsibus0 target 2 lun ?  # SCSI disk drives
    sd3 at scsibus0 target 3 lun ?  # SCSI disk drives
    sd4 at scsibus0 target 4 lun ?  # SCSI disk drives
    sd5 at scsibus0 target 5 lun ?  # SCSI disk drives
    sd6 at scsibus0 target 6 lun ?  # SCSI disk drives
    

    Или для дисков EIDE/ATA:

    wd0 at atabus0 drive 0 flags 0x0000
    wd1 at atabus0 drive 1 flags 0x0000
    wd2 at atabus1 drive 0 flags 0x0000
    wd3 at atabus1 drive 1 flags 0x0000
    

    Как только вы закончите этот процесс, возможно вас заинтересует распределение дисков относительно controller/bus/ID. Для системы, содержащей более чем два диска можно составить некоторый порядок действий, особенно важный для i386:

    Таблица 15.1. Пример аппаратной конфигурации для i386

    Component BIOS Mapping Boot Block Device Kernel Device
    Disk0 0×80 hd0 wd0 at atabus0 drive 0 flags 0×0000
    Disk1 0×81 hd1 wd1 at atabus0 drive 1 flags 0×0000

    15.2.2. Избыточность питания и кэширование дисков:

    Если ваша система располагает источником бесперебойного питания (UPS) и/или несколькими блоками питания, то вам стоит рассмотреть вопрос включения кэша на чтение/запись. На системах без резервирования питания есть риск потери данных, находящихся в кэше, в случае пропадания электроэнергии.

    Для SCSI дисков вы можете использовать утилиту scsictl(8):

    # scsictl /dev/rsd0{c,d} getcache
    /dev/rsd0d: no caches enabled
    /dev/rsd0d: caching parameters are savable
    # scsictl /dev/rsd0{c,d} setcache rw save 
    # scsictl /dev/rsd0{c,d} getcache
    /dev/rsd0d: read cache enabled
    /dev/rsd0d: write-back cache enabled
    /dev/rsd0d: caching parameters are savable
    

    Для дисков на других шинах (EIDE, SATA, USB, IEEE1394) можно использовать atactl(8) или пользоваться виртуальной шиной SCSI.

    15.3. Пример: реализация RAID-1

    В этом примере рассказывается про установку RAID-1. В случае RAID-1 компоненты зеркалируются и сервер сохранит функциональность при выходе из строя одного из дисков. Целью примера и будет обеспечение необходимого уровня избыточности для:

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

    Рисунок 15.1. Размещение логических дисков в RAID-1

    Размещение логических дисков в RAID-1
    Поскольку RAID-1 обеспечивает и избыточность и повышение производительности, самым разумным будет его использование для критических «системных» разделов, таких как /, /usr, /var, swap, где операции чтения чаще, чем операции записи. Для других файловых систем, таких как /home или /var/{application} стоит рассмотреть другой уровень RAID. В случае простого создания тома RAID-1 для не корневого раздела можно воспользоваться готовым примером из страницы руководства man, но поскольку корневой раздел должен быть загрузочным, нам придется предпринять некоторые шаги в ходе начальной установки.

    Замечание

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

    15.3.1. Схема псевдо-процессов

    Хотя довольно много наработок было сделано в специализированных копиях NetBSD для специфичных мобильных носителей, инструментарий и поддержка RAIDframe находится на недостаточно высоком уровне. Вследствие этого, нижеследующий псевдо-процесс является стандартом де-факто при установке RAID-1.

    1. Установка заготовки NetBSD на Disk0.

      Рисунок 15.2. Подготовка к первичной установке на Disk0/wd0

      Подготовка к первичной установке на Disk0/wd0

    2. Используйте установленную на Disk0/wd0 систему для создания RAID состоящего из одного Disk1/wd1.

      Рисунок 15.3. Setup RAID Set

      Setup RAID Set

    3. Перезагрузите систему после создания на Disk1/wd1 тома RAID.

      Рисунок 15.4. Reboot using Disk1/wd1 of RAID

      Reboot using Disk1/wd1 of RAID

    4. Add / re-sync Disk0/wd0 back into the RAID set.

      Рисунок 15.5. Зеркалируйте Disk1/wd1 на Disk0/wd0

      Зеркалируйте Disk1/wd1 на Disk0/wd0

    15.3.2. Обзор аппаратного обеспечения

    В настоящее время NetBSD для платформ i386 sparc64 поддерживается загрузка только с RAID-1. Загрузка с RAID осуществляется на первом этапе работы загрузчика и заключается в определении 4.2BSD/FFS и RAID разделов. Код первого загрузочного кода должен только получить данные о файловых системах и разделах, чтобы передать их второму этапу загрузки. Поэтому, в любое время, BIOS или другое программное обеспечение низкого уровня должно быть способно прочитать и выполнить первый блок начального загрузчика. На платфирме i386 это реализуется производителем дискового контроллера, на sparc64 за это отвечает IEEE 1275 Sun OpenBoot Firmware.

    В этой статье рассматриваются два идентичных диска IDE (/dev/wd{0,1}), которые и будут зеркалированы RAID-1). Эти диски идентифицируются как:

     # grep ^wd /var/run/dmesg.boot
    wd0 at atabus0 drive 0: <WDC WD100BB-75CLB0>
    wd0: drive supports 16-sector PIO transfers, LBA addressing
    wd0: 9541 MB, 19386 cyl, 16 head, 63 sec, 512 bytes/sect x 19541088 sectors
    wd0: drive supports PIO mode 4, DMA mode 2, Ultra-DMA mode 5 (Ultra/100)
    wd0(piixide0:0:0): using PIO mode 4, Ultra-DMA mode 2 (Ultra/33) (using DMA data transfers)
    
    wd1 at atabus1 drive 0: <WDC WD100BB-75CLB0>
    wd1: drive supports 16-sector PIO transfers, LBA addressing
    wd1: 9541 MB, 19386 cyl, 16 head, 63 sec, 512 bytes/sect x 19541088 sectors
    wd1: drive supports PIO mode 4, DMA mode 2, Ultra-DMA mode 5 (Ultra/100)
    wd1(piixide0:1:0): using PIO mode 4, Ultra-DMA mode 2 (Ultra/33) (using DMA data transfers)
    

    Замечание

    Если вы используете SCSI, замените /dev/{,r}wd{0,1} на /dev/{,r}sd{0,1}

    В этом примере оба наших диска выставлены как Master на разных каналах. Иметь два Master диска на одном канале врядли получится. В идеальном случае стоило бы иметь диски на отдельных каналах разных контроллеров. Некоторые SCSI контроллеры имеют несколько каналов на том же самом контроллере, однако шинный сброс SCSI на одном канале мог бы неблагоприятно затронуть другой канал, в случае перегрузки ASIC/IC.

    Замечание

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

    Подсказка

    Даже два диска одного производителя могут иметь различную геометрию вследствие «дефектов производства». Используйте низкоуровневое программное обеспечение для составления таблицы дефектов дисков. После этого уже можно определить кандидатов в RAID.

    15.3.3. Начальная установка на Disk0/wd0

    Установите систему на ваш диск Disk0/wd0, руководствуясь инструкциями в файле INSTALL для вашей платформы. Устанавливайте все наборы, но не беспокойтесь о настройке, так как это все равно будет перезаписано.

    Подсказка

    На платформе i386 при вопросе программы установки sysinst «use the entire disk for NetBSD» ответьте «yes».

    После завершения установки воспользуйтесь утилитами disklabel(8) and fdisk(8) / sunlabel(8) для просмотра данных:

    # df
    Filesystem  1K-blocks     Used     Avail Capacity  Mounted on
    /dev/wd0a     9343708   191717   8684806     2%    /
    

    На i386:

    # disklabel -r wd0
    type: unknown
    disk: Disk00
    label:
    flags:
    bytes/sector: 512
    sectors/track: 63
    tracks/cylinder: 16
    sectors/cylinder: 1008
    cylinders: 19386
    total sectors: 19541088
    rpm: 3600
    interleave: 1
    trackskew: 0
    cylinderskew: 0
    headswitch: 0           # microseconds
    track-to-track seek: 0  # microseconds
    drivedata: 0
    
    16 partitions:
    #        size    offset     fstype [fsize bsize cpg/sgs]
     a:  19276992        63     4.2BSD   1024  8192 46568  # (Cyl.      0* - 19124*)
     b:    264033  19277055       swap                     # (Cyl.  19124* - 19385)
     c:  19541025        63     unused      0     0        # (Cyl.      0* - 19385)
     d:  19541088         0     unused      0     0        # (Cyl.      0 - 19385)
    
    # fdisk /dev/rwd0d
    Disk: /dev/rwd0d
    NetBSD disklabel disk geometry:
    cylinders: 19386, heads: 16, sectors/track: 63 (1008 sectors/cylinder)
    total sectors: 19541088
    
    BIOS disk geometry:
    cylinders: 1023, heads: 255, sectors/track: 63 (16065 sectors/cylinder)
    total sectors: 19541088
    
    Partition table:
    0: NetBSD (sysid 169)
        start 63, size 19541025 (9542 MB, Cyls 0-1216/96/1), Active
    1: <UNUSED>
    2: <UNUSED>
    3: <UNUSED>
    Bootselector disabled.
    

    На Sparc64 команда и вывод немного отличается:

    # disklabel -r wd0
    type: unknown
    disk: Disk0
    [...snip...]
    8 partitions:
    #        size    offset     fstype [fsize bsize cpg/sgs]
     a:  19278000         0     4.2BSD   1024  8192 46568  # (Cyl.      0 -  19124)
     b:    263088  19278000       swap                     # (Cyl.  19125 -  19385)
     c:  19541088         0     unused      0     0        # (Cyl.      0 -  19385)
    
    # sunlabel /dev/rwd0c
    sunlabel> P
    a: start cyl =      0, size = 19278000 (19125/0/0 - 9413.09Mb)
    b: start cyl =  19125, size =   263088 (261/0/0 - 128.461Mb)
    c: start cyl =      0, size = 19541088 (19386/0/0 - 9541.55Mb)
    

    15.3.4. Подготовка Disk1/wd1

    Как только вы установили NetBSD на Disk0/wd0, можно начинать самое интересное. Disk1/wd1 должен быть виден и неиспользуем системой. Для распределения набора RAID-1 на диск Disk1/wd1 мы будем использовать disklabel(8).

    Подсказка

    Лучший способ гарантировать, что Disk1/wd1 является полностью пустым, состоит в том, чтобы ‘обнулить’ первые сектора диска с помощью dd(1). Это сотрет MBR (i386) или метку диска Sun (sparc64), так же как м метку диска NetBSD. Если Вы делаете ошибку в любой точке в течение процесса установки RAID, вы можете всегда вернуться сюда, чтобы очистить диск от следов предыдущей попытки.

    Замечание

    На sparc64 используйте /dev/rwd1c вместо /dev/rwd1d!

    # dd if=/dev/zero of=/dev/rwd1d bs=8k count=1
    1+0 records in
    1+0 records out
    8192 bytes transferred in 0.003 secs (2730666 bytes/sec)
    

    После завершения процесса, убедитесь, что на i386 удалена MBR и метки диска NetBSD, а на sparc64 метка диска Sun.

    На i386:

    # fdisk /dev/rwd1d
    
    fdisk: primary partition table invalid, no magic in sector 0
    Disk: /dev/rwd1d
    NetBSD disklabel disk geometry:
    cylinders: 19386, heads: 16, sectors/track: 63 (1008 sectors/cylinder)
    total sectors: 19541088
    
    BIOS disk geometry:
    cylinders: 1023, heads: 255, sectors/track: 63 (16065 sectors/cylinder)
    total sectors: 19541088
    
    Partition table:
    0: <UNUSED>
    1: <UNUSED>
    2: <UNUSED>
    3: <UNUSED>
    Bootselector disabled.
    
    # disklabel -r wd1
    
    [...snip...]
    16 partitions:
    #        size    offset     fstype [fsize bsize cpg/sgs]
     c:  19541025        63     unused      0     0        # (Cyl.      0* - 19385)
     d:  19541088         0     unused      0     0        # (Cyl.      0 - 19385)
    

    На sparc64:

    # sunlabel /dev/rwd1c
    
    sunlabel: bogus label on `/dev/wd1c' (bad magic number)
    
    # disklabel -r wd1
    
    [...snip...]
    3 partitions:
    #        size    offset     fstype [fsize bsize cpg/sgs]
     c:  19541088         0     unused      0     0        # (Cyl.      0 -  19385)
    disklabel: boot block size 0
    disklabel: super block size 0
    

    После того, как вы убедились, что второй диск пуст, на i386 необходимо установить MBR используя значения, полученные с Disk0/wd0. Вы должны помнить, что необходимо сделать раздел NetBSD активным, иначе система не будет загружаться. Также вы должны создать метку диска NetBSD на Disk1/wd1, которая будет использоваться для создания и работы RAID. На sparc64 вам необходимо просто воспользоваться disklabel(8) для записи метки диска Sun.

    Подсказка

    disklabel(8) может использовать переменную среды $EDITOR для установки редактора, в котором будет осуществляться правка. По умолчанию используется vi(1)

    На i386:

    # fdisk -0ua /dev/rwd1d
    fdisk: primary partition table invalid, no magic in sector 0
    Disk: /dev/rwd1d
    NetBSD disklabel disk geometry:
    cylinders: 19386, heads: 16, sectors/track: 63 (1008 sectors/cylinder)
    total sectors: 19541088
    
    BIOS disk geometry:
    cylinders: 1023, heads: 255, sectors/track: 63 (16065 sectors/cylinder)
    total sectors: 19541088
    
    Do you want to change our idea of what BIOS thinks? [n]
    
    Partition 0:
    <UNUSED>
    The data for partition 0 is:
    <UNUSED>
    sysid: [0..255 default: 169]
    start: [0..1216cyl default: 63, 0cyl, 0MB]
    size: [0..1216cyl default: 19541025, 1216cyl, 9542MB]
    bootmenu: []
    Do you want to change the active partition? [n] y
    Choosing 4 will make no partition active.
    active partition: [0..4 default: 0] 0
    Are you happy with this choice? [n] y
    
    We haven't written the MBR back to disk yet.  This is your last chance.
    Partition table:
    0: NetBSD (sysid 169)
        start 63, size 19541025 (9542 MB, Cyls 0-1216/96/1), Active
    1: <UNUSED>
    2: <UNUSED>
    3: <UNUSED>
    Bootselector disabled.
    Should we write new partition table? [n] y
    
    # disklabel -r -e -I wd1
    type: unknown
    disk: Disk1
    label:
    flags:
    bytes/sector: 512
    sectors/track: 63
    tracks/cylinder: 16
    sectors/cylinder: 1008
    cylinders: 19386
    total sectors: 19541088
    [...snip...]
    16 partitions:
    #        size    offset     fstype [fsize bsize cpg/sgs]
     a:  19541025        63       RAID                     # (Cyl.      0*-19385)
     c:  19541025        63     unused      0     0        # (Cyl.      0*-19385)
     d:  19541088         0     unused      0     0        # (Cyl.      0 -19385)
    

    На sparc64:

    # disklabel -r -e -I wd1
    type: unknown
    disk: Disk1
    label:
    flags:
    bytes/sector: 512
    sectors/track: 63
    tracks/cylinder: 16
    sectors/cylinder: 1008
    cylinders: 19386
    total sectors: 19541088
    [...snip...]
    3 partitions:
    #        size    offset     fstype [fsize bsize cpg/sgs]
     a:  19541088         0       RAID                     # (Cyl.      0 -  19385)
     c:  19541088         0     unused      0     0        # (Cyl.      0 -  19385)
    
    # sunlabel /dev/rwd1c 
    sunlabel> P
    a: start cyl =      0, size = 19541088 (19386/0/0 - 9541.55Mb)
    c: start cyl =      0, size = 19541088 (19386/0/0 - 9541.55Mb)
    

    Замечание

    На i386 слайсы c: и d: зарезервированы. c: представляет собой часть диска, d: представляет собой весь диск. Поскольку мы будем использовать под NetBSD весь диск, слайс a: находится в границах слайса c: и имеют одинаковые размеры и смещение. Смещение должно начаться в границе дорожки (приращение секторов, соответствующих значению sectors/track в метке диска). Однако, на sparc64 c: представляет полный раздел NetBSD и в метке диска Sun d: не зарезервирован. Также обратите внимание, что на sparc64 c: и a: не требуют никакого смещения с начала диска, однако если оно есть, то должно начаться в границе цилиндра (приращение секторов, соответствующих значению sectors/cylinder).

    15.3.5. Инициализация устройства RAID

    Затем создаем файл конфигурации для RAID. Традиционно он находится в /etc , читается и нициализируется во время загрузки. Но, поскольку мы создаем самозагружаемый том RAID, данные конфигурации будут фактически записаны в том RAID, используя возможность «автоматического выбора конфигурации». Поэтому файлы необходимы только в течение начальной установки и не должны постоянно находиться в /etc.

    # vi /var/tmp/raid0.conf
    START array
    1 2 0
    
    START disks
    /dev/wd9a
    /dev/wd1a
    
    START layout
    128 1 1 1
    
    START queue
    fifo 100
    

    Обратите внимание, что wd9 – несуществующий диск. Это позволит нам устанавливать том RAID с поддельным компонентом, которым мы несколько позже заменим Disk0/wd0. Независимо от того, устройство в /dev для wd9 должно существовать.

    # cd /dev
    # sh MAKEDEV wd9
    # cd -

    Подсказка

    В NetBSD 2.0+ в качестве «поддельного» устройства /dev/wd9a вы можете использовать специальное имя диска «absent».

    Затем мы конфигурируем устройство RAID и инициализуем уникальный серийный номер. В этом примере мы используем схему «YYYYMMDDRevision«. Вы можете выбирать формат полностью на свое усмотрение, учтите только, что в нашей схеме не должно быть два набора RAID с одним номером в единицу времени.

    После чего мы инициализируем набор RAID, ингнорируя ошибки, связанные с «поддельным» диском.

    # raidctl -v -C /var/tmp/raid0.conf raid0
    raidlookup on device: /dev/wd9a failed!
    raid0: Component /dev/wd9a being configured at col: 0
    	 Column: 0 Num Columns: 0
    	 Version: 0 Serial Number: 0 Mod Counter: 0
    	 Clean: No Status: 0
    Number of columns do not match for: /dev/wd9a
    /dev/wd9a is not clean!
    raid0: Component /dev/wd1a being configured at col: 1
    	 Column: 0 Num Columns: 0
    	 Version: 0 Serial Number: 0 Mod Counter: 0
    	 Clean: No Status: 0
    Column out of alignment for: /dev/wd1a
    Number of columns do not match for: /dev/wd1a
    /dev/wd1a is not clean!
    raid0: There were fatal errors
    raid0: Fatal errors being ignored.
    raid0: RAID Level 1
    raid0: Components: /dev/wd9a[**FAILED**] /dev/wd1a
    raid0: Total Sectors: 19540864 (9541 MB)
    # raidctl -v -I 2004082401 raid0
    # raidctl -v -i raid0
    Initiating re-write of parity
    # tail -1 /var/log/messages
    raid0: Error re-writing parity!
    # raidctl -v -s raid0
    Components:
    	   /dev/wd9a: failed
    	   /dev/wd1a: optimal
    No spares.
    /dev/wd9a status is: failed.  Skipping label.
    Component label for /dev/wd1a:
       Row: 0, Column: 1, Num Rows: 1, Num Columns: 2
       Version: 2, Serial Number: 2004082401, Mod Counter: 7
       Clean: No, Status: 0
       sectPerSU: 128, SUsPerPU: 1, SUsPerRU: 1
       Queue size: 100, blocksize: 512, numBlocks: 19540864
       RAID Level: 1
       Autoconfig: No
       Root partition: No
       Last configured as: raid0
    Parity status: DIRTY
    Reconstruction is 100% complete.
    Parity Re-write is 100% complete.
    Copyback is 100% complete.
    

    15.3.6. Установка файловой системы

    Устройство RAID теперь сконфигурирован и доступен. Он является псевдо дисковым устройством. Теперь вам остается определиться с размерами слайсов. В целях упрощения примеров, на нашей системе 8.5 гигабайт выделено для / как /dev/raid0a и все остальное под swap как /dev/raid0b.

    Предостережение

    Эта схема разбиения диска неподходит для сервера. Руководство NetBSD затрагивает вопрос выделения дискового пространства в Глава 2, Установка.

    Замечание

    Обратите внимание, что 1 Гб это 2*1024*1024=2097152 blocks (1 блок это 512 байт или 0.5 килобайта). Несмотря на используемое оборудование, в псевдо диске RAID всегда будет 512 байтов/сектор.

    Замечание

    В этом примере пространство, выделенное слайсу a:, различается между i386 и sparc64, поэтому различается размер томов RAID:

    На i386:

     # disklabel -r -e -I raid0
    type: RAID
    disk: raid
    label: fictitious
    flags:
    bytes/sector: 512
    sectors/track: 128
    tracks/cylinder: 8
    sectors/cylinder: 1024
    cylinders: 19082
    total sectors: 19540864
    rpm: 3600
    interleave: 1
    trackskew: 0
    cylinderskew: 0
    headswitch: 0 # microseconds
    track-to-track seek: 0 # microseconds
    drivedata: 0
    
    #        size    offset     fstype [fsize bsize cpg/sgs]
     a:  19015680         0     4.2BSD      0     0     0  # (Cyl.      0 - 18569)
     b:    525184  19015680       swap                     # (Cyl.  18570 - 19082*)
     d:  19540864         0     unused      0     0        # (Cyl.      0 - 19082*)
    

    На sparc64:

    # disklabel -r -e -I raid0
    [...snip...]
    total sectors: 19539968
    [...snip...]
    3 partitions:
    #        size    offset     fstype [fsize bsize cpg/sgs]
     a:  19251200         0     4.2BSD      0     0     0  # (Cyl.      0 -  18799)
     b:    288768  19251200       swap                     # (Cyl.  18800 -  19081)
     c:  19539968         0     unused      0     0        # (Cyl.      0 -  19081)
    

    Затем, форматируем созданный раздел / как 4.2BSD FFSv1:

    # newfs -O 1 /dev/raid0a
    /dev/rraid0a: 9285.0MB (19015680 sectors) block size 16384, fragment size 2048
    	using 51 cylinder groups of 182.06MB, 11652 blks, 22912 inodes.
    super-block backups (for fsck -b #) at:
           32,   372896,   745760,  1118624,  1491488,  1864352,  2237216, 2610080,
      2982944,  3355808,  3728672,  4101536,  4474400,  4847264,  5220128, 5592992,
      5965856,  6338720,  6711584,  7084448,  7457312,  7830176,  8203040, 8575904,
      8948768,  9321632,  9694496, 10067360, 10440224, 10813088, 11185952,11558816,
     11931680, 12304544, 12677408, 13050272, 13423136, 13796000, 14168864,14541728,
     14914592, 15287456, 15660320, 16033184, 16406048, 16778912, 17151776,17524640,
     17897504, 18270368, 18643232,
    
    # fsck -fy /dev/rraid0a
    ** /dev/rraid0a
    ** File system is already clean
    ** Last Mounted on
    ** Phase 1 - Check Blocks and Sizes
    ** Phase 2 - Check Pathnames
    ** Phase 3 - Check Connectivity
    ** Phase 4 - Check Reference Counts
    ** Phase 5 - Check Cyl groups
    1 files, 1 used, 4680062 free (14 frags, 585006 blocks, 0.0% fragmentation)
    

    15.3.7. Перенос системы на RAID

    Теперь файловая система RAID готова к использованию. Мы монтируем ее в /mnt и копируем все файлы со старой системы. Это можно сделать, используя утилиты dump(8) или pax(1).

    # mount /dev/raid0a /mnt
    # df -h /mnt
    Filesystem    Size     Used     Avail Capacity  Mounted on
    /dev/raid0a   9.0G     2.0K      8.6G     0%    /mnt
    # cd /; pax -v -X -rw -pe / /mnt
    [...snip...]
    

    Теперь NetBSD установлена на файловой системе RAID. Мы должны установить точки монтирования в новой копии /etc/fstab иначе не произойдет монтирования разделов. Замените wd0 на raid0.

    # vi /mnt/etc/fstab
    
    /dev/raid0a  /  ffs  rw  1  1
    /dev/raid0b  none  swap  sw  0  0
    kernfs    /kern  kernfs  rw
    procfs    /proc  procfs  rw
    

    Раздел подкачки должен быть расконфигурирован перед выключением системы, для избежания ошибок четности на устройстве RAID. Это очень легко сделать добавив одну строку в /etc/rc.conf.

    # vi /mnt/etc/rc.conf
    swapoff=YES
    

    Затем загрузчик должен быть установлен на Disk1/wd1. Ошибка на этом этапе оставит загрузочным только Disk0/wd0 и сделает RAID-1 бессмысленным в случае отказа загрузочного диска.

    Подсказка

    Поскольку на многих материнских платах i386 меню BIOS/CMOS может вводить в заблуждение относительно порядка опроса загрузочных устройств, я настоятельно рекомендую использовать опцию начального загрузчика «-o timeout=X». Установка уникального значения для каждого диска позволит точно определить, с какого диска загружается система.

    Предостережение

    Хотя может казаться логичным установить 1-ый блок начальной загрузки в /dev/rwd1{c,d}, (что являтся идеологически верным для NetBSD 1.6.x installboot(8)) сейчас это не так. Если вы делаете эту ошибку, загрузочный сектор будет поврежден без возможности восстановления и вам придется начать процесс сначала.

    На i386 установка загрузчика в /dev/rwd1a :

    # /usr/sbin/installboot -o timeout=30 -v /dev/rwd1a /usr/mdec/bootxx_ffsv1
    File system:         /dev/rwd1a
    File system type:    raw (blocksize 8192, needswap 1)
    Primary bootstrap:   /usr/mdec/bootxx_ffsv1
    Preserving 51 (0x33) bytes of the BPB
    

    На sparc64 также устанавливаем загрузчик в /dev/rwd1a на флаг «-o» не поддерживается (и ненужен, благодаря OpenBoot):

    # /usr/sbin/installboot -v /dev/rwd1a /usr/mdec/bootblk
    File system:         /dev/rwd1a
    File system type:    raw (blocksize 8192, needswap 0)
    Primary bootstrap:   /usr/mdec/bootblk
    Bootstrap start sector: 1
    Bootstrap byte count:   4915
    Writing bootstrap
    

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

    # raidctl -v -A root raid0
    raid0: Autoconfigure: Yes
    raid0: Root: Yes
    # tail -2 /var/log/messages
    raid0: New autoconfig value is: 1
    raid0: New rootpartition value is: 1
    # raidctl -v -s raid0
    [...snip...]
       Autoconfig: Yes
       Root partition: Yes
       Last configured as: raid0
    [...snip...]
    # shutdown -r now

    Внимание

    Всегда используйте shutdown(8) для выключения системы. Не используйте просто reboot(8). reboot(8) не совсем корректно отрабатывает скрипты rc и не отключает раздел подкачки. Это приведет к ошибкам четности после каждой перезагрузки.

    15.3.8. Первая загрузка с RAID

    В этой точке временно сконфигурируйте вашу систему для загрузки с Disk1/wd1. Для получения дополнительной информации обратитесь к Раздел 15.3.10, «Тестирование загрузочной области». Теперь система должна загрузиться и все файловые системы должны находиться на RAID. RAID будет функционален с единственным компонентом, однако набор не реализован полностью, потому что поддельный диск (wd9) считается аварийным.

    # egrep -i "raid|root" /var/run/dmesg.boot
    raid0: RAID Level 1
    raid0: Components: component0[**FAILED**] /dev/wd1a
    raid0: Total Sectors: 19540864 (9541 MB)
    boot device: raid0
    root on raid0a dumps on raid0b
    root file system type: ffs
    
    # df -h
    Filesystem    Size     Used     Avail Capacity  Mounted on
    /dev/raid0a   8.9G     196M      8.3G     2%    /
    kernfs        1.0K     1.0K        0B   100%    /kern
    
    # swapctl -l
    Device      1K-blocks     Used    Avail Capacity  Priority
    /dev/raid0b    262592        0   262592     0%    0
    # raidctl -s raid0
    Components:
    	  component0: failed
    	   /dev/wd1a: optimal
    No spares.
    component0 status is: failed.  Skipping label.
    Component label for /dev/wd1a:
       Row: 0, Column: 1, Num Rows: 1, Num Columns: 2
       Version: 2, Serial Number: 2004082401, Mod Counter: 65
       Clean: No, Status: 0
       sectPerSU: 128, SUsPerPU: 1, SUsPerRU: 1
       Queue size: 100, blocksize: 512, numBlocks: 19540864
       RAID Level: 1
       Autoconfig: Yes
       Root partition: Yes
       Last configured as: raid0
    Parity status: DIRTY
    Reconstruction is 100% complete.
    Parity Re-write is 100% complete.
    Copyback is 100% complete.
    

    15.3.9. Добавление Disk0/wd0 в RAID

    Теперь мы добавим Disk0/wd0 как компонент RAID. Это уничтожит первоначальную структуру файловой системы. На i386, метка диска MBR не будет затронута (помните, что мы скопировали метку wd0 к wd1), поэтому нет никакой потребности «обнулять» Disk0/wd0. Однако, мы должны повторно маркировать Disk0/wd0, чтобы иметь идентичную метку диска NetBSD, как и на Disk1/wd1. Тогда мы добавляем Disk0/wd0 как «горячее резервирование» к набору RAID и инициализируем реконструкцию четности для всех устройств RAID, фактически добавляя Disk0/wd0 в RAID-1 набор и «синхронизируя» оба диска.

    # disklabel -r wd1 > /tmp/disklabel.wd1
    # disklabel -R -r wd0 /tmp/disklabel.wd1

    В качестве последней проверки, можно воспользоваться diff(1), чтобы гарантировать соответствие метки диска Disk0/wd0 и Disk1/wd1. Вы должны также зарезервировать эти файлы для изучения в случае аварии.

    # disklabel -r wd0 > /tmp/disklabel.wd0
    # disklabel -r wd1 > /tmp/disklabel.wd1
    # diff /tmp/disklabel.wd0 /tmp/disklabel.wd1
    # fdisk /dev/rwd0 > /tmp/fdisk.wd0
    # fdisk /dev/rwd1 > /tmp/fdisk.wd1
    # diff /tmp/fdisk.wd0 /tmp/fdisk.wd1
    # mkdir /root/RFbackup
    # cp -p /tmp/{disklabel,fdisk}* /root/RFbackup

    Как только вы будете готовы, добавьте Disk0/wd0 как резервный компонент и начинайте реконструкцию:

    # raidctl -v -a /dev/wd0a raid0
    /netbsd: Warning: truncating spare disk /dev/wd0a to 241254528 blocks
    # raidctl -v -s raid0
    Components:
    	  component0: failed
    	   /dev/wd1a: optimal
    Spares:
    	   /dev/wd0a: spare
    [...snip...]
    # raidctl -F component0 raid0
    RECON: initiating reconstruction on col 0 -> spare at col 2
     11% |****                                   | ETA:    04:26 \
    

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

    # raidctl -S raid0
    Reconstruction is 0% complete.
    Parity Re-write is 100% complete.
    Copyback is 100% complete.
    Reconstruction status:
      17% |******                                 | ETA: 03:08 -
    

    После перезагрузки оба диска должны быть «optimal».

    # tail -f /var/log/messages
    raid0: Reconstruction of disk at col 0 completed
    raid0: Recon time was 1290.625033 seconds, accumulated XOR time was 0 us (0.000000)
    raid0:  (start time 1093407069 sec 145393 usec, end time 1093408359 sec 770426 usec)
    raid0: Total head-sep stall count was 0
    raid0: 305318 recon event waits, 1 recon delays
    raid0: 1093407069060000 max exec ticks
    
    # raidctl -v -s raid0
    Components:
    	   component0: spared
    	   /dev/wd1a: optimal
    Spares:
         /dev/wd0a: used_spare
         [...snip...]
    

    Когда реконструкция закончена, мы должны установить загрузчик на Disk0/wd0. На i386 установка загрузчика в /dev/rwd0a:

    # /usr/sbin/installboot -o timeout=15 -v /dev/rwd0a /usr/mdec/bootxx_ffsv1
    File system:         /dev/rwd1a
    File system type:    raw (blocksize 8192, needswap 1)
    Primary bootstrap:   /usr/mdec/bootxx_ffsv1
    Preserving 51 (0x33) bytes of the BPB
    

    На sparc64:

    # /usr/sbin/installboot -v /dev/rwd0a /usr/mdec/bootblk
    File system:         /dev/rwd0a
    File system type:    raw (blocksize 8192, needswap 0)
    Primary bootstrap:   /usr/mdec/bootblk
    Bootstrap start sector: 1
    Bootstrap byte count:   4915
    Writing bootstrap
    

    И снава перезагрузка. Это необходимо для перевода Disk0/wd0 из состояния «used_spare» как «Component0″ в «optimal». Обратитесь к комментариям следующей секции для контроля за состоянием четности после каждой перезагрузки.

    # shutdown -r now

    15.3.10. Тестирование загрузочной области

    В этой точке вы должны гарантировать, что аппаратные средства вашей системы могут должным образом обработать загрузочные блоки на любом диске. На i386 это аппаратно-зависимый процесс, и выполняется через меню CMOS/BIOS или меню конфигурации платы контроллера.

    На i386 используется система меню для установки приоритетов загрузки устройств (Disk1/wd1 прежде Disk0/wd0). Приведем пример для Award BIOS.

    Рисунок 15.6. Award BIOS i386. Загрузка с Disk1/wd1

    Award BIOS i386. Загрузка с Disk1/wd1

    Сохраняем изменения и выходим.

    >> NetBSD/i386 BIOS Boot, Revision 3.1
    >> (seklecki@localhost, Fri Aug 13 08:08:47 EDT 2004)
    >> Memory: 640/31744 k
    Press return to boot now, any other key for boot menu
    booting hd0a:netbsd - starting in 30
    

    Вы можете убедиться, что BIOS читает Disk1/wd1, поскольку таймаут загрузчика составляет 30 секунд вместо 15. После перезагрузки верните настройки BIOS для загрузки по умолчанию:

    Рисунок 15.7. Award BIOS i386. Загрузка с Disk0/wd0

    Award BIOS i386. Загрузка с Disk0/wd0
    Сохраняем изменения и выходим.

    >> NetBSD/i386 BIOS Boot, Revision 3.1
    >> (seklecki@localhost, Fri Aug 13 08:08:47 EDT 2004)
    >> Memory: 640/31744 k
    Press return to boot now, any other key for boot menu
    booting hd0a:netbsd - starting in 15
    

    Обратите внимание, как ваше ядро обнаруживает controller/bus/drive, независимо от того, что назначает BIOS в качестве загрузочного диска. Это нормальное поведение.

    На sparc64 используйте Sun OpenBoot devalias для подтверждения загрузки:

    Sun Ultra 5/10 UPA/PCI (UltraSPARC-IIi 400MHz), No Keyboard
    OpenBoot 3.15, 128 MB memory installed, Serial #nnnnnnnn.
    Ethernet address 8:0:20:a5:d1:3b, Host ID: nnnnnnnn.
    
    ok devalias
    [...snip...]
    cdrom /pci@1f,0/pci@1,1/ide@3/cdrom@2,0:f
    disk /pci@1f,0/pci@1,1/ide@3/disk@0,0
    disk3 /pci@1f,0/pci@1,1/ide@3/disk@3,0
    disk2 /pci@1f,0/pci@1,1/ide@3/disk@2,0
    disk1 /pci@1f,0/pci@1,1/ide@3/disk@1,0
    disk0 /pci@1f,0/pci@1,1/ide@3/disk@0,0
    [...snip...]
    
    ok boot disk0 netbsd
    Initializing Memory [...]
    Boot device /pci/pci/ide@3/disk@0,0 File and args: netbsd
    NetBSD IEEE 1275 Bootblock
    >> NetBSD/sparc64 OpenFirmware Boot, Revision 1.8
    >> (lavalamp@j8, Thu Aug 19: 15:45:42 EDT 2004)
    loadfile: reading header
    elf64_exec: Booting [...]
    symbols @ [....]
     Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001
         The NetBSD Foundation, Inc.  All rights reserved.
     Copyright (c) 1982, 1986, 1989, 1991, 1993
         The Regents of the University of California.  All rights reserved.
    [...snip...]
    

    И второй диск:

    ok boot disk2 netbsd
    Initializing Memory [...]
    Boot device /pci/pci/ide@3/disk@2,0: File and args:netbsd
    NetBSD IEEE 1275 Bootblock
    >> NetBSD/sparc64 OpenFirmware Boot, Revision 1.8
    >> (lavalamp@j8, Thu Aug 19: 15:45:42 EDT 2004)
    loadfile: reading header
    elf64_exec: Booting [...]
    symbols @ [....]
     Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001
         The NetBSD Foundation, Inc.  All rights reserved.
     Copyright (c) 1982, 1986, 1989, 1991, 1993
         The Regents of the University of California.  All rights reserved.
    [...snip...]
    

    При каждой последующей загрузку ядро NetBSD должно выдать сообщение, видимое dmesg(8) как:

    raid0: RAID Level 1
    raid0: Components: /dev/wd0a /dev/wd1a
    raid0: Total Sectors: 19540864 (9541 MB)
    boot device: raid0
    root on raid0a dumps on raid0b
    root file system type: ffs
    

    Как только вы убедитесь, что оба диска загрузочные, проверьте четность RAID после перезагрузки:

    # raidctl -v -s raid0
    Components:
    	  /dev/wd0a: optimal
    	  /dev/wd1a: optimal
    No spares.
    [...snip...]
    Component label for /dev/wd0a:
       Row: 0, Column: 0, Num Rows: 1, Num Columns: 2
       Version: 2, Serial Number: 2004082401, Mod Counter: 67
       Clean: No, Status: 0
       sectPerSU: 128, SUsPerPU: 1, SUsPerRU: 1
       Queue size: 100, blocksize: 512, numBlocks: 19540864
       RAID Level: 1
       Autoconfig: Yes
       Root partition: Yes
       Last configured as: raid0
    Component label for /dev/wd1a:
       Row: 0, Column: 1, Num Rows: 1, Num Columns: 2
       Version: 2, Serial Number: 2004082401, Mod Counter: 67
       Clean: No, Status: 0
       sectPerSU: 128, SUsPerPU: 1, SUsPerRU: 1
       Queue size: 100, blocksize: 512, numBlocks: 19540864
       RAID Level: 1
       Autoconfig: Yes
       Root partition: Yes
       Last configured as: raid0
    Parity status: clean
    Reconstruction is 100% complete.
    Parity Re-write is 100% complete.
    Copyback is 100% complete.
    

    Глава 14. Конфигурация Concatenated Disk Device (CCD)

    Русский перевод: Михаил Сгибнев

    Содержание

    14.1. Установка физичесих носителей
    14.2. Конфигурирование ядра
    14.3. Присоединяем метку каждого диска к CCD
    14.4. Конфигурирование CCD
    14.5. Инициализация устройства CCD
    14.6. Создание файловой системы 4.2BSD/UFS на новом устройстве CCD device
    14.7. Монтирование файловой системы

    Драйвер CCD позволяет пользователю «объединять» несколько физических дисков в один псевдо-диск. В то время, когда RAIDframe (смотри Глава 15, NetBSD RAIDframe) позволяет организовывать массивы RAID level 0 только с одинаковой геометрией, CCD позволяет преодолевать эти ограничения. При работе с CCD возможно «чередование» дисков для повышения быстродействия, но с потерей дискового пространства. В этом примере такую возможность мы не рассматриваем.

    Для установка CCD необходимо выполнить несколько шагов:

    1. Установить физический носитель
    2. Сконфигурировать ядро
    3. Метку каждого диска присоединить к CCD
    4. Создать файл конфигурации CCD
    5. Инициализировать устройство CCD
    6. Создать файловую систему на новом устройстве CCD
    7. Примонтировать файловую систему CCD

    В этом примере CCD устанавливается на NetBSD/sparc 1.5. CCD будет занимать 4 SCSI диска внешней корзины Sun, подсоединенной через стандартный 50 пиновый разьем SCSI.

    14.1. Установка физичесих носителей

    Первый Ваш шаг зависит от Вашей платформы и от имеющихся в наличии аппаратных средств.

    Вывод моего DMESG:

    Disk #1:
      probe(esp0:0:0): max sync rate 10.00MB/s
      sd0 at scsibus0 target 0 lun 0: <SEAGATE, ST32430N SUN2.1G, 0444> SCSI2 0/direct fixed
      sd0: 2049 MB, 3992 cyl, 9 head, 116 sec, 512 bytes/sect x 4197405 sectors
    
    Disk #2
      probe(esp0:1:0): max sync rate 10.00MB/s
      sd1 at scsibus0 target 1 lun 0: <SEAGATE, ST32430N SUN2.1G, 0444> SCSI2 0/direct fixed
      sd1: 2049 MB, 3992 cyl, 9 head, 116 sec, 512 bytes/sect x 4197405 sectors
    
    Disk #3
      probe(esp0:2:0): max sync rate 10.00MB/s
      sd2 at scsibus0 target 2 lun 0: <SEAGATE, ST11200N SUN1.05, 9500> SCSI2 0/direct fixed
      sd2: 1005 MB, 1872 cyl, 15 head, 73 sec, 512 bytes/sect x 2059140 sectors
    
    Disk #4
      probe(esp0:3:0): max sync rate 10.00MB/s
      sd3 at scsibus0 target 3 lun 0: <SEAGATE, ST11200N SUN1.05, 8808 > SCSI2 0
      sd3: 1005 MB, 1872 cyl, 15 head, 73 sec, 512 bytes/sect x 2059140 sectors

    14.2. Конфигурирование ядра

    Для обеспечения поддержки CCD в ядре должна быть прописана следующая директива (имеется в ядре GENERIC):

    pseudo-device  ccd  4    # concatenated disk devices

    В моем файле конфигурации я также жестко привязал SCSI ID и запись устройства в /dev, дабы чего не вышло.

    sd0     at scsibus0 target 0 lun ?
    # SCSI disk drives
    sd1     at scsibus0 target 1 lun ?
    # SCSI disk drives
    sd2     at scsibus0 target 2 lun ?
    # SCSI disk drives
    sd3     at scsibus0 target 3 lun ?
    # SCSI disk drives
    sd4     at scsibus0 target 4 lun ?
    # SCSI disk drives
    sd5     at scsibus0 target 5 lun ?
    # SCSI disk drives
    sd6     at scsibus0 target 6 lun ?
    # SCSI disk drives

    14.3. Присоединяем метку каждого диска к CCD

    Каждый диск, входящий в CCD, нуждается в специализированной файловой системе. В этом примере, для disklabel:

    /dev/rsd0c
    /dev/rsd1c
    /dev/rsd2c
    /dev/rsd3c

    Замечание

    Всегда помните, что метка диска — признак символьного устройства, а не блочного.

    Замечание

    На всех платформах слайс c является символической записью NetBSD и зарезервирован.

    Вероятнее всего Вы захотите удалить старые разделы на дисках, отведенных под CCD. Делается это с помощью команды dd(1):

    # dd if=/dev/zero of=/dev/rsd0c bs=8k count=1
    # dd if=/dev/zero of=/dev/rsd1c bs=8k count=1
    # dd if=/dev/zero of=/dev/rsd2c bs=8k count=1
    # dd if=/dev/zero of=/dev/rsd3c bs=8k count=1

    Если Ваша архитектура подразумевает использование MBR (Master Boot Record) и кроме NetBSD на диске могут оказаться разделы других систем, таких как Windows или Linux, то можно убрать MBR и все разделы с диска, используя команду:

    # dd if=/dev/zero of=/dev/rsd0d bs=8k count=1
    # dd if=/dev/zero of=/dev/rsd1d bs=8k count=1
    # dd if=/dev/zero of=/dev/rsd2d bs=8k count=1
    # dd if=/dev/zero of=/dev/rsd3d bs=8k count=1

    После выполнения этой операции все данные на диске окажутся недоступными. Обратите внимание на занимающий весь диск слайс d на платформе i386 (и некоторых других) и c на остальных (например на sparc). Смотрите «kern.rawpartition» sysctl – «3″ для «d», «2″ для «c».

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

    # disklabel -r sd0
    [...snip...]
    bytes/sector: 512
    sectors/track: 116
    tracks/cylinder: 9
    sectors/cylinder: 1044
    cylinders: 3992
    total sectors: 4197405
    [..snip...]
    3 partitions:
    #        size   offset    fstype   [fsize bsize   cpg]
      c:  4197405       0     unused     1024  8192        # (Cyl.    0 - 4020*)

    Вам необходимо будет создать один «slice» для раздела NetBSD на диске. «Slice» должен начинаться со смещением ,по крайней мере, в один цилиндр от начала диска/раздела для размещения специальной CCD disklabel. Смещение должно быть кратно отношению «sectors/cylinder», поэтому «size» будет равен «total sectors» за вычетом 1x «sectors/cylinder». Отредактируйте метку диска соответственно:

    # disklabel -e sd0

    Замечание

    Смещение слайса типа «ccd» должно соответствовать значению «sectors/cylinder»

    Замечание

    Выполните export EDITOR=[path to your favorite editor] перед редактированием метки диска.

    Замечание

    Тип слайса должен быть указан как ccd.

    Поскольку у нас будет только один слайс на разделе, то Вы можете использовать c, обычно зарезервированный. Измените вашу метку диска на следующее:

    3 partitions:
    #        size   offset    fstype   [fsize bsize   cpg]
      c:  4196361     1044       ccd                       # (Cyl. 1 - 4020*)

    Также можно установить слайс, отличный от c, для этого просто отредактируйте:

    3 partitions:
    #        size   offset    fstype   [fsize bsize   cpg]
      a:  4196361     1044       ccd                       # (Cyl. 1 - 4020*)
      c:  4197405       0     unused     1024  8192        # (Cyl. 0 - 4020*)

    Убедитесь в том, что метка записалась. Disklabel попросит вас подтвердить изменения, проявите благоразумие в этом вопросе и вспомните, все ли правильно вы сделали?

    14.4. Конфигурирование CCD

    Как только все диски соответствующим образом размечены, необходимо создать файл конфигурации /etc/ccd.conf. Этот файл не создается по умолчанию, поэтому вам необходимо создать его. Формат файла представлен ниже:

    #ccd    ileave    flags   component    devices

    Замечание

    Если значение «ileave» равно 0, то диски обьединяются, если используется значение, эквивалентное значению «sectors/track», диски чередуются.

    В нашем случае:

    # more /etc/ccd.conf
    ccd0  0  none /dev/sd0c /dev/sd1c /dev/sd2c /dev/sd3c

    Замечание

    Файл конфигурации CCD необходим для функционирования только что созданной файловой системы CCD. Не используйте здесь блочное устройство, необходимо указывать символьное.

    14.5. Инициализация устройства CCD

    Как только вы почувствовали, что конфигурирование произведено правильно, можно инициализировать устройство, используя команду ccdconfig(8). Конфигурируем:

    # ccdconfig -c -f /etc/ccd.conf

    Расконфигурируем:

    # ccdconfig -u -f /etc/ccd.conf

    Инициализация устройства CCD активирует в /dev записи /dev/{,r}ccd#::

    # ls -la  /dev/{,r}ccd0*
    brw-r-----  1 root  operator   9, 0 Apr 28 21:35 /dev/ccd0a
    brw-r-----  1 root  operator   9, 1 Apr 28 21:35 /dev/ccd0b
    brw-r-----  1 root  operator   9, 2 May 12 00:10 /dev/ccd0c
    brw-r-----  1 root  operator   9, 3 Apr 28 21:35 /dev/ccd0d
    brw-r-----  1 root  operator   9, 4 Apr 28 21:35 /dev/ccd0e
    brw-r-----  1 root  operator   9, 5 Apr 28 21:35 /dev/ccd0f
    brw-r-----  1 root  operator   9, 6 Apr 28 21:35 /dev/ccd0g
    brw-r-----  1 root  operator   9, 7 Apr 28 21:35 /dev/ccd0h
    crw-r-----  1 root  operator  23, 0 Jun 12 20:40 /dev/rccd0a
    crw-r-----  1 root  operator  23, 1 Apr 28 21:35 /dev/rccd0b
    crw-r-----  1 root  operator  23, 2 Jun 12 20:58 /dev/rccd0c
    crw-r-----  1 root  operator  23, 3 Apr 28 21:35 /dev/rccd0d
    crw-r-----  1 root  operator  23, 4 Apr 28 21:35 /dev/rccd0e
    crw-r-----  1 root  operator  23, 5 Apr 28 21:35 /dev/rccd0f
    crw-r-----  1 root  operator  23, 6 Apr 28 21:35 /dev/rccd0g
    crw-r-----  1 root  operator  23, 7 Apr 28 21:35 /dev/rccd0h

    14.6. Создание файловой системы 4.2BSD/UFS на новом устройстве CCD device

    Теперь можно создавать разделы на новом виртуальном диске, ассоциированным с устройством CCD.

    # disklabel -e ccd0

    Поскольку у нас один слайс, будем использовать слайс c или создадим отдельный слайс для использования:

    # disklabel -r ccd0
    # /dev/rccd0c:
    type: ccd
    disk: ccd
    label: default label
    flags:
    bytes/sector: 512
    sectors/track: 2048
    tracks/cylinder: 1
    sectors/cylinder: 2048
    cylinders: 6107
    total sectors: 12508812
    rpm: 3600
    interleave: 1
    trackskew: 0
    cylinderskew: 0
    headswitch: 0           # microseconds
    track-to-track seek: 0  # microseconds
    drivedata: 0
    #        size   offset    fstype   [fsize bsize   cpg]
      c: 12508812        0    4.2BSD     1024  8192    16  # (Cyl. 0 - 6107*)

    Затем необходимо отформатировать файловую систему:

    # newfs /dev/rccd0c
    Warning: 372 sector(s) in last cylinder unallocated
    /dev/rccd0c:    12508812 sectors in 6108 cylinders of 1 tracks, 2048 sectors
    	6107.8MB in 382 cyl groups (16 c/g, 16.00MB/g, 3968 i/g)
    
    super-block backups (for fsck -b #) at:
    [...]

    14.7. Монтирование файловой системы

    После создания файловой системы на устройстве CCD она может быть примонтирована обычным образом. Монтируем слайс ffs или 4.2BSD:

    # mount /dev/ccd0c /mnt

    Затем:

    # export BLOCKSIZE=1024; df
    Filesystem  1K-blocks     Used   Avail Capacity  Mounted on
    /dev/sd6a      376155   320290   37057    89%    /
    /dev/ccd0c    6058800       1  5755859     0%    /mnt

    Поздравляем, теперь у вас есть работающий CCD. Для конфигурирования устройства CCD при начальной загрузке, добавьте опцию ccd=yes в файл /etc/rc.conf. Вы должны добавить следущую строку в /etc/fstab для монтирования файловой системы при загрузке:

    /dev/ccd0c  /home ffs     rw,softdep    1 2