Рассел Сейдж. Приемы профессиональной работы в unix перевод "Tricks of the unix masters" by Russel G

Вид материалаДокументы

Содержание


Формат вызова
Пример вызова
Текст программы
Переменные среды выполнения
Подобный материал:
1   ...   23   24   25   26   27   28   29   30   ...   45

мандную подстановку для получения списка слов, образованного из перво-

го поля команды who. Каждое зарегистрированное имя сравнивается со

списком предварительно определенных имен, за которыми мы наблюдаем.

Обратите внимание, что внешний цикл while сам себя помещает на выпол-

нение в фоновом режиме. Это означает, что вам нет необходимости вво-

дить это с клавиатуры.


Строки 29-33 управляют внутренним циклом, который проходит по

именам, содержащимся в нашем основном списке, и сравнивает их с имена-

ми, полученными от команды who. Когда имя, полученное от команды who

(имя зарегистрированного пользователя) совпадает с именем в нашем

списке, на экран выводится сообщение о том, что данное лицо зарегист-

рировалось.


После того как все имена проверены, командный файл watch приоста-

навливается на 10 секунд (строка 35). Когда он снова пробуждается, вы-

полняется следующая итерация вечного цикла while. Все зарегистрирован-

ные имена вновь сравниваются со списком. Это будет продолжаться до тех

пор, пока вы не прекратите выполнение watch. Как отмечалось ранее,

watch можно легко уничтожить с помощью опции -k или же вручную путем

ввода команды "kill `cat $HOME/.watch`".


МОДИФИКАЦИИ


Watch выполняет довольно мало работы и использует какую-то часть

времени центрального процессора. Вы можете поэкспериментировать с уве-

личением интервала паузы (sleep), чтобы watch запускался не так часто.

Большинство пользователей находятся в системе по крайней мере минуту,

поэтому вы можете попробовать значение sleep(60). Вы по-прежнему може-

те обнаружить регистрацию всех интересующих вас пользователей?


------------------------------------------------------------------------


ИМЯ: whox

------------------------------------------------------------------------


whox Команда who с дополнительными возможностями


НАЗНАЧЕНИЕ


Предоставляет много дополнений к выходу команды who и позволяет

применять данные who для других приложений.


ФОРМАТ ВЫЗОВА


whox [-f] [-n] [-m] [-p] [-t] [-w] [-x]


где

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


-n сортирует выход команды who по именам


-m передает почту каждому пользователю


-p выводит информацию о паролях пользователей


-t сортирует выход команды who по времени (умолчание)


-w показывает возможность записи на зарегистрированные

терминальные устройства


-x дополнительная информация о регистрационном

каталоге и паролях


ПРИМЕР ВЫЗОВА


whox -w


Показывает права доступа к файлу (возможность чтения и записи)

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


ТЕКСТ ПРОГРАММЫ


1 :

2 # @(#) whox v1.0 Who with expanded options Author: Russ Sage

2а Команда who с дополнительными опциями


4 XTRA="no"

5 SORT="sort -b +2"

6 DISPLAY="norm"


8 CUT1="cut -d' ' -f1"

9 CUT5="cut -d: -f5"

10 CUT6="cut -d: -f6"


12 for ARG in $@

13 do

14 case $ARG in

15 -f) DISPLAY="finger"

16 COMMAND="finger \$NAME; echo";;

17 -n) SORT="sort";;

18 -m) DISPLAY="mail";;

19 -p) DISPLAY="pass"

20 COMMAND="grep \"\$NAME:\" /etc/passwd";;

21 -t) SORT="sort -b +2";;

22 -w) DISPLAY="write";;

23 -x) XTRA="yes";;

24 *) echo "whox: invalid option $ARG"

25 echo "usage: whox [-f] [-n] [-m] [-p] [-t] [-w] [-x]"

26 echo " -f finger users"

27 echo " -n sort by name"

28 echo " -m mail to each user"

29 echo " -p password info on users"

30 echo " -t sort by time (default)"

31 echo " -w show writeability of devices"

32 echo " -x extra home dir and gcos info"

33 exit 1;;

34 esac

35 done


37 if [ "$XTRA" = "yes" ]

38 then EXTRA="| while read LINE; do \

39 NAME=\`echo \$LINE | cut -d' ' -f1\`;\

40 ENTRY=\`grep \"\$NAME:\" /etc/passwd\`;\

41 echo \"\$LINE\t\`echo \$ENTRY|\$CUT6\`\t\`echo \$ENTRY|\$CUT5\`

\";done"

42 else EXTRA=""

43 fi


45 case $DISPLAY in

46 norm) eval "who | $SORT $EXTRA";;

47 finger|pass) for NAME in `who | $SORT | cut -d' ' -f1`

48 do

49 eval $COMMAND

50 done;;

51 mail) who | cut -d' ' -f1 | while read NAME

52 do

53 echo "mail to $NAME (y/n): \c"

54 KB=`line < /dev/tty`

55 if [ "$KB" = "y" ]

56 then mail $NAME < /dev/tty

57 fi

58 done;;

59 write) ls -il `who | sed "s/...........\(.......\).*

/\/dev\/\1/"`;;

60 esac


ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ


ARG Аргументы командной строки


COMMAND Команда, которую следует выполнить при использовании

команды who со списком имен


CUT1 Содержит синтаксис для выделения первого поля строки


CUT5 Содержит синтаксис для выделения пятого поля строки


CUT6 Содержит синтаксис для выделения шестого поля строки


DISPLAY Определяет, какой режим отображения использовать


ENTRY Запись в файле паролей для указанного пользователя


EXTRA Данная переменная содержит полный цикл shell-команд,

хранимых в виде одной строки


KB Входные данные от клавиатуры, полученные в цикле


NAME Содержит в каждый данный момент времени одно имя из

списка всех регистрационных имен


SORT Содержит выполняемый тип сортировки


XTRA Флаг, определяющий, должны ли быть активизированы

дополнительные опции


ОПИСАНИЕ


ЗАЧЕМ НАМ НУЖЕН КОМАНДНЫЙ ФАЙЛ whox?


Как уже ранее обсуждалось в других местах этой книги, система

UNIX стремится обеспечить минимум возможностей в любой заданной об-

ласти интересов. Это не значит, что UNIX плохая система. Наоборот, она

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

очень часто мы хотим сделать немного больше того, что нам предоставля-

ет базовая система.


Получение информации о том, кто использует машину, может быть

применено для многих целей. Основная информация предоставляется коман-

дой who, но она может быть не в том виде, который вам нужен для конк-

ретной цели. В любом случае, все, что делает команда who - дает вам

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

некоторый способ автоматического доступа к этому списку зарегистриро-

ванных имен и использования его для наблюдения, общения или других це-

лей.


ЧТО ДЕЛАЕТ whox?


Whox - это инструментальное средство, расширяющее возможности ко-

манды who. Оно не только может переупорядочить в соответствии с вашими

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

каждого зарегистрированного пользователя, передать почтовое сообщение

любому зарегистрированному пользователю, просмотреть парольную инфор-

мацию всех зарегистрированных пользователей и показать информацию,

взятую из индексного дескриптора файла, соответствующего терминальному

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


По умолчанию действие whox заключается в печати обычного выхода

команды who в порядке времени регистрации от более раннего до более

позднего. Опция -x добавляет к этому списку информацию из регистраци-

онного каталога и поле комментария из файла паролей. Если эта опция -x

кажется вам знакомой, то так оно и есть, поскольку это то же самое,

что и команда info, представленная ранее.


Whox имеет четыре различных режима отображения. Первый это формат

обычного выхода команды who. Whox позволяет вам сортировать его двумя

разными способами. Опция -n сортирует по именам, а опция -t (которую

не нужно указывать, поскольку она используется по умолчанию) сортирует

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


Второй режим отображения состоит из режимов указания и паролей,

включаемых опциями -f и -p. Основное отличие от первого режима заклю-

чается в том, что выход команды who не печатается, а используется для

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

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

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

тому мы можем иметь общий цикл, использующий особым образом перемен-

ные. (Команда finger имеется в системе Berkeley UNIX и в некоторых

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

яснить, что выводится на экран по этой команде.)


Третий режим - это почтовый режим, в котором вы имеете возмож-

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

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

это. Больше от вас ничего не требуется. Этот режим выбирает опция -m.


Последний режим - это режим записи на терминал. Режим записи (оп-

ция -w) показывает информацию о файле терминала для каждого зарегист-

рированного терминального устройства. Эта информация полезна, если вы

хотите использовать команду UNIX'а write. Посмотрев на права доступа к

файлу устройства пользователя, вы можете сказать, имеется ли у вас

возможность записать текст на его экран. Некоторые пользователи, кото-

рые не хотят, чтобы их прерывали, закрывают право записи на их терми-

нал, выполняя команду "mesg n". Вопрос о праве записи касается любого

способа посылки текста в другой файл, а не только с использованием ко-

манды write. Право записи также защищает от таких вещей, как "echo

hello > /dev/tty00".


Способ обработки аргументов в командной строке приводит к

несколько странному обращению с данной утилитой. Каждый аргумент про-

веряется по порядку и устанавливает внутренние флаги. Если вы постави-

те в конце списка какую-либо опцию, меняющую флаг, установленный одной

из предыдущих опций, то вы получите действие последней опции. (Другими

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

изучить это - внимательно прочитать исходный текст командного файла и

выполнить несколько экспериментов с различными наборами опций.)


Например, мы хотим указать каждого пользователя. Мы используем

опцию -f. Опция -f устанавливает в качестве режима отображения режим

указания. Если мы поместим опцию -w справа от -f, как в команде "whox

-f -w", то установится режим записи на терминал. Команда whox будет

считать, что вы вообще не указывали опцию -f. На самом деле это не

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

ция. Случайно смешивая их в одной команде, вы можете получить несколь-

ко странные выходные данные.


ПРИМЕРЫ


1. $ sh -x whox -x


Запуск интерпретатора shell в отладочном режиме выполнения, пода-

ча ему командного файла whox в качестве данных, передача опции -x для

whox. Отладочный режим показывает присвоение значений переменным и вы-

зовы команд. (Мы видели это ранее.)


2. $ whox -n -x


Печать выходных данных команды who, отсортированных по именам и

выдача дополнительных данных.


ПОЯСНЕНИЯ


В строках 4-10 выполняется инициализация переменных. Переменная

XTRA устанавливается в значение "no". Эта переменная используется для

построения командной строки при использовании опции -x. Установка XTRA

в значение "no" означает, что действие по умолчанию - не получать до-

полнительную информацию.


Умолчанием для сортировки является сортировка по времени регист-

рации. Это указывается сортировкой по колонке, стоящей после второй

(+2) и игнорированием ведущих пробелов (-b) в строке 5. Такой же син-

таксис применен ниже с опцией -t. Опция -t здесь лишняя, но она делает

более понятной командную строку. Опция -n также изменяет синтаксис

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

списком имен.


Строка 6 инициализирует обычный режим отображения, которым явля-

ется печать стандартного выхода команды who. Если присутствуют другие

опции, соответственно изменяется переменная DISPLAY.


Строки 8,9 и 10 инициализируют некоторые переменные для команд

вырезки, что делает более компактными последующие команды. Если неко-

торые командные строки оказываются слишком длинными, вы можете по-

местить нужный текст в переменные и подставить их при необходимости.

Переменная CUT1 выглядит так, как будто она должна работать, но она не

работает в моей системе. Почему она не работает, объясняется ниже.

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

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

жете убрать ее, если хотите.


Строки 12-35 обрабатывают аргументы командной строки. Цикл for

подставляет в переменную ARG каждый параметр по порядку и выполняет

оператор case по значению ARG.


Если опцией является -f, строка 15 изменяет переменную DISPLAY в

режим указания. Она также подставляет в переменную COMMAND команду

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

нужно иметь переменную, содержащую команду, заключается в том, что

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

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

ми, мы помещаем эти задачи в переменную и выполняем эту переменную.

Это значительно сокращает общее количество текста, хотя привносит не-

которую дополнительную работу. Обратите внимание в строке 16, что сим-

вол $ экранирован в операторе присваивания. Это необходимо, ведь мы

хотим, чтобы переменная COMMAND содержала символьную строку $NAME, а

не значение, которое имеет переменная NAME после присваивания. Значе-

ние NAME расшифровывается в цикле во время его выполнения.


Строка 17 обрабатывает опцию -n. Все, что здесь требуется - изме-

нить способ сортировки выхода команды who, чтобы отразить порядок по

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

команда sort сортирует по умолчанию по первой колонке, то используется

команда sort без опций.


Строка 18 обрабатывает опцию -m для передачи почтовых сообщений.

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

для этого, находится в цикле mail, и не требуется инициализировать ни-

какие переменные.


Строки 19 и 20 справляются с опцией -p. Опция паролей изменяет

режим отображения на парольный режим и устанавливает команду, которую

мы вызываем, находясь в общем цикле. В данном случае мы используем ко-

манду grep для получения парольной записи из файла /etc/passwd. Обра-

тите внимание, что в строке 20 мы используем внутренние двойные кавыч-

ки. Для этого мы вынуждены экранировать их символами обратной косой

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

циального значения особых shell-символов.


Строка 21 управляет опцией -t. Как уже упоминалось ранее, опция

-t в действительности не требуется в данной программе. Поскольку она

является умолчанием, требуемые для нее действия уже были предприняты в

начале программы - была выполнена точно такая же инициализация. Син-

таксис команды sort точно такой же, как и в строке 5.


Строка 22 обрабатывает опцию -w для показа возможности записи в

файлы терминалов. Единственное, что нужно здесь сделать - изменить ре-

жим работы терминала.


Строка 23 управляет опцией -x. Поскольку для получения дополни-

тельной информации требуется довольно сложная инициализация, то мы

только устанавливаем в этом месте флаг XTRA, показывающий, что мы хо-

тим выполнить эту инициализацию позже.


Строка 24 - это улавливатель для обработки ошибок. Символ * соот-

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

сообщение об ошибке и синтаксическая подсказка, и whox завершается.


Строки 37-43 устанавливают переменные, используемые в опции до-

полнительной информации. Строка 37 проверяет, установлена ли перемен-

ная XTRA в состояние "yes", что имеет место только тогда, когда в ко-

мандной строке имелась опция -x. Если это так, то в переменную EXTRA

заносится много всяких вещей, которые мы рассмотрим позже. В противном

случае в переменную EXTRA заносится пустая строка, так что она никак

не проявляется на стадии фактического выполнения.


Переменная EXTRA здесь очень важна и на самом деле делает неболь-

шой фокус. Мы собираемся поместить в переменную некоторый код, требуе-

мый для обработки опции -x. Поскольку дополнительная информация, кото-

рую мы хотим получить, требует предварительно некоторой обработки, то

мы помещаем в переменную некоторый командный текст. Как только эта пе-

ременная начинает выполняться, выполняется и этот командный текст. Это

похоже на макрокоманду, только ее текст находится фактически в испол-

няемой программе.


Строки 38-41 вставлены внутрь переменной EXTRA. Это сделано путем

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

которые должны быть частью данных в этой переменной, должны быть экра-

нированы символами обратной косой черты. В строке 38 в переменную

EXTRA заносится символ конвейера (|) и начало цикла while. В конце

строки 38 имеется символ косой черты, указывающий интерпретатору

shell, что присваивание продолжается после символа конца строки (возв-

рата каретки или перевода строки).


Строка 39 присваивает переменной NAME значение поля, вырезанного

из данных, читаемых в цикле while. Напомним, что весь данный оператор

помещается внутрь переменной EXTRA. Когда я выше упоминал, что в стро-

ке с переменной CUT1 есть проблемы, то как одно из таких проблемных

мест я имел в виду именно это. Когда я попытался использовать перемен-

ную CUT1 в этом операторе вместо указания команды cut, shell не смог

правильно распознать этот оператор. Одинарные кавычки, отмечающие сим-

вол-разделитель для вырезки, не были распознаны. В результате команда

cut считала, что символом-разделителем является символ ' и после этого

аварийно завершалась, поскольку второй символ ' представлял собой не-

допустимое описание списка для опции -f. Строка с опцией -f шла позже,

но команда cut этого никогда не узнавала, поскольку аварийно заверша-

лась до этого. Когда я заменил переменную CUT1 просто командой cut,

эта проблема исчезла.


Давайте рассмотрим, как я отлаживал эту часть. Я использовал

shell с опцией -x, поэтому я мог следить за тем, что происходит. Как

вы можете видеть, когда переменная CUT1 была инициализирована, одинар-

ные кавычки находились все еще в операторе, но когда выполнялась

настоящая команда cut, одинарные кавычки уходили при синтаксическом

расширении. Для генерации такого списка данных я выполнил следующий

вызов: sh -x whox -x. Вот что я увидел:


XTRA=no

SORT=sort -b +2

DISPLAY=norm

CUT1=cut -d' ' -f1 <- Одинарные кавычки все еще здесь.

Основная проблема.

CUT5=cut -d: -f5

CUT6=cut -d: -f6

XTRA=yes

+ who

+ read LINE

+ sort -b +2

+ echo russ console Jun 20 14:11

+ cut -d -f1 <- Теперь выполняется правильно.

Кавычек нет.


Это сокращенная распечатка. Она показывает, что когда выполнялась

команда cut, она не имела одинарных кавычек. Когда же запускалась пе-

ременная CUT1, она имела одинарные кавычки. Я не мог представить, как

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

cut обратно на это место. Может быть какой-нибудь молодой растущий