Искусство программирования на языке сценариев командной оболочки
Шрифт:
# === КОНЕЦ БЛОКА ИЗМЕНЕНИЙ, ВНЕСЕННЫХ ПЕРЕВОДЧИКОМ ===
echo "Сценарий отработал $SECONDS $units."
# В случае перегруженности системы, скрипт может перескакивать через отдельные
#+ значения счетчика
sleep $INTERVAL
done
echo -e "\a" # Сигнал!
exit 0
$SHELLOPTS
список
bash$ echo $SHELLOPTS
braceexpand:hashall:histexpand:monitor:history:interactive-comments:emacs
$SHLVL
Уровень вложенности shell. Если в командной строке
echo $SHLVL
дает 1, то в сценарии значение этой переменной будет больше на 1, т.е. 2.
$TMOUT
Если переменная окружения $TMOUT содержит ненулевое значение, то интерпретатор будет ожидать ввод не более чем заданное число секунд, что, в первичном приглашении (см. описание PS1 выше), может привести к автоматическому завершению сеанса работы.
Организация ограничения времени ожидания ввода от пользователя в сценариях возможна, но это требут довольно сложных махинаций. Как один из вариантов, можно предложить организовать прерывание цикла ожидания по сигналу. Но это потребует написание функции обработки сигналов командой trap (см. Пример 29-5).
Пример 9-2. Ограничения времени ожидания ввода
#!/bin/bash
# timed-input.sh
# TMOUT=3 бесполезно в сценариях
TIMELIMIT=3 # Три секунды в данном случае, но может быть установлено и другое значение
PrintAnswer
{
if [ "$answer" = TIMEOUT ]
then
echo $answer
else # Чтобы не спутать разные варианты вывода.
echo "Ваше любимое растение $answer"
kill $! # "Прибить" ненужную больше функцию TimerOn, запущенную в фоновом процессе.
# $!
– - PID
fi
}
TimerOn
{
sleep $TIMELIMIT && kill -s 14 $$ &
# Ждать 3 секунды, после чего выдать sigalarm сценарию.
}
Int14Vector
{
answer="TIMEOUT"
PrintAnswer
exit 14
}
trap Int14Vector 14 # переназначить процедуру обработки прерывания от таймера (14)
echo "Ваше любимое растение? "
TimerOn
read answer
PrintAnswer
# По общему признанию, это не очень хороший способ ограничения времени ожидания,
#+ однако опция "-t"команды "read" упрощает задачу.
# См. "t-out.sh", ниже.
# Если вам нужно что-то более элегантное...
#+ подумайте о написании программы на C или C++,
#+ с использованием соответствующих библиотечных функций, таких как 'alarm' и 'setitimer'.
exit 0
В качестве альтернативы можно использовать stty.
Пример 9-3. Еще один пример ограничения времени ожидания ввода от пользователя
#!/bin/bash
# timeout.sh
# Автор: Stephane Chazelas,
# дополнен автором документа.
INTERVAL=5 # предел времени ожидания
timedout_read {
timeout=$1
varname=$2
old_tty_settings=`stty -g`
stty -icanon min 0 time ${timeout}0
eval read $varname # или просто read $varname
stty "$old_tty_settings"
# См. man stty.
}
echo; echo -n "Как Вас зовут? Отвечайте быстрее! "