$
Правила получения значений переменных приведены в табл. 5.3. Возвращаясь к нашему исходному примеру
t=${1-60}
видим, что
t
присваивается
$1
или 60, если аргумент не задан.
$var
| Значение var ; ничего, если var не определено |
${var}
| То же; полезно, если за именем переменной следует буквенно-цифровая строка |
${var-thing}
| Значение var , если оно определено; в противном случае — thing ; $var не изменяется |
${var=thing}
| Значение var , если оно определено; в противном случае — thing . Если var не определено, то $var присваивается thing
|
${var?строка}
| Если var определено — $var ; в противном случае выводится строка и интерпретатор прекращает работу. При пустой строке выводится: var: parameter not set
|
${var+thing}
| thing , если $var определено; в противном случае — ничего |
Таблица 5.3: Получение значений переменных в языке
Упражнение 5.9
Обратите внимание на реализацию команд
true
и
false
в
/usr/bin
или
/bin
. (Как бы вы определили, где они находятся?)
Упражнение 5.10
Измените команду
watchfor
так, чтобы пользователь мог задавать несколько имен, а не вводить
'joe|mary'
.
Упражнение 5.11
Напишите версию команды
watchwho
, которая использует команду
comm
вместо
awk
для сравнения новой и старой информации. Какая версия вам больше нравится?
Упражнение 5.12
Напишите версию команды
watchwho
, в которой вывод команды
who
хранится в переменных языка
shell
, а не в файлах. Какая версия лучше? Какая версия быстрее работает? Следует ли в командах
watchwho
и
checkmail
автоматически использовать операцию
&
?
Упражнение 5.13
В чем состоит различие между пустой командой языка
shell
: и символом примечания
#
? Нужны ли они?
5.4 Команда
trap
: обработка прерываний Если во время выполнения команды
watchwho
нажать клавишу
DEL (
УДЛ) или отключить компьютер от сети, то один или несколько временных файлов останутся в каталоге
/tmp
. Команда
watchwho
удаляет временные файлы перед окончанием своей работы. Необходимы средства обнаружения таких ситуаций и восстановления после прерывания.
При нажатии клавиши DEL всем процессам, запущенным с этого терминала, посылается сигнал прерывания. Аналогично в случае отключения посылается сигнал отбоя. Существуют и другие сигналы. Если в программе не предусмотрены специальные действия по обработке сигналов, то указанные сигналы прекращают ее выполнение. Интерпретатор защищает программы, запущенные с помощью
&
, от прерываний, но не от отключений.
В гл. 7 сигналы рассматриваются подробнее, но для работы с ними на языке
shell
глубоких знаний не требуется. Встроенная команда интерпретатора
trap
устанавливает последовательность команд, которая должна выполняться при возникновении сигнала:
trap последовательность_команд список_номеров_сигналов
Последовательность команд — единый аргумент, поэтому его почти всегда нужно брать в кавычки. Номера сигналов обозначаются небольшими целыми числами, например, 2 соответствует сигналу, возникающему при нажатии клавиши DEL, а 1 — сигналу, возникающему при отключении от сети. Номера сигналов, наиболее часто используемых в
shell
-программах, приведены в табл. 5.4.
0 | Выход из интерпретатора (по любой причине, включая конец файла) |
1 | Отбой |
2 | Прерывание (клавиша DEL) |
3 | Останов (ctl-\; вызывает распечатку содержимого памяти программы) |
9 | Уничтожение (нельзя перехватить или игнорировать) |
15 | Окончание выполнения; сигнал по умолчанию, производимый kill(1)
|
Таблица 5.4: Номера сигналов в интерпретаторе
Для удаления временных файлов в команде
watchwho
вызов команды
trap
должен указываться перед циклом, чтобы перехватить сигналы прерывания, отбоя и окончания выполнения:
...
trap 'rm -f $new $old; exit 1' 1 2 15
while:
...
Последовательность команд, образующих первый аргумент команды
trap
, подобна вызову подпрограммы, который происходит сразу по возникновении сигнала. Когда эта последовательность окончится, прерванная программа возобновляется с места прерывания, если только сигнал не уничтожит ее. Таким образом, последовательность команд в
trap
должна явно вызывать
exit
, иначе
shell
-программа продолжит свое выполнение после прерывания. Кроме того, последовательность команд будет читаться дважды: при установке команды
trap
и при обращении к ней. Поэтому последовательность команд лучше защищать апострофами, чтобы значения переменных вычислялись только при выполнении программ, указанных в команде
trap
. В данном случае это не имеет значения, но позднее вы столкнетесь с ситуацией, когда это важно. Кстати, флаг
-f
предписывает команде
rm
не задавать вопросов.