Добавил:
github.com Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
10
Добавлен:
30.09.2023
Размер:
181.76 Кб
Скачать
    1. Работа с потоками ввода-вывода

Для каждой команды, записанной в файле скрипта, возможно перенаправление ее потоков ввода-вывода точно так же, как и при вводе отдельных команд в окне терминала. Однако зачастую при разработке скрипта требуются более расширенные возможности, которые предоставляет командная оболочка.

При запуске скрипта, ОС создает соответствующий ему процесс и автоматически связывает с порожденным процессом 9 файловых дескрипторов, обращение к которым внутри скрипта может осуществляться по их порядковым номерам от 0 до 9.

Файловому дескриптору с номером 0 соответствует стандартный поток ввода stdin [ CITATION Sta \l 1049 ], который используется для ввода данных в процесс с клавиатуры или для получения данных из файла. Файловому дескриптору с номером 1 соответствует стандартный поток stdout [ CITATION Sta1 \l 1049 ], данные которого отображаются на экране терминала. Файловому дескриптору с номером 2 соответствует стандартный поток вывода ошибок stderr [ CITATION Sta2 \l 1033 ], который по умолчанию также выводит данные на экран терминала. Файловые дескрипторы от 3 до 9 могут использоваться произвольно.

В Таблице Таблица 1 представлена справка по частым сценариям использования механизмов перенаправления потоков ввода-вывода.

Таблица 1. Часто используемые механизмы перенаправления потоков ввода-вывода

Команда

Пример

Описание

program > %filename%

program 1> %filename%

echoHello!” > testfile

echoHello!” 1> testfile

перенаправление потока stdout в файл с именем %filename%. Если файла не существовало, то он создается. Если файл существовал и в нем были данные – он очищается перед записью

program >> %filename%

program 1>> %filename%

echoFirst line” >> testfile

echoSecond line” 1>> testfile

перенаправление потока stdout в файл с именем %filename%. Данные в файл дописываются в конец

program 2> %filename%

whoami 2> debugfile

перенаправление потока stderr в файл с именем %filename%. Если файла не существовало, то он создается. Если файл существовал и в нем были данные – он очищается перед записью

program 2>> %filename%

pwd 2>> debugfile

whoami 2>> debugfile

перенаправление потока stderr в файл с именем %filename%. Данные в файл дописываются в конец

program &> %filename%

ps &> testfile

перенаправление потоков stdout и stderr в файл с именем %filename%

program i>&j

script.sh 4>&5

перенаправление файла с дескриптором i в дескриптор j.

program < %filename%

program 0< %filename%

grep word < file_of_words

grep word 0< file_of_words

ввод в программу данных из файла с именем %filename%

program < %inputfile% > %outputfile%

grep word < file_of_words > outputfile

ввод в программу данных из файла с именем %inputfile% и перенаправление потока stdout в файл %outputfile%

Для того, чтобы управлять перенаправлением дескрипторов или задействовать дескрипторы с номерами от 3 до 9 в скрипте часто используется встроенная команда «exec» [ CITATION exe \l 1033 ]:

exec 3 <> filename # дескриптор 3 может использоваться для работы с filename

exec 0< filename # stdin скрипта будет браться из filename, вместо клавиатуры

exec 4> filename # отправлять данные из дескриптора 4 в файл filename exec 5>&2 # перенаправлять дескриптор 5 в дескриптор 2 (stderr)

exec 5>&- # закрыть дескриптор 5

Помимо перенаправления дескрипторов с помощью exec можно замещать текущий процесс новым процессом.

Чтение данных из одного из дескрипторов или произвольного файла может быть произведено в скрипте с помощью встроенной команды «read»:

read [-ers] [-u fd] [-t timeout] [-p <PROMPT>] [-a <ARRAY>] [-n <NCHARS>] [-d <DELIM>] [<NAME...>]

По умолчанию она считывает одну строку данных из стандартного потока ввода (stdin) и записывает ее в переменную с именем <NAME>. Например, при вызове двух команд

read A echo $A

скрипт сначала будет ожидать ввода данных с клавиатуры, затем эти данные окажутся в переменной A, а после выведены на экран терминала с помощью echo. Если при вызове read указать несколько переменных, то в каждую из них будет помещено одно слово из введенной пользователем строки (слова разделяются пробелами или табуляцией).

С помощью опции «-n» возможно указать для read какое количество байт необходимо считать из stdin:

read -n 4 A # ожидание получения из stdin 4 байт для их помещения в A

Как только read получит указанное количество байт, то они будут помещены в переменную и выполнение скрипта продолжится.

Для того, чтобы считать данные из произвольного файлового дескриптора, используется опция «-u». Для чтения данных из произвольного файла используется перенаправление стандартного потока ввода:

exec 6<>filename

read -u 6 -n 2 A # получение двух байт в переменную A из дескриптора 6

read -n 2 A < filename # получение двух байт в переменную A из файла filename

Остальные опции read дают следующие возможности:

  • «-a» считывает по слову в массив <ARRAY> вместо переменных (подробнее про массивы см. п. 3.1);

  • «-d» распознает <DELIM> вместо символа <newline> для обозначения конца строки;

  • «-e» для интерактивной оболочки: использует bash-интерфейс readline для того, чтобы читать данные;

  • «-p» добавляет строку приглашения <PROMPT>. Обычно в ней выводят подсказку, перед тем как команда read будет считывать данные;

  • «-r» – сырой ввод: отключает интерпретацию специальных символов в считываемых данных;

  • «-s» – секретный ввод: не выводит в терминал введенные данные (для паролей);

  • «-t» – таймаут, ожидает данных <TIMEOUT> секунд и потом выходит.

В Листинге Листинг 5 приведен пример скрипта, который демонстрирует возможности работы с файловыми дескрипторами с помощью чтения данных из файла /proc/cpuinfo, в котором содержится информация об используемых процессорах. Пример его содержимого показан на Рисунке Рисунок 5.

Рисунок 5. Содержимое файла /proc/info

Листинг 5. Пример работы с файловыми дескрипторами

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

#!/bin/bash

 

exec 3</proc/cpuinfo

 

read -u 3 processor delim1 delim2 pr_value

read -u 3 model delim1 delim2 model_value

 

read -p "Entry name of file for model:" filename

 

echo "processor $pr_value - $model_value" > $filename

echo "Model of processor $pr_value is $model_value"

 

exec 3>&-

В строке 3 с помощью exec файловый дескриптор 3 связывается с файлом /proc/cpuinfo. Строки 5 и 6 содержат вызов read, который помещает слова из файлового дескриптора 3 в соответствующие переменные. В строке 8 у пользователя запрашивается имя файла filename. В строках 10 и 11 с помощью echo записываются строки в файл filename и выводятся в стандартный поток вывода. После этого файловый дескриптор 3 закрывается с помощью exec.

Соседние файлы в папке OS_labs