Конфигурационные файлы
Проектирование свойств системы
Операционная система, позволяющая задействовать все возможности компьютера, резко отличается от специализированного программного обеспечения огромным числом так называемых "вариантов использования" (use cases) и обширнейшими возможностями тонкой настройки для решения задач конкретного пользователя наилучшим способом. Достаточно сравнить какую-нибудь игровую приставку (например, PlayStation2) под управлением собственной операционной системы и ее же под управлением Linux. Вычислительная и мультимедийная мощность такого компьютера весьма высока (известно, что именно компьютерные игры определяют сейчас ресурсопотребление персонального компьютера). Однако способы управления одной и другой системами настолько различны, что неподготовленный человек просто теряется при виде возможностей Linux: на какие кнопки нажимать? А кнопок-то и нет...
Можно попытаться описать операционную систему как большой и сложный универсальный инструмент для решения любых задач. Предполагается, что пользователь, прочтя документацию, в которой описывается, как работает система и как применять ее в различных ситуациях, сможет решать и свои задачи. Правда, для этого ему придется прочесть большую часть документации по системе (в том числе и технической) и перепрограммировать некоторые части системы сообразно своим нуждам. На такой подвиг способны немногие, времени это займет немало, да и вероятность ошибки (которая тем выше, чем сложнее средства управления системой) при таком подходе недопустимо велика. Сами утилиты или службы Linux, каждую из которых можно "окинуть взором" и понять, что она умеет и чего в ней не хватает, разрабатываются именно теми из пользователей, у которых хватает времени, знаний и навыков на такое полное освоение (см. лекции 17 и 18). Вывод: пользователь – не разработчик, ему все-таки важнее быстро и качественно решить задачу, чем долго совершенствовать инструмент решения.
Можно пойти обратным путем: попытаться предусмотреть все основные способы использования операционной системы на всех основных пользовательских задачах, и на каждый такой способ создать (запрограммировать) отдельную часть, управляемую "кнопкой" или утилитой. Эту часть обычно называют "решением" (solution), и в документации пишут, что должно быть "на входе" системы, и что получается "на выходе" после применения решения. Если пользователь не умеет сам поставить задачу, или делает это в неопределенной форме ("хочу, чтобы был текст", "хочу, чтобы играла музыка"), этот способ работает превосходно: та же игровая приставка – это отличное решение крайне неопределенной задачи "хочу без толку потратить время". Однако стоит пользователю захотеть чего-то конкретного, начинаются трудности. Трудности могут быстро стать непреодолимыми, как только для этого "конкретного" не окажется готового решения: внутренняя структура систем, ориентированных на "решения", столь сложна и столь плохо документирована, что сделать что-либо вручную, скорее всего, не удастся. Вывод: пользователь, понимающий суть собственных задач, – не "клиент", он должен иметь возможность быстро и качественно решать задачи самостоятельно, а не выбирать из готовых "решений" то, которое нанесет меньше вреда.
Что же нужно идеальному – достаточно подготовленному, чтобы действовать самостоятельно, и достаточно занятому, чтобы не переделывать систему – пользователю? По-видимому, механизм, с помощью которого можно сформулировать и придать операционной системе все требуемые свойства, имея возможность описывать решение задачи, по крайней мере, на том же уровне конкретности, на котором было поставлено ее условие. Большая часть других, не нужных для решения собственных задач пользователя, свойств должны быть "стандартными" и не требовать его вмешательства.
Профиль системы
Так возникает идея разделить систему на два подмножества: профиль и реализацию. Все, что не потребует вмешательства пользователя, необходимо запрограммировать и применять в готовом виде в качестве составных частей реализации. В Linux этому соответствуют программы и подпрограммы: ядро, модули, демоны, утилиты; используемые ими библиотеки и прочие разделяемые файлы и т. п. Реализация – это монолитная, неизменяемая часть системы, устроенная по типу "решений" основных задач, только задачи эти, как правило, не совпадают с задачами пользователей, а только помогают решать их, то есть служат как бы строительным материалом, деталями и инструментами сборки "больших" решений.
Все, чего может коснуться рука человека, из реализации переносится в профиль системы. Профиль задает поведение реализации на данных пользователя и должен быть устроен так, чтобы пользователь мог его беспрепятственно изменять, если понадобится. С одной стороны, это может быть вариант "высокоуровневого программирования", когда пользователь описывает алгоритм решения и структуру используемых данных на некотором высокоуровневом языке (специализированном или общем, например, на shell). С другой стороны, задание свойств может превращаться в указание модификаторов поведения, когда пользователь просто перечисляет необходимые параметры работы программы, которые изменяют ее заранее известную, но достаточно общую функциональность.
Таким образом система полностью описывается в виде набора необходимых компонентов реализации, активизированных (запущенных) с определенными профилями, вкупе с текущим состоянием каждого компонента. Поскольку компонент реализации не может изменяться, а его текущее состояние, наоборот, меняется постоянно и не управляется пользователем, можно считать, что систему задает ее профиль. Это означает, что для того, чтобы продублировать работу системы на другом компьютере, достаточно установить там стандартную реализацию и перенести профиль (обычно занимающий несравненно меньше места) и пользовательское наполнение. Наполнение (файлы пользователей, содержимое www-страниц и т. п.) может занимать много места, но оно входит в понятие "задача пользователя", поэтому забывать о нем нельзя.
Профиль. Изменяемая часть системы, определяющая ее поведение во время работы.
Как проще всего создать профиль если не всей системы, то хотя бы ее компонента (программы)? Один из вариантов такой: снабдить программу функцией "сохранить настройки", тогда можно будет эту программу запустить, любым способом добиться ее работоспособности, а после зафиксировать достигнутое состояние с помощью этой функции. При этом поначалу совершенно неважно, как выглядят эти настройки: программа-то заработала, значит, цель достигнута (проницательный Мефодий немедленно заметил, что название функции "сохранить настройки" как-то подозрительно похоже на название кнопки ).
Зачастую для того, чтобы собрать более или менее отвечающий требованиям пользователя профиль, задействуется больше ресурсов, чем для работы самой программы. Утилита автоматической настройки выглядит эдаким шаманом, или кудесником, который, задав всего несколько вопросов человеку, непонятным образом приводит систему в работоспособное состояние. Такая подсистема и называется "wizard", причем в русском переводе ее отчего-то стесняются называть "шаманом", а величают уважительно "мастером".
Вот пример поведения обычного шамана-настройщика (пакет wvdial, заведующий модемным подключением к Internet):
[root@localhost root]# wvdialconf Usage: wvdialconf (create/update a wvdial.conf file automatically) [root@localhost root]# wvdialconf .wvdialrc Scanning your serial ports for a modem. Port Scan<*1>: Scanning ttyS4 first, /dev/modem is a link to it. . . . ttyS4<*1>: Modem Identifier: ATI -- Xircom CardBus 10/100+Modem 56 (Revision 2.40) . . . ttyS4<*1>: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 -- OK ircomm0<*1>: ATQ0 V1 E1 -- failed at 9600 and 19200 baud. . . . ircomm9<*1>: ATQ0 V1 E1 -- failed at 9600 and 19200 baud. Port Scan<*1>: LT0 . . . ttyS0<*1>: ATQ0 V1 E1 -- and failed too at 115200, giving up. . . . ttyS1<*1>: ATQ0 V1 E1 -- and failed too at 115200, giving up. Port Scan<*1>: S2 S3 S5 S6 S7 S8 S10 . . . Port Scan<*1>: USB11 USB12 USB13 USB14 USB15 Found a modem on /dev/ttyS4, using link /dev/modem in config. Modem configuration written to .wvdialrc. ttyS4: Speed 115200; init "ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0"Пример 12.1. Кудесник wvdialconf
Ни о каких наводящих вопросах даже речи не зашло! Программа проверила более полусотни устройств, не модемы ли они, но нашла всего одно – /dev/ttyS4. Его настройки определились автоматически (и хорошо, потому что Мефодий не знает, что такое " ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 "). Профиль (а wvdialrc создает именно профиль ) лежит теперь в файле .wvdialrc, так что программа wvdial начнет работать с модемом, нуждаясь только в пользовательских настройках ( входное имя, пароль и т. п.).
Яркий пример того, как элементы реализации связываются профилем в единую подсистему для решения определенной задачи – командная строка и сценарии командного интерпретатора. Здесь утилиты играют роль элементов реализации, их параметры – роль "настроечной" части профиля, а способ их объединения в сценарий – "программируемой" части профиля. Скажем, команда find /etc -type f 2> /dev/null | xargs -n1 file | cut -d: -f2 | sort | uniq -c задействует шесть утилит системы: командную оболочку, find, xargs, cut, sort и uniq, причем четыре из них запускаются с измененным профилем 1Эта команда определяет, файлы какого типа и в каком количестве содержатся в каталоге /etc .. Командная оболочка дополнительно программируется для создания конвейера между командами.