Рейтинговые книги
Читем онлайн Искусство программирования для Unix - Эрик Реймонд

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 50 51 52 53 54 55 56 57 58 ... 161

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

7.2.3. Упаковщики

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

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

7.2.3.1. Учебный пример: сценарии резервного копирования

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

tar -czvf /dev/st0 "[email protected]"

Приведенная выше команда является упаковщиком для утилиты архивирования tar(1), который предоставляет один фиксированный аргумент (накопитель на магнитных лентах /dev/st0) и передает tar все остальные аргументы, указанные пользователем ("[email protected]")[69].

7.2.4. Оболочки безопасности и цепи Бернштайна

Один из распространенных способов использования сценариев упаковщиков — это создание оболочек безопасности (security wrappers). Сценарий безопасности может вызывать программу-диспетчер (gatekeeper) для проверки мандата (credential), а затем в зависимости от значения, возвращенного программой-диспетчером, запустить другую программу.

Образование цепей Бернштайна (Bernstein chaining) представляет собой специализированную методику применения оболочек безопасности, впервые разработанную Даниелем Бернштайном (Daniel J. Bernstein), который задействовал ее в многих своих пакетах. (Подобная модель наблюдается в таких командах, как nohup(1) и su(1), но условность выполнения отсутствует.) Концептуально цепи Бернштайна подобны конвейерам, но, в отличие от последних, в цепях каждый успешный этап заменяет предыдущий, а не выполняется одновременно с ним.

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

Пакет Бернштайна rblsmtpd является принципиальным примером. Он служит для поиска узла в антиспамной DNS-зоне системы предотвращения некорректного использования почты (Mail Abuse Prevention System). Свои функции данный пакет выполняет путем отправки DNS-запроса на IP-адрес, переданный ему как значение переменной среды TCPREMOTEIP. Если запрос оказался успешным, то rblsmtpd запускает собственный SMTP-сервер, который отклоняет почту. В противном случае предполагается, что оставшиеся аргументы командной строки вводят в действие агент доставки почты, который поддерживает протокол SMTP, и передаются для запуска ехес(2).

Еще один пример можно встретить в пакете qmail Бернштайна. Пакет содержит программу, которая называется condredirect. Первым параметром является адрес электронной почты, остальные параметры — программа-диспетчер и аргументы, condredirect разветвляется и запускает программу-диспетчер со своими аргументами. В случае успешного завершения программой-диспетчером своей работы, condredirect перенаправляет почтовое сообщение, ожидающее в stdin, на указанный адрес электронной почты. В этом случае, в противоположность rblsmtpd, решение принимается дочерним процессом. Этот случай несколько больше походит на классический вызов с созданием подоболочки.

Более сложным примером является POP3-сервер qmail. Он состоит из трех программ: qmail-popup, checkpassword и qmail-pop3d. Программа Checkpassword взята из отдельного пакета, остроумно названного checkpassword, и, естественно, предназначена для проверки паролей. В протоколе POP3 предусмотрен этап аутентификации и этап работы с почтовым ящиком. Перейдя к этапу работы с почтовым ящиком, пользователь не имеет возможности вернуться к этапу аутентификации. Это идеальное применение для цепей Бернштайна.

Первым параметром программы qmail-popup является имя узла для использования в POP3-приглашениях. Остальные ее параметры, после того как имя пользователя POP3 и пароль были доставлены, разделяются и передаются ехес(2). Если данная программа возвращает отказ, то пароль, вероятнее всего, не верный, qmail-popup сообщает об этом и ожидает ввода другого пароля. В противном случае предполагается, что программа окончила POP3-диалог, поэтому qmail-popup завершает работу.

Ожидается, что программа, указанная в командной строке qmail-popup, считывает 3 строки, ограниченные символом NULL, из дескриптора файла 3[70]: имя пользователя, пароль и ответ на криптографический запрос, если он есть. В настоящее время такой программой является checkpassword, которая принимает в качестве параметров имя qmail-pop3d и его параметры. Программа checkpassword завершается с ошибкой в том случае, если был введен несоответствующий пароль. В противном случае она принимает пользовательские идентификаторы uid и gid, домашний каталог пользователя и выполняет оставшуюся часть командной строки от имени данного пользователя.

Создание цепей Бернштайна полезно в ситуациях, когда приложение требует setuid- или setgid-привилегий для инициализации соединения или для получения какого-либо мандата, а затем понижает эти привилегии, чтобы можно было использовать последующий вовсе не обязательно "благонадежный" код. Поскольку дочерняя программа была запущена с помощью вызова exec, она не может установить свой действительный идентификатор пользователя равным идентификатору администратора. Такая методика является более гибкой, чем использование одного процесса, поскольку можно модифицировать поведение системы путем внедрения в цепочку другой программы.

Например, программа rblsmtpd (упомянутая выше) может быть вставлена в цепь Бернштайна между программой tcpserver (из пакета ucspi-tcp) и реальным SMTP-сервером, обычно qmail-smtpd. В то же время она также работает с inetd(8) и sendmail -bs.

7.2.5. Подчиненные процессы

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

Вызов popen(3) в Unix способен устанавливать либо канал ввода, либо канал вывода для подоболочки, но не оба канала для подчиненного процесса — видимо, для поощрения более простого программирования. И фактически интерактивный обмен данными между главным и подчиненным процессом является настолько сложным, что обычно используется только в ситуациях, когда (а) связанный протокол является крайне примитивным, либо (b) подчиненный процесс спроектирован для обмена данными по протоколу прикладного уровня в соответствии с принципами, которые описывались в главе 5. Данная проблема и способы ее разрешения рассматриваются в главе 8.

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

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

1 ... 50 51 52 53 54 55 56 57 58 ... 161
На этой странице вы можете бесплатно читать книгу Искусство программирования для Unix - Эрик Реймонд бесплатно.
Похожие на Искусство программирования для Unix - Эрик Реймонд книги

Оставить комментарий