Текст скрипта test4.sh:
#!/bin/sh
tmpfile=/usr/tmp/tmp.$$
...
rm $tempfile
Перенаправление ввода/вывода
Каждая запущенная из командного интерпретатора программа получает три открытых потока ввода/вывода:
□ стандартный ввод
□ стандартный вывод
□ стандартный вывод ошибок
По умолчанию все эти потоки ассоциированы с терминалом. То есть любая программа, не использующая потоки, кроме стандартных, будет ожидать ввода с клавиатуры терминала, весь вывод этой программы, включая сообщения об ошибках, будет происходить на экран терминала. Большое число утилит, с которыми вам предстоит работать, используют только стандартные потоки. Для таких программ shell позволяет независимо перенаправлять потоки ввода/вывода. Например, можно подавить вывод сообщений об ошибках, установить ввод или вывод из файла и даже передать вывод одной программы на ввод другой.
В табл. 1.9 приведен синтаксис перенаправления ввода/вывода, а на рис. 1.9 схематически показаны примеры перенаправления потоков.
Таблица 1.9. Перенаправление потоков ввода/вывода
| >file | Перенаправление стандартного потока вывода в файл file |
| >>file | Добавление в файл file данных из стандартного потока вывода |
| <file | Получение стандартного потока ввода из файла file |
| p1 | p2 | Передача стандартного потока вывода программы p1 в поток ввода p2 |
| n>file | Переключение потока вывода из файла с дескриптором n в файл file |
| n>>file | To же, но записи добавляются в файл file |
| n>&m | Слияние потоков с дескрипторами n и m |
| <<str | "Ввод здесь": используется стандартный поток ввода до подстроки str. При этом выполняются подстановки метасимволов командного интерпретатора |
| <<\str | To же, но подстановки не выполняются |
Рис. 1.9. Пример перенаправления стандартных потоков ввода/вывода
Рассмотрим несколько примеров перенаправления потоков.
Запуск некой программы ведения журнала можно выполнить следующим образом:
$ logger >> file.log
При этом вывод программы logger будет записываться в конец файла file.log, сохраняя все предыдущие записи. Если файла file.log не существует, он будет создан. В отличие от этого, использование символа '>' указывает, что сначала следует очистить файл, а затем производить запись.
Стандартным потокам ввода, вывода и вывода ошибок присваиваются дескрипторы — числовые значения, являющиеся указателями на соответствующий поток. Они, соответственно, равны 0, 1 и 2. Перенаправлять потоки можно, используя эти числовые значения. Таким образом, предыдущему примеру эквивалентна следующая запись:
$ logger 1>>file.log
Чаще всего числовое значение дескриптора потока используется для потока ошибок. Например, чтобы подавить вывод ошибок, можно использовать следующую запись:
$ run 2>/dev/null
где /dev/null является псевдоустройством, удаляющим все введенные в него символы.
Командный интерпретатор предоставляет возможность слияния потоков. Например, при запуске команды
$ run_long_program >/dev/null 2>&1 &
сообщения об ошибках будут также выводиться в файл /dev/null. Символ '&' перед именем потока необходим, чтобы отличить его от файла с именем 1. Заметим, что изменение порядка двух перенаправлений потоков приведет к тому, что сообщения об ошибках будут по-прежнему выводиться на экран. Дело в том, что Shell анализирует командную строку слева направо, таким образом сначала будет осуществлено слияние потоков и оба будут указывать на терминал пользователя, а затем стандартный поток вывода (1) будет перенаправлен в файл /dev/null.
Передача потока вывода одной программы в поток ввода другой осуществляется с помощью конвейера '|' (программного канала). Программные каналы часто используются для фильтрации вывода некоторой команды:
$ ps - ef | grep myproc
позволяет получить информацию о конкретном процессе myproc. Утилита ps(1) выводит на экран информацию обо всех процессах в системе, программа grep(1) фильтрует этот поток, оставляя лишь строки, в которых присутствует слово myproc.[14]
Можно усложнить задачу и попытаться получить идентификатор процесса myproc. Однако здесь нам не обойтись без других средств системы. В данном случае мы будем использовать интерпретатор awk(1):
$ ps -ef | grep myproc | awk '{ print $2 }'
Идея заключается в фильтрации второго поля записи о процессе myproc, содержащего идентификатор процесса (см. описание утилиты ps(1)).
Иногда возникает необходимость разместить поток ввода вместе с командой. Для этого используется выражение "ввод здесь". Проиллюстрируем его на примере:
$ at Dec 31 <<!
cat happy.new.year | elm -s"C Новым Годом"
congratulations@everybody.ru
!
По определению, команда at(1) устанавливает вызов команды, полученной ею со стандартного ввода (клавиатуры терминала), на определенное время (в данном случае — на 31 декабря каждого года). С помощью выражения "ввод здесь" мы явно задали вид этой команды, точнее комплекса команд: cat(1) передает текст поздравления программе elm(1), отвечающей за отправление сообщения электронной почты.
Команды, функции и программы
Все команды, которые вводятся в строке приглашения shell, относятся к одной из следующих категорий:
□ встроенные функции
□ функции shell, определенные пользователем
□ внешние программы и утилиты
Непосредственное отношение к shell имеют только первые две категории, а программы и утилиты являются обычными исполняемыми файлами.
Запуск встроенной функции не требует порождения нового процесса, поскольку эта функция реализована в самой программе shell (например, /bin/sh). Соответственно, встроенные функции shell выполняются быстрее всего. Рассмотрим важнейшие встроенные функции shell.
: |