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

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

Содержание


Переменные среды выполнения
Возможные модификации
2.2. Вывод информации
Формат вызова
Текст программы
Переменные среды выполнения
Подобный материал:
1   2   3   4   5   6   7   8   9   10   ...   45

11 shift;;

12 -s) FORMAT="set"

13 set "1";;

14 *) echo $0: arg error" >&2

15 echo "usage: $0 [-l] [-s] file [file ...]" >&2

16 exit 1;;

17 esac

18 fi

19 done


21 IFS="${IFS}:"


23 for FILE in $@

24 do

25 for DIR in $PATH

26 do

27 case $FORMAT in

28 path) if [ -f $DIR/$FILE ]

29 then echo $DIR/$FILE

30 fi;;

31 ls) if [ -f $DIR/$FILE ]

32 then ls -l $DIR/$FILE

33 fi;;

34 set) echo "\n:::::::::::::::::::"

35 echo "$DIR"

36 echo "::::::::::::::::::::"

37 ls -al $DIR | grep "[ ]*s[ ]*";;

38 esac

39 done

40 done


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


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

DIR Элемент с именем каталога в переменной PATH

FILE Содержит имя каждого файла в командной строке

FORMAT Тип требуемого формата выходных данных

IFS Переменная shell'а, разделитель полей

PATH Переменная shell'а, пути к каталогам исполняемых

модулей


ОПИСАНИЕ


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


В нашей среде интерпретатора shell переменная с именем PATH со-

держит имена каталогов, отделенные друг от друга символами двоеточия

(:). Каждый раз, когда вы вводите команду после приглашения shell'а,

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

ной PATH, смотрит, находится ли введенная вами команда в этом катало-

ге. Если да, то команда выполняется. Если нет, то shell идет в следую-

щий каталог, указываемый переменной PATH, и так далее, пока не будут

проверены все каталоги. Если команда все же не будет найдена, то вы

получите следующее сообщение об ошибке:


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


|

| $ whatchamacallit

| sh: whatchamacallit: not found

|

|


Такой поиск команды осуществляется автоматически, но сама система

не сообщает вам, ГДЕ размещена команда. Нам необходима утилита, кото-

рая ищет и выводит на экран маршрут к указанному файлу. Имея такую

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

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

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

мощных средств. С маршрутом можно также комбинировать команды more,

ls, file и cd системы UNIX. Возможно, вы обнаружите и другие команды

по мере экспериментирования.

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

где-то в мире системы UNIX Systev V. Например, в системе AT&T это ко-

манда where. В системе UNIX Berkeley это команда which (текст на языке

Си-shell'а) или whereis (исполняемая программа). Whereis дает дополни-

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

текстами (в каталоге /usr/src). Увидев, как мы создаем нашу собствен-

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

ния работы с особенностями некоторых других команд и приспособить та-

кие вещи к вашим нуждам.

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

команду path, более простую, чем paths. Вся программа выглядит пример-

но так:


IFS="${IFS}:"

for FILE in $@

do

for DIR in $PATH

do

if [ -f $DIR/$FILE ]

then echo $DIR/$FILE

fi

done

done


Основная идея очень проста. Сперва мы добавляем двоеточие (:) к

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

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

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

символов-разделителей. Символ : дает нам возможность отдельно рассмат-

ривать каждый маршрут, хранимый в переменной PATH.

Вся программа представляет собой два цикла for. Внешний цикл

просматривает имена всех файлов, указанных в командной строке. Внут-

ренний цикл последовательно обходит все каталоги, содержащиеся в пере-

менной PATH. Для каждого файла просматриваются все каталоги с целью

определения, содержит ли этот каталог файл с таким именем. Полное

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

файла (называемых именем каталога и базовым именем соответственно).

Встроенная shell-команда test использована для определения того, су-

ществует ли файл в определенном каталоге.


Если ваша переменная PATH выглядит так:


PATH=.:/bin:/usr/bin:/etc/:$HOME/bin


то внутренний цикл выполнит пять итераций в таком порядке: ., /bin,

/usr/bin, /etc и, наконец, $HOME/bin. Если бы запрос имел вид "path

ll" для поиска утилиты, которую мы создадим позже в этой главе, то ре-

зультат мог бы выглядеть так:


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


|

| /usr/bin/ll

| /usr/russ/bin/ll

|

|


Это значит, что команда ll была найдена в двух местах из вашего набора

маршрутов поиска.


ЧТО ДЕЛАЕТ paths?


Теперь, когда мы знаем, как работает более простая команда path,

мы можем по достоинству оценить дополнительные возможности специальной

команды получения маршрута - команды paths. Paths имеет три основные

функции. Она может выполняться как основная команда path, которую мы

уже рассмотрели, и давать полное маршрутное имя исполняемого модуля.

Она может выдавать маршрут файла в длинном формате. Она также может

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

тором (setuid bit files), которые есть в ваших маршрутных каталогах.

(См. главу 8, где описаны биты setuid.)

Синтаксис вызова немного отличается для разных опций. Для того

чтобы использовать формат выдачи маршрута или формат команды ls, нужна

такая командная строка:


paths [-l] file [file ...]


как, например, в командах "paths ls who date" или "paths -l ll". Для

поиска файлов с установленным пользовательским идентификатором (setuid

files) не нужно указывать имена файлов в командной строке. Вся команда

должна быть такой:


paths -s


Формат setuid и форматы выдачи маршрута являются взаимоисключаю-

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

какие и где находятся файлы, а не отгадывать имена файлов.

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

стандартный вывод выводится сообщение об ошибке и командный файл за-

вершается. Опции устанавливают флаг формата вывода в одно из трех зна-

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

форматом вывода.


ПРИМЕРЫ


1. $ paths ls more who paths

/bin/ls

/usr/bin/more

/bin/who

/usr/russ/bin/paths


Поиск маршрутов к командам ls, more, who, paths. При выводе ука-

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

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

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


2. $ more `paths gettydefs termcap paths`


Если ваша переменная PATH содержит каталог /etc, то этот пример

будет работать. Если нет, то первые два файла не будут найдены. Снача-

ла запускается команда paths, и ее вывод помещается на свое место в

командной строке команды more. Когда запускается команда more, она не

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

работы команды paths команда more принимает вид:


more /etc/gettydefs /etc/termcap /usr/russ/bin/paths


с полными маршрутными именами каждого файла. Этот пример показывает,

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

казу файлов, которые вы хотите увидеть.


3. $ ll `paths ll`


В этом примере в длинном формате выводятся файлы с именами ll,

которые найдет path. (Мы представим нашу версию команды ll несколько

позже в этой же главе.) Как и в предыдущем случае, сначала генериру-

ется информация о маршруте, затем она помещается в командную строку, а

затем запускается команда ll.


4. $ m `paths paths`


В данном примере генерируется маршрутное имя самого командного

файла paths и передается программе m, которая использует команду more

для распечатки. (Командный файл m мы также покажем вам позже.)


ПОЯСНЕНИЯ


В строке 4 инициализируется переменная FORMAT, указывая маршрут-

ный тип поиска. Выполняется действие по умолчанию, точно такое же, как

в командном файле path, который мы рассмотрели ранее.

В строках 6-19 все аргументы командной строки проверяются на кор-

ректность. Критерием того, что аргумент есть опция, является дефис в

роли первого символа. Заметим, что здесь не разрешено использование

синтаксиса "-xyz". Это заставляет вас пользоваться синтаксисом "-x -y

-z". Хотя этот момент может показаться несущественным, на самом деле

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

командного файла при согласии на недостатки жесткого синтаксиса - и

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

нию и отладке и за счет более медленного выполнения. Ваш выбор зависит

от ваших приоритетов, от количества людей, использующих ваше инстру-

ментальное средство, и от того, насколько критична скорость выполне-

ния. Конечно, если скорость критична, вы, вероятно, захотите использо-

вать каким-то образом язык Си. Мы оставляем обработку конкатенирован-

ных опций в качестве упражнения для читателя.

Цикл for проходит по всем позиционным параметрам. Если первым

символом аргумента является "-", то он сверяется со списком допустимых

аргументов с помощью оператора case в строках 9-17. Опция "-l" изменя-

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

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

просто имена файлов в командной строке.

Опция "-s" также изменяет переменную формата. Однако, вместо то-

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

мандную строку и заменяет ее символом "l". Это заставляет цикл for

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

только один параметр. Благодаря такому обращению с командной строкой,

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

определении маршрута, без всяких модификаций. Поскольку после опции s

не ожидается никаких имен файлов, мы больше не хотим рассматривать ко-

мандную строку.

Если использована опция, которая не является ни l, ни s, то этой

опции соответствует звездочка (*) и в стандартный файл ошибок выво-

дится сообщение об ошибке. Затем командный файл завершается.

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

чтобы выяснить, является ли он опцией, и если является, то установить

эту опцию. Поскольку можно использовать только одну опцию за один раз,

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

имена файлов. Тем не менее, этот цикл допускает простое добавление

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

ной. Это более предпочтительно, и оно не влияет на производительность.

В строке 21 мы добавляем символ двоеточия (:) к другим символам

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

тить разделитель полей только в двоеточие. Если бы мы сделали послед-

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

Основной цикл представлен в строках 23-40. Это двойной цикл for.

Внешний цикл проходит по каждому файлу в командной строке, а внутрен-

ний цикл обрабатывает каждый каталог, указанный в вашей переменной

PATH. Обратите внимание, что внешний цикл идет по именам файлов, а не

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

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

логам.

Следовательно, для каждого имени файла и каталога действие за-

висит от требуемого формата. Маршрутный формат печатает полное имя,

листинговый формат выполняет команду ls, а формат set не ищет указан-

ные имена файлов, но проверяет права доступа и ищет файлы с установ-

ленным пользовательским идентификатором.

Обрат ПРИЕМЫ ПРОФЕССИОНАЛЬНОЙ РАБОТЫ В UNIX

аналогами. Опция ls есть дополнение, которое сокращает объем работы

при вызове. Наличие комбинации поиска и команды ls освобождает того,

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

подстановки. Старая и новая команды выглядят примерно так:


ll `path ll`

Находит путь к ll, а затем запускает на нем команду ls -l.


paths -l ll

Находит путь и вместо того, чтобы его напечатать,

выполняет команду ls -l применительно к этому пути.


Формат setuid в строке 34 прощается с подходом "один файл за один

раз" и включает каталоговую машину. Поскольку внешний цикл установлен

на одну итерацию, внутренний цикл становится главным. Для каждого ка-

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

каталога. Это делает распечатку приятной, информативной и наглядной.

Ключевой командой является комбинация ls-grep. Каждое имя файла в

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

установки пользовательского идентификатора. Модель такова, что команда

ls -al $DIR печатает следующее:


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


|

| -rws--x--x 1 root bin 16235 Sep 13 1985 /bin/su

|

|


Аргумент "[ ]*s[ ]*" означает поиск от начала строки символа,

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

личных от пробела, затем символ s и затем один или более символов, от-

личных от пробела. Это выражение ограничивает поиск битами прав досту-

па в начале строки. Если имеется символ s где-либо в правах доступа

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

идентификаторе процесса), то команда grep отрабатывает успешно и печа-

тается вся строка.

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

несколько "легковесен" в том смысле, что поиск ведется только согласно

переменной PATH, которая у вас есть. Файлы с установленным пользова-

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

заны в PATH. Однако в такой реализации данная опция обеспечивает быст-

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

тельским идентификатором.


ВОЗМОЖНЫЕ МОДИФИКАЦИИ


Данный командный файл открыт для многих различных видов модифика-

ции. Поиск полного имени файла является фундаментальной задачей прог-

раммного обеспечения по сопровождению файлов. Эта возможность позволя-

ет нам полагаться на саму программу paths или использовать paths в ка-

честве куска более объемной программы.

При разработке ваших собственных программ следует обратить внима-

ние на гибкость командного файла paths, которая выражается в отличии

между обрабатываемыми форматами. Первые два формата используют отдель-

ные файлы, а формат set использует каталоги. Дальнейшие дополнения к

командному файлу paths могут касаться любой из этих строк или могут

комбинировать их. Если есть необходимость, программное обеспечение мо-

жет приспособиться к этому.


2.2. ВЫВОД ИНФОРМАЦИИ


2.2.1. lc - вывод файловой информации на экран по столбцам


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


ИМЯ: lc

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


lc Выдает список файлов в колоночном формате


НАЗНАЧЕНИЕ


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

