формате, иначе awk не распознает их как таковые. Эти правила заключа-
ются в том, что имя функции должно находиться в начале строки, состоять
из разрешенных символов и за ним должна следовать левая скобка. Пробелы
в имени функции не допускаются. Вот пример модуля программы на Си, по-
даваемого на рассмотрение командному файлу ctags:

main()
{
}

func1(arg1,arg2)
int arg1,arg2;
{
}

func2(arg1,arg2)int arg1,arg2;
{
}

Результат работы ctags направляется в стандартный вывод (на эк-
ран), поэтому он должен быть перенаправлен, чтобы попасть в файл. Вхо-
дом для ctags является любое число имен файлов. Напомним, что если на
входе имеется несколько файлов, то выход представляет собой один непре-
рывный поток данных, попадающий в один файл. Если вам нужен выводной
файл для каждого входного файла, то для управления ctags можно приме-
нить такой командный файл с циклом:

for F in *.c
do
ctags $F > $F.tags
done

Выход ctags состоит из трех полей в таком формате:

признак имя_файла шаблон_поиска

Реальный выход для примера программы на Си, приведенного выше, был бы
таким:

main /usr/russ/src/program.c /^main()$/
func1 /usr/russ/src/program.c /^func1(arg1,arg2)$/
func2 /usr/russ/src/program.c /^func2(arg1,arg2)$/

Первое поле является именем признака (которое совпадает с именем
функции). Второе поле - маршрутное имя файла, содержащего данную функ-
цию. Третье поле - шаблон поиска, используемый признаковыми средствами
редактора для доступа к функции внутри файла (более подробно об этом -
позже).
Предположим, вы можете сгенерировать правильный файл признаков.
Как согласовать файл признаков с редакторами таким образом, чтобы вы
могли найти интересующую вас функцию? Редактор vi предоставляет много
путей для этого. Первый способ - поместить имя используемого файла
признаков в файл .exrc. (Файл .exrc является аналогом файла .profile
для редактора ex и работает также с редактором vi, что не удивительно,
так как vi построен na ex. Поскольку vi - наиболее популярный редактор
системы UNIX, мы применяем его здесь для наших примеров.) Вы можете
иметь файл .exrc, который выглядит примерно так:
set tags=/usr/russ/mytags
Впоследствии, когда вы обращаетесь к некоторому признаку, исполь-
зуется данный файл признаков. Другой способ - установить файл признаков
после того, как вы вошли в редактор. Чтобы посмотреть, каким является
ваш файл признаков по умолчанию, введите, находясь в vi, следующее:
:set tags
Эта команда печатает файл признаков, о котором она знает. Для из-
менения определенного в настоящий момент файла признаков, используйте
синтаксис, который был в примере файла .exrc:
:set tags=/usr/russ/mytags
Теперь, когда редактор знает, в каком файле искать признаки, к ко-
торым вы обращаетесь, давайте рассмотрим, как обращаться к признаку
(т.е. к имени функции). Первый способ - объявить его в командной строке
при вызове редактора. Например:
$ vi -t tag
Если вы уже находитесь в редакторе vi, можете применить такую ко-
манду для поиска признака:
:ta tag
Двоеточие означает, что мы направляемся в ex, чтобы выполнить этот
поиск. Мы просим ex найти указанную строку как признак, который разме-
щается в текущем файле признаков. Когда этот признак найден в файле
признаков, редактор vi редактирует файл с соответствующим именем, кото-
рое он берет из поля 2. Это аналогично команде ":e имя_файла". Когда
новый файл внесен в буфер редактора, последнее поле файла признаков
используется в качестве строки шаблона поиска. Синтаксис точно такой
же, как если бы вы набирали его вручную. Курсор перемещается в позицию
в файле, которая соответствует строке поиска, при этом вы попадаете на
интересующую вас функцию.

ВЗАИМОСВЯЗЬ МЕЖДУ ex И vi

Несколько отклоняясь от темы, рассмотрим два файла: /bin/ ex и
/bin/vi. Небольшое исследование обнаруживает, что на самом деле это
один и тот же файл. Мы можем проверить это, посмотрев на их индексные
описатели файлов. Введите такую команду:
$ ls -li `path ex vi`
Выход показывает, что два числа в первой колонке одинаковы.

510 -rwx--x--t 5 bin bin 121412 Sep 19 1985 /bin/ex
510 -rwx--x--t 5 bin bin 121412 Sep 19 1985 /bin/vi

Это число и есть индексный описатель файла (inode). Поскольку оба
файла являются одним и тем же, вызов любого из них запускает один и тот
же исполняемый модуль. Каким образом он знает, как вы его вызвали?
Программа смотрит на строку argv[0] и видит, какое имя вы использовали
для вызова файла. Затем редактор устанавливает свой интерфейс в соот-
ветствии с тем, как вы его вызвали.
Обратите внимание, что эта программа имеет пять связей. Как нам
найти все другие имена, которыми можно вызвать vi и ex? Мы можем
использовать команду системы UNIX ncheck. Эта команда воспринимает ин-
дексный описатель файла и печатает все файлы, имеющие такой описатель
файла . Примеры таких команд:
$ ncheck -i 510 /dev/root
$ ncheck -i 510
Первый синтаксис указывает команде ncheck искать файлы с inode,
равным 510, только в корневой файловой системе. Ncheck ограничена по-
иском в одной файловой системе. Это подкрепляет тот факт, что файлы не
могут быть привязаны к различным файловым системам, поскольку каждая
файловая система начинается с inode 2 и последовательно наращивается.
Каждая файловая система имеет inode 510, который уникален для каждой
файловой системы. Выход предыдущей команды выглядит так:

dev/root:
510 /bin/edit
510 /bin/ex
510 /bin/vedit
510 /bin/vi
510 /bin/view

Если файловая система не указана, как во втором примере, выполня-
ется поиск по всем файловым системам, смонтированным в настоящее время.
Это не слишком хорошо для нас, поскольку пять связей vi должны нахо-
диться в одной и той же файловой системе. В противном случае файлы были
бы связаны поперек границ файловых систем. Мы уже можем сказать, что
никаких файлов редактора нет в каталоге /usr, размещенном во втором
разделе диска от корневой файловой системы.

    ПРИМЕРЫ


1. $ ctags *.c
Генерирует файл признаков для всех файлов с исходным кодом на Си в
текущем каталоге. Выход направляется на экран в отсортированном порядке
для каждого файла. Порядок файлов алфавитный, так как указано расшире-
ние файла. Конечно, в большинстве случаев вы захотите перенаправить вы-
ход ctags в файл.

2. $ ctags `Find /usr/src -name "*.c" -print`

Этот синтаксис использует командную подстановку, чтобы найти все
имена файлов, оканчивающиеся на .c и поместить их в командную строку.
Проблема в том, что если найдено слишком много файлов, командная строка
ctags может переполниться и испортить всю команду. В зависимости от
серьезности переполнения, она может испортить и весь ваш процесс shell.

3. $ find /usr/src -name "*.c" -exec ctags {} \; > tags

Находит все исходные файлы на Си в сегменте дерева /usr/src. Для
каждого подходящего файла запускает программу ctags на этом файле.
Использование такой формы записи предотвращает порчу вашей команды (о
которой только что шла речь), а также запускает ctags для каждого имени
файла. Весь выход помещается в файл tags для последующего использова-
ния.
4. $ find /usr/src -type f -print | sort |
> while read FILE
> do
> ctags $FILE
> done >> tags

Используя преимущество множественных каталогов, находит и сортиру-
ет все файлы из каталога /usr/src и печатает их маршрутные имена в
стандартный вывод. Затем они сортируются и поступают по конвейеру в
цикл while. Цикл while используется для обслуживания сколь угодно боль-
шого числа файлов без переполнения буферов. Выход цикла while добавля-
ется к одному файлу - tags. Этот цикл громоздкий и медленный, но он вы-
полняет свою работу.

5. $ find /usr/src -print | ctags

Это неправильный способ использования ctags. Выходом команды find
являются маршрутные имена. Ctags читает стандартный ввод, поскольку в
командной строке нет файлов. Получается, что данные, которые читает
awk, являются маршрутными именами от find, которые не имеют корректных
полей для соответствия шаблонам функций. Никакого сопоставления не про-
исходит.
Аналогичную проблему могла бы вызвать такая командная строка:

find /usr -print | wc -l

Вы могли бы интерпретировать это так: "посчитать, сколько строк
имеется во всех файлах каталога /usr". Но в действительности здесь ска-
зано: "сколько имен файлов имеется в древовидной структуре /usr". Для
подсчета общего количества строк в этих файлах нужен такой синтаксис:
find /usr -exec cat {} \; | wc -l
который гласит: "найти все файлы в /usr, распечатать каждый из
них, затем посчитать, сколько строк в них имеется". Чтобы так же посту-
пить с ctags, нужен такой синтаксис:
find /usr/src -name "*.c" -exec cat {} \; | ctags
В отличие от результата, который мы получили бы в предыдущих при-
мерах:

func1 /usr/russ/src/program.c /^func1(arg1,arg2)$/
func2 /usr/russ/src/program.c /^func2(arg1,arg2)$/

теперь выход будет выглядеть так:

func1 - /^func1(arg1,arg2)$/
func2 - /^func2(arg1,arg2)$/


    ПОЯСНЕНИЯ



Символы "-" вместо имени файла появляются из-за того, что ctags
читает из стандартного ввода. Awk автоматически присваивает своей внут-
ренней переменной FILENAME значение "-", так как знает, что в командной
строке не было файлов.
Весь командный файл есть программа awk. Входом для командного фай-
ла утилиты awk является $@, что представляет все позиционные параметры.
Каждый параметр считается именем исходного файла на Си. Если никакие
файлы не передаются в командной строке, awk ищет данные в стандартном
входном потоке, но это создает некорректный выход, так как переменная
FILENAME в awk имеет по умолчанию значение "-". Поскольку awk требует
имена файлов, мы должны вызывать ctags с именами файлов, а не переда-
вать ему данные по конвейеру через стандартный ввод, как показано в
предыдущем примере.
Awk читает каждый раз одну строку из файла данных и сверяет ее с
шаблоном, пытаясь установить соответствие. Для каждой строки, соот-
ветствующей шаблону, awk выполняет заданную программу. Первое, что де-
лает ctags,- изменяет подразумеваемый разделитель полей утилиты awk с
пробела на левую скобку. Благодаря использованию этого символа в ка-
честве разделителя полей, строка определения функции разбивается на два
поля: имя функции и остаток строки.
Шаблон поиска утилиты awk соответствует синтаксису имени Си-функ-
ции. Оно может начинаться с символов a-z, A-Z или символа подчеркива-
ния. Далее в имени могут быть любые символы из набора a-z, A-Z, 0-9 и
_. Между именем и скобкой нельзя использовать пробелы. Поиск начинается
от начала строки (^), за которым следует последовательность допустимых
символов (a-z, A-Z, 0-9), а затем левая скобка.
Когда строка соответствует данному шаблону, генерируется выход с
помощью оператора printf. Первое поле - строка, представленная обозна-
чением $1. В данном случае $1 - это только имя функции, исключая левую
скобку. Печатается символ табуляции, затем следующая строка, которая
является переменной FILENAME из утилиты awk. Эта переменная должна быть
получена из командной строки, иначе awk не будет знать имя файла, в ко-
тором размещена данная функция, и файл признаков потеряет информацию,
необходимую для доступа к файлу, содержащему функцию. Печатается еще
одна табуляция, затем строка поиска. Строкой поиска является $0, что
представляет всю строку, с которой работает awk. Строке предшествует
символ ^, а за строкой следует символ $.
Выход пропускается по конвейеру через sort с той целью, чтобы все
признаки шли в отсортированном порядке. Опции сортировки указывают ути-
лите sort проверять только первое поле и печатать только одно появление
строки, если имеется несколько записей.

МОДИФИКАЦИИ ДЛЯ ctags

Теперь, когда мы знакомы с общим форматом редактируемого файла
признаков, можем ли мы применить его для других полезных целей? Мы зна-
ем, что мы можем идентифицировать регулярные структуры в программах на
Сии создать признаки, с помощью которых можно получить доступ к этим
структурам в редакторе. В программах на Си имеются не только имена
функций, но и другие интересные конструкции, например имена структур.
Их можно обслуживать с помощью модифицированной версии ctags.
Единственное, что нам нужно знать,- это официальный синтаксис структуры
данных. Структура данных, которая нас бы заинтересовала, часто имеет
такой формат:

struct name {
int val1;
char val2;
};

Все, что мы должны сделать,- это заставить awk искать все появле-
ния определения структуры. Затем мы можем построить файл признаков, в
котором признаком является имя структуры. Этот файл, видимо, будет та-
ким же, как и прежде, а строка поиска будет обнаруживать определение
структуры, а не имя функции. Фактически, комбинация утилиты awk, приз-
наков и редактора может быть использована для любого вида информации,
которую вы можете захотеть хранить в файле специального формата, напри-
мер для адресов, заметок, библиографических ссылок и т.д. Вам просто
нужно подобрать соответствующие разделители и правильно их использо-
вать.
Мы надеемся, что облегчили сопровождение ваших программ и предло-
жили вам идеи для других способов автоматической обработки документа-
ции. Вы можете без особого труда учреждать и поддерживать локальные
соглашения о документации с помощью командных файлов, аналогичных
представленным здесь. Примером проекта, за который вы можете взяться,
является согласование наших программ извлечения информации (stripf,
stripc, strips) и других программ, которые вы пишете, таким образом,
чтобы они могли читать файл-формирователь (makefile, см. Make(1)) и вы-
давать полную документацию по всем исходным файлам, участвующим в дан-
ном проекте.

    * ГЛАВА 5. УПРАВЛЕНИЕ ЛИЧНОЙ ИНФОРМАЦИЕЙ I: *




    УПРАВЛЕНИЕ ВРЕМЕНЕМ


    И ДЕЛОПРОИЗВОДСТВОМ




    УПРАВЛЕНИЕ ВРЕМЕНЕМ




at выполнение задач в указанное время
b порожденный shell фоновых задач
greet своевременное приветствие с терминала
lastlog сообщение времени последней регистрации
timelog учет и статистика сеансов работы
today печать календаря с отмеченной текущей датой


    УПРАВЛЕНИЕ ДЕЛОПРОИЗВОДСТВОМ



jargon генератор технических терминов
phone база данных с телефонными номерами
office делопроизводитель


УПРАВЛЕНИЕ ЛИЧНОЙ ИНФОРМАЦИЕЙ I:

    УПРАВЛЕНИЕ ВРЕМЕНЕМ


    И ДЕЛОПРОИЗВОДСТВОМ




    ВВЕДЕНИЕ



Мы уже многое знаем о файлах и о том, как управлять файловой
структурой. Пора рассмотреть, как мы можем использовать систему UNIX
для управления множеством задач, которые составляют наш рабочий день и
держат нас в курсе того, что делают другие пользователи. Термин "уп-
равление личной информацией" (personal management) подразумевает, что
вы хотите создать свою собственную ПЕРСОНАЛЬНУЮ рабочую среду и
инструментальные средства. Мы предлагаем вам пакет программ, которые
вы можете приспособить к вашим требованиям. Фактически мы в этой и
следующей главе представляем четыре отдельных набора программ, каждый
из которых посвящен определенному аспекту управления личной информаци-
ей.
Средства управления временем помогают нам спланировать выполнение
задач компьютером, а также контролировать наше личное время. Управле-
ние делопроизводством имеет дело с хранением и извлечением информации,
а также с организацией доступа к различным функциям системы UNIX
посредством простого в использовании интерфейса в виде меню.
Для каждой из этих областей деятельности мы даем ее обзор, а за-
тем представляем соответствующую группу средств.


    УПРАВЛЕНИЕ ВРЕМЕНЕМ



Поскольку система UNIX имеет встроенные функции поддержки времени
и часы, она может следить за временем. Объединение функций поддержки
времени с возможностью автоматического запуска группы команд означает,
что мы можем настроить их так, чтобы компьютер выполнял многие наши
рутинные работы, связанные со временем. Мы также можем использовать
компьютер для отслеживания нашего собственного времени.
В данном разделе представлены инструментальные средства at, b,
greet, lastlog, timelog и today.
Командный файл at дает нам возможность сказать машине о том, что
в указанное время необходимо сделать то-то и то-то (вывести на экран
сообщение или выполнить какие-то другие команды). Задача запускается в
фоновом режиме, так что мы можем продолжать другую работу, а фоновая
задача выполнится автоматически в указанное время. Эта задача может
состоять из любых разрешенных в UNIX команд, поэтому ее возможности
очень гибкие. Мы просто предлагаем некоторые идеи, связанные с ее
использованием.
Вторым средством является командный файл b. Это обработчик фоно-
вых задач. Очень часто при порождении фоновых процессов мы не можем
узнать, когда они закончились. Для того, чтобы это определить, нам не-
обходимо вручную просмотреть таблицу процессов или найти какой-то иной
признак того, что данная работа завершена. Командный файл b запускает
задачу, управляет операциями ввода-вывода и затем сообщает нам о том,
что задача завершена.
Командный файл greet показывает, каким образом переводить внут-
реннее время компьютера в более понятные пользователю категории. Он
различает три перида суток (утро, день и вечер) и реагирует на них
соответствующими сообщениями. Это довольно просто, но обеспечивает
неплохое основание для подхода к решению других проблем, связанных со
временем.
Далее мы представляем два средства, которые образуют базис систе-
мы управления временем. При выполнении множества работ нам необходимо
подсчитать время, которое мы потратили на данный проект, чтобы мы мог-
ли выставить нашему клиенту соответствующий счет. Командный файл
lastlog запускается автоматически, когда вы регистрируетесь в системе.
Поддерживается база данных, в которую каждый раз записывается время
вашей регистрации для последующего анализа или хранения записей.
С этим инструментальным средством соседствует командный файл
timelog. Это утилита, которая выполняет подсчет времени. Она может
следить за общим временем, затраченным на любой указанный проект. За-
тем можно сгенерировать статистику, которая показывает, когда и сколь-
ко времени вы работали над каждым проектом.
Последнее средство, относящееся ко времени - это командный файл
today. Это утилита, которая изменяет вид выходных данных команды UNIX
cal. Она печатает обычный календарь, только текущая дата выводится в
инверсном виде. Это очень наглядно. Вы можете развить этот инструмент
для того, чтобы отмечать праздники или другие особые дни.

----------------------------------------------------
ИМЯ: at
----------------------------------------------------

at - выполнить команду или файл в указанное время

    НАЗНАЧЕНИЕ



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

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



at hr:min cmd [;cmd ...]

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



at 12:00 echo "time for lunch!"

В двенадцать часов дня выводит сообщение на экран терминала.

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

1 :
2 # @(#) tree v1.0 Execute command line at specific time
Author: Russ Sage
2а Выполнить командную строку в указанное время

4 if [ $# -lt 2 ]
5 then echo "at: wrong arg count" >&2
6 echo "usage: at hr:min cmd [;cmd ...]" >&2
7 exit 1
8 fi

10 ITS=$1; shift

12 while :
13 do
14 TIME=`date | cut -c12-16`

16 if [ "$ITS" = "$TIME" ]
17 then eval $@
18 exit 0
19 else sleep 35
20 fi
21 done &

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



ITS Время, в которое следует выполнить указанные команды
TIME Текущее время в системе


ОПИСАНИЕ

ЗАЧЕМ НАМ НУЖЕН at?

На протяжении рабочего дня мы выполняем много небольших работ,
которые нужно делать через различные интервалы времени. Некоторые вещи
просто должны быть сделаны один раз в любое время, тогда как другие
должны делаться в определенное время каждый день. Например, вам может
понадобиться запускать процедуру копирования файлов каждую ночь, вхо-
дить в другую систему раз в день и проверять почту или сообщения поль-
зователей сети по заданной теме раз в несколько дней.
Командный файл at предоставляет механизм для выполнения задач,
связанных со временем. Мы можем сказать системе, что и когда мы хотим
сделать. Задача остается "спящей" в фоновом режиме до назначенного
времени. Это дает нам возможность превратить компьютер в будильник,
секретаря, администратора встреч и т.д.
Данная концепция не нова и уже существует в системе Berkeley UNIX
под тем же именем. Она реализована также в последних версиях System V.
Почему же тогда мы представляем здесь нашу собственную версию?
Одна из причин в том, что многие из вас имеют более ранние версии
UNIX, в которых это средство отсутствует. Но важнее, видимо, другое -
наша цель не в том, чтобы сделать существующие команды at устаревшими,
а в показе того, как легко отслеживать время и реализовывать обработ-
ку, связанную со временем. Имея нашу собственную команду at, мы можем
настроить ее по своему вкусу и изменить ее, когда необходимо. Команда
at, представленная здесь, фактически более гибкая, чем at в системе
Berkeley, хотя в первой отсутствуют некоторые особенности второй. Она
более гибкая потому, что вы можете поместить настоящие команды в фоно-
вую задачу at, в то время как для at в системе Berkeley вы должны
использовать имя командного файла интерпретатора shell. Метод Berkeley
запрещает вам вызывать исполняемые модули непосредственно в командной
строке, а наша at - нет. (Конечно, вы можете с таким же успехом
использовать командные файлы интерпретатора shell, если вам это необ-
ходимо.)

ЧТО ДЕЛАЕТ at?

Команда at дает нам возможность собирать несколько команд в одно
целое и впоследствии запускать их. Когда они выполняются, их вывод мо-
жет либо идти на экран, либо перенаправляться в определенный файл.
Командная строка принимает два параметра: время выполнения и ко-
мандную строку, которую следует выполнить. Время выражено в формате
час:минута. Час должен быть указан строкой из двух цифр (в диапазоне
от 0 до 23 часов), так как его использует команда date. Использование
того же стандарта, что и в команде date, значительно упрощает команду
at. В качестве второго параметра может быть любая команда, которую
обычно можно ввести в командной строке интерпретатора shell. Можно
также использовать конвейеры, составные команды и переназначения. Нет
ограничений на то, какая команда может быть выполнена. Команда at мо-
жет запустить обычный исполняемый модуль UNIX или ваш собственный ко-
мандый файл.
Выход at по умолчанию направляется в стандартный вывод. Стандарт-
ным выводом в данном случае является экран терминала. Команда at в
системе Berkeley не имеет вывода по умолчанию, что несколько затрудня-
ет получение результата и отправку его на экран.
Команда at всегда запускается как фоновая задача. Нецелесообразно
запускать ее в приоритетном режиме, где она блокирует терминал на все
время своего выполнения. Пребывая в фоновом режиме, at освобождает
ресурсы, но все же работает для вас. Между прочим, отметим, что когда
процессы ставятся в фоновый режим изнутри командного файла, идентифи-
катор процесса не печатается на экран, как это происходит, когда про-
цессы запускаются в фоновом режиме с клавиатуры.
Порождение большого количества фоновых процессов может иметь от-
рицательный эффект для системы. Каждая фоновая задача - это цикл while
интерпретатора shell, который работает очень медленно. Когда много фо-
новых процессов, мало времени центрального процессора остается на дру-
гие цели. В результате производительность системы ухудшается. В боль-
ших системах это, вероятно, не проблема, если только система не загру-
жена множеством пользователей, но вы должны использовать это средство
с осторожностью.
Отметим, что формат час:минута годится только для одного полного
дня. Данная программа at задумана как ежедневная и не имеет средств
запуска в определенный день или месяц, хотя вы можете легко расширить
ее, как только поймете, как читается и используется информация о вре-
мени.


    ПРИМЕРЫ



1. $ at 11:45 echo ^G^G It's almost lunch time

Без пятнадцати минут двенадцать дважды выдается звуковой сигнал
(control-G) и выводится сообщение о ленче.

2. $ at 10:45 "if [ -s $MAIL ]; then echo ^G You have mail; fi"

Без пятнадцати одиннадцать проверяется, существует ли мой почто-
вый файл и есть ли в нем хотя бы один символ ($MAIL есть
/usr/spool/mail/russ). Если это так, выдается звуковой сигнал и сооб-
щение о том, что у меня есть почта.

3. $ at 17:00 "c; date; banner ' time to' ' go home'"

В пять часов вечера очищается экран (с помощью команды c, описан-
ной далее в данной книге), печатается дата и выводится крупными буква-
ми на весь экран сообщение "time to go home" ("пора домой"). С помощью
апострофов в командной строке banner мы можем добиться вывода символа
возврата каретки, чтобы разместить каждый набор слов в отдельной стро-
ке. Если какая-либо из этих команд не срабатывает (например, не найде-
на команда c), то и весь фоновый процесс оканчивается неудачей.


    ПОЯСНЕНИЯ



Прежде всего at проверяет, правильно ли она была вызвана. Строки
4-8 делают проверку ошибок. В командной строке должны присутствовать
по крайней мере два параметра: время и команда. Если это так, то счет-
чик позиционных параметров равен 2. Если этот счетчик меньше 2, прои-
зошла ошибка. В стандартный файл ошибок посылаются сообщения об ошибке