Как сохранить в файл вывод консоли. Linux: перенаправление

07.09.2019

Три направления ввода-вывода являются выделенными - стандартный ввод, вывод и поток ошибок (stdin, stdout, stderr ). По умолчанию, все три потока связаны (ассоциированы) с терминалом. При этом программа выводит все свои сообщения в том числе и об ошибках на терминал. Shell позволяет перенаправить эти стандартные потоки, установить ввод-вывод и объединение потоков.

Перенаправление потоков ввода-вывода.

>file Перенаправление стандартного потока вывода в файл file

>>file -Перенаправление стандартного потока вывода в файл file с добавлением в конец файла.

-получение стандартного потока ввода из файла file.

prog1 | prog2 -Передача выходного потока программы prog1 во входной поток программы prog2.

n>file file.

n>>file -Перенаправление стандартного потока с дескриптором n в файл file с добавлением в конец файла.

n>&m -Объединение потоков с дескрипторами n и m .

$ prog1 >/dev/null 2>&1

/dev/null - это псевдоустройство, которое уничтожает направленный в него поток.

Передача потока вывода одной программы в поток ввода другой используется часто. Например:

$ gzip -d archive.tar.gz | tar –xf

Здесь происходит разархивация файла archive.tar.gz , запакованного двумя архиваторами. Выходной поток от утилиты gzip передается во входной поток утилите tar . Аналогично эту же операцию можно было выполнить и по другому:

$ gzip -d archive.tar.gz

$ tar -xf archive.tar

Поскольку язык Bourne Shell является процедурным языком программирования, в нем также как и в других подобных языках есть операторы, позволяющие управлять последовательностью выполнения команд. Необходимым оператором является проверка некоторого условия, в зависимости от выполнения которого определяется дальнейший ход программы. Таким оператором является команда test. Эта команда проверяет выполнение некоторого условия. У команды test существует два варианта вызова:

test условие

[ условие ]

Следует отметить, что между скобкой и условием необходимо наличие пробелов, иначе Shell не сможет опознать "[" как команду test . При успешном завершении test возвращает "0" .

Условия проверки файлов:

-f file Файл "file" является обычным файлом.

-d file Файл "file" является каталогом.
-c file Файл "file" является специальным файлом.
-r file Файл "file" имеет разрешение на чтение.

-w file Файл "file" имеет разрешение на запись.

-x file Файл "file" имеет разрешение на исполнение.

-s file Файл "file" не пустой.

Условия проверки строк:

string1=string2 Строки string1 и string2 совпадают.

string1!=string2 Строки string1 и string2 не совпадают.

-n string1 Строка string1 существует.

-z string1 Строка string1 не существует.

Условия операций с целыми числами:

x -eq y x равно y

x -ne y x не равно y

x -gt y x больше y

x -ge y x больше или равно y

x -lt y x меньше y

x -le y x меньше или равно y

В этом случае команда test воспринимает строки именно как целые числа. Нулевому значению так же соответствует пустая строка.

Логические операции в контексте test

! (not) Логическое "НЕ"

-o (or) Логическое "ИЛИ"

-a (and) Логическое "И"

Условный оператор "if "

Общий вид использования условного оператора if представляется следующим образом:

if <условие>

then <список команд>

[ elif <условие>

then <список> ]

Выражения, выделенные в квадратных скобках, являются необязательными. Т.е. можно представить наиболее употребительную "порезанную" модификацию условного оператора:

if <условие>

then <список команд>

В этом случае если <условие> выполнено (код завершения 0) то выполняется <список команд>. В противном случае <список команд> пропускается.

Оператор выбора case

В общем случае синтаксис оператора case выглядит следующим образом:

case <строка> in

Шаблон 1)

........

Шаблон2)

........

........

Значение <строка> сравнивается с шаблонами, по порядку. Если было найдено совпадение, тогда выполняются команды соответствующего раздела. Следует отметить, что шаблоны допускают использование масок. Если совпадения не было найдено, тогда выполняются команды из раздела с шаблоном "*" (аналогично default селектора switch в С ).

Для примера приведем кусочек инициализационного скрипта BSD UNIX . Здесь переменные (inetd_enable и inetd_flags ) были получены из другого файла (rc.conf).

. /etc/rc.conf

case {$inetd_enable} in

)

if [ -x /usr/sbin/inetd ]; then

/usr/sbin/inetd $inetd_flags

fi

;;

esac

Оператор цикла с перечислением for

Синтаксис оператора for

for <имя>

<список команд>

Фрагмент, выделенный в квадратные скобки, может отсутствовать. Оператор for обеспечивает выполнение цикла столько раз, сколько слов в списке значений. При этом переменная <имя> принимает последовательно значения слов из списка. Сам по себе список может формироваться из вывода других команд. Если же список отсутствует, тогда <имя> принимает значения, переданные как позиционные параметры скрипта.

Оператор цикла с истинным условием while

Синтаксис оператора while в общем случае имеет следующую структуру:

while <условие>

<список команд>

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

Оператор цикла с ложным условием until

Синтаксис оператора until в общем случае имеет следующую структуру:

until <условие>

<список команд>

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

Основные команды ОС UNIX для работы с файлами

1. Команда pwd .

Синтаксис: pwd .

Описание: команда выводит имя текущей директории для работающего командного интерпретатора.

Задание 1.

Воспользуйтесь командой pwd для определения своей домашней директории.

Отразите команду и результат ее работы в отчете.

2. Команда man .

Синтаксис: man имя.

Имя - это имя интересующей нас команды, утилиты, системного вызова, библиотечной функции, файла.

Описание: UNIX MANUAL - руководство по операционной системе UNIX. Информация оттуда доступна в интерактивном режиме с помощью утилиты man .

Задание 2.

С помощью утилиты man посмотрите информацию о команде pwd.

Запишите кратко информацию о команде в отчет (на русском языке).

3. Команда cd .

Синтаксис:cd имя_директории.

Описание: это команда смены текущей директории. Имя_директории - это полное или относительное имя директории, которую вы хотите сделать текущей.

cd без параметров текущей сделает вашу домашнюю директорию.

Задание 3.

Сделайте текущей директорию на уровень выше. Проверьте это, затем вернитесь в свою домашнюю директорию. Проверьте смену директории.

Выполнение проделанных команд отразите в отчете.

4. Команда ls .

Синтаксис: ls имя_директории

Описание: команда просмотра состава указанной директории.

ls без параметров распечатывает список файлов из текущей директории.

В полученный список не войдут файлы, имена которых начинаются с символа “. ” - файлы, созданные различными системными программами в своих целях. Посмотреть полный список файлов можно, указав в команде ls ключ “-a”,

т.е. ls -aимя_директории

Права доступа к файлам

С каждым файлом в ОС UNIX связано 12-битное слово, называемое «правами доступа» к файлу.

Младшие 9 бит этого слова объединены в три группы по три бита; каждая группа задает права доступа для владельца файла, для его группы и для всех остальных пользователей. Три бита в каждой группе отвечают за право на чтение, запрос и использование файла.

Чтобы узнать права доступа к тому или иному файлу, можно воспользоваться командой

, например:

> ls -l /bin/cat

Расположенная в начале строки группа символов -rwxr-xr-x показывает тип файла (первый символ; минус означает, что мы имеем дело с обыкновенным файлом, буква d означала бы каталог и т.п.) и права доступа, соответственно, для владельца (в данном случае rwx , т.е. чтение, запись и исполнение), группы и всех остальных (в данном случае r-x , т.е. права на запись отсутствуют). Таким образом, файл /bin/cat доступен любому пользователю на чтение и исполнение, но модифицировать его может только пользователь root (т.е. администратор).

Можно записать слово прав доступа к файлу в виде восьмеричного числа (3 знака - восьмеричная цифра), трехзначного (владелец, группа, остальные пользователи) каждый знак в этом трехзначном восьмеричном числе формируется как сумма прав: 4- права на чтение, 2- права на запись, 1 - на использование (из двоичной триады): (111) 2 =2 0 +2 1 +2 2 =(1+2+4) 10 .

Например, 7 = 1 + 2 + 4 Þ права rwx

4 2 1

6 = 0 + 2+ 4 Þ права rw- -

4 2 0

В трехзначном числе задания прав: 744 для владельца определены все права, для группы - только чтение, для остальных пользователей - только на чтение.

Для использования прав доступа к файлам используется команда chmod , которая позволяет задать новые права доступа в виде восьмеричного числа, например:

$ chmod 744 filel.c.

Задание 4.

а) Для получения полной информации о команде ls воспользуйтесь утилитой man. Перенаправьте вывод команды в какой-либо текстовый файл.

б) Посмотрите полное содержимое текущей директории и перенаправьте этот вывод также в текстовый файл.

в) С помощью команды ls -l <имя_файла> выведите информацию о правах доступа к тому текстовому файлу, с которым вы работали в п. 4б, затем перенаправьте эту информацию в тот же текстовый файл. Объясните полученный вывод.

5. Команда cat .

Перенаправление ввода/вывода.

Для просмотра содержимого небольшого текстового файла на экране можно воспользоваться командой:

сat имя_файла

Внимание! Не пытайтесь просматривать таким образом содержимое директории и бинарных файлов.

Большой тестовый файл удобно просматривать командой more (описание использования найдите в UNIX MANUAL ). Почему здесь неудобна команда сat ?

В команде сat можно задавать несколько имен файлов:

сat файл1 файл 2 … файл N

при этом содержимое всех файлов подряд будет выведено на экран.

Можно перенаправить вывод в какой-нибудь файл:

сat файл 1 файл 2 > файл_ результатов

Перенаправление вывода со стандартного потока вывода (экрана) в файл является стандартным для всех команд. Перенаправить стандартный ввод (с клавиатуры), например, брать данные для программы из файла, можно с помощью знака “<”.

сat > новый_файл - создаст новый текстовый файл с содержимым, вводимым вами с клавиатуры.

Прервать процесс ввода данных-

Задание 5.

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

6. Простейшие команды работы с файлами: cp, rm, mkdir, mv

Для создания новой директории используется команда:

mkdir имя_директории

Для копирования содержимого одного файла в другой используется команда:

cp файл_источник файл_назначение.

Команда

cp файл 1 файл 2 …. файл N директория назначения

служит для копирования файла или файлов в уже существующую директорию с именем директории_назначения под своими именами. Вместо имен копируемых файлов можно использовать их шаблоны. Шаблоны задаются с помощью метасимволов:

* - соответствует всем цепочкам литер, включая пустую.

Все одиночные литеры

[ …] - соответствует любой литере, заключенной в скобки. Пара литер, разделенных минусом, задает диапазон литер.

Команда

cp - r дир_источник дир_назначение

служит для рекурсивного копировария одной директории (дир_источник) в новую директориию (дир_назначение).

Вместо имен в командах копирования могут использоваться их шаблоны.

Команда

rm файл 1 файл 2 …. файл N

позволяет удалить 1 или несколько регулярных файлов из текущей директории.

Вместо имен могут использоваться шаблоны. Если хотите удалить одну или несколько директорий вместе с их содержимым (рекурсивное удаление) в команде rm используйте ключ -r

Rm-r дир 1 дир 2

Команда переименования:

mv имя_источника имя_назначения

Файл с именем имя_источника переименовывает в файл с именем имя_назначения. При этом перед выполнением команды файла с именем имя_назначения существовать не должно.

Задание 6.

Создайте новую директорию внутри своей домашней. Организуйте там небольшой тестовый файл с содержимым из двух строк:

«Изучаю работу в ОС UNIX

Организую скрипт».

