Все программы в UNIX/Linux запускаются с тремя открытыми файлами: стандартным вводом (stdin), стандартным выводом (stdout) и стандартным выводом сообщений об ошибках (stderr). В оболочке bash поддерживается возможность перенаправления информации в командной строке посредством использования символов «<» для перенаправления стандартного ввода и «>» для стандартного вывода. По умолчанию стандартный ввод и стандартный вывод ассоциированы с консолью (ввод с клавиатуры, вывод на монитор). Но часто возникает необходимость выводить информацию не на экран (пользователя в это время у компьютера может не оказаться либо объем выводимой информации может оказаться слишком
большим для ее чтения с экрана), а в файл, который можно прочитать или распечатать потом.
Перенаправить данные можно различными способами. Например, команда
ls –la /home/user1 > /root/user1.ls
записывает список файлов пользователя в текстовый файл. Если этот файл не существует, то он создается. Если он существует, то он перезаписывается, т. е. его прежнее содержимое стирается.
echo ”Содержимое каталога /home/user1” >> /root/user1.ls
в этом случае выводимая информация дописывается к содержимому файла. Если файл не существует, при первом исполнении команды он будет создан.
Иногда вывод информации необходимо перенаправить в какое-либо устройство. В этом случае мы адресуемся к специальному файлу устройства, который является посредником между командным интерпретатором и драйверами устройства. Например, читаем ранее созданный образ дискеты и копируем его на сменный носитель:
cat image_fd > /dev/fd0
Выводим содержимое файла на принтер, подключенный к первому параллельному порту:
cat file1.txt > /dev/lp0
Воспроизводим звуковой файл через звуковой адаптер:
cat /usr/share/sndconfig/sample.au > /dev/audio
Аналогично можно изменить стандартный ввод информации, которым по умолчанию является клавиатура. С помощью перенаправления ввода можно записывать в файл сигналы с устройства, подключенного к последовательному интерфейсу. Комбинируя команды перенаправления ввода и вывода, можно передавать данные программе из одного файла и выводить результаты в другой файл. Так, например, утилита iconv позволяет изменить кодировку символов в файле, для чего целевой файл следует указать с операциями перенаправления вывода:
Еще одним средством перенаправления информационных потоков в Linux являются каналы, в этом случае они являются средством межпроцессного взаимодействия. Каналом называется однонаправленное логическое устройство, предназначенное для передачи данных от одного процесса другому. По своей сути канал представляет собой буфер памяти небольшого размера (обычно 4 Кб), в который один процесс может записывать данные, а другой – эти данные оттуда читать. И запись, и чтение данных осуществляется последовательно: данные всегда читаются в том порядке, в каком они были записаны. Канал может быть использован как средство связи между родственными процессами. Каналы могут иметь имя подобно файлам либо обходиться без него, т. е. могут быть именованными или неименованными.
Более простыми и распространенными являются неименованные каналы. В языке командных интерпретаторов неименованный канал обозначается символом «|». В некоторых источниках он именуется конвейером и служит средством группирования команд с передачей информации между стандартным выводом одной команды и стандартным вводом следующей за ней. Одним из простейших примеров использования неименованных каналов является постраничный просмотр на экране большого списка файлов, формируемый соответствующей командой. Так, чтобы последовательно просмотреть листинг файлов каталога большого объема, используют сочетание команд:
ls –la /bin|more
Вторая команда more как раз и обеспечивает поэкранный вывод данных с возможностью «листать» страницы вперед при нажатии любой клавиши. Комбинированная команда
ls –la /bin|less
позволяет постранично «листать» файл в обе стороны. Правда, при работе в графическом режиме и эмуляции текстового терминала в окне просматривать файл можно и без дополнительных команд, используя для этого боковые полосы прокрутки.
Приведем еще несколько примеров использования неименованных каналов. Утилита catчитает текстовый файл file_name и передает последовательный поток символов программе wc, которая подсчитывает число строк, слов и символов в файле:
cat <file_name>|wc
Впрочем, команда
wc <file_name>
делает то же самое, но пишется короче.
Утилита ps выводит таблицу процессов, а утилита head отображает первые 20 строк этой таблицы:
ps –ef | head -20
Утилита dd читает содержимое оптического диска, установленного в привод /dev/hdc, а grep ищет в считываемых данных строку «Linux»:
dd if=/dev/hdc | grep “Linux”
В следующем примере уже упомянутая утилита dd считывает из логического раздела на жестком диске второй 4-килобайтный блок данных, находит в нем описатель 5-й группы блоков и выводит его шестнадцатеричный и символьный дамп на экран:
Утилиты ps и top отображают каждый процесс, участвующий в конвейере, отдельной строкой.
Как уже указывалось, емкость канала ограничена размером буфера памяти, и если передающий процесс записывает в него данные быстрее, чем принимающий читает их, то он приостанавливается до тех пор, пока читающий процесс не освободит канал, и наоборот, если в канале ничего нет, то читающий процесс приостанавливается до появления информации в канале. Таким образом происходит синхронизация передачи по каналу.
Именованные каналы в UNIX системах представлены в виде специальных файлов, по своей сути подобных файлам устройств с последовательным доступом. За именованными каналами закрепилось еще одно название – файлы FIFO (First-In, First-Out – первым вошел, первым обслужен). К таким каналам может обратиться любой процесс. В консольном режиме именованные каналы создаются командой mkfifo, например: