Ниже приведены основные формы каждого цикла:
for i in список слов
do
тело цикла, $i последовательно получает значения элементов
done
for i (явно перечисляются аргументы командного файла, т.е. $*)
do
тело цикла, $i последовательно получает значения аргументов
done
while команда
do
тело цикла выполняется, пока команда возвращает истина
done
until команда
do
тело цикла выполняется, пока команда возвращает ложь
done
Вторая форма цикла for
, в которой пустой список обозначается как $*
, является удобным сокращением записи для наиболее типичного использования.
Командой условия, управляющей циклами while
или until
, может быть любая команда. Очевидным примером служит цикл while
, в котором осуществляется контроль входа (пусть Мэри) в систему:
while sleep 60
do
who | grep mary
done
Команда sleep
, устанавливающая паузу на 60 с, всегда выполняется нормально (если ее не прервали) и, значит, всегда возвращает код "успех", поэтому в цикле раз в минуту будет проверяться, находится ли Мэри в системе. Недостаток такого решения состоит в том, что если Мэри уже вошла в систему, то нужно ждать 60 с, чтобы узнать об этом. О продолжении же работы Мэри в системе каждую минуту будет поступать сообщение. Цикл можно перевернуть и записать с помощью until
, чтобы получать информацию сразу без задержки, если Мэри в данный момент работает в системе:
until who | grep mary do
sleep 60
done
Теперь условие представляется более интересным. Если Мэри вошла в систему, то 'who | grep mary'
выдаст запись о ней из списка команды who
и вернет код "истина". Это связано с тем, что grep
выдает код завершения, показывающий, удалось ли ей найти что-нибудь, а код завершения конвейера есть код завершения последней команды.
В заключение мы можем оформить команду, дав ей имя и установив в системе:
$ cat watchfor
# watchfor: watch for someone to log in
PATH=/bin:/usr/bin case $# in
0) echo 'Usage: watchfor person' 1>&2; exit 1
esac
until who | egrep "$1"
do
sleep 60
done
$ cx watchfor
$ watchfor you
you tty0 Oct 1 08:01
Работает
$ mv watchfor /usr/you/bin
Установим в системе
$
Мы заменили grep
на egrep
, чтобы было можно задавать
$ watchfor 'joe | mary'
и следить за несколькими пользователями.
Более сложный пример: можно контролировать вход в систему и выход из нее всех пользователей и сообщать обо всех фактах входа или выхода. Это можно рассматривать как некоторое дополнение к команде who
. Основная идея проста: раз в минуту запускать команду who
и сравнивать результат ее действия с результатом, полученным минутой ранее, сообщая обо всех различиях. Вывод команды who
хранится в файле, и мы можем записывать его в каталог /tmp
. Чтобы отличить свои файлы от файлов, принадлежащих другим процессам, в имена файлов вставляется переменная интерпретатора $$
(номер процесса команды интерпретатора), что является обычной практикой. Имя команды упоминается во временных файлах главным образом для администратора системы. Часто команды (включая данную версию watchfor
) оставляют после себя файлы в /tmp, и полезно знать, какая команда это сделала. Здесь ":"
— встроенная команда, которая
$ cat watchwho
# watchwho: watch who logs in and out
PATH=/bin:/usr/bin
new=/tmp/wwho1.$$
old=/tmp/wwho2.$$
> $old # create an empty file
while : # loop forever
do
who >$new
diff $old $new
mv $new $old
sleep 60
done | awk '/>/ { $1 = "in: "; print }
/</ { $1 = "out: "; print }'
$
только обрабатывает свои аргументы и возвращает код "истина". Мы могли бы заменить ее командой true
, просто передающей код завершения "истина" (есть также команда false
), но команда ':'
более эффективна, поскольку не нужно выполнять эту команду, выбирая ее из файловой системы.
В выводе команды diff
используются символы <
и >
для разделения данных из двух файлов. Программа, написанная на языке awk
, обрабатывает результаты, чтобы сообщить об изменениях в более понятном формате. Обратите внимание на то, что весь цикл передает результаты работы по конвейеру awk
программе, вместо того, чтобы запускать заново awk
программу каждую минуту. Для такой обработки редактор sed
не подходит, поскольку его вывод всегда задерживается по сравнению с входным потоком на одну строку: всегда есть одна входная строка, которая уже обработана, но не напечатана, а это приводит к ненужной задержке.
Читать дальше
Конец ознакомительного отрывка
Купить книгу