Скопируйте содержимое этого файла в другой - с тем же именем, но в директории /home. Удалите первоначально созданный файл из вашей директории, если копирование прошло успешно. Проверьте содержимое использованных директориий и файлов.

Задание 7.

1). Когда вы освоили работу в интерактивном режиме с простейшими командами ОС UNIX, создайте с помощью редактора Kwriter скрипт со сценарием, соответствующим последовательному выполнению:

Задание 3,

Задание 4Б,4В,

Задание 5,

Задание 6.

В задании 6 не забудьте проверить программно успешно ли прошло копирование файла, с выдачей на экран дисплея текстовых сообщений и содержимого соответствующих директорий.

Необходимо, чтобы в командном файле была организована грамотная выдача запросов на ввод данных с клавиатуры с помощью команды: $ echo - n “текст запроса”.

2). Сохраните скрипт с именем Myscript1, запустите его на выполнение командой

sh Myscript1

введите запрашиваемые данные и проверьте полученные результаты.

3). Составьте отчет о выполненной лабораторной работе, в котором должна быть отражена и ваша работа в интерактивном режиме и со скриптом, включая текст скрипта (с комментариями) и полученные результаты на экране и в файлах.

Системные вызовы getuid и getpid

Узнать идентификатор пользователя, запустившего программу на выполнение,-UID и идентификатор группы, к которой он относится,-GID можно с помощью системных вызовов getuid() и getpid() ,применив их внутри этой программы.

Прототипы системных вызовов:

#include

#include

uid_t getuid(void);

gid_t getgid(void);

Задание 8.

Напишите, откомпилируйте и запустите программу, которая печатала бы идентификатор пользователя, запустившего программу, и идентификатор его группы.

Включите программу с результатами в отчет.

Контрольные вопросы

1. Понятие файла в ОС UNIX . Что такое домашняя директория?

2. Какие существуют средства группирования команд Shell -интерпретатора? приведите примеры использования.

3. Как осуществляется перенаправление ввода-вывода?

4. Что такое конвейер команд? приведите пример.

5. Как средствами Shell выполнить арифметические действия над Shell -переменной?

6. Каковы правила генерации имен файлов?

7. Как выполняется подстановка результатов выполнения команд?

8. Как интерпретировать строку cmd1 & cmd2 & ?

9. Как интерпретировать строку cmd1 && cmd2 & ?

10. Как интерпретировать строку cmd1 || cmd2 & ?

11. Как в UNIX определены права доступа к файлу? Какой командой их можно посмотреть для конкретного файла?

12. Как определить идентификатор пользователя, запустившего программу и идентификатор его группы?

Лабораторная работа № 3.

Процессы в операционной системе UNIX.

Цель работы

Научиться создавать процессы и освоить изменение пользовательского контекста процессов с помощью системных вызовов, применяемых в программах на языке С , в ОС UNIX .

1. Изучить организацию процессов в UNIX : понятие процесса, контекст процесса, жизненный цикл процесса, идентификация процессов, иерархическая структура процессов. Написать на С и отладить программу в соответствии с заданием 1.

2. Ознакомиться с созданием процесса в UNIX , с организацией завершения процесса. Написать и отладить программу (язык С ) в соответствии с Заданием 2, включить ее в отчет.

3. Изучить параметры функции main() в языке С , переменные среды и аргументы командной строки. Написать программу на языке С в соответствии с Заданием 3, отладить и включить ее в отчет вместе с результатами.

4. Изучить семейство функций для организации системного вызова exec().

5. Написать программу на языке С в соответствии с вариантом Задания 4, выданного преподавателем, отладить программу и продемонстрировать полученные результаты преподавателю. Включить программу с результатами в отчет.

6. Защитить работу преподавателю, ответив на контрольные вопросы.

Вы уже знакомы с двумя методами работы с тем, что выводят сценарии командной строки:

  • Отображение выводимых данных на экране.
  • Перенаправление вывода в файл.
Иногда что-то надо показать на экране, а что-то - записать в файл, поэтому нужно разобраться с тем, как в Linux обрабатывается ввод и вывод, а значит - научиться отправлять результаты работы сценариев туда, куда нужно. Начнём с разговора о стандартных дескрипторах файлов.

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

Всё в Linux - это файлы, в том числе - ввод и вывод. Операционная система идентифицирует файлы с использованием дескрипторов.

Каждому процессу позволено иметь до девяти открытых дескрипторов файлов. Оболочка bash резервирует первые три дескриптора с идентификаторами 0, 1 и 2. Вот что они означают.

  • 0 , STDIN - стандартный поток ввода.
  • 1 , STDOUT - стандартный поток вывода.
  • 2 , STDERR - стандартный поток ошибок.
Эти три специальных дескриптора обрабатывают ввод и вывод данных в сценарии.
Вам нужно как следует разобраться в стандартных потоках. Их можно сравнить с фундаментом, на котором строится взаимодействие скриптов с внешним миром. Рассмотрим подробности о них.

STDIN

STDIN - это стандартный поток ввода оболочки. Для терминала стандартный ввод - это клавиатура. Когда в сценариях используют символ перенаправления ввода - < , Linux заменяет дескриптор файла стандартного ввода на тот, который указан в команде. Система читает файл и обрабатывает данные так, будто они введены с клавиатуры.

Многие команды bash принимают ввод из STDIN , если в командной строке не указан файл, из которого надо брать данные. Например, это справедливо для команды cat .

Когда вы вводите команду cat в командной строке, не задавая параметров, она принимает ввод из STDIN . После того, как вы вводите очередную строку, cat просто выводит её на экран.

STDOUT

STDOUT - стандартный поток вывода оболочки. По умолчанию это - экран. Большинство bash-команд выводят данные в STDOUT , что приводит к их появлению в консоли. Данные можно перенаправить в файл, присоединяя их к его содержимому, для этого служит команда >> .

Итак, у нас есть некий файл с данными, к которому мы можем добавить другие данные с помощью этой команды:

Pwd >> myfile
То, что выведет pwd , будет добавлено к файлу myfile , при этом уже имеющиеся в нём данные никуда не денутся.

Перенаправление вывода команды в файл

Пока всё хорошо, но что если попытаться выполнить что-то вроде показанного ниже, обратившись к несуществующему файлу xfile , задумывая всё это для того, чтобы в файл myfile попало сообщение об ошибке.

Ls –l xfile > myfile
После выполнения этой команды мы увидим сообщения об ошибках на экране.


Попытка обращения к несуществующему файлу

При попытке обращения к несуществующему файлу генерируется ошибка, но оболочка не перенаправила сообщения об ошибках в файл, выведя их на экран. Но мы-то хотели, чтобы сообщения об ошибках попали в файл. Что делать? Ответ прост - воспользоваться третьим стандартным дескриптором.

STDERR

STDERR представляет собой стандартный поток ошибок оболочки. По умолчанию этот дескриптор указывает на то же самое, на что указывает STDOUT , именно поэтому при возникновении ошибки мы видим сообщение на экране.

Итак, предположим, что надо перенаправить сообщения об ошибках, скажем, в лог-файл, или куда-нибудь ещё, вместо того, чтобы выводить их на экран.

▍Перенаправление потока ошибок

Как вы уже знаете, дескриптор файла STDERR - 2. Мы можем перенаправить ошибки, разместив этот дескриптор перед командой перенаправления:

Ls -l xfile 2>myfile cat ./myfile
Сообщение об ошибке теперь попадёт в файл myfile .


Перенаправление сообщения об ошибке в файл

▍Перенаправление потоков ошибок и вывода

При написании сценариев командной строки может возникнуть ситуация, когда нужно организовать и перенаправление сообщений об ошибках, и перенаправление стандартного вывода. Для того, чтобы этого добиться, нужно использовать команды перенаправления для соответствующих дескрипторов с указанием файлов, куда должны попадать ошибки и стандартный вывод:

Ls –l myfile xfile anotherfile 2> errorcontent 1> correctcontent

Перенаправление ошибок и стандартного вывода

Оболочка перенаправит то, что команда ls обычно отправляет в STDOUT , в файл correctcontent благодаря конструкции 1> . Сообщения об ошибках, которые попали бы в STDERR , оказываются в файле errorcontent из-за команды перенаправления 2> .

Если надо, и STDERR , и STDOUT можно перенаправить в один и тот же файл, воспользовавшись командой &> :


Перенаправление STDERR и STDOUT в один и тот же файл

После выполнения команды то, что предназначено для STDERR и STDOUT , оказывается в файле content .

Перенаправление вывода в скриптах

Существует два метода перенаправления вывода в сценариях командной строки:
  • Временное перенаправление, или перенаправление вывода одной строки.
  • Постоянное перенаправление, или перенаправление всего вывода в скрипте либо в какой-то его части.

▍Временное перенаправление вывода

В скрипте можно перенаправить вывод отдельной строки в STDERR . Для того, чтобы это сделать, достаточно использовать команду перенаправления, указав дескриптор STDERR , при этом перед номером дескриптора надо поставить символ амперсанда (&):

#!/bin/bash echo "This is an error" >&2 echo "This is normal output"
Если запустить скрипт, обе строки попадут на экран, так как, как вы уже знаете, по умолчанию ошибки выводятся туда же, куда и обычные данные.


Временное перенаправление

Запустим скрипт так, чтобы вывод STDERR попадал в файл.

./myscript 2> myfile
Как видно, теперь обычный вывод делается в консоль, а сообщения об ошибках попадают в файл.


Сообщения об ошибках записываются в файл

▍Постоянное перенаправление вывода

Если в скрипте нужно перенаправлять много выводимых на экран данных, добавлять соответствующую команду к каждому вызову echo неудобно. Вместо этого можно задать перенаправление вывода в определённый дескриптор на время выполнения скрипта, воспользовавшись командой exec:

#!/bin/bash exec 1>outfile echo "This is a test of redirecting all output" echo "from a shell script to another file." echo "without having to redirect every line"
Запустим скрипт.


Перенаправление всего вывода в файл

Если просмотреть файл, указанный в команде перенаправления вывода, окажется, что всё, что выводилось командами echo , попало в этот файл.

Команду exec можно использовать не только в начале скрипта, но и в других местах:

#!/bin/bash exec 2>myerror echo "This is the start of the script" echo "now redirecting all output to another location" exec 1>myfile echo "This should go to the myfile file" echo "and this should go to the myerror file" >&2
Вот что получится после запуска скрипта и просмотра файлов, в которые мы перенаправляли вывод.


Перенаправление вывода в разные файлы

Сначала команда exec задаёт перенаправление вывода из STDERR в файл myerror . Затем вывод нескольких команд echo отправляется в STDOUT и выводится на экран. После этого команда exec задаёт отправку того, что попадает в STDOUT , в файл myfile , и, наконец, мы пользуемся командой перенаправления в STDERR в команде echo , что приводит к записи соответствующей строки в файл myerror.

Освоив это, вы сможете перенаправлять вывод туда, куда нужно. Теперь поговорим о перенаправлении ввода.

Перенаправление ввода в скриптах

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

Exec 0< myfile
Эта команда указывает оболочке на то, что источником вводимых данных должен стать файл myfile , а не обычный STDIN . Посмотрим на перенаправление ввода в действии:

#!/bin/bash exec 0< testfile count=1 while read line do echo "Line #$count: $line" count=$(($count + 1)) done
Вот что появится на экране после запуска скрипта.


Перенаправление ввода

В одном из предыдущих материалов вы узнали о том, как использовать команду read для чтения данных, вводимых пользователем с клавиатуры. Если перенаправить ввод, сделав источником данных файл, то команда read , при попытке прочитать данные из STDIN , будет читать их из файла, а не с клавиатуры.

Некоторые администраторы Linux используют этот подход для чтения и последующей обработки лог-файлов.

Создание собственного перенаправления вывода

Перенаправляя ввод и вывод в сценариях, вы не ограничены тремя стандартными дескрипторами файлов. Как уже говорилось, можно иметь до девяти открытых дескрипторов. Остальные шесть, с номерами от 3 до 8, можно использовать для перенаправления ввода или вывода. Любой из них можно назначить файлу и использовать в коде скрипта.

Назначить дескриптор для вывода данных можно, используя команду exec:

#!/bin/bash exec 3>myfile echo "This should display on the screen" echo "and this should be stored in the file" >&3 echo "And this should be back on the screen"
После запуска скрипта часть вывода попадёт на экран, часть - в файл с дескриптором 3 .


Перенаправление вывода, используя собственный дескриптор

Создание дескрипторов файлов для ввода данных

Перенаправить ввод в скрипте можно точно так же, как и вывод. Сохраните STDIN в другом дескрипторе, прежде чем перенаправлять ввод данных.

После окончания чтения файла можно восстановить STDIN и пользоваться им как обычно:

#!/bin/bash exec 6<&0 exec 0< myfile count=1 while read line do echo "Line #$count: $line" count=$(($count + 1)) done exec 0<&6 read -p "Are you done now? " answer case $answer in y) echo "Goodbye";; n) echo "Sorry, this is the end.";; esac
Испытаем сценарий.


Перенаправление ввода

В этом примере дескриптор файла 6 использовался для хранения ссылки на STDIN . Затем было сделано перенаправление ввода, источником данных для STDIN стал файл. После этого входные данные для команды read поступали из перенаправленного STDIN , то есть из файла.

После чтения файла мы возвращаем STDIN в исходное состояние, перенаправляя его в дескриптор 6 . Теперь, для того, чтобы проверить, что всё работает правильно, скрипт задаёт пользователю вопрос, ожидает ввода с клавиатуры и обрабатывает то, что введено.

Закрытие дескрипторов файлов

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

#!/bin/bash exec 3> myfile echo "This is a test line of data" >&3 exec 3>&- echo "This won"t work" >&3
После исполнения скрипта мы получим сообщение об ошибке.


Попытка обращения к закрытому дескриптору файла

Всё дело в том, что мы попытались обратиться к несуществующему дескриптору.

Будьте внимательны, закрывая дескрипторы файлов в сценариях. Если вы отправляли данные в файл, потом закрыли дескриптор, потом - открыли снова, оболочка заменит существующий файл новым. То есть всё то, что было записано в этот файл ранее, будет утеряно.

Получение сведений об открытых дескрипторах

Для того, чтобы получить список всех открытых в Linux дескрипторов, можно воспользоваться командой lsof . Во многих дистрибутивах, вроде Fedora, утилита lsof находится в /usr/sbin . Эта команда весьма полезна, так как она выводит сведения о каждом дескрипторе, открытом в системе. Сюда входит и то, что открыли процессы, выполняемые в фоне, и то, что открыто пользователями, вошедшими в систему.

У этой команды есть множество ключей, рассмотрим самые важные.

  • -p Позволяет указать ID процесса.
  • -d Позволяет указать номер дескриптора, о котором надо получить сведения.
Для того, чтобы узнать PID текущего процесса, можно использовать специальную переменную окружения $$ , в которую оболочка записывает текущий PID .

Ключ -a используется для выполнения операции логического И над результатами, возвращёнными благодаря использованию двух других ключей:

Lsof -a -p $$ -d 0,1,2

Вывод сведений об открытых дескрипторах

Тип файлов, связанных с STDIN , STDOUT и STDERR - CHR (character mode, символьный режим). Так как все они указывают на терминал, имя файла соответствует имени устройства, назначенного терминалу. Все три стандартных файла доступны и для чтения, и для записи.

Посмотрим на вызов команды lsof из скрипта, в котором открыты, в дополнение к стандартным, другие дескрипторы:

#!/bin/bash exec 3> myfile1 exec 6> myfile2 exec 7< myfile3 lsof -a -p $$ -d 0,1,2,3,6,7
Вот что получится, если этот скрипт запустить.


Просмотр дескрипторов файлов, открытых скриптом

Скрипт открыл два дескриптора для вывода (3 и 6) и один - для ввода (7). Тут же показаны и пути к файлам, использованных для настройки дескрипторов.

Подавление вывода

Иногда надо сделать так, чтобы команды в скрипте, который, например, может исполняться как фоновый процесс, ничего не выводили на экран. Для этого можно перенаправить вывод в /dev/null . Это - что-то вроде «чёрной дыры».

Вот, например, как подавить вывод сообщений об ошибках:

Ls -al badfile anotherfile 2> /dev/null
Тот же подход используется, если, например, надо очистить файл, не удаляя его:

Cat /dev/null > myfile

Итоги

Сегодня вы узнали о том, как в сценариях командной строки работают ввод и вывод. Теперь вы умеете обращаться с дескрипторами файлов, создавать, просматривать и закрывать их, знаете о перенаправлении потоков ввода, вывода и ошибок. Всё это очень важно в деле разработки bash-скриптов.

В следующий раз поговорим о сигналах Linux, о том, как обрабатывать их в сценариях, о запуске заданий по расписанию и о фоновых задачах.

Уважаемые читатели! В этом материале даны основы работы с потоками ввода, вывода и ошибок. Уверены, среди вас есть профессионалы, которые могут рассказать обо всём этом то, что приходит лишь с опытом. Если так - передаём слово вам.

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

В этой статье мы рассмотрим как выполняется перенаправление потоков ввода вывода в Linux, какие операторы для этого используются, а также где все это можно применять.

Все команды, которые мы выполняем, возвращают нам три вида данных:

  • Результат выполнения команды, обычно текстовые данные, которые запросил пользователь;
  • Сообщения об ошибках - информируют о процессе выполнения команды и возникших непредвиденных обстоятельствах;
  • Код возврата - число, которое позволяет оценить правильно ли отработала программа.

В Linux все субстанции считаются файлами, в том числе и потоки ввода вывода linux - файлы. В каждом дистрибутиве есть три основных файла потоков, которые могут использовать программы, они определяются оболочкой и идентифицируются по номеру дескриптора файла:

  • STDIN или 0 - этот файл связан с клавиатурой и большинство команд получают данные для работы отсюда;
  • STDOUT или 1 - это стандартный вывод, сюда программа отправляет все результаты своей работы. Он связан с экраном, или если быть точным, то с терминалом, в котором выполняется программа;
  • STDERR или 2 - все сообщения об ошибках выводятся в этот файл.

Перенаправление ввода / вывода позволяет заменить один из этих файлов на свой. Например, вы можете заставить программу читать данные из файла в файловой системе, а не клавиатуры, также можете выводить ошибки в файл, а не на экран и т д. Все это делается с помощью символов "<" и ">" .

Перенаправить вывод в файл

Все очень просто. Вы можете перенаправить вывод в файл с помощью символа >. Например, сохраним вывод команды top:

top -bn 5 > top.log

Опция -b заставляет программу работать в не интерактивном пакетном режиме, а n - повторяет операцию пять раз, чтобы получить информацию обо всех процессах. Теперь смотрим что получилось с помощью cat:

Символ ">" перезаписывает информацию из файла, если там уже что-то есть. Для добавления данных в конец используйте ">>" . Например, перенаправить вывод в файл linux еще для top:

top -bn 5 >> top.log

По умолчанию для перенаправления используется дескриптор файла стандартного вывода. Но вы можете указать это явно. Эта команда даст тот же результат:

top -bn 5 1>top.log

Перенаправить ошибки в файл

Чтобы перенаправить вывод ошибок в файл вам нужно явно указать дескриптор файла, который собираетесь перенаправлять. Для ошибок - это номер 2. Например, при попытке получения доступа к каталогу суперпользователя ls выдаст ошибку:

Вы можете перенаправить стандартный поток ошибок в файл так:

ls -l /root/ 2> ls-error.log
$ cat ls-error.log

Чтобы добавить данные в конец файла используйте тот же символ:

ls -l /root/ 2>>ls-error.log

Перенаправить стандартный вывод и ошибки в файл

Вы также можете перенаправить весь вывод, ошибки и стандартный поток вывода в один файл. Для этого есть два способа. Первый из них, более старый, состоит в том, чтобы передать оба дескриптора:

ls -l /root/ >ls-error.log 2>&1

Сначала будет отправлен вывод команды ls в файл ls-error.log c помощью первого символа перенаправления. Дальше в тот же самый файл будут направлены все ошибки. Второй метод проще:

ls -l /root/ &> ls-error.log

Также можно использовать добавление вместо перезаписи:

ls -l /root/ &>> ls-error.log

Стандартный ввод из файла

Большинство программ, кроме сервисов, получают данные для своей работы через стандартный ввод. По умолчанию стандартный ввод ожидает данных от клавиатуры. Но вы можете заставить программу читать данные из файла с помощью оператора "<" :

cat

Вы также можете сразу же перенаправить вывод тоже в файл. Например, пересортируем список:

sort sort.output

Таким образом, мы в одной команде перенаправляем ввод вывод linux.

Использование тоннелей

Можно работать не только с файлами, но и перенаправлять вывод одной команды в качестве ввода другой. Это очень полезно для выполнения сложных операций. Например, выведем пять недавно измененных файлов:

ls -lt | head -n 5

С помощью утилиты xargs вы можете комбинировать команды таким образом, чтобы стандартный ввод передавался в параметры. Например, скопируем один файл в несколько папок:

echo test/ tmp/ | xargs -n 1 cp -v testfile.sh

Здесь параметр -n 1 задает, что для одной команды нужно подставлять только один параметр, а опция -v в cp позволяет выводить подробную информацию о перемещениях. Еще одна, полезная в таких случаях команда - это tee. Она читает данные из стандартного ввода и записывает в стандартный вывод или файлы. Например:

echo "Тест работы tee" | tee file1

В сочетании с другими командами все это может использоваться для создания сложных инструкций из нескольких команд.

Выводы

В этой статье мы рассмотрели основы перенаправления потоков ввода вывода Linux. Теперь вы знаете как перенаправить вывод в файл linux или вывод из файла. Это очень просто и удобно. Если у вас остались вопросы, спрашивайте в комментариях!

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

В следующей таблице описаны операторы перенаправления потоков ввода и вывода команд.

Оператор перенаправления

Описание

Записывает данные на выходе команды вместо командной строки в файл или на устройство, например, на принтер.

Читает поток входных данных команды из файла, а не с клавиатуры.

Добавляет выходные данные команды в конец файла, не удаляя при этом существующей информации из файла.

Считывает данные на выходе одного дескриптора как входные данные для другого дескриптора.

Считывает входные данные одного дескриптора как выходные данные другого дескриптора.

Считывает выходные данные одной команды и записывает их на вход другой команды. Эта процедура известна под названием «канал».

По умолчанию, входные данные команды (дескриптор STDIN) отсылаются с клавиатуры интерпретатору команд Cmd.exe, далее Cmd.exe отправляет выходные данные команды (дескриптор STDOUT) в окно командной строки.

В следующей таблице представлены доступные дескрипторы.

Номера от 0 до 9 представляют первые 10 дескрипторов. Для запуска программы и перенаправления любого из 10 дескрипторов используется интерпретатор команд Cmd.exe. Для задания требуемого дескриптора перед оператором перенаправления введите его номер. Если дескриптор не определен, то по умолчанию оператором перенаправления ввода «<» будет ноль (0), а оператором перенаправления вывода «>» будет единица (1). После ввода оператора «<» или «>» необходимо указать, откуда читать и куда записывать данные. Можно задать имя файла или любой из существующих дескрипторов.

Для задания перенаправления в существующие дескрипторы используется амперсанд (&), затем номер требуемого дескриптора (например, & номер_дескриптора ). Например, для перенаправления дескриптора 2 (STDERR) в дескриптор 1 (STDOUT) введите:

Дублирование дескрипторов

Оператор перенаправления «&» дублирует выходные или входные данные с одного заданного дескриптора на другой заданный дескриптор. Например, для отправки выводных данных команды dir в файл File.txt и отправки ошибки вывода в файл File.txt введите:

dir>c:\file.txt 2>&1

При дублировании дескриптора происходит копирование всех его исходных характеристик. Например, если дескриптор доступен только для записи, то все его дубликаты будут доступны только для записи. Нельзя продублировать дескриптор с доступом только для чтения в дескриптор с доступом только для записи.

Перенаправление ввода команд (<)

Для перенаправления ввода команд с цифровой клавиатуры на файл или на устройство используйте оператор «<». Например, для ввода команды sort из файла List.txt введите:

sort

Содержимое файла File.txt появится в командной строке в виде списка в алфавитном порядке.

Оператор «<» открывает заданное имя файла с доступом только для чтения. Поэтому с его помощью нельзя записывать в файл. Например, при запуске программы с оператором <&2 все попытки прочитать дескриптор 0 ни к чему не приведут, так как изначально он был открыт с доступом только для записи.

Примечание

  • Дескриптор 0 задан по умолчанию для оператора перенаправления ввода «<».

Перенаправление вывода команд (>)

Выходные данные практически всех команд высвечиваются в окне командной строки. Даже команды, выводящие данные на диск или принтер, выдают сообщения и запросы в окне командной строки.

Для перенаправления вывода команд из окна командной строки в файл или на устройство применяется оператор «>». Этот оператор используется с большинством команд. Например, для перенаправления вывода команды dir в файл Dirlist.txt введите:

dir>dirlist.txt

Если файл Dirlist.txt не существует, интерпретатор команд Cmd.exe создаст его. Если файл существует, Cmd.exe заменит информацию в файле на данные, полученные от команды dir .

Для запуска команды netsh routing dump и последующей отправки результатов ее работы в Route.cfg введите:

netsh routing dump >c:\route.cfg

Оператор «>» открывает заданный файл с доступом только для записи. Поэтому с помощью данного оператора файл прочитать нельзя. Например, при запуске программы с оператором перенаправления <&0 все попытки записать дескриптор 1 ни к чему не приведут, так как изначально дескриптор 0 был открыт с доступом только для чтения.

Примечание.

  • Дескриптор 1 задан по умолчанию для оператора перенаправления вывода «>».

Использование оператора «<&» для перенаправления ввода и дублирования

Для использования оператора перенаправления ввода необходимо, чтобы задаваемый файл уже существовал. Если файл для ввода существует, то интерпретатор команд Cmd.exe открывает его с доступом только для чтения и его содержимое отправляет в команду так, как если бы это был ввод с цифровой клавиатуры. При задании дескриптора интерпретатор команд Cmd.exe дублирует его в дескриптор, существующий в системе.

Например, для считывания файла File.txt на вход в дескриптор 0 (STDIN) введите:

< file.txt

Для открытия файла File.txt, сортировки его содержимого и последующей отправки в окно командной строки (STDOUT) введите:

sort< file.txt

Для того чтобы найти файл File.txt и перенаправить дескриптор 1 (STDOUT) и дескриптор 2 (STDERR) в Search.txt введите:

findfile file.txt>search.txt 2<&1

Для дублирования определенного пользователем дескриптора 3 в качестве входной информации для дескриптора 0 (STDIN) введите:

Использование оператора «>&» для перенаправления ввода и дублирования

При перенаправлении вывода в файл и задании существующего имени файла интерпретатор команд Cmd.exe открывает файл с доступом только для записи и переписывает его содержимое. Если дескриптор задан, интерпретатор команд Cmd.exe дублирует файл в существующий дескриптор.

Для дублирования определенного пользователем дескриптора 3 в дескриптор 1 введите:

Для перенаправления всех выходных данных, включая выходные данные дескриптора 2 (STDERR), команды ipconfig в дескриптор 1 (STDOUT) и последующего перенаправления выходных данных в Output.log введите:

ipconfig.exe>>output.log 2>&1

Использование оператора «>>» для добавления вывода

Для добавления выходных данных команды в конец файла без потери хранящейся в нем информации используется двойной символ «больше» (>>). Например, следующая команда добавляет список каталогов, созданный командой dir , в файл Dirlist.txt:

dir>>dirlist.txt

Для добавления выходных данных команды netstat в конец файла Tcpinfo.txt введите:

netstat>>tcpinfo.txt

Использование оператора канала (|)

Оператор канала «вертикальная линия» (|) забирает выходные данные одной команды (по умолчанию STDOUT) и направляет их на вход другой команды (по умолчанию STDIN). Например, следующая команда сортирует каталог:

dir | sort

В данном примере обе команды запускаются одновременно, но команда sort приостанавливает работу до получения выходных данных команды dir . Команда sort использует выходные данные команды dir в качестве своих входных данных, а затем свои выходные данные отправляет в дескриптор 1 (STDOUT).

Комбинирование команд с операторами перенаправления

Комбинируя команды-фильтры с другими командами и именами файлов, можно создавать команды на заказ. Например, для сохранения имен файлов, содержащих строку «LOG», используется следующая команда:

dir /b | find "LOG" > loglist.txt

Выход команды dir отсылается в команду-фильтр find . Имена файлов, содержащие строку «LOG», хранятся в файле Loglist.txt в виде списка (например, NetshConfig.log, Logdat.svd и Mylog.bat).

При использовании более одного фильтра в одной команде их необходимо отделять с помощью канала (|). Например, следующая команда ищет в каждом каталоге диска C файлы, в названии которых присутствует строка «Log», и выводит их постранично на экран:

dir c:\ /s /b | find "LOG" | more

Наличие канала (|) указывает Cmd.exe, что выход команды dir нужно отправить команде-фильтру find . Команда find выбирает только те имена файлов, в которых содержится строка «LOG». Команда more выводит на экран имена файлов, полученные командой find с паузой после заполнения каждого экрана.

1403

Перенаправление "2>&1", ">/dev/null" или потоки вывода в Unix (bash/sh)

Ваша оценка: шедевр замечательно очень хорошо хорошо нормально Не читал терпимо посредственно плохо очень плохо не читать

Потоки вывода

Сообщения скриптов выводятся во вполне определенные потоки - потоки вывода. Таким образом то, что мы выводим через

echo "Hello, world!"

Не просто выводится на экран, а, с точки зрения системы, а конкретно - командных интерпретаторов sh и bash - выводится через определенный поток вывода. В случае echo - поток под номером 1 (stdout), с которым ассоциирован экран.

Некоторые программы и скрипты так-же используют другой поток вывода - под номером 2 (stderr). В него они выводят сообщения об ошибках. Благодаря этому можно раздельно выхватывать из потоков обычные информационные сообщения и сообщения об ошибках и направлять и обрабатывать их раздельно.

Например, Вы можете заблокировать вывод информационных сообщения, оставив только сообщения об ошибках. Или направить вывод сообщений об ошибках в отдельный файл для логирования.

Что такое ">somefile"

Такой записью в Unix (в интерпретаторах bash и sh) указывается перенаправление потоков вывода.

В следующем примере мы перенаправим все информационные (обычные) сообщения команды ls в файл myfile.txt, получив таким образом в этом файле просто список ls:

$ ls > myfile.txt


При этом после нажатия на Enter Вы не увидите ничего на экране, зато в файле myfile.txt будет находится все то, что должно было отобразиться на экране.

Однако давайте сделаем заведомо ошибочную операцию:

$ ls /masdfasdf > myfile.txt


И что случится? Т.к. директории masdfasdf в корне файловой системы не существует (я так предполагаю - вдруг у Вас есть?), то команда ls сгенерирует ошибку. Однако вывалит эту ошибку она уже не через обычный поток stdout (1), а через поток ошибок stderr (2). А перенаправление задано лишь для stdout ("> myfile.txt").

Т.к. поток stderr (2) мы никуда не перенаправили - сообщение об ошибке появится на экране и НЕ появится в файле myfile.txt

А теперь давайте выполним команду ls так, чтобы информационные данные записались в файл myfile.txt, а сообщения об ошибках - в файл myfile.err, при этом на экране во время выполнения не появится ничего:

$ ls >myfile.txt 2>myfile.err


Здесь нам встречается впервые указание номера потока в качестве перенаправления. Запись "2>myfile.err" указывает, что поток с номером 2 (stderr) нужно перенаправить в файл myfile.err.

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

2>&1

Нередко в скриптах можно встретить такую запись. Она означает: "Поток с номером 2 перенаправить в поток с номером 1", или "Поток stderr - направить через поток stdout". Т.е. все сообщения об ошибках мы направляем через поток, через который обычно печатаются обычные, не ошибочные сообщения.

$ ls /asfasdf 2>&1


А вот еще пример, в котором все сообщения перенаправляются в файл myfile.txt:

$ ls /asfasdf >myfile.txt 2>&1


При этом все сообщения, как об ошибках, так и обычные, будут записаны в myfile.txt, т.к. поток stdout мы сначала перенаправлили в файл, а потом указали, что ошибки нужно вываливать в stdout - соответственно, в файл myfile.txt

/dev/null

Однако иногда нам нужно просто скрыть все сообщения - не сохраняя их. Т.е. просто блокировать вывод. Для этого служит виртуальное устройство /dev/null. В следующем примере весь вывод обычных сообщений команды ls мы направим в /dev/null:

$ ls > /dev/null


На экране не будет отображено ничего, кроме сообщений об ошибках. А в следующем примере - и сообщения об ошибках будут блокированы:

$ ls > /dev/null 2>&1


Причем эта запись эквивалентна записи вида:

$ ls >/dev/null 2>/dev/null


А в следующем примере мы заблокируем только сообщения об ошибках:

$ ls 2>/dev/null

Заметьте, что здесь уже нельзя указывать "2>&1", т.к. поток (1) не перенаправлен никуда и в таком случае сообщения об ошибках будут банально вывалены на экран.

Что первее - яйцо или курица?

Я приведу Вам здесь 2 примера.

Пример 1)

$ ls >/dev/null 2>&1


Пример 2)

$ ls 2>&1 >/dev/null


С виду - от перестановки мест слогаемых сумма не меняется. Но порядок указателей перенаправления играет роль!

Дело в том, что интерпретаторы читают и применяют перенаправления слева направо. И сейчас мы разберем оба примера.

Пример 1

1) ">/dev/null" - мы направляем поток 1 (stdout) в /dev/null. Все сообщения, попадающие в поток (1) - будут направлены в /dev/null.

2) "2>&1" - мы перенаправляем поток 2 (stderr) в поток 1 (stdout). Но, т.к. поток 1 уже ассоциирован с /dev/null - все сообщения все-равно попадут в /dev/null.

Результат: на экране - пусто.

Пример 2

1) "2>&1" - мы перенаправляем поток ошибок stderr (2) в поток stdout (1). При этом, т.к. поток 1 по-умолчанию ассоциирован с терминалом - сообщения об ошибках мы успешно увидим на экране.

2) ">/dev/null" - а уже здесь мы перенаправляем поток 1 в /dev/null. И обычные сообщения мы не увидим.

Результат: мы будем видеть сообщения об ошибках на экране, но не будет видеть обычные сообщения.

Вывод: сначала перенаправьте поток, а потом на него ссылайтесь.

Похожие статьи