Текст книги "Linux и UNIX: программирование в shell. Руководство разработчика"
Автор книги: Дэвид Тейнсли
сообщить о нарушении
Текущая страница: 21 (всего у книги 25 страниц)
# pskill
HOLD1=/tmp/HOLD1.$$
PROCESS=$1
usage () {
# usage
echo "Usage :''`basename $0` process_name"
exit 1
}
if [ $# -ne 1 ]; then
usage
fi
case $1 in
*)
применение программы grep для исключения нашего сценария из вывода команды ps
извлечение полей 1 и 6, перенаправление во временный файл
ps x | grep $PROCESS | grep -v $0 | awk '{print $1"t" $6}'>$HOLD1
# ps -ef |.. если команда ps x не срабатывает
;;
esac
#есть ли файл??
if [ ! -s $HOLD1 ]; then
echo "No processes found…sorry"
exit 1
fi
#просмотр содержимого временного файла и отображение значений полей
while read LOOP1 LOOP2
do
echo $LOOP1 $LOOP2
done <$HOLD1
echo -n "Are these the processes to be killed? [y..n] >"
read ANS
case $ANS in
Y|y) while read LOOP1 LOOP2
do
echo $LOOP1
kill -9 $LOOP1 done
<$HOLD1
rm /tmp/*.$$
;;
N|n);;
esac
При выполнении сценария поток вывода имеет вид:
$ pskill web
1760 ./webmon
1761 /usr/apps/web_col
Are these the processes to be killed? [y..n] >y
1760 1761 [1]+ Killed webmon
Чтобы убедиться в том, что процесс уничтожен, введите команду повторно:
$ pskill web
No processes found..sorry
26.2.2. Обнаружение сигнала
Некоторые сигналы можно захватить и выполнить соответствующие действия. Другие сигналы нельзя уловить. Например, если команда получает сигнал 9, пользователю не нужно предпринимать какие‑либо действия.
Если ограничиться написанием сценариев, следует обращать внимание только на сигналы 1,2,3 и 15. Если сценарий получает сигнал, возможен один из трех вариантов дальнейших действий: 1. Ничего не предпринимать, система самостоятельно отреагирует на полученный
сигнал.
1. Захватить сигнал, но игнорировать его.
2. Захватить сигнал и предпринять определенные действия.
Большинство сценариев используют сигнал с номером 1. Этот метод применяется далее в книге во всех сценариях.
Чтобы применить два других метода, нужно воспользоваться командой trap.
26.3. Команда trap
Команда trap позволяет перехватывать сигналы. Формат команды trap:
trap "имя" сигнал(ы)
Имя представляет собой функцию, содержащую инструкции, которые выполняются при перехвате сигнала. В действительности функцию следует называть так, чтобы ее имя было связано именно с перехваченными сигналами. Имя следует заключать в двойные кавычки (""). Сигналы являются входящими.
Когда сигнал перехватывается, сценарий обычно находится в стадии обработки. Самые распространенные действия следующие:
1. Очистить временные файлы.
2. Игнорировать сигналы.
3. Запросить пользователя, следует ли завершить сценарий.
Ниже приводится таблица, где описаны наиболее распространенные варианты применения команды trap:
trap "" 2 3
Игнорирование сигналов 2 и 3; пользователь не может
завершить сценарий
trap "команды" 2 3
Если захвачены сигналы 2 и 3, выполняются команды
trap 2 3
Восстановление сигналов 2 и 3; пользователь может завер-
шить сценарий
Вместо двойных кавычек можно использовать одинарные; результат будет аналогичен.
26.3.1. Перехват сигналов и выполнение действий
А теперь создадим сценарий, выполняющий подсчет итераций до тех пор, пока пользователь не нажмет комбинацию клавиш [Ctrl+C] (сигнал 2). После этого сценарий отобразит сообщение, содержащее номер текущей итерации цикла.
В этом случае применяется следующий формат:
trap "какие‑либо действия" номер сигнала: (s)
Соответствующий сценарий имеет вид:
$ pg trap1
#!/bin/sh
#trap1
trap "my_exit" 2
LOOP=0
my_exit ()
{
echo "You just hit
echo " I will now exit "
exit 1
}
while : do
LOOP=`expr $LOOP + 1`
echo $LOOP
done
Рассмотрим сценарий более подробно.
trap "my_exit" 2
В результате выполнения команды trap после получения сигнала 2 выполняется команда, заключенная в двойные кавычки; в данном случае вызывается функция
my_exit.
my_exit ()
{
echo "You just hit
echo " I will now exit "
exit 1
}
Функция myexit вызывается при получении сигнала 2; при этом отображается значение переменной $LOOP, информирующее пользователя о том, какая итерация цикла выполнялась при нажатии комбинации клавиш [Ctrl+C]. Функции подобного типа применяются на практике для удаления временных файлов.
При выполнении сценария получим следующие результаты:
$ trap1
211 212
You just hit
26.3.2. Захват сигнала и выполнение действий
Наиболее часто выполняемым действием является удаление временных файлов.
В следующем сценарии с помощью команд df и ps непрерывно добавляется информация во временные файлы HOLD1.$$ и HOLD2.$$. Не забывайте, что символы $$ заменяют ID процесса. Когда пользователь нажимает комбинацию клавиш [Ctrl+C], эти файлы удаляются.
$ pg trap2
#!/bin/sh
# trap2
# перехват только сигнала 2….
trap "my_exit" 2
HOLD1=/tmp/HOLD1.$$
HOLD2=/tmp/HOLD2.$$
my_exit {)
{
# my_exit
echo "
# удаление временных файлов
rm /tmp/*.$$ 2>/dev/null
exit 1
}
echo "processing…."
# основной цикл
while :
do
df >> $HOLD1
ps xa >>$HOLD2
done
Результаты выполнении этого сценария будут следующими:
$ trap2
processing….
При получении сигнала можно предоставлять пользователю определенный выбор. Однако если получены сигналы 2 или 3, следует убедиться, что они не появились случайно. Необходимо предусмотреть поток ошибок, благодаря чему выявляется ошибочное нажатие клавиш [Ctrl+C].
В следующем примере пользователю предоставляется возможность решить, следует ли выйти из сценария после получения сигнала 2. Отображается запрос о том, действительно ли пользователь желает завершить работу. Для уточнения предпринимаемого действия применяется конструкция case.
Если пользователь желает выйти из сценария, он выбирает 1, в результате чего после отображения статуса "exit 1" запускается процесс очистки. Если пользователь не желает выходить из сценария, никакие действия не производятся; зададим, что при выполнении конструкции case результаты выбора будут неудачными и произойдет возврат к исходному коду. Конечно, при подтверждении должны захватываться значения всех пустых полей.
Далее приводится функция, которая при получении сигнала предоставляет пользователю возможность выбора.
my_exit () {
# my_exit
echo -e "nReceived interrupt …"
echo "Do you really wish to exit ???"
echo " 1: Yes" echo " 2: No"
echo -n " Your choice [1..2] >"
read ANS
case $ANS in
1) # удаление временных файлов.. и т. д…
exit 1
;;
# не выполняет ничего
;; esac
}
Соответствующий сценарий выглядит так:
$ pg trap4
#!/bin/sh
#trap4
#перехват сигналов 1 2 3 и 15
trap "my_exit" 1 2 3 15
LOOP=0
# временные файлы
HOLD1=/tmp/HOLD1.$$
HOLD2=/tmp/HOLD2.$$
my_exit() {
# функция my_exit
echo -e "nRecieved interrupt…"
echo "Do you wish to really exit ???"
echo " Y: Yes"
echo " N: No"
echo -n " Your choice [Y..N] >"
read ANS
case $ANS in
Y|y) exit 1;; # выход из сценария
N|n) ;; # возврат к обычной обработке
esac
}
# цикл while применяется здесь, например, для просмотра полей
echo -n "Enter your name :"
read NAME
echo -n "Enter your age :"
read AGE
Если при выполнении этого сценария происходит нажатие клавиш [Ctrl+C] в середине поля ввода (сразу после начала ввода имени), то пользователю предоставляется выбор: возвратиться к обычной обработке или выйти из сценария.
$ trap4
Enter your name :David Та
Received interrupt…
Do you really wish to exit ???
1: Yes
2: No
Your choice [1. .2] >2
Enter your age :
26.3.3. Блокировка терминала
Ниже приводится сценарий, в котором предлагается другой путь для перехвата сигналов в функционирующем сценарии. Сценарий lockit блокирует терминал пользователя с помощью командной строки. При этом командная строка помещается в непрерывный цикл while. Команда trap захватывает сигналы 2, 3 и 15. Если пользователь пытается прервать выполнение сценария, отображается сообщение о том, что действия пользователя не были успешными.
При первом обращении к сценарию запрашивается пароль. Для отмены блокировки терминала сведения поступают из устройства /dev/tty, следовательно, отсутствует запрос на разблокировку терминала; нужно просто ввести пароль и нажать клавишу ввода.
Если пользователь забыл пароль, нужно зарегистрироваться на другом терминале и устранить сценарий. Проверка длины пароля не производится, но при желании ее можно установить.
Если сценарий уничтожен с помощью другого терминала, можно вернуться на ваш терминал и разобраться с проблемами, связанными с настройками терминала: например, выяснить, почему не функционирует клавиша ввода. По командному запросу воспользуйтесь приведенной подсказкой. Это позволит устранить большую часть затруднений, связанных с терминалом.
$ stty sane
Сценарий имеет вид:
$ pg lockit
#!/bin/sh
#lockit
#перехват сигналов 2 3 и 15
trap "nice_try" 2 3 15
#устройство, на котором выполняется сценарий
TTY=`tty`
nice_try () {
# nice_try
echo "Nice try, the terminal stays locked"
}
# сохраните настройки stty, скрытие символов при вводе пароля
SAVEDSTTY=`stty -g`
stty -echo
echo -n "Enter your password to lock $TTY :"
read PASSWORD
clear
while : do
# чтение только из tty !!
read RESPONSE < $TTY
if [ "$RESPONSE"="$PASSWORD" ]; then
# пароль соответствует…разблокировка
echo "unlocking…"
break
fi
#отображение сообщения, если пользователь введет неверный пароль
#или нажмет клавишу ввода
echo "wrong password and terminal is locked.."
done
# восстановление настроек stty stty=$SAVEDSTTY
Вывод сценария lockit:
$ lockit
Enter your password to lock /dev/tty1 :
Затем экран очищается. При нажатии клавиши ввода или наборе неверного пароля сценарии выводит следующие данные:
wrong password and terminal is locked..
Nice try, the terminal stays locked
wrong password and terminal is locked..
Nice try, the terminal stays locked '
wrong password and terminal is locked..
Введите правильный пароль
unlocking… $
Теперь возвращаемся обратно, в командную строку.
26.3.4. Игнорирование сигналов
Когда пользователь регистрируется в системе, просматривается файл /etc/profile; нежелательно, чтобы пользователь прерывал этот процесс. Обычно задается перехват, или игнорирование, сигналов 1, 2, 3 и 15, но потом при просмотре сообщения motd (ежедневного сообщения) их подключают вновь (восстанавливают). Затем для игнорирования сигналов 1, 2, 3 и 15 снова устанавливается перехват.
Аналогичный подход можно, реализовать при работе со сценариями. Можно ввести понятие критического момента, который наступает при открытии большого количества файлов. Начиная с этого момента, нельзя прерывать выполнение сценария, поскольку это может повредить файлы. Для решения этой проблемы следует установить, команду trap, что позволит игнорировать некоторые сигналы. Когда завершится критический момент в функционировании сценария, примените команду trap, чтобы снова можно было захватывать сигналы.
Для игнорирования входящих сигналов (кроме сигнала 9) применяется следующая команда:
trap "" номер_сигнала:{n}
Обратите внимание, что двойные кавычки ничего не содержат. Чтобы восстановить перехват и заново захватывать сигналы, выполните команду:
trap "любые действия" номер_сигнала:{n}
Суммируем сведения о процессах игнорирования и выявления сигналов.
trap "" 1 2 3 15 # игнорирование сигналов code that does really critical stuff
trap "my_exit" 1 2 3 15 # выполните снова захват сигналов с помощью функции
# my_exit
Обратите внимание на сценарий, выполняющий критическую обработку. Цикл while аккуратно передвигает имеющийся критический момент. Для игнорирования сигналов 2, 3 и 15 применяется команда trap. После завершения цикла while, завершается еще один цикл while, но перехват уже восстановлен и прерывания разрешены.
Оба цикла while выполняются до завершения шести итераций, затем в цикле активизируется команда sleep. Благодаря этому имеется достаточно времени для того, чтобы прервать выполнение сценария.
Рассмотрим следующий сценарий:
$ pg trap_ignore
#!/bin/sh
#trap_ignore
#игнорирование сигналов
trap "" 1 2 3 15
LOOP=0
my_exit ()
# my_exit
{
echo "Received interrupt on count $LOOP"
echo "Now exiting…" exit 1
}
# критическая обработка, нельзя прерывать….
LOOP=0
while : do
LOOP=`expr $LOOP + 1`
echo "critical processing..$LOOP..you cannot interrupt me"
sleep 1
if [ "$LOOP" -eq 6 ]; then
break
fi
done
LOOP=0
#критическая обработка завершена, перехват задан снова, но разрешены прерывания
trap "my_exit" 1 2 3 15
while :
do
LOOP=`expr $LOOP + 1`
echo "Non‑critical processing..$LOOP..interrupt me now if you want"
sleep 1
if [ "$LOOP" -eq 6 ]; then
break
fi
done
Если в процессе работы этого сценария попытаться нажать клавиши [Ctrl+C] во время выполнения первого цикла "критической обработки", ничего не произойдет. Это связано с тем, что была введена команда trap для игнорирования сигналов.
После того как начинается второй цикл "некритической обработки", статус команды trap восстанавливается, в результате чего разрешаются прерывания.
$ trap_ignore
critical processing..1..you cannot interrupt me
critical processing..2..you cannot interrupt me
critical processing..3..you cannot interrupt me
critical processing..4..you cannot interrupt me
critical processing..5..you cannot interrupt me
critical processing..6..you cannot interrupt me
Non‑critical processing..1..interrupt me now if you want
Non‑critical processing..2..interrupt me now if you want
Received interrupt on count 2
Now exiting…
Благодаря применению команды trap можно обрести большую степень контроля над "поведением" сценария при получении сигнала. Перехват и последующая обработка сигналов обеспечивают устойчивую работу сценариев.
26.4. Команда eval
Команда eval служит для оценки командной строки с целью завершения каких‑либо подстановок интерпретатора shell с последующим их вызовом. Команда eval используется для расширения значений переменных (если в результате одного прохода расширения не происходит, выполняется второй проход). Переменные, для оценки которых требуется два прохода, иногда называют сложными переменными. Хотя, по моему мнению, переменные не могут быть сложными.
Команда eval также может применяться для отображения значений простых переменных; эти переменные не должны быть сложными.
$ NAME=Honeysuckle
$ eval echo $NAME
Honeysuckle
$ echo $NAME
Honeysuckle
Наилучшим методом для понимания работы команды eval является изучение оценки командной строки, выполняемой этой командой.
26.4.1. Выполнение команд, находящихся в строке
Вначале создадим небольшой файл, testf, содержащий некоторый текст. Затем переменной myfile будет присвоена команда cat testf с последующим отображением значения переменной. Благодаря этому можно проверить возможность отображения на экране содержимого файла testf.
$ pg testf
May Day, May Day Going Down
Присвоим переменной myfile строку "cat testf:
$ MYFILE="cat testf"
Если требуется вывести содержимое файла testf на экран, нужно выполнить команду cat testf.
$ echo $MYFILE
cat testf
Теперь применим команду eval для оценки значения переменной; при этом следует помнить, что eval выполняет два прохода при оценке переменной myfile.
$ eval $MYFILE
May Day, May Day Going Down
В результате этого успешно оценивается значение переменной и применяется команда cat к файлу testf. При первом проходе отображается фактическая строка "cat testf", при втором проходе выполняется содержимое строки, в данном случае cat testf.
Рассмотрим другой пример. Переменной cat_passwd будет присвоена строка "cat /etc/passwd | more". Команда eval выполняет оценку содержимого данной строки.
$ CAT_PASSWD=`cat /etc/passwd | more`
$ echo $CAT_PASSWD
cat /etc/passwd|more
$ eval
$CAT_PASSWD
root:HccPbzT5tbOOg:0:0:root:/root:/bin/sh
bin:*:l:l:bin:/bin:
daemon:*:2:2:daemon:/sbin:
adm:*:3:4:ada:/var/adm:
Команда eval также хорошо подходит для отображения значения последнего параметра, передаваемого сценарию. Значение последнего параметра уже отображалось, но в этом случае оно будет отображено снова.
$ pg evalit
#!/bin/sh
# сценарий evalit
echo " Total number of arguments passed is $#"
echo " The process ID is $$"
echo "' Last argument is "$(eval echo $$)
При выполнении этого сценария получим следующий результат (ID процесса может отличаться от случая к случаю):
$ evalit alpha bravo charlie
Total number of arguments passed is 3
The process ID is 780
Last argument is Charlie
В этом сценарии команда eval сначала оценивает значение переменной $$ в сравнении с ID процесса, а при выполнении второго прохода производится оценка последнего параметра, передаваемого переменной.
26.4.2. Присвоение значения имени переменной
Можно также поставить в соответствие полю данных имя переменной. Рассмотрим, что это означает на практике. Предположим, что в нашем распоряжении имеется следующий файл:
$ pg data
PC 486 MONITOR svga NETWORK yes
Нам необходимо, чтобы первому столбцу текста соответствовали имена переменных, а второму столбцу текста – значения соответствующих переменных. При этом должно отображаться следующее:
echo $PC
466
Как же можно достичь желаемого результата? Ниже приведен соответствующий сценарий, использующий команду eval.
$ pg eval_it
#!/bin/sh
#сценарий eval_it
while read NAME TYPE
do
eval `echo "${NAME}=${TYPE}"`
done < data
echo "You have a $PC pc, with a $MONITOR monitor"
echo "and have you network? $NETWORK"
Рассмотрим, как функционирует сценарий. Сначала берутся значения рс и 486, которые присваиваются переменным name и type соответственно. При первом проходе команда eval отображает на экране два значения переменных, PC и 486; во время выполнения второго прохода вместо переменной name подставляется значение рс, а вместо переменной type – значение 486. При выполнении сценария получаются следующие результаты:
$ eval_it
You have a 486 рс, with a svga monitor and have you network? yes
Команда eval не слишком часто применяется в сценариях, однако ее удобно использовать при оценке значения переменной, выполняемой более одного раза.
26.5. Команда logger
В системе поддерживается достаточно много журнальных файлов. Некоторые из них, именуемые messages, обычно размещены в каталоге /var/adm или /var/log. Сообщения, регистрируемые в этом файле, передаются с помощью файла конфигурации syslog и имеют строго заданный формат. Чтобы убедиться, что система сконфигурирована для генерирования сообщений из программ, проверьте файл /etc/syslog.conf. Этот файл содержит описания приоритетов и свойств, которые программа может использовать для отсылки различных типов сообщений.
Здесь мы не будем подобно рассматривать, каким образом UNIX либо Linux регистрирует сообщения в файле. Все, что вам требуется пока знать, это номера различных уровней сообщений (от информационных до критических).
Сообщения могут отсылаться в файл с помощью команды logger. Перед тем как использовать эту команду, нужно обратиться к справочной странице man, так как различные версии этой команды могут иметь отличающийся синтаксис. Поскольку в этой главе рассматриваются только информационные сообщения, нужно обратить внимание на соответствующие команды, рассматриваемые далее.
Необходимость отправки сообщений в файл диктуется одной из следующих причин:
• количество попыток доступа/регистрации за определенный период;
• критическая обработка одного из сбойных сценариев;
• мониторинг отчетов сценариев.
Ниже показано, как выглядит файл /var/adm/messages. Формат этого файла может немного отличаться от данного образца:
$ tail /var/adm/messages
Jun 16 20:59:03 localhost login[281]: DIALUP AT ttyS1 BY root
Jun 16 20:59:03 localhost login[281]: ROOT LOGIN ON tty$1
Jun 16 20:59:04 localhost PAM_pwdb [281] : (login) session closed for user root
Jun 16 21:56:38 localhost named[211: Cleaned cache of 0 RRs]
Jun 16 21:56:39 localhost named[211]: USAGE 929570318 929566719
Jun 16 21:56:39 localhost named[211]: NSTATS 929570318 929566719
Общий формат команды logger выглядит так:
logger -p -i message
Параметры этой команды выполняют следующие функции:
–p Определяет приоритет; в данном случае затрагивается только файл user.notice,
который всегда является используемым по умолчанию
–i Регистрирует ID процесса для каждого сообщения
26.5.1. Использование команды logger
В командной строке интерпретатора shell введите следующую команду:
$ logger -p notice "This is a test message. Please Ignore $LOGNAME"
Возможно, вам придется подождать пару минут, пока не отобразится информация о регистрации сообщения.
$ tail /var/adm/messages
Jun 17 10:36:49 acers6 dave: This is a test message. Please Ignore dave
Из приведенного примера видно, что регистрируется, пользователь, выполняющий регистрацию сообщения.
А теперь создадим небольшой сценарий, регистрирующий сообщение, в котором говорится о количестве пользователей в системе. Данный сценарий может использоваться для оценки интенсивности ежедневной загрузки системы. Для этого нужно просто запускать его из файла crontab примерно каждые 30 минут.
$ pg test_logger
#!/bin/sh
# test_logger
logger -p notice "`basename $0`: there are currently `who |wc -l` users on the system"
Запустим сценарий.
$ test_logger
Теперь отобразим содержимое файла сообщений.
$ tail /var/adm/messages
Jun 17 11:02:53 acers6 dave: test_logger:there are currently 15 users on the system
26.5.2. Использование команды logger в сценариях
Регистрацию сообщений лучше использовать в том случае, когда осуществляется безусловное прерывание выполнения одного из сценариев. Для регистрации этих типов сообщений просто включите команду logger в функции, выполняющие перехват сигналов при выходе из сценария.
В следующем сценарии очистки при получении любого из сигналов с номерами 2, 3 или 15 производится регистрация сообщения.
$ pg cleanup
#!/bin/sh
#cleanup
#очистка журнальных файлов системы
trap "my_exit" 2 3 15
my_exit () {
# my_exit
logger -p notice "`basename $0`: Was killed while cleaning up system logs..CHECK OUT ANY DAMAGE"
exit 1
}
tail -3200c /var/adm/utmp > /tmp/utmp
mv /tmp/utmp /var/adm/utmp
>/var/adm/wtmp
#
tail -10 /var/adm/sulog > /tmp/o_sulog
mv /tmp/o_sulog /var/adm/sulog
При просмотре файла сообщений можно заметить, что возникла проблема, связанная с выполнением сценария очистки.
$ tail /var/adm/messages
Jun 17 11:34:28 acers6 dave: cleanup:Was killed whilst cleaning up systemlogs.. CHECK OUT ANY DAMAGE
Помимо использования при работе с различными критическими сценариями, команду logger можно также применять для регистрации любых подключений удаленных пользователей к системе. Ниже приведен сегмент кода, регистрирующий пользователей, которые подключаются к системе с помощью последовательных линий tty0 и tty2. Этот фрагмент кода берет свое начало от одного из файлов /etc/profile.
TTY_LINE=`tty`
case $TTY_LINE in
"/dev/tty0") TERM=ibm3151 ;;
"/dev/tty2") TERM=vt220
#проверка пользователей, которым разрешен доступ к модемной линии
#
echo "This is a modem connection"
# modemf содержит регистрационные имена для допустимых пользователей
modemf=/usr/local/etc/modem.users
if [ -s $modemf ] then
user=`cat $modemf | awk '{print $1}' | grep $LOGNAME`
# если имя не содержится в файле, пользователь не допускается в систему
if [ "$USER" != "$LOGNAME" ]
then
echo "INVALID USER FOR MODEM CONNECTION"
echo " DISCONNECTING………"
sleep 1
exit 1
else
echo "modem connection allowed"
fi
fi
logger -p notice "modem line connect $TTY_LINE… $LOGNAME"
;;
*) TERM=vt220
stty erase '^h' ;;
esac
Команда logger является превосходным инструментальным средством, применяемым для регистрации информации в глобальных файлах сообщений системы.
26.6. Заключение
Благодаря использованию функции перехвата и сигналов реализуется изящное завершение выполнения сценариев. Возможность регистрации сообщений в системном журнальном файле обеспечивает пользователей и администраторов полезной информацией, облегчающей распознавание и устранение любых потенциальных проблем.
ГЛАВА 27
Небольшая коллекция сценариев
В настоящей главе содержатся примеры некоторых наиболее распространенных сценариев. Изучая их, можно заметить, что все они невелики по размеру и довольно просты. В этом и состоит преимущество использования сценариев; они не должны быть сложными и объемными, поскольку сценарии создаются с целью экономии времени пользователя.
Конечно, в состав данной главы неплохо было бы включить сценарий comet, выполняющий общую проверку баз данных. Но поскольку этот сценарий содержит более 500 строк, нецелесообразно включать его в эту небольшую книгу. Разаботка сценария comet началась еще пару лет назад. Тогда этот сценарий состоял не более чем из пяти строк. Но в ходе естественного процесса эволюции величина сценария существенно выросла. Приведем перечень сценариев, рассматриваемых в данной главе:
pingall
Сценарий, использующий записи из файла /etc/hosts для выполнения опроса всех хостов
backup_gen
Общий сценарий резервного копирования, который загружает заданные по умолчанию настройки
del.lines
Оболочка потокового редактора sed, выполняющая удаление строк из файлов
access deny
Утилита, реализующая запрет доступа для определенных пользователей при выполнении регистрации
logroll
Утилита, реализующая прокрутку журнального файла в случае, если он достигает определенного размера
nfsdown
Утилита, реализующая быстрый метод демонтирования всех каталогов nfs
27.1. Сценарий pingall
Еще несколько лет назад сценарий pingall представлял собой часть общего сценария отчета, который выполнялся по ночам. Этот сценарий опрашивает все хосты, записи о которых находятся в файле hosts.
Сценарий реализует просмотр файла /etc/hosts и разыскивает все строки, которые не начинаются с символа #. Затем цикл while считывает строки отфильтрованного текста. Для присваивания переменной addr значения первого поля отфильтрованного текста используется утилита awk. Затем с помощью цикла for по каждому найденному адресу отправляется запрос.
Ниже приводится сам сценарий.
$ pg pingall
#!/bin/sh
# pingall
# просмотр файла /etc/hosts и отправка запроса по каждому адресу
cat /etc/hosts | grep -v '^#' | while read LINE
do
ADDR=`awk '{print $1}'`
for MACHINE in $ADDR
do
ping -s -c1 $MACHINE
done
done
Сценарий pingall можно легко расширить и включить в него функции отчетов, связанные с другими сетевыми утилитами.
27.2. Сценарий backup_gen
Сценарий backup_gen приводится здесь вовсе не для иллюстрации методики резервирования каталогов. Этот сценарий является удачным примером совместного использования настроек, общих для нескольких сценариев.
Сценарий backup_gen предназначен для создания резервных копий. При выполнении сценария просматривается заданный по умолчанию файл конфигурации, который затем используется для резервирования системы. При желании пользователь может изменять настройки, заданные по умолчанию. Сценарий является отличным примером того, как различные сценарии могут применять одинаковые настройки или изменять их во время выполнения сценария. После запуска сценария выполняется проверка на наличие исходного файла (backup.defaults). Если этот файл не найден, сценарий завершается.
При выполнении сценария отображается заголовок экрана и настройки, заданные по умолчанию. Пользователю направляется запрос о том, требуется ли изменять какие‑либо настройки, заданные по умолчанию. Если ответ положителен, поступает запрос на ввод кода, применяемого для изменения необходимых настроек. Для ввода правильного кода пользователю предоставляются три попытки; если введен неверный код, используются настройки, заданные по умолчанию. При вводе корректного кода пользователь может изменить приведенные ниже настройки (значения, заданные по умолчанию, содержатся в квадратных скобках []):
tape device [rmt0]
Можно выбрать rmt1 и rmt3
mail admin when the backup has finished [yes]
Нет вариантов выбора
type of backup [full]
Можно выбрать опцию
normal или sybase
Изменения настроек выполняются с помощью временных переменных. Для получения доступа к заданным по умолчанию настройкам установите курсор мыши в любом поле и нажмите клавишу [Return]. Однако следующие настройки изменять нельзя:
backup log filename code name.
Все внесенные изменения затем подтверждаются. После завершения процесса подтверждения значения временных переменных снова присваиваются исходным переменным. До завершения резервного копирования выполняется тестирование магнитной ленты. В процессе резервного копирования применяются команды find и cpio. С помощью этих команд используются переменные из файла настроек или значения новых переменных, указанные пользователем.
Далее приводится соответствующий сценарий.
$ pg backup_run
#!/bin/sh
#backup_run
#сценарий выполнения резервного копирования
#загрузка файла с конфигурационными параметрами
SOURCE=/appdva/bin/backup.defaults
check_source ()
{
#check_source
#файл backup.defaults содержит параметры конфигурации/функции
#проверка того, что путь содержит нужный каталог
if [ -r $SOURCE ]; then
. $SOURCE
else
echo "`basename $0`: cannot locate defaults file"
exit 1
fi
}
header () {
# header
USER=`whoami`
MYDATE=`date + %A" "%e" of "%B-%Y`
clear
cat << MAYDAY
User : $USER $MYDATE
NETWORK SYSTEM BACKUP
MAYDAY
}
change_settings () {
# change_settings
# отображение параметров, заданных по умолчанию
header
echo "Valid Entries Are…"
echo "Tape Device: rmt0, rmt1, rmt3"
echo "Mail Admin: yes, no"
echo "Backup Type: full, normal, sybase "
while :
do
echo -n -c "nn Tape Device To Be Used For This Backup [$_DEVICE] :"
read T_DEVICE
: ${T_DEVICE:=$_DEVICE}
case $T_DEVICE in
rmt0|rmt1|rmt3) break;;
*) echo "The devices are either… rmt0, rmt1, rmt3"
esac
done
#если пользователь нажимает клавишу ввода при установке курсора в любом
#из полей, применяются настройки, заданные по умолчанию
while :
do
echo -n "Mail Admin When Done [$INFORM] :"
read T_INFORM
: ${T_INFORM:=$_INFORM}
case $T_INFORM in
yes|Yes) break;;
no|No) break;;
*) echo "The choices are yes, no";;
esac
done
while :
do
echo -n " Backup Type [$_TYPE] :"
read T_TYPE
: ${T_TYPE:=$_TYPE}
case $T_TYPE in
Full|full) breaks;;
Normal|normal)break;;
Sybase|sybase)break;;
*) echo "The choices are either… full, normal, sybase";;
esac
done
#повторное присваивание значений временных переменных исходным переменным,
#которые были загружены
_DEVICE=$T_DEVICE;
_INFORM=$T_INFORM;
_INFORM=$T_INFORM
}
show_settings ()
# отображение текущих настроек
{
cat << MAYDAY
Default Settings Are…
Tape Device To Be Used : $_DEVICE
Mail Admin When Done : $_INFORM