Чтение онлайн

ЖАНРЫ

Искусство программирования на языке сценариев командной оболочки

Купер Мендель

Шрифт:

#!/bin/bash

# assert.sh

assert # Если условие ложно,

{ #+ выход из сценария с сообщением об ошибке.

E_PARAM_ERR=98

E_ASSERT_FAILED=99

if [ -z "$2" ] # Недостаточное количество входных параметров.

then

return $E_PARAM_ERR

fi

lineno=$2

if [ ! $1 ]

then

echo "Утверждение ложно: \"$1\""

echo "Файл: \"$0\", строка: $lineno"

exit $E_ASSERT_FAILED

# else

# return

# и

продолжить исполнение сценария.

fi

}

a=5

b=4

condition="$a -lt $b" # Сообщение об ощибке и завершение сценария.

# Попробуйте поменять условие "condition"

#+ на что нибудь другое и

#+ посмотреть -- что получится.

assert "$condition" $LINENO

# Сценарий продолжит работу только в том случае, если утверждение истинно.

# Прочие команды.

# ...

echo "Эта строка появится на экране только если утверждение истинно."

# ...

# Прочие команды.

# ...

exit 0

5. Ловушка на выхто в этом сценарии может быть неправильно (подсказка: после ключевого словоде.

Команда exit, в сценарии, порождает сигнал 0, по которому процесс завершает работу, т.е.
– - сам сценарий [ 60 ] . Часто бывает полезным по выходу из сценария выдать "распечатку" переменных.

60

В соответствии с соглашениями, сигнал с номером 0 соответствует команде exit.

Установка ловушек на сигналы

trap

Определяет действие при получении сигнала; так же полезна при отладке.

Сигнал (signal) -- это просто сообщение, передается процессу либо ядром, либо другим процессом, чтобы побудить процесс выполнить какие либо действия (обычно -- завершить работу). Например, нажатие на ControlC, вызывает передачу сигнала SIGINT, исполняющейся программе.

trap '' 2

# Игнорировать прерывание 2 (Control-C), действие по сигналу не указано.

trap 'echo "Control-C disabled."' 2

# Сообщение при нажатии на Control-C.

Пример 29-5. Ловушка на выходе

#!/bin/bash

trap 'echo Список переменных --- a = $a b = $b' EXIT

# EXIT -- это название сигнала, генерируемого при выходе из сценария.

a=39

b=36

exit 0

# Примечательно, что если закомментировать команду 'exit',

# то это никак не скажется на работе сценария,

# поскольку "выход" из сценария происходит в любом случае.

Пример 29-6. Удаление временного файла при нажатии на Control-C

#!/bin/bash

# logon.sh:

Сценарий, написаный "на скорую руку", контролирует вход в режим on-line.

TRUE=1

LOGFILE=/var/log/messages

# Обратите внимание: $LOGFILE должен быть доступен на чтение (chmod 644 /var/log/messages).

TEMPFILE=temp.$$

# "Уникальное" имя для временного файла, где расширение в имени -- это pid процесса-сценария.

KEYWORD=address

# При входе, в файл /var/log/messages,

# добавляется строка "remote IP address xxx.xxx.xxx.xxx"

ONLINE=22

USER_INTERRUPT=13

CHECK_LINES=100

# Количество проверяемых строк.

trap 'rm -f $TEMPFILE; exit $USER_INTERRUPT' TERM INT

# Удалить временный файл, когда сценарий завершает работу по control-c.

echo

while [ $TRUE ] #Бесконечный цикл.

do

tail -$CHECK_LINES $LOGFILE> $TEMPFILE

# Последние 100 строк из системного журнала переписать во временный файл.

# Совершенно необходимо, т.к. новейшие версии ядер генерируют много сообщений при входе.

search=`grep $KEYWORD $TEMPFILE`

# Проверить наличие фразы "address",

# свидетельствующей об успешном входе.

if [ !
– z "$search" ] # Кавычки необходимы, т.к. переменная может содержать пробелы.

then

echo "On-line"

rm -f $TEMPFILE # Удалить временный файл.

exit $ONLINE

else

echo -n "." # ключ -n подавляет вывод символа перевода строки,

# так вы получите непрерывную строку точек.

fi

sleep 1

done

# Обратите внимание: если изменить содержимое переменной KEYWORD

# на "Exit", то сценарий может использоваться для контроля

# неожиданного выхода (logoff).

exit 0

# Nick Drage предложил альтернативный метод:

while true

do ifconfig ppp0 | grep UP 1> /dev/null && echo "соединение установлено" && exit 0

echo -n "." # Печать последовательности точек (.....), пока соединение не будет установлено.

sleep 2

done

# Проблема: Нажатия Control-C может оказаться недостаточным, чтобы завершить этот процесс.

# (Точки продолжают выводиться на экран.)

# Упражнение: Исправьте этот недостаток.

# Stephane Chazelas предложил еще одну альтернативу:

CHECK_INTERVAL=1

while ! tail -1 "$LOGFILE" | grep -q "$KEYWORD"

do echo -n .

sleep $CHECK_INTERVAL

done

echo "On-line"

# Упражнение: Найдите сильные и слабые стороны

# каждого из этих подходов.

Аргумент DEBUG, команды trap, заставляет сценарий выполнять указанное действие после выполнения каждой команды. Это можно использовать для трассировки переменных.

Поделиться с друзьями: