Использование бездисковых X-терминалов на базе Linux-PC

Оригинал данного документа находится по адресу: http://ppg.ice.ru/ppg/xterminals.
20.08.2001, Виктор Вагнер

Использование бездисковых X-терминалов на базе Linux-PC

Более-менее подробное описание процедуры настройки бездисковых X-терминалов

Вы еще не используете X-терминалы? Зря. Linux - система многопользователсякая, и позволив нескольким пользователям работать на одном компьютере одновременно, вы сильно облегчите жизнь. Рабочее место на базе X-терминала ничем не отличается от локального X-сервера - есть и графика, и мышиный интерфейс, и звук, а администрировать и апгрейдить X-терминал не надо.

Что такое X-терминал

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

X-терминалы бывают аппаратные и сделанные из дешевых персональных компьютеров. К аппаратным обычно прилагается специализированная ОС, которая содержит в себе необходимые драйвера и X-сервер. Если вы собираетесь делать X-терминал из старой писишки, то в качестве такой ОС, вы, несомненно будете использовать Linux.

В чем преимущества X-терминала

Во-первых его не надо администрировать. На X-терминале нет своего файла /etc/passwd, его пользователи логинятся сразу на основную машину, пользователи не засоряют его диск ненужными файлами (да и диска-то там как правило нет), там практически нет программ, которые могут повести себя странно. Поэтому время, затрачиваемое на администрирование X-терминала стремится к нулю. У меня дома есть два X-терминала, один - из старой 486 машины, второй аппаратный NCD ECX. О первом я вспоминаю только тогда, когда у меня на основной машине в результате апгрейда освобождается звуковая карта или монитор, который можно было бы туда переставить, а о втором - и того реже - за два года - единственный раз, когда там сдохла неизвестно из каких запасников вырытая клавиатура, и пришлось покупать новую.

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

В-третьих, X-терминал, сделанный из PC оказывается сильно дешевле полноценной рабочей станции. 486 процессор или слабый Pentium, 8-16 мегабайт памяти и никакого жесткого диска. В результате монитор начинает стоить не 30-50% машины, как у типичной рабочей станции, а 80-90%.

В-четвертых, вам не надо заботиться о том, чтобы на всех X-терминалах стояли все необходимые программы. Конечно, под Linux, да еще и при монтировании /usr, да еще и с современными package manager-ами поддерживать десяток рабочих станций в актуальном состоянии не в пример проще, чем под Windows или DOS, но здесь вы поддерживаете ровно одну машину, а пользователи остальных рабочих мест приходят к этой, заботливо поддерживаемой, конфиграции сами.

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

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

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

Все это в первую очередь касается X-терминалов в оффисе. А дома?

Но ведь почти никто не живет дома в одиночку. И у большинства не хватает денег (или желания их потратить) для покупки полноценного компьютера для каждого члена семьи. Вот здесь-то разница в стоимости владения между компьютером и X-терминалом может окажаться критичной.

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

Недостатки X-терминалов

Есть у X-терминалов и свои недостатки. Во-первых, по 10-мегабайтной сети приложения с интенсивной графикой типа the Gimp работают, несомненно, медленнее, чем на локальном мониторе. А некоторые игрушки - так вообще не работают (хотя OpenGL на X-терминале более чем возможен).

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

В-третьих, вы начинаете очень сильно зависеть от надежности локальной сети. Но опять же - не более сильно чем при активном использовании NFS.

Как это делается

Настройка хоста

Для того, чтобы X-терминалы могли работать с хостом, требуется на нем кое-что настроить.

xdm

Во-первых, должен исполняться xdm или его аналог (dtlogin, kdm,gdm), который умеет обеспечивать графический login. Если для пользователей, работающих на локальной консоли графический логин - роскошь, то для X-терминалов - необходимость, ведь они кроме X-сервера ничего не выполняют, и своего /etc/passwd не имеют, следовательно логин им должна обеспечивать базовая машина. При этом на этой машине совершенно не обязательно должен быть локальный X-сервер. Нам нужен xdm чтобы управлять удаленными дисплеями. Поэтому строчку в файле /etc/X11/xdm/Xservers, описывающую параметры локального X-сервера, можно выкинуть. В Debian 2.1 может потребоваться при этом еще и поправить скрипты запуска xdm, чтобы не производилась проверка на существование корректной конфигурации X-сервера.

Сам xdm может запускаться двумя способами - либо как обычный демон, либо из /etc/inittab с опцией respawn и флагом -nodaemon (чтобы он не уходил в background, а то init решит, что он завершился, и начнет плодить их в немерянном количестве.

В современных дистрибутивах по соображениям гипертрофированной заботы о безопасности, xdm поставляется с файлом /etc/X11/xdm/Xaccess запрещающим доступ с удаленных машин. Нужно этот доступ разрешить, прописав в этом файле строчки

# Any host can get logim window
*
и, возможно,
* CHOOSER BROADCAST
Смысл этой строчки мы объясним позже, разбирая конфигурацию X-сервера на терминале.

Кроме этого, стоит поправить файл /etc/X11/xdm/Xresources в котором описаны настройки, действующие в момент работы chooser-а или login-widget-а. В этих настройках можно употреблять некоторые переменные, такие как CLIENTHOST, SERVERHOST, указывающие соответственно, на машину выполняющую X-клиента (xdm) и машину выполняющую X-сервер (терминал). Полный список этих переменных можно найти в man xrdb.

font server

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

для этого ему надо посылать не SIGHUP (при котором закрываются все соединения), а SIGUSR1.

Пользовательские ресурсы

Настройка пользовательских файлов ~/.Xresources необходима только если у вас используются терминалы с разным разрешением экрана. Тогда воспользовавшись тем, что xrdb пропускает ~/.Xresources через препроцессор C, определяя ряд полезных макросов, среди которых кроме CLIENTHOST есть также и WIDTH и HEIGHT можно задать разные шрифты по умолчанию для экранов разного размера. К сожалению, это подействует только на классические программы использующие графические тулкиты Motif, Xaw, Tk и др. Программы, написанные с использованием популярного среди начинающих программистов тулкита gtk, не используют стандартный механизм X-ресурсов для конфигурирования, и много от этого теряют.

Настройка удаленной загрузки

Теперь мы подошли к самому главному - как заставить компьютер грузиться по сети. Первое, что для этого необходимо, это сетевая карточка с Boot-ROM (по-русски - ПЗУ удаленной загрузки). Гнездо под микросхему Boot-ROM есть на многих сетевых карточках, в том числе и самых дешевых. Но, к сожалению, те Boot-ROM, которые продаются для этих карточек, поддерживают только загрузку с сервера Novell. Можно, конечно, поэкспериментировать с эмулятором Novel mars-nwe или Caldera Netware for Linux, но проще либо найти знакомого с программатором, и прошить в микросхемы собственноручно изготовленный с помощью пакета netboot, etherboot или NILO загрузочный код, либо купить более дорогую сетевую карточку, поддерживающую спецификацию PXE фирмы Intel (это спецификация фирмы Intel, а карточка может быть, скажем 3COM. Но стоить будет в районе $30). Если предполагается прошить ПЗУ с помощью netboot или etherboot, то на время экспериментов можно просто вставить в терминал дисковод для гибких дисков и грузить образ памяти (тот же самый, который потом будет зашит в ПЗУ-шку) с дискеты. Пользоваться этим способом для реальной работы не рекомендую, потому что дискеты последнее время стали слишком ненадежны, да и дисководы тоже.

Что должно выполняться на сервере удаленной загрузки

В любом случае, удаленная загрузка linux выполняется по протоколу tftp. Поэтому понадобится tftp-сервер. Он может либо находиться в отдельном пакете tftpd, либо входить в состав базовых сетевых сервисов. Рекомендую сначала посмотреть в /usr/sbin, вдруг там уже есть in.tftpd или tftpd, потом поискать на дистрибутивном компакт-диске, и только потом что-то искать в сети. tftpd обязан быть в любом дистрибутиве. Правда, вашей ПЗУ-шке может не понравиться его версия. Особенно привередливы в этом отношении PXE-совместимые Boot-Rom от Intel. В этом случае стоит последовать рекомендациям из файла pxelinux.doc.

Как и любой IP-протокол tftp предполагает, что у клиента есть ip-адрес, и ему известен IP-адрес сервера. А сетевой карте в момент загрузки известен только ее аппаратный адрес (это не касается аппаратных терминалов фирмы NCD - там можно и то и другое настроить в аналоге BIOS Setup). Поэтому необходим сервер, который сможет выделить клиенту IP адрес и сообщить адрес сервера, с которого можно взять ядро и имя файла на этом сервере. Для этого можно использовать либо проткол BOOTP, либо протокол DHCP, являющийся расширением BOOTP. DHCP поможет также снабдить IP-адресами рабочие станции Windows и ноутбуки, подключаемые к сети. BOOTP такими возможностями не обладает. В то же время dhcpd умеет обрабатывать BOOTP-запросы. Поэтому, ставьте dhcpd.

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

Компиляция ядра для X-терминала

Для X-терминала ядро Linux вам придется собирать самостоятельно. Ядра, идущие в составе дистрибутивов не поддерживают корневой файловой системы по NFS. Кроме того, вам жизненно необходимо, чтобы драйвер сетевой карты был вкомпилирован в ядро, а не был модулем. Кроме того, следует включить при компиляции автоконфигурирование через BOOTP. (в новых ядрах можно и через dhcp). Ядро не наследует параметров IP от загрузчика и должно уметь посылать bootp/dhcp запросы само. Можно, конечно передать параметры через командную строку ядра (это описано в /usr/src/linux/Documentation/nfsroot.txt), но в случае netboot это означает отдельный загрузочный образ для каждого терминала.

Поскольку X-терминалу нужно поддерживать минимальный набор устройств - клавиатуру, мышь, сетевую карту, может быть звук --- то модули можно вообще отключить. Единственное исключение - если вы хотите использовать видеокарту i810. Тогда без модуля agpgart вам не обойтись. Ну и еще PnP звуковые карты.

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

Каждый ваш терминал должен быть описан в /etc/dhcp.conf отдельно. Должна быть секция host, в которй написано, что устройству с таким-то ethernet-адресом нужно вот такое ядро и вот такой корневой NFS-каталог. Поэтому можно им давать статические IP-адреса. Можно и динамические, но с учетом того, что мы говорили ранее про макрос SERVERHOST в ресурсах, полезно чтобы терминалы были прописаны в DNS.

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

Типичное описание X-терминала в /etc/dhcp.conf выглядит так:

group xterminals {

  domain-name-servers party.lan.ice.ru,feast.lan.ice.ru;
  # Вы удивлены, что имена name-серверов указаны в символическом виде?
  # но dhcpd работает на машине, у которой есть и /etc/hosts и
  # /etc/resolv.conf. Поэтому он может разрезолвить имена сам, а
  # клиентам отдать уже готовые IP адреса
  routers party.lan.ice.ru;
  netmask 255.255.255.0;
  broadcast 192.168.219.255;
  domain lan.ice.ru
host steel {
  option dhcp-class-identifier "PXEClient";
  hardware ethernet 00:d0:b7:17:09:53;
  fixed-address steel.lan.ice.ru;
  filename "pxelinux.bin";
  option root-path "/var/diskless/steel";
  # Следующая строчка должна быть в одну строку
  option vendor-encapsulated-options 09:0f:80:00:0c:4e:65:74:77:6f\
         :72:6b:20:62:6f:6f:74:0a:07:00:50:72:6f:6d:70:74:06:01:02\
	 :08:03:80:00:00:47:04:80:00:00:00:ff;
  }	  
}
В данном случае в описании хоста присутствуют магические слова vendor-encapsulated-options и dhcp-class-identifier. Признаюсь честно, я не понимаю их смысла. Они были просто скопированы из документации к pxelinux. В случае если используется не PXE а netboot или etherboot, они не нужны.

Настройка удаленной загрузки через Netboot/etherboot

Пакеты netboot и etherboot в первую очередь предназначены для создания образов загрузочных Boot-ROM.

Как подсказал Константин Токарь образы etherboot можно также использовать в качестве загрузчика ядра, подгружаемого родным boot ROM многих сетвых карт. Для этого, правда понадобится DHCPD версии 3.0. Подробности на http://www.geocrawler.com/lists/3/SourceForge/5299/125/6129709/ (Пользоваться этим способом не рекомендую. Если уж у вас есть PXE-карточка, то лучше обратитесь к следующему разделу)

Эти образы состоят из:

драйвера сетевой карты,
в качестве которого используется обычный пакетный драйвер, который либо поставляется вместе с сетевой картой, либо берется из общедоступного архива пакетных драйверов. Если вы пользовались каким-либо freeware TCP/IP софтом под DOS (pine, NCSA telnet, doslynx, tnfs) то, вероятно знаете что это такое. В состав etherboot входит и набор собственных драйверов, для более новых сетевых карт, для которых уже нет DOS-овских пакетных драйверов.
Клиента BOOTP и TFTP
интерпретатора простого командного языка,
позволяющего сделать кое-какие загрузочные меню. (Зачем - не понимаю. Проще сразу грузить ядро и разбираться с выбором пользователя уже потом.
Создав образ BootROM c помощью этого пакета, вы получите его сразу в двух форматах - в виде COM-файла, который можно запустить из DOS, и в одном из стандартных форматов, понимаемым софтом, управляющим программатором.

Образ в виде COM-файла можно записать на дискетку, на которой есть либо три загрузочных файла DOS либо загрузчик syslinux (ldlinux.sys) который используется для загрузочных дискет всеми современными дистрибутивами. Последний вариант проще - не надо искать где взять DOS, способную осистемить дискету, все есть в дистрибутиве Linux. Форматируете дискету как DOS-овскую файловую систему с помощью mformat или superformat, кладете туда COM-файл и текстовый файл SYSLINUX.CFG, содержащий следующие строки:

TIMEOUT 0
PROMPT 0
LABEL 3COM
  KERNEL 3COM.COM
Поскольку COM-файлы маленькие - они рассчитаны на прошивку в ROM размером не более 16К, вы можете написать на одну дискетку загрузочные образы для всех имеющихся у вас типов сетевых карт и чуточку более сложный SYSLINIX.CFG:
DEFAULT 3COM
TIMEOUT 30
PROMPT 1
LABEL ANY
  KERNEL ALL.COM
LABEL NE
  KERNEL NE.COM
LABEL 3COM
  KERNEL 3C509.COM
Теперь нам нужно сконфигурировать tftp-директорию на сервере. В данном случае для каждого терминала (вернее типа терминалов) там должен лежать один единственный файл, содержащий ядро Linux. Загрузчик входящий в состав netboot или etherboot не умеет грузить обычный vmlinuz, поэтому скомпилированное ядро нужно обработать програмкой mknbi-linux, входящей в netboot/etherboot, заодно в образ попадут параметры командной строки ядра и initrd, если он нужен.

Кстати, там есть и mknbi-dos, так что если вы хотите использовать в качестве терминала слабенькую 286 или 386 машину, то не все потеряно. Конечно, X-ов там не будет, но графический терминал, совместимый с Tektronics вы получите.

Настройка удаленной загрузки через PXE

Настройка удаленной загрузки по PXE в некотором смысле проще. Вам не надо возиться с прошивкой BootROM - можно купить готовую. Вам не надо создавать специальный образ ядра - используется обыкновенный zImage. Платой за это является необходимость прописывания странных слов в dhcpd.conf и возможно, замена tftpd пришедшего с вашим дистрибутивом на взятый с ftp.kernel.org.

Загрузка через PXE выглядит так:

  1. Грузится по tftp файл pxelinux.bin, входящий в пакет syslinux (который можно найти на www.kernel.org, если версия в вашем дистрибутиве слишком старая)
  2. Он грузит по tftp файл конфигурации который должен лежать в pxelinux.cfg/адрес где адрес - IPадрес терминала в виде 16-ричного числа. (если такого не найдено, от адреса последовательно откусываются младшие цифры, и если не найдено даже файла соответствующего старшей цифре то грузится файл default). Файл конфигурации имеет тот же формат, что и на загрузочной дискете с syslinux.

    Вот так, например, выглядит файл конфигурации для терминала steel.

    DEFAULT ee100 root=/dev/nfs nfsroot=192.168.219.1:/var/diskless/steel rw
    LABEL i810
      KERNEL vmlinuz.i810	
    LABEL ee100
      KERNEL vmlinuz.ee100
    
  3. Грузится (опять же по tftp) ядро (и, возможно, initrd) указанный в файле конфигурации.

Рут для X-терминала

Теперь надо разобраться с корневой файловой системой, которая монтируется по NFS.

Если терминалы аппаратно немножко разные (разные видеокарты, например) и требуются некоторые различия в конфигурации, то каждому терминалу потребуется по крайней мере свой XF86Config

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

Те файлы, которые должны быть разными - просто копируются, а потом редактируются по месту.

Минимальный набор файлов, который должен присутствовать на nfs-root

На X-терминале должен быть /sbin/init, ибо как же без него, /bin/sh(не обязательно bash) для того, чтобы выполнять rc-скрипты и X-сервер и используемые ими разделяемые библиотеки и конфигурационные файлы. В принципе, этого может быть уже достаточно, но тогда придется очень тщательно прописывать init-скрипты.

Если для русификации используется Xkb, то нужна еще xkbcomp, используемые ей файлы в /usr/X116/lib и каталог /var/lib/xkb. В /var кроме этого нужен только /var/run.

Если на терминале есть звуковая карта, то понадобится еще аудиосервер (nasd или esd).

Я предпочитаю не усложнять себе жизнь ради экономии пары мегов дискового пространства на сервере, и копирую /bin и /sbin в /var/diskless полностью. А /usr вообще монтирую с сервера. Это, во-первых, избавляет от разбирательства какие файлы нужны X-серверу для работы, а какие нет, а во-вторых позволяет воспользоваться процессором X-терминала для запуска, скажем rdesktop.

Стартап-файлы X-терминала

Полный список файлов в etc моих терминалов выглядит так:
etc
etc/X11
etc/X11/XF86Config
etc/X11/Xserver
etc/X11/dpi
etc/fstab
etc/passwd
etc/rc
etc/nsswitch.conf
etc/resolv.conf
etc/ld.so.conf
etc/inittab
Красным цветом помечены те файлики, которые индивидуальны для каждого терминала.

Файлик dpi хранит физическое разрешение монитора в пикселах на дюйм. Ну люблю я, когда представление X-овых программ о сантиметрах на экране соответствует истине

inittab на терминалах может выглядеть следующим образом:

# /etc/inittab: init(8) configuration.

# The default runlevel.
id:2:initdefault:

# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/rc

l6:6:wait:/sbin/reboot
# What to do in single-user mode.
~~:S:wait:/sbin/sulogin


# What to do when CTRL-ALT-DEL is pressed. Really not needed, becouse
# terminals can be safely power-cycled
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now

# Start X server asking specified host to provide chooser window 
x:2:respawn:/usr/bin/X11/X -dpi `cat /etc/X11/dpi` \
  -indirect some.local.server.my.net >/tmp/xmessages 2>&1
Где /etc/rc ма-аленький shell-скрипт, заменяющий сложную систему init-скриптов на полноценной машине. Например, вот такой:
#!/bin/sh
rm /etc/mtab
echo "Mounting /proc filesystem"
mount /proc
echo "Mounting remote filesystems"

mount /usr 
dmesg > /tmp/kernel-messages
В fstab при этом должно быть написано:
# /etc/fstab: static file system information.
192.168.219.1:/var/diskless/common   /   nfs   defaults 
192.168.219.1:/usr       /usr            nfs   ro,defaults    
proc            /proc         proc   defaults                  

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

Другие ресурсы по этой теме

  1. A new use for old and outdated PCs by Rich Kaszeta
  2. Diskless-HOWTO