Перенаправление «2>&1», «>/dev/null» или потоки вывода в Unix (bash/sh)
Потоки вывода
Сообщения скриптов выводятся во вполне определенные потоки — потоки вывода. Таким образом то, что мы выводим через
не просто выводится на экран, а, с точки зрения системы, а конкретно — командных интерпретаторов sh и bash — выводится через определенный поток вывода. В случае echo — поток под номером 1 (stdout), с которым ассоциирован экран.
Некоторые программы и скрипты так-же используют другой поток вывода — под номером 2 (stderr). В него они выводят сообщения об ошибках. Благодаря этому можно раздельно выхватывать из потоков обычные информационные сообщения и сообщения об ошибках и направлять и обрабатывать их раздельно.
Например, Вы можете заблокировать вывод информационных сообщения, оставив только сообщения об ошибках. Или направить вывод сообщений об ошибках в отдельный файл для логирования.
Что такое «>somefile»
Такой записью в Unix (в интерпретаторах bash и sh) указывается перенаправление потоков вывода.
В следующем примере мы перенаправим все информационные (обычные) сообщения команды ls в файл myfile.txt, получив таким образом в этом файле просто список ls:
При этом после нажатия на Enter Вы не увидите ничего на экране, зато в файле myfile.txt будет находится все то, что должно было отобразиться на экране.
Однако давайте сделаем заведомо ошибочную операцию:
И что случится? Т.к. директории masdfasdf в корне файловой системы не существует (я так предполагаю — вдруг у Вас есть?), то команда ls сгенерирует ошибку. Однако вывалит эту ошибку она уже не через обычный поток stdout (1), а через поток ошибок stderr (2). А перенаправление задано лишь для stdout («> myfile.txt»).
Т.к. поток stderr (2) мы никуда не перенаправили — сообщение об ошибке появится на экране и НЕ появится в файле myfile.txt
А теперь давайте выполним команду ls так, чтобы информационные данные записались в файл myfile.txt, а сообщения об ошибках — в файл myfile.err, при этом на экране во время выполнения не появится ничего:
Здесь нам встречается впервые указание номера потока в качестве перенаправления. Запись «2>myfile.err» указывает, что поток с номером 2 (stderr) нужно перенаправить в файл myfile.err.
Конечно, мы можем оба потока направить в один файл или в одно и то же устройство.
Нередко в скриптах можно встретить такую запись. Она означает: «Поток с номером 2 перенаправить в поток с номером 1», или «Поток stderr — направить через поток stdout». Т.е. все сообщения об ошибках мы направляем через поток, через который обычно печатаются обычные, не ошибочные сообщения.
При этом все сообщения, как об ошибках, так и обычные, будут записаны в myfile.txt, т.к. поток stdout мы сначала перенаправлили в файл, а потом указали, что ошибки нужно вываливать в stdout — соответственно, в файл myfile.txt
/dev/null
Однако иногда нам нужно просто скрыть все сообщения — не сохраняя их. Т.е. просто блокировать вывод. Для этого служит виртуальное устройство /dev/null. В следующем примере весь вывод обычных сообщений команды ls мы направим в /dev/null:
Заметьте, что здесь уже нельзя указывать «2>&1», т.к. поток (1) не перенаправлен никуда и в таком случае сообщения об ошибках будут банально вывалены на экран.
Что первее — яйцо или курица?
Я приведу Вам здесь 2 примера.
С виду — от перестановки мест слогаемых сумма не меняется. Но порядок указателей перенаправления играет роль!
Дело в том, что интерпретаторы читают и применяют перенаправления слева направо. И сейчас мы разберем оба примера.
1) «>/dev/null» — мы направляем поток 1 (stdout) в /dev/null. Все сообщения, попадающие в поток (1) — будут направлены в /dev/null.
2) «2>&1» — мы перенаправляем поток 2 (stderr) в поток 1 (stdout). Но, т.к. поток 1 уже ассоциирован с /dev/null — все сообщения все-равно попадут в /dev/null.
Результат: на экране — пусто.
1) «2>&1» — мы перенаправляем поток ошибок stderr (2) в поток stdout (1). При этом, т.к. поток 1 по-умолчанию ассоциирован с терминалом — сообщения об ошибках мы успешно увидим на экране.
2) «>/dev/null» — а уже здесь мы перенаправляем поток 1 в /dev/null. И обычные сообщения мы не увидим.
Результат: мы будем видеть сообщения об ошибках на экране, но не будет видеть обычные сообщения.
Вывод: сначала перенаправьте поток, а потом на него ссылайтесь.
Перенаправление ввода вывода Linux
Одна из самых интересных и полезных тем для системных администраторов и новых пользователей, которые только начинают разбираться в работе с терминалом — это перенаправление потоков ввода вывода Linux. Эта особенность терминала позволяет перенаправлять вывод команд в файл, или содержимое файла на ввод команды, объединять команды вместе, и образовать конвейеры команд.
В этой статье мы рассмотрим как выполняется перенаправление потоков ввода вывода в Linux, какие операторы для этого используются, а также где все это можно применять.
Как работает перенаправление ввода вывода
Все команды, которые мы выполняем, возвращают нам три вида данных:
- Результат выполнения команды, обычно текстовые данные, которые запросил пользователь;
- Сообщения об ошибках — информируют о процессе выполнения команды и возникших непредвиденных обстоятельствах;
- Код возврата — число, которое позволяет оценить правильно ли отработала программа.
В Linux все субстанции считаются файлами, в том числе и потоки ввода вывода linux — файлы. В каждом дистрибутиве есть три основных файла потоков, которые могут использовать программы, они определяются оболочкой и идентифицируются по номеру дескриптора файла:
- STDIN или 0 — этот файл связан с клавиатурой и большинство команд получают данные для работы отсюда;
- STDOUT или 1 — это стандартный вывод, сюда программа отправляет все результаты своей работы. Он связан с экраном, или если быть точным, то с терминалом, в котором выполняется программа;
- STDERR или 2 — все сообщения об ошибках выводятся в этот файл.
Перенаправление ввода / вывода позволяет заменить один из этих файлов на свой. Например, вы можете заставить программу читать данные из файла в файловой системе, а не клавиатуры, также можете выводить ошибки в файл, а не на экран и т д. Все это делается с помощью символов » «.
Перенаправить вывод в файл
Все очень просто. Вы можете перенаправить вывод в файл с помощью символа >. Например, сохраним вывод команды top:
Опция -b заставляет программу работать в не интерактивном пакетном режиме, а n — повторяет операцию пять раз, чтобы получить информацию обо всех процессах. Теперь смотрим что получилось с помощью cat:
Символ «>» перезаписывает информацию из файла, если там уже что-то есть. Для добавления данных в конец используйте «>>». Например, перенаправить вывод в файл linux еще для top:
По умолчанию для перенаправления используется дескриптор файла стандартного вывода. Но вы можете указать это явно. Эта команда даст тот же результат:
Перенаправить ошибки в файл
Чтобы перенаправить вывод ошибок в файл вам нужно явно указать дескриптор файла, который собираетесь перенаправлять. Для ошибок — это номер 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
Вы также можете сразу же перенаправить вывод тоже в файл. Например, пересортируем список:
Таким образом, мы в одной команде перенаправляем ввод вывод linux.
Использование тоннелей
Можно работать не только с файлами, но и перенаправлять вывод одной команды в качестве ввода другой. Это очень полезно для выполнения сложных операций. Например, выведем пять недавно измененных файлов:
С помощью утилиты xargs вы можете комбинировать команды таким образом, чтобы стандартный ввод передавался в параметры. Например, скопируем один файл в несколько папок:
echo test/ tmp/ | xargs -n 1 cp -v testfile.sh
Здесь параметр -n 1 задает, что для одной команды нужно подставлять только один параметр, а опция -v в cp позволяет выводить подробную информацию о перемещениях. Еще одна, полезная в таких случаях команда — это tee. Она читает данные из стандартного ввода и записывает в стандартный вывод или файлы. Например:
echo «Тест работы tee» | tee file1
В сочетании с другими командами все это может использоваться для создания сложных инструкций из нескольких команд.
Выводы
В этой статье мы рассмотрели основы перенаправления потоков ввода вывода Linux. Теперь вы знаете как перенаправить вывод в файл linux или вывод из файла. Это очень просто и удобно. Если у вас остались вопросы, спрашивайте в комментариях!