Perl для системного администрирования

       

Finger простая служба каталогов



Finger: простая служба каталогов

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

Finger был одной из первых широко используемых служб каталогов. Когда-то очень давно при необходимости выяснить адрес электронной почты пользователя на другом узле или даже на вашем собственном лучшим решением было применение команды finger. Команда finger harry@hogwarts.edu сообщала адрес электронной почты Гарри, будь он harry, hpotter или даже что-то менее очевидное (правда, эта команда выводила список всех остальных учащихся школы с именем Гарри). И
хотя finger применяется до сих пор, популярность команды со временем уменьшилась, т. к. вошли в обиход домашние страницы и свободное получение информации о пользователе стало делом проблематичным.

Использование протокола Finger из Perl - еще один хороший пример правила TMTOWTDI. Когда я первый раз искал на CPAN хоть что-то, выполняющее операции с Finger, мне не удалось найти ни одного такого модуля. Сейчас-то там можно натолкнуться на модуль Net: : Finger Дениса Тейлора (Dennis Taylor), который появился спустя примерно шесть месяцев после моего первого посещения. Скоро вы с ним познакомитесь, а пока предположим, что его не существует, и не упустим
случая выяснить, как применять более общий модуль, позволяющий «связываться» по специфическому протоколу.

Протокол Finger - это очень простой текстовый протокол на базе TCP/IP. В соответствии с определением в RFC1288, он ожидает стандартное TCP-соединение на порту 79. После установки соединения клиент передает простую строку, завершающуюся последовательностью CRLF. В этой строке запрашивается информация либо о конкретном пользователе, либо обо всех пользователях на машине, если строка пустая. Сервер отвечает на запрос и закрывает соединение после передачи потока данных. Можно увидеть, как это происходит, если подсоединиться к порту Finger на удаленной машине напрямую при помощи telnet:

$ telnet kantine.diku.dk 79

Trying 192.38.109.142 . . .

Connected to kantine.diku.dk.

Escape character is '"]'.

cola<CR><LF>

Login: cola Name: RHS Linux User

Directory: /home/cola Shell: /bin/noshell

Never logged in.

No mail.

Plan:



Current state of the coke machine at DIKU

This file is updated every 5 seconds

At the moment, it's necessary to use correct change.

This has been the case the last 19 hours and 17 minutes

Column 1 is currently «empty*.

It's been 14 hours and 59 minutes since it became empty.

31 items were sold from this column before it became empty. Column 2 contains some cokes.

It's been 2 days, 17 hours, and 43 minutes since it was filled.

Meanwhile, 30 items have been sold from this column. Column 3 contains some cokes.

It's been 2 days, 17 hours, and 41 minutes since it was filled.

Meanwhile, 11 items have been sold from this column. Column 4 contains some cokes.

It's been 5 days, 15 hours, and 28 minutes since it was filled.

Возврат каретки + перевод строки, т. е. символы с ASCII-кодами 13 и!0.

Finger: простая служба каталогов 207

Meanwhile, 26 items have been sold from this column. Column 5 contains some cokes.

It's been 5 days, 15 hours, and 29 minutes since it was filled.

Meanwhile. 18 items have been sold from this column Column 6 contains some coke-lights.

It's been 5 days, 15 hours, and 30 minutes since it «as fillec.

Meanwhile, 16 items have been sold from this column.

Connection closed by foreign host. $

В данном примере мы напрямую соединились с портом Finger, набрали имя пользователя «cola», и сервер вернул требуемую информацию.

Я выбрал этот узел и этого пользователя только затем, чтобы показать, какие чудеса творились на заре появления Интернета. Серверы Finger превратились в службы для задач различного вида. В этом случае кто угодно может посмотреть, заполнен ли автомат газированных напитков, расположенный на факультете компьютерных наук в университете Копенгагена. Примеры странных устройств, подключенных к серверам Finger, можно найти на страницах Беннета Йи (Bennet Yee) в
«Internet Accessible Coke Machines» и «Internet Accessible Machines» H&http://www.cs.ucsd.edu/~bsy/fun.html.

Перенесем сетевое соединение, установленное с помощью telnet, в мир Perl. Средствами Perl можно открыть сокет и общаться через него. Вместо того чтобы применять низкоуровневые команды сокета, воспользуемся модулем Net::Telnet Джея Роджера (Jay Roger) и познакомимся с семейством модулей, работающих с сетевыми соединениями.
Другие модули этого семейства (некоторые из них будут применяться в иных главах) включают Comm.pl Эрика Арнольда (Eric Arnold), Expect.pm Остина Шатца (Austin Schutz) и хорошо известный, но устаревший и непереносимый модуль chat2.pl Рэндала Л. Шварца (Randal L. Schwartz).

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

Вот Net: :Telnet-версия простого Finger-клиента. Эта программа принимает аргумент в виде user@finger_server. Если имя пользователя пропущено, будет возвращен список всех активных пользователей с сервера. Если пропущено имя узла, будет запрашиваться локальный
узел:

use Net::Telnet;

($username.$host) = solit(/W, $ARGV[0]);

Shost = Shost ? Shost : 'localhost';

создаем новое соединение

$cn = new Net::Telnet(Host => $host,

Port => ' finger');

посылаем имя пользователя

unless ($cn->print( "$username")){ tt может быть "/W Susernarre"

$cn->close:

die "Невозможно отправить строку: ".$cn->errmg."\n";

собираем все полученные данные, останавливаясь при завершении соединения while (defined ($ret = Scn^get)1) {

$data .= $ret; }

# закрываем соединение $cn->close;

# отображаем полученные данные print $data;

В RFC1288 определено, что перед именем пользователя, отправляемым на сервер, можно добавить ключ /W для «вывода подробной информации о пользователе», поэтому в программу добавлен комментарий об этом ключе.

Если нужно соединиться, используя помимо Finger другой текстовый протокол на основе TCP, можно применить очень похожую программу. Например, для соединения с сервером Daytime (который выводит локальное время) используется очень похожая программа:

use Net::Telnet;

$host = $ARGV[0] ? $ARGV[0] : 'localhost';

Sen = new Net::Telnet(Host => Shost,

Port => 'daytime');

while (defined ($ret = $cn->get)2) {

Sdata .= $ret; } $cn->close:

print Sdata;

Теперь читатель имеет представление о том, насколько легко создавать типовые сетевые клиенты на основе TCP. Если кто-то уже потратил время и написал модуль, специально созданный для работы с протоколом, все окажется еще проще. В случае с Finger можно воспользоваться модулем Net Finger и заменить все вызовом одной функции:

use Net::Finger;

# fingerO принимает строку useriahost и возвращает полученные дачные print finger($ARGV[0]);

Желая показать все варианты, упомянем о возможности вызвать внешнюю программу (если она существует):

($username,$host) = split('@',$ARGV[0]); $host = $host 7 $host : 'localhost';

местоположение команды finger executable, пользователи MacOS

этим методом воспользоваться не могут

Sfingerex = ($"0 eq "MSWin32") ?

$ENV{'SYSTEMROOT'}."\\System32\\finger" : "/usr/ucb/finger"; # (также может быть и /usr/bin/finger)

print 'Sfingerex ${username}\@${host}'

Вы познакомились с тремя различными способами выполнения Finger-запросов. Третий метод, вероятно, самый неудачный, т. к. в нем порождается другой процесс. Net:. Finger обрабатывает простые Finger-запросы; все остальное может очень хорошо выполнить Net: : Tel net
или родственные ему модули.



Содержание раздела