и исполняемые модули. Этот листинг можно пропустить через команду

more.


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


lc [-m] [ls options] file [file ...]


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


lc -R $HOME


Выдает список всех файлов во всех подкаталогах моего регистра-

ционного каталога.


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


1 :

2 # @(#) lc v1.0 List files in a column Author: Russ Sage

2а Выводит список файлов в колоночном виде


4 if [ "$1" = "-m" ]

5 then MORE="| /usr/bin/more"

6 shift

7 else MORE=""

8 fi


10 eval "/bin/ls -a $@ | /bin/pr -5t" $MORE # pre System V

11 eval /bin/ls -aCF $@ $MORE # System V


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


MORE Содержит программный канал к команде more


ОПИСАНИЕ


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


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

изобретают его снова. Если первое колесо не того размера или не того

цвета, делается другое колесо. В нашей конкретной ситуации исходным

колесом является команда ls системы UNIX, которая имеет некоторые не-

достатки в своих ранних реализациях. Она выдает хорошую информацию, но

она печатает имена файлов только в одну колонку, что приводит к нера-

циональному расходованию места и затрудняет чтение имен файлов. Поэто-

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

несколько колонок.

Как видно из предыдущего листинга, lc имеет две формы. Одна пред-

назначена для систем, более ранних, чем System V, а другая - для

System V и последующих версий UNIX. Причина в том, что System V версии

2 имеет новую команду ls, которая делает именно то, что мы хотим.

Система Berkeley также имеет версию команды ls, которая по умолчанию

использует несколько колонок при выводе на терминал. Но для XENIX и

ранних версий System V мы должны делать это сами. Дело в том, что хотя

в вашей версии UNIX, XENIX или чего-либо еще могут отсутствовать ко-

манды, имеющиеся в других версиях, вы обычно можете построить то, что

вам нужно. Это может потребовать определенных усилий, и ваши программы

могут работать не так быстро и не так эффективно, но вы МОЖЕТЕ полу-

чить нужное средство.

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

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

lc псевдонимом (alias). Использовать возможность введения псевдонимов,

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

вызову команды ls с указанными опциями). Это легче, чем писать команд-

ный файл, но ограничивает вас необходимостью работать с уже имеющимися

командами или опциями. Это быстрее, так как не создается никаких до-

полнительных процессов.

При работе со старым интерпретатором sh мы должны пройти через

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

талоге bin. С другой стороны, SCO XENIX System V решает эту проблему,

связывая эти же имена (lc, lf, l) с обычной командной ls и используя

вызывающее имя для определения формы распечатки.

Итак, зачастую имеется много альтернатив. Мастера UNIX, сталкива-

ясь с какой-либо проблемой, не борются с ней с помощью Си или команд-

ного файла интерпретатора shell. Поскольку они знакомы с существующими

ресурсами системы UNIX, они могут рассмотреть проблему и выбрать стра-

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

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

сложности, это могут быть непонятная, но существующая команда и/или