Одна из самых интересных и полезных тем для системных администраторов и новых пользователей, которые только начинают разбираться в работе с терминалом - это перенаправление потоков ввода вывода Linux. Эта особенность терминала позволяет перенаправлять вывод команд в файл, или содержимое файла на ввод команды, объединять команды вместе, и образовать конвейеры команд.
В этой статье мы рассмотрим как выполняется перенаправление потоков ввода вывода в Linux, какие операторы для этого используются, а также где все это можно применять.
Содержание статьи
- Как работает перенаправление ввода вывода
- Перенаправить вывод в файл
- Перенаправить ошибки в файл
- Перенаправить стандартный вывод и ошибки в файл
- Стандартный ввод из файла
- Использование тоннелей
- Выводы
Как работает перенаправление ввода вывода
Все команды, которые мы выполняем, возвращают нам три вида данных:
- Результат выполнения команды, обычно текстовые данные, которые запросил пользователь;
- Сообщения об ошибках - информируют о процессе выполнения команды и возникших непредвиденных обстоятельствах;
- Код возврата - число, которое позволяет оценить правильно ли отработала программа.
В Linux все субстанции считаются файлами, в том числе и потоки ввода вывода linux - файлы. В каждом дистрибутиве есть три основных файла потоков, которые могут использовать программы, они определяются оболочкой и идентифицируются по номеру дескриптора файла:
- STDIN или 0 - этот файл связан с клавиатурой и большинство команд получают данные для работы отсюда;
- STDOUT или 1 - это стандартный вывод, сюда программа отправляет все результаты своей работы. Он связан с экраном, или если быть точным, то с терминалом, в котором выполняется программа;
- STDERR или 2 - все сообщения об ошибках выводятся в этот файл.
Перенаправление ввода / вывода позволяет заменить один из этих файлов на свой. Например, вы можете заставить программу читать данные из файла в файловой системе, а не клавиатуры, также можете выводить ошибки в файл, а не на экран и т д. Все это делается с помощью символов "<" и ">".
Перенаправить вывод в файл
Все очень просто. Вы можете перенаправить вывод в файл с помощью символа >. Например, сохраним вывод команды top:
top -bn 5 > top.log
Опция -b заставляет программу работать в не интерактивном пакетном режиме, а n - повторяет операцию пять раз, чтобы получить информацию обо всех процессах. Теперь смотрим что получилось с помощью cat:
cat top.log
Символ ">" перезаписывает информацию из файла, если там уже что-то есть. Для добавления данных в конец используйте ">>". Например, перенаправить вывод в файл linux еще для top:
top -bn 5 >> top.log
По умолчанию для перенаправления используется дескриптор файла стандартного вывода. Но вы можете указать это явно. Эта команда даст тот же результат:
top -bn 5 1>top.log
Перенаправить ошибки в файл
Чтобы перенаправить вывод ошибок в файл вам нужно явно указать дескриптор файла, который собираетесь перенаправлять. Для ошибок - это номер 2. Например, при попытке получения доступа к каталогу суперпользователя ls выдаст ошибку:
ls -l /root/
Вы можете перенаправить стандартный поток ошибок в файл так:
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 <domains.list
Вы также можете сразу же перенаправить вывод тоже в файл. Например, пересортируем список:
sort <domains.list >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 или вывод из файла. Это очень просто и удобно. Если у вас остались вопросы, спрашивайте в комментариях!
> Использование тоннелей
С какой стати здесь "тоннели"?
Это всегда было конвейеры команд!
И самое главное, что не сказано при этом, что программы (команд) при этом: выполняются параллельно! : $ cmd1 | cmd2 | cmd 3
Я очень не уверен по поводу параллельности, мы в универе конвейеры мусолили вдоль и поперек, и никогда ничего такого замечено не было
Зато я уверен 😉
Ваша уверенность обманчива
Я могу подтвердить, что уверенность Олега не обманчива.
Каждая команда выполняется в отдельном экземпляре оболочки.
man man > test.txt
Попробуйте две команды:
cat test.txt | grep man | wc -l
и
cat test.txt ; grep man ; wc -l
Результат будет очевиден. Во втором случае для остановки ввода используйте Ctl+D.
Не дай Бог вам вести лекции по Linux и Bash! 🙂
Спасибо за статью! Вообще хорошо зашла! 😉
Добрый день. Подскажите, пожалуйста, возможен ли вариант выполнения команды в один заход с выводом всей информации в файл, а не пошагово (на примере построчного списка директорий в домашней папке пользователя и корневого раздела с разделителем).
Нужно чтобы результат цепочки команд
$ cd ~ ; echo " ------------------ " ; ls -1 /
записался в 1 файл.
Колхоз в виде
$ cd ~ ; ls -1 > 1.txt ; echo " ------------------ " >> 1.txt ; ls -1 / >> 1.txt
работает, но никакой элегантности.
Пока что практического применения не получила задача, но вопрос возник, пока решения не нашел.
Спасибо.
$ (cd ~ ; echo " ------------------ " ; ls -1 /) >> 1.txt
(ls ~ -1; printf "%9s\n" '' | sed "s/ /-/g"; ls -1 /) >> 1.txt
Вот более наглядная команда для того чтобы показать переаправление STDOUT и STDERR в один и тот же файл:
echo '/root/' '/' | xargs ls -l 1> error.log 2>&1
Пример перенаправления STDIN:
echo 'Some text' > ./text.txt; cat < ./text.txt
А команда ls поддерживает перенаправление ввода?
Почему не работает ls < ./file,
где file - это файл в котором написан путь к каталогу в системе?
Параметры и перенаправление ввода это разные вещи. В данном случае должно быть так:
ls $(cat file)
Подскажите пожалуйста как перенаправить из программы 1 стандартный поток ошибок на стандартный поток ввода программы 2 через через "|" (не через файл).
В Bash есть оператор >() который позволяет подставлять программу вместо файла. Подробнее тут. Работать это будет вот так:
ls -l /root 2> >(tee file2)
Вместо tee там может быть любая другая команда куда надо перенаправить вывод ошибок. Или же, если поток ошибок нужен вместе со стандартным потоком вывода, то можно их совместить и перенаправить через обычный туннель:
ls -l /root 2>&1 | tee file3
Вопрос, в общем, не сложный, на первый взгляд: можно ли передавать таким образом бинарные данные. К примеру, содержимое медиафайлов?
А как можно запросы к юзеру направлять в терминал, а прочий вывод в файл?
Добрый вечер ,я новичок и честно сказать не совсем понимаю в теме , тем более не владею знанием инглиш, где можно почитать обо всём этом с самого начала?