Текст книги "Linux и UNIX: программирование в shell. Руководство разработчика"
Автор книги: Дэвид Тейнсли
сообщить о нарушении
Текущая страница: 14 (всего у книги 25 страниц)
read ANS
if [ "$ANS"="y" ] || [ "$ANS"="Y" ]; then
# да, пользователь желает изменить значение
echo "Enter a sensible value "
read VALUE
#простой тест для уточнения, является ли значение численным,
#добавим к VALUE любое число, проверим код возврата
expr $VALUE + 10 > /dev/null 2>&1
STATUS=$?
# проверим код возврата для expr
if [ "$VALUE"="" ] || [ "$STATUS" != "0" ]; then
# направим ошибки в стандартный поток ошибок
echo " You either entered nothing or a non‑numeric " >&2
echo " Sorry now exiting..counter stays at. $COUNTER" >&2 exit 1 fi
# если мы здесь, значит, это – число, добавим его к COUNTER
COUNTER=`expr $COUNTER + $VALUE`
echo " Counter now set to $COUNTER" else
#если мы здесь, значит, пользователь вместо того, чтобы ввести число,
#нажал клавишу ввода
#или ответим n для изменения значения приглашения
echo " Counter stays at $COUNTER"
fi
Рассмотрим результаты выполнения приведенного сценария.
$ ifcount
Do you wish to change the counter value currently set at 100? [y..n]:n Counter stays at 100
$ ifcount
Do you wish to change the counter value currently set at 100? [y..n]:y
Enter a sensible value: fdg
You either entered nothing or a non‑numeric
Sorry now exiting..counter stays at 100
$ ifcount
Do you wish to change the counter value currently set at 100? [y..n]:y Enter a sensible value: 250
Counter now set to 350
18.3.21. Простой сценарий, обеспечивающий безопасность при регистрации
А теперь рассмотрим структурное дополнение, которое усиливает меры безопасности при регистрации пользователя перед запуском приложений. Поступает приглашение на ввод имени пользователя и пароля; если имя пользователя и пароль
совпадают со строками, включенными в сценарий, пользователь регистрируется. Если
такого совпадения не наблюдается, пользователь завершает работу.
Сценарий устроен так, что вначале переменные получают значение "ложь". Предполагается, что вводные данные пользователя окажутся ошибочными. Текущие установки команды stty сохраняются, поэтому можно скрыть символы, которые вводятся в поле пароля. Затем установки stty восстанавливаются.
Если вводится корректный ID пользователя и пароль (паролем является mayday), переменные invalid_user и invalid_passwd для недействительного пользователя или пароля имеют значение "по". Затем производится тестирование, и если какая‑либо из переменных принимает значение yes, сценарий для этого пользователя завершается по умолчанию.
К работе допускаются пользователи с действительными ID и паролями. В регистрационном сценарии удобно применять описанное структурное дополнение. В данном примере действительными ID пользователя служат dave или pauline.
$ pg ifpass
#!/bin/sh
#ifpass
#установим значения переменных в "ложь" INVALID_USER=yes
INVALID_PASSWD=yes
# сохранение текущих установок команды stty
SAVEDSTTY=`stty -g`
echo "You are logging into a sensitive area"
echo -n "Enter your ID name :"
read NAME
# скройте символы, введенные в терминале
stty -echo
echo "Enter your password :"
read PASSWORD
# попробуем снова
stty $SAVEDSTTY
if [ "$NAME"="dave" ] || [ "$NAME"="pauline" ]; then
# если действительно, установите переменную
INVALID_USER=no
fi
if [ "$PASSWORD"="mayday" ]; then
# если пароль действителен, установите переменную
INVALID_PASSWD=no
fi
if [ "$INVALIDUSER"="yes" -o "$INVALID_PASSWD"="yes" ]; then
echo " `basename $0 :` Sorry wrong password or userid"
exit 1
fi
# если вы здесь, ваш ID и пароль в порядке.
echo "correct user id and password given"
Если при выполнении приведенного сценария указывается недействительный пароль, получим:
$ ifpass
You are logging into a sensitive area
Enter your ID name : dave
Enter your password :
ifpass :Sorry wrong password or userid
Введем верное имя регистрационное имя и пароль.
$ ifpass
You are logging into a sensitive area
Enter your ID name : dave
Enter your password :
correct user id and password given
18.3.22. Применение elif
Часть elif оператора if then else применяется для проверки при наличии более чем двух условий,
18.3.23. Несколько проверок, реализуемых с помощью elif
В следующем несложном примере протестируем введенные в сценарий имена пользователей.
Сначала в сценарии проверяется, действительно ли пользователь ввел имя; если имя не введено, то проверка не выполняется. Если имя введено, с помощью части elif проверяется, совпадает ли имя с root, louise или dave. В случае несовпадения имени ни с одним из перечисленных имен на экран выводится сообщение, что пользователь не является пользователем root, louise или dave.
$ pg ifelif
#!/bin/sh
# ifelif
echo -n "enter your login name :"
read NAME
# имя не введено, рассмотрение прекращается
if [ -z $NAME ] || [ "$NAME"="" ]; then
echo "You did not enter a name"
elif
# является ли именем root
[ "$NAME"="root" ]; then echo "Hello root"
elif
# именем является louise
[ $NAME="louise" ]; then echo "Hello louise"
elif
# именем является dave
[ "$NAME"="dave" ]; then echo "Hello dave"
else
# нет, это какое‑то другое имя
echo "You are not root or louise or dave but hi $NAME"
fi
При выполнении приведенного сценария с использованием различных регистрационных имен получим следующее:
$ ifelif
enter your login name : dave Hello dave
$ ifelif
enter your login name : You did not enter a name
$ ifelif2
enter your login name : peter
You are not root or louise or dave but hi peter
18.3.24. Проверка нескольких вариантов размещения файла
Предположим, что к файлу проверки регистрации требуется применить команду cat. Файл в зависимости от того, кто из пользователей выполнял инсталляцию. находится либо в каталоге /usr/opts/audit/logs, либо в каталоге /usr/Iocal/audit/logs. Перед применением к файлу команды cat следует убедиться в том, что его можно просматривать; именно это и будет уточняться при проверке. Если файл нельзя найти или же его нельзя просматривать, на экран выводится сообщение об ошибке. Ниже приводится соответствующий сценарий:
$ pg ifcataudit
#!/bin/sh
#ifcataudit
#размещение файла регистрации
LOCAT_1=/usr/opts/audit/logs/audit.log
LOCAT_2=/usr/local/audit/audit, logs
if [ -r $LOCAT_1]; then
#если файл находится в этом каталоге и может просматриваться,
#применим к нему команду cat echo "Using L0CAT_1"
cat $LOCAT_1
elif
# иначе, файл должен находиться в этом каталоге и можно его просматривать
[ -r §L0CAT_2 ]
then
echo "Using LOCAT_2"
cat $LOCAT_2
else
# нет ни в одном каталоге…
echo `basename $0`: Sorry the audit file ls not readable or cannot be located." >S2
exit 1
fi
Если при выполнении указанного сценария установлено, что файл находится в каком‑либо из двух каталогов и может просматриваться, то к нему можно применить команду cat. В противном случае на экран выводится сообщение об ошибке, и сценарий завершается. Этот пример неудачен, поскольку наш воображаемый файл отсутствует.
$ ifcataudit
ifcataudit: Sorry the audit file ls not readable or cannot be located.
18.4. Оператор case
Оператор case является многовариантным оператором. С его помощью можно искать значения, используя заданный шаблон. Если совпадение с шаблоном установлено, можно выполнять команды, основываясь исключительно на этом соответствии. Ниже приводится формат оператора case:
case значение in шаблон1)
команды1
;;
шаблон2)
команды2
;;
esac
Рассмотрим, как функционирует оператор case. После значения должен находиться предлог "in", а каждый шаблон должен завершаться правой скобкой. В качестве значения может применяться переменная или константа. Когда устанавливается соответствие с шаблоном, для этого шаблона выполняются все команды вплоть до символов ;;.
Поиск значения, совпадающего с шаблоном, выполняется по каждому шаблону. Если устанавливается соответствие с шаблоном, то оставшиеся шаблоны уже не проверяются. Эти шаблоны не принимаются во внимание даже после выполнения команд, относящихся к шаблону, с которым установлено соответствие. Если поиск соответствия по всем шаблонам оказался безрезультатным, можно принять значение с помощью символа звездочки. Этот символ используется для фиксации любых вводимых данных.
Шаблонная часть может содержать метасимволы. Аналогичным образом соответ–ствие с шаблоном устанавливается при обработке расширений имен файлов в командной строке:
* Произвольные символы
? Произвольный отдельный символ
[. . ] Произвольный символ из класса или диапазона
А теперь рассмотрим несколько примеров.
18.4.1. Простой оператор case
Следующий сценарий отображает приглашение для ввода чисел от 1 до 5. Число передается оператору case, переменной ans присваивается значение ans оператора case, и значение ANS сравнивается с каждым шаблоном.
Если соответствие установлено, команды из шаблонной части выполняются до тех пор, пока не появятся символы ;;. Тогда на экран выводится команда, которая информирует пользователя о сделанном выборе. Затем выполнение оператора case завершается, поскольку совпадение с шаблоном установлено.
Далее выполняются операции, находящиеся после оператора case.
Если соответствие не найдено, с помощью шаблона * выполняется прием всей информации. Затем отображается сообщение об ошибке.
$ pg caseselect
#!/bin/sh
# caseselect
echo -n "enter a number from 1 to 5 :"
read ANS
case $ANS in
1) echo "you select 1"
;;
2) echo "you select 2"
;;
3) echo "you select 3"
;;
4) echo "you select 4"
;;
5) echo "you select 5"
;;
*) echo "`basename $0`: This is not between 1 and 5" >&2
;;
exit 1
esac
Если этот сценарий выполняется с различными вводимыми данными, получим:
$ caseselect
enter a number from 1 to 5 : 4 you select 4
С помощью шаблона * выполним прием информации, с которой не установлено соответствия:
$ caseselect
enter a number from 1 to 5 :pen
caseselect: This ls not between 1 and 5
18.4.2. Применение символа | при поиске по шаблону
При использовании оператора case в качестве команды or можно указывать символ. Например, vt100|vt102) соответствует шаблону vt100 или vt102.
В следующем примере у пользователя запрашивают тип терминала. Если пользователь вводит vt100 или vt102, выполняется сравнение с шаблоном "vtl00| vtl02)". В данном случае переменной term присваивается значение vt100. Если пользователь
указывает тип терминала, который не соответствует шаблону, с помощью шаблона * выполняется прием этой информации и значение типа терминала все равно устанавливается как vt100. Наконец, за пределами действия оператора case производится экспорт переменной term. Независимо от тех сведений, которые вводит пользователь, переменная term представляет действительный тип терминала, поскольку используется поиск по шаблону*.
$ pg caseterm
#!/bin/sh
# caseterm
echo " choices are.. vt100, vtl02, vt220"
echo -n "enter your terminal type :"
read TERMINAL
case $TERMINAL in
vtl00|vt102) TERM=vt100
;;
vt220) TERM=vt220
;;
*) echo "`basename $0`: Unknown response" >&2
;;
echo "setting it to vt100 anyway, so there"
TERM=vt100
esac
export TERM
echo "Your terminal ls set to $TERM"
Если при выполнении сценария указывается некорректный тип терминала, получим следующее:
$ caseterm
choices are.. vt100, vtl02, vt220 enter your terminal type :vt900
caseterm: Unknown response setting it to vt100 anyway, so there
Your terminal ls set to vt100
Если вводится существующий тип терминала, получим:
$ case2
choices are.. vt100, vtl02, vt220 enter your terminal type :vt220
Your terminal ls set to vt220
В любом случае пользователь устанавливает тип терминала.
18.4.3. Приглашение для ввода y или n
Оператор case удобно применять при отображении запроса на продолжение обработки. Ниже приводится сценарий, в котором пользователю предлагается указать в качестве ответа либо 'у', что означает продолжение обработки, либо 'n' – выход из сценария. Если пользователь введет у, Y, yes или Yes, обработка будет продолжена в соответствии с частью сценария после оператора case. Если пользователь введет n, N, no или какой‑либо другой ответ, работа со сценарием для него завершается.
$ pg caseans
#!/bin/sh
# caseans
echo -n "Do you wish to proceed [y..n] :"
read ANS
case $ANS in
y|Y|yes|Yes) echo "yes is selected"
;;
n|N) echo "no is selected"
exit 0 # нет ошибки, поэтому для выхода укажите 0
;;
*) echo "`basename S0`" : Unknown response" >&2
exit 1
;;
esac
# если мы оказались здесь, были выбраны значения y|Y|yes|Yes.
Если при выполнении указанного сценария выбрать некорректный вариант ответа, отображаются следующие данные:
$ caseans
Dо you wish to proceed [y..n] :df
caseans : Unknown response
В случае корректного ответа:.
$ caseans
Dо you wish to proceed [y..n] :y
yes is selected
18.4.4. Оператор case и передача командных параметров
Можно также использовать оператор case при передаче параметров в сценарии.
В следующем сценарии при осуществлении проверки используется специальный параметр $#, который представляет число передаваемых аргументов. Если это число отлично от 1, сценарий завершает работу, отображая соответствующее сообщение.
Затем оператор case выполняет прием следующих параметров: passwd, start, stop или help. В дальнейшем код реализуется для каждого совпадения с этими шаблонами. При передаче неизвестного значения на экран выводится стандартное сообщение об ошибке.
$ pg caseparam
#!/bin/sh
# caseparam
if [ $# != 1 ]; then
echo "Usage:`basename $0` [start | stop | help] >&2
exit 1
fi;
# присвойте переменной ОРТ параметр
OPT=$1
case $OPT in
start) echo "starting… `basename $0`"
# здесь коды для начала процесса
;;
stop) echo "stopping..`basenarae $0`"
# здесь колы для прекращения процесса
;;
help)
# здесь находится код для отображения справочной страницы
;;
*) echo "Usage: `basename $0` [start | stop | help]"
;;
esac
Если сценарию передается неверный параметр, получим следующее:
$ caseparam what
Usage:caseparam [start|stop | help]
В случае передачи действительного параметра:
$ caseparam stop
stopping..caseparam
18.4.5. Прием потока ввода без применения шаблонных команд
После шаблонной части необязательно указывать команды; если после шаблонной части команды отсутствуют, до перехода к дальнейшей обработке выполняется фильтрация нежелательных откликов.
Если в отдел учета следует направить отчет об учетной записи, сначала желательно удостовериться, что пользователь правильно ввел номер отдела, а затем уже уточнить, какой отчет выполняется. Такой подход реализуется при сравнении с шаблоном всех требуемых значений; любые другие методы неприемлемы.
В следующем сценарии указано, что если пользователь вводит номер отдела, который не совпадает со значением 234, 453, 655 или 454, то пользователь выйдет из сценария. Если номер отдела указан правильно, аналогичный подход применяется при определении типа отчета. По окончании выполнения оператора case остаются действительный номер отдела и правильный тип отчета. Ниже приводится соответствующий сценарий.
$ pg casevalid
#!/bin/sh
# casevalid
TYPE=""
echo -n "enter the account dept No: :"
read ACC
case $ACC in
234);;
453);;
655);;
454) ;;
*) echo "`basename $0`: Unknown dept No:" >&2
echo "try..234,453,655,454" exit, 1
esac
# если оказались здесь, получен верный номер отдела
echo " 1. post"
echo " 2. prior"
echo -n "enter the type of report: "
read ACC_TYPE
case $ACC_TYPE in
l)TYPE=post;;
2}TYPE=prior;;
*) echo "`basename $0`: Unknown account type." >&2
exit 1
;;
esac
# если оказались здесь, значит все указано правильно!
echo "now running report for dept $ACC for the type $TYPE"
# выполняем отчет о команде.
Если вводимые данные достоверны, получим:
$ casevalid
enter the account dept No: :234
1. . post
2. . prior
enter the type of report:2
now running report for dept 234 for the type prior
Если номер отдела введен неверно, получим:
$ casevalid
enter the account dept No: :432
casevalid: Unknown dept No: try..234,453,655,454
При вводе неправильного типа отчета, получим:
$ casevalid
enter the account dept No: :655
1. . post
2. . prior
enter the type of report:4
casevalid: Unknown account type.
18.4.6. Значения переменных, заданные по умолчанию
Если при просмотре значения переменной пользователь нажимает клавишу [Return], сценарий завершает работу не всегда. С помощью проверки определяется, установлена ли данная переменная, и если не установлена, то ей может быть присвоено значение.
В следующем сценарии для выполнения отчета пользователю предлагают ввести название дня недели. Если пользователь нажимает клавишу [Return], используется день недели, заданный по умолчанию, а именно "Saturday". Это название и присваивается переменной when.
Если пользователь вводит название другого дня, с помощью оператора case выполняется проверка, совпадает ли введенное название с названием одного из дней недели, предназначенных для выполнения сценария, а именно "Saturday", "Sunday"
и "Monday". Обратите внимание, что всевозможные аббревиатуры названий дней недели составлены так, чтобы выполнялся перехват "всех возможных" комбинаций этих названий.
Ниже приводится соответствующий сценарий.
$ pg caserep
#!/bin/sh
# caserep
echo " Weekly Report"
echo -n "What day do you want to run report [Saturday] :"
#если нажать клавишу ввода, принимается заданное по умолчанию название Saturday
read WHEN
echo "validating..
${WHEN:="Saturday"}"
case $WHEN in Monday|MONDAY|mon);;
Sunday|SUNDAY|sun);;
Saturday|SATURDAY}sat);;
*) echo " Are you nuts!, this report can only be run on " >&2
echo " on a Saturday, Sunday or Monday" >&2
exit 1
esac
echo "Report to run on $WHEN"
# здесь команда для выполнения действительного отчета
При корректных начальных данных получим:
$ caserep
Weekly Report What day do you want to run report [Saturday] : validating..Saturday Report to run on Saturday
Если начальные данные были неправильны, получим:
$ caserep
Weekly Report What day do you want to run report [Saturday] :Tuesday validating..Tuesday
Are you nuts! this report can only be run on a Saturday, Sunday or Monday
Можно заключить, что оператор case функционирует так же, как и несколько операторов if then else. Такой вывод вполне правомерен.
18.5. Цикл for
Общий формат цикла:
for имя_перемениой in list
do
команда1 команда…
done
Цикл for однократно обрабатывает всю информацию для каждого значения, включенного в список list. Чтобы получить доступ к каждому значению в списке, достаточно задать параметр имя_переменной. Командой служит любая действительная команда или оператор интерпретатора shell. В качестве параметра имя_переменной можно указать любое слово.
Применение опции in list не является обязательным; если не включать эту часть, цикл воспользуется позиционными параметрами командной строки.
Опция in list может содержать подстановки, строки и имена файлов. Рассмотрим несколько примеров.
18.5.1. Простой цикл for
Этот цикл просто выводит на экран список, который состоит из " 1 2 3 4 5". Чтобы получить доступ к каждой переменной, в качестве параметра имя_переменной указывается "loop".
$ pg for_i
#!/bin/sh
# for_i
for loop in 1 2 3 4 5
do
echo $LOOP done
Приведенный выше сценарий выводит следующие данные:
$ for_i
1
2
3
4
5
18.5.2. Вывод на экран строки списка
Ниже приводится цикл for, список которого содержит строку значений "orange red blue grey". Для каждой переменной указана команда echo, в качестве параметра имя_переменной указывается loop. Команда echo с помощью части $LOOP выводит на экран каждое значение списка до тех пор, пока список не окажется пустым.
$ pg forlist
#!/bin/sh
# forlist
for LOOP in orange red blue grey
do
echo $LOOP
done
$ forlist
orange
red
blue
grey
Также с помощью цикла имя_переменной можно комбинировать строки (в данном случае речь идет о цикле loop).
echo "this ls the fruit $LOOP"
Результат:
This ls the fruit orange red blue grey
18.5.3. Использование команды ls совместно с циклом for
Этот цикл оценивает команду ls интерпретатора shell и отображает сведения о файлах текущего каталога.
$ pg forls
#!/bin/sh
# forls
for loop in `ls`
do
echo $LOOP
done
$ forls
array
arrows
center
center1
center2
centerb
18.5.4. Применение параметров вместе с циклом for
Если в цикле for опустить часть in list, позиционные параметры командной строки становятся аргументами. Действительно, этот подход аналогичен следующему:
for params in "$@"
или
for params in "$*"
Ниже приводится пример, который показывает, как можно избежать применения конструкции in list. Цикл for обращается к специальному параметру $@ или $* для получения аргументов из командной строки.
$ pg forparam2
#/bin/sh
# forparam2
for params in $*
do
echo "You supplied $params as a command line option"
done
echo $params done
$ forparam2 myfile1 myfile2 myfile3
You supplied myfile1 as a command line option
You supplied myfile2 as a command line option
You supplied myfile3 as a command line option
Следующий сценарий содержит часть in "$@" и образует тот же самый поток вывода, что и предыдущий сценарий.
$ pg forparam3
#!/bin/sh
# forparam3
for params in $@
do
echo "You supplied $params as a command line option"
done
echo $params done
Если развить этот подход далее и осуществлять поиск набора файлов, то совместно с циклом for можно применять команду find . При передаче всех файлов используют преимущество параметра командной строки.
$ pg forfind
#!/bin/sh
# forfind
for LOOP in $@
do
find / -name $LOOP -print
done
Значения передаются с помощью параметра командной строки и образуют часть -name команды find .
$ forfind passwd LPSO.AKSOP
/etc/passwd
/etс/pam.d/passwd
/etc/uucp/passwd
/usr/bin/passwd
/usr/local/accounts/LPSO.AKSOP
18.5.5. Посылка сигналов серверам с помощью цикла for
Поскольку цикл for может обработать каждое слово списка, установим переменную для отображения названий некоторых серверов сети. Воспользуемся циклом for для посылки сигналов каждому из этих серверов.
$ pg forping
#!/bin/sh
# forping
HOSTS=”1itserv dnssevr acctsmain ladpd ladware"
for loop in $HOSTS
do
ping -c 2 $LOOP
done
18.5.6. Создание резервных копий файлов с помощью цикла for
Цикл for можно использовать для создания резервных копий файлов. При этом переменная просто добавляется к целевому аргументу команды ср. Ниже применяется переменная под названием ВАК. Эта переменная добавляется к каждому имени целевого файла при использовании цикла с помощью команды ср. Список включает shell–команду ls.
$ pg forcp
#!/bin/sh
# forcp
BAK=".bak"
for loop in `ls`
do
echo "copying $LOOP to $LOOP$BAK"
cp $LOOP $LOOP$BAK done
$ forcp
copying array to array.bak
copying arrows to arrows.bak
copying center to center.bak
copying center1 to center1.bak
18.5.7. Массовое преобразование
Чтобы найти все файлы, которые начинаются символами "LPSO", и преобразовать их содержимое в символы верхнего регистра, используются команды ls и cat. Команда ls отображает список файлов, а команда cat применяется для передачи списка команде tr. Передаваемые файлы получают расширение UC. Обратите внимание, что при использовании в цикле for команды ls применяются обратные кавычки.
$ pg forUC
#!/bin/sh
# forUC
for files in Us LPSO*'
do
cat $files | tr "[a‑z]" "[A‑Z]" > $files.UC
done
18.5.8. Удаления, выполняемые с помощью редактора sed
В следующем примере для удаления всех пустых строк применяется потоковый редактор sed. Выходной поток данных направляется в новые файлы с расширением .HOLD. Затем команда mv возвращает файлам их исходные имена.
$ pg forsed
#!/bin/sh
# forsed
for files in `ls LPSO*` do
sed -e "/^$/d" $files > $files. HOLD
mv $flies. HOLD $files
done
18.5.9. Подсчет с помощью циклов
При обсуждении команды expr отмечалось, что эта команда применяется, если в циклы необходимо ввести счетчики. Ниже рассматривается пример, в котором цикл for обрабатывает файлы, а вывод и подсчет количества файлов осуществляется с помощью команды ls.
$ pg forcount
#!/bin/sh # forcount counter=0
for files in *
do
# increment
counter=`expr $COUNTER + 1`
done
echo "There are $COUNTER files in `pwd` we need to process"
$ forcount
There are 45 files in /apps/local we need to process
Аналогичный результат можно получить с помощью команды wc.
$ ls |wc -l
45
18.5.10. Циклы for для обработки документов
С циклом for можно комбинировать любые команды. В приведенном примере переменная содержит имена всех зарегистрированных пользователей. Для реализации этой конструкции обращаются к команде who и утилите awk. Затем цикл for обрабатывает имена этих пользователей и каждому высылает электронное сообщение. При отправке сообщения используется конструкция "документ здесь".
$ pg formallit
#!/bin/sh
# formallit
WHOS_ON=`who -u | awk '{print $1}'`
for user in $WHOS_ON
do
mail $user << MAYDAY
Dear Colleagues,
It's my birthday today, see you down the
club at 17:30 for a drink.
See ya.
$LOGNAME
MAYDAY
done
Ниже приводится электронное сообщение для данного сценария.
$ pg mbox
Dear Colleagues,
It's my birthday today, see you down the
club at 17:30 for a drink.
See ya. dave
18.5.11. Вложенные циклы for
Чтобы вложить, циклы, достаточно цикл for поместить в другой цикл:
for имя_переменной in list
do
for имя_переменной2 in list2
do
команда1
done
done
В следующем сценарии представлен вложенный цикл for. Имеются два списка, APPS и SCRIPTS, первый из которых содержит путь к приложениям на сервере, а второй включает административные сценарии, которые выполняются для каждого приложения. Для каждого приложения из списка apps имеется соответствующее название сценария в списке SCRIPTS. Обычно сценарии выполняются в фоновом режиме (с помощью указания префикса &). Данный сценарий посредством команды tee размещает также запись в журнальном файле, поэтому наряду с файлом на экране отображается поток выходных данных. Обратите внимание на выходные данные, чтобы понять, как цикл for использует список SCRIPTS при обработке элементов списка apps.
$ pg audit_run
#!/bin/sh
# audit_run
APPS="/apps/accts /apps/claims /apps/stock /apps/serv"
SCRIPTS="audit.check report.run cleanup"
LOGFILE=audit.log
MY_DATE=`date +%H:%M" on "%d/%m%Y`
# внешний цикл
for loop in $APPS
do
# внутренний цикл
for 1оор2 in $SCRIPTS
do
echo "system $LOOP now running $LOOP2 at $MY_DATE" | tee -a $LOGFILE
$LOOP $LOOP2 &
done
done
$ audit_run
system /apps/accts now running audit.check at 20:33 on 23/051999
system /apps/accts now running report.run at 20:33 on 23/051999
system /apps/accts now running cleanup at 20:33 on 23/051999
system /apps/claims now running audit.check at 20:33 on 23/051999
system /apps/claims now running report.run at 20:33 on 23/051999
system /apps/claims now running cleanup at 20:34 on 23/051999
system /apps/stock now running audit.check at 20:34 on 23/051999
system /apps/stock now running report.run at 20:34 on 23/051999
system /apps/stock now running cleanup at 20:34 on 23/051999
system /apps/serv now running audit.check at 20:34 on 23/051999
system /apps/serv now running report.run at 20:34 on 23/051999
system /apps/serv now running cleanup at 20:34 on 23/051999
18.6. Цикл until
Цикл until позволяет выполнять ряд команд, пока условие остается истинным. Практически цикл until противоположен по смыслу циклу while. Цикл while является более предпочтительным, но в определенных случаях цикл until лучше справляется с работой. Формат цикла until:
until условие
команда1
done
В качестве условия выступает любое действительное проверочное условие. Проверка производится в конце цикла, поэтому в любом случае цикл выполняется однократно – не забывайте об этом обстоятельстве. А теперь рассмотрим несколько примеров.
18.6.1. Простой цикл until
Этот сценарий непрерывно ищет пользователя "root" и выполняет команду who. Результат выполнения команды grep содержится в переменной IS_ROOT.
Если пользователь "root" обнаружен, цикл завершает обработку. Затем пользователю simon направляется электронное сообщение, в котором отмечается, что пользователь "root" зарегистрирован. Обратите внимание на применение команды sleep, которая довольно часто используется в циклах until. Эта команда дает возможность приостановить выполнение цикла на несколько секунд, что позволяет указать дополнительные команды.
$ pg until_who
#!/bin/sh
# until_who
ls_ROOT=`who | grep root`
until [ "$IS_ROOT" ]
do
sleep 5
done
echo "Watch it. roots in " | mail simon
18.6.2. Контроль наличия файла
В этом примере в цикле until выполняется команда "sleep 1" до тех пор, пока не будет удален файл под именем /tmp/monitor. LCK. После удаления файла сценарий продолжает выполняться в обычном режиме.
$ pg until_lck
#!/bin/sh
# until_lck
LOCK_FILE=/trap/process. LCK
until [ ! – f $1OCK_FILE ]
do
sleep 1 done echo "file deleted "
# обычная обработка, файл имеется
В приведенном примере показан один из методов, обеспечивающий совместную работу сценариев при выполнении.
В данном случае речь идет об одном из методов взаимодействия сценариев. Предположим, что другой сценарий, например process_main, используется для сбора информации со всех компьютеров локальной сети и размещения этих данных в файле отчета.
Когда выполняется сценарий process_main, создается файл lck (файл блокировки). Приведенный выше сценарий получает информацию, собранную сценарием process_main. Однако он не обрабатывает файл, если сценарий process_main продолжает обновление файла отчета.
Чтобы устранить эти затруднения, сценарий process_main создает файл lck при запуске и удаляет его при завершении работы.
Рассматриваемый сценарий ожидает удаления файла LCK. После того как файл lck удален, сценарий может обрабатывать содержимое файла отчета.
18.6.3. Мониторинг дисковой памяти
Цикл until также полезно применять для контроля состояния системы. Предположим, что необходимо уточнить пространство, занимаемое файлами на диске, и направить пользователю "root" электронное сообщение по достижении определенного уровня.
В следующем сценарии просматривается система файлов /logs. С помощью утилиты awk и команды grep информация постоянно извлекается из переменной $LOOK_out. Значения этой переменной характеризуют объем, занимаемый системой файлов /logs.
Если занятый объем превышает 90%, опция command запускает триггер, пользователю "root" направляется сообщение и сценарий завершает работу. Сценарий следует завершить, поскольку в противном случае, если условие истинно (например, занятый объем по–прежнему превышает 90%(, электронное сообщение пользователю "root" будет высылаться непрерывно.
$ pg until_mon
#!/bin/sh
#until_ mon
# получите столбец со значениями процентов и удалите заголовок строки из df