Linux и UNIX: программирование в shell. Руководство разработчика
Linux и UNIX: программирование в shell. Руководство разработчика читать книгу онлайн
Данная книга является практическим руководством по программированию интерпретатора Bourne shell -cтандартного командного интерпретатора в UNIX, полностью совместимого с интерпретатором BASH shell в Linux. Книга предназначена для начинающих и опытных программистов и содержит множество полезных примеров, советов и подсказок. С ее помощью читатель сможет быстро научиться создавать shell–сценарии для реальных задач и ситуаций, возникающих в большинстве систем UNIX и Linux.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
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 <CTRL‑C>, at number $LOOP"
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 <CTRL‑C>, at number $LOOP"
echo " I will now exit "
exit 1
}
Функция myexit вызывается при получении сигнала 2; при этом отображается значение переменной $LOOP, информирующее пользователя о том, какая итерация цикла выполнялась при нажатии комбинации клавиш [Ctrl+C]. Функции подобного типа применяются на практике для удаления временных файлов.
При выполнении сценария получим следующие результаты:
$ trap1
211 212
You just hit <CTRL‑C>, at number 213 I will now exit
26.3.2. Захват сигнала и выполнение действий
Наиболее часто выполняемым действием является удаление временных файлов.
В следующем сценарии с помощью команд df и ps непрерывно добавляется информация во временные файлы HOLD1.$$ и HOLD2.$$. Не забывайте, что символы $$ заменяют ID процесса. Когда пользователь нажимает комбинацию клавиш [Ctrl+C], эти файлы удаляются.
$ pg trap2
#!/bin/sh
# trap2
# перехват только сигнала 2….<CTRL‑C>
trap "my_exit" 2
HOLD1=/tmp/HOLD1.$$
HOLD2=/tmp/HOLD2.$$
my_exit {)
{
# my_exit
echo "<CTRL‑C> detected..Now cleaning up..wait"
# удаление временных файлов
rm /tmp/*.$$ 2>/dev/null
exit 1
}
echo "processing…."
# основной цикл
while :
do
df >> $HOLD1
ps xa >>$HOLD2
done
Результаты выполнении этого сценария будут следующими:
$ trap2
processing….
<CTRL-C> detected..Now cleaning up..wait
При получении сигнала можно предоставлять пользователю определенный выбор. Однако если получены сигналы 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