$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
не задавать вопросов.Иногда команду
trap
полезно применять в диалоговом режиме, чаще всего для того, чтобы не допустить уничтожения программы сигналом отбоя, возникшим при обрыве телефонной связи:$ (trap "" 1; долго_выполняемая команда) &
2134
$
Для процесса и его потомков пустая последовательность означает, что нужно игнорировать прерывания. При наличии скобок команда
trap
и долго_выполняемая_команда
выполняются порожденным интерпретатором вместе и как фоновые; без них команда trap
действовала бы на исходный интерпретатор, так же как и на долго_выполняемую_команду.Команда
nohup(1)
— небольшая shell
-программа, обеспечивающая непрерывное выполнение команд. Ниже полностью приведен ее вариант из седьмой версии:$ cat 'which nohup'
trap "" 1 15
if test -t 2>&1
then
echo "Sending output to 'nohup.out'"
exec nice -5 $* >>nohup.out 2>&1
else
exec nice -5 $* 2>&1
fi
$
Команда
test -t
проверяет, направлен ли стандартный выходной поток на терминал, чтобы вы могли решить, следует ли его сохранять. Фоновая программа выполняется с помощью команды nice
, что снижает ее приоритет по сравнению с диалоговыми программами. (Обратите внимание, что команда nohup
не устанавливает значение PATH
. А может быть, это нужно?)Команда
exec
использована только для повышения эффективности; команда nice
может выполняться и без нее. Exec
— встроенная команда интерпретаторов, которая заменяет процесс, играющий роль текущего интерпретатора, на указанную программу. Таким образом она избавляется от одного процесса, а именно от интерпретатора, обычно ожидающего завершения программы. Мы могли бы применять