- Sysadminium
- Стандартные потоки ввода вывода
- Перенаправление потоков stdout и stderr в файл
- Перенаправление stdout в файл
- Перенаправление stderr в файл
- Перенаправление потоков stdout и stderr в файл одновременно
- Перенаправление stdout одного процесса на stdin другого
- Итог
- Перенаправление ввода вывода Linux
- Как работает перенаправление ввода вывода
- Перенаправить вывод в файл
- Перенаправить ошибки в файл
- Перенаправить стандартный вывод и ошибки в файл
- Стандартный ввод из файла
- Использование тоннелей
- Выводы
Sysadminium
Из статьи вы узнаете про стандартные потоки ввода и вывода, и перенаправление этих потоков в файл или от одного процесса другому.
Стандартные потоки ввода вывода
В этом курсе мы работает в терминале, вводим какие-то команды и иногда получаем какой-нибудь вывод. То есть консольные утилиты получают от нас какую-то информацию и могут выводить нам информацию на терминал.
Я уже писал о том, что в Linux всё считается файлом. Из этого следует, когда команда выводит результат своей работы, она пишет в какой-то файл. А когда получает данные, она читает какой-то файл.
По умолчанию, файл, из которого осуществляется чтение, называется стандартным потоком ввода, а в который осуществляется запись — стандартным потоком вывода.
Также существует стандартный поток ошибок — это файл, в который процесс записывает ошибки, если они возникают при работе.
В Linux стандартные потоки это виртуальные файлы и по умолчанию стандартные потоки вывода ассоциированы с экраном терминала пользователя. Поэтому вывод результата или ошибок поступает на экран терминала. А стандартный поток ввода связан с клавиатурой терминала, поэтому чтение данных происходит с клавиатуры.
Название | Файловый дескриптор | Связанное устройство | Файл |
---|---|---|---|
stdin стандартный поток ввода | 0 | клавиатура терминала | /dev/stdin |
stdout стандартный поток вывода | 1 | экран терминала | /dev/stdout |
stderr стандартный поток ошибок | 2 | экран терминала | /dev/stderr |
Таблица файлов стандартных потоков в Linux
Вот как эти файлы увидеть:
alex@deb-11:~$ ls -l /dev/std* lrwxrwxrwx 1 root root 15 сен 9 10:57 /dev/stderr -> /proc/self/fd/2 lrwxrwxrwx 1 root root 15 сен 9 10:57 /dev/stdin -> /proc/self/fd/0 lrwxrwxrwx 1 root root 15 сен 9 10:57 /dev/stdout -> /proc/self/fd/1 alex@deb-11:~$ ls -l /proc/self/fd/[0,1,2] lrwx------ 1 alex alex 64 сен 12 14:28 /proc/self/fd/0 -> /dev/pts/0 lrwx------ 1 alex alex 64 сен 12 14:28 /proc/self/fd/1 -> /dev/pts/0 lrwx------ 1 alex alex 64 сен 12 14:28 /proc/self/fd/2 -> /dev/pts/0 alex@deb-11:~$ ls -l /dev/pts/0 crw--w---- 1 alex tty 136, 0 сен 12 14:28 /dev/pts/0
Из вывода мы можем понять что файлы потоков это символические ссылки, ведущие на номера файловых дескрипторов. А эти файловые дескрипторы ведут на одно и тоже устройство — /dev/pts/0. Это устройство называется псевдо-терминалом. Именно этому псевдо-терминалу (pts/0) подключен я по ssh:
alex@deb-11:~$ loginctl list-sessions SESSION UID USER SEAT TTY 83 1000 alex pts/0 1 sessions listed. alex@deb-11:~$ w 14:43:19 up 3 days, 3:45, 1 user, load average: 0,00, 0,00, 0,00 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT alex pts/0 172.28.80.14 10:46 0.00s 0.17s 0.00s w
И все эти потоки можно перенаправлять, например можно пустить:
Про эти файлы можно почитать в официальном мануале здесь, или выполнив команду man stdin .
Перенаправление потоков stdout и stderr в файл
Перенаправление stdout в файл
Допустим мы запустили какую-то команду, которая выводит нам что-нибудь на экран терминала:
alex@deb-11:~$ id uid=1000(alex) gid=1000(alex) группы=1000(alex),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev)
Мы можем перенаправить результат в файл с помощью символа «>«:
alex@deb-11:~$ id > id.txt alex@deb-11:~$ cat id.txt uid=1000(alex) gid=1000(alex) группы=1000(alex),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev)
Как видим на терминале ничего показано не было, а всё записалось в файл. При этом, если бы файла не было то он создастся. А если бы файл был, то он пере-запишется, то есть все содержимое файла очищается и заменяется.
Если мы не хотим пере-записывать файл целиком, а хотим дописать в файл, то нужно использовать «>>«:
alex@deb-11:~$ id root >> id.txt alex@deb-11:~$ cat id.txt uid=1000(alex) gid=1000(alex) группы=1000(alex),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev) uid=0(root) gid=0(root) группы=0(root)
Перенаправление stderr в файл
Если нам нужно перенаправить stderr в файл, то используется «2>«:
alex@deb-11:~$ touch test.txt alex@deb-11:~$ ls test.txt test2.txt ls: невозможно получить доступ к 'test2.txt': Нет такого файла или каталога test.txt alex@deb-11:~$ ls test.txt test2.txt 2> ls-error.txt test.txt alex@deb-11:~$ cat ls-error.txt ls: невозможно получить доступ к 'test2.txt': Нет такого файла или каталога
Как видим при таком перенаправлении stdout идет на терминал, а stderr в файл.
Тут как и с перенаправлением stdout:
Перенаправление потоков stdout и stderr в файл одновременно
Вы можете простым образом перенаправить оба потока:
alex@deb-11:~$ ls test.txt test2.txt > ls-out.txt 2> ls-error.txt alex@deb-11:~$ cat ls-out.txt test.txt alex@deb-11:~$ cat ls-error.txt ls: невозможно получить доступ к 'test2.txt': Нет такого файла или каталога
А чтобы все перенаправить в один файл используется довольно интересная конструкция: > file 2>&1 :
alex@deb-11:~$ ls test.txt test2.txt > ls-out.txt 2>&1 alex@deb-11:~$ cat ls-out.txt ls: невозможно получить доступ к 'test2.txt': Нет такого файла или каталога test.txt
То есть мы перенаправляем stdout в файл, а stderr в stdout, напомню что stdout имеет файловый дескриптор 1.
Есть такой файл в Linux — /dev/null, это как черная дыра, все что идет в /dev/null никуда не сохраняется. Во многих инструкциях можно найти примерно такую команду:
Это делает процесс безмолвным, весь результат и все ошибки от выполнения подобной команды будут уходить в никуда.
Перенаправление stdout одного процесса на stdin другого
Допустим первая команда выводит какой-то результат, и нам нужно этот результат использовать как входные данные для следующей команды. В этом случае используется «|» (пайплайн (pipeline)).
Я очень долго путал stdin с параметрами команды, то есть я думал что:
alex@deb-11:~$ ls test.txt test.txt
Результат предыдущей команды «test.txt» пере-направится как параметр. То есть я думал что:
alex@deb-11:~$ ls test.txt | cat
alex@deb-11:~$ cat test.txt 1 2 3
alex@deb-11:~$ ls test.txt | cat test.txt
Как же это работает на самом деле?
Pipeline заставляет cat читать не из файла а из stdout предыдущей команды. А первая команда пишет в stdout слово «test.txt«, вот и cat читает посимвольно слово «test.txt«.
Чтобы пайплайны работали, вторая команда должна уметь читать из stdin, а это умеют далеко не все утилиты. Но почти все утилиты, которые умеют читать данные из файла могут читать и из stdin. Как пример, могу привести следующие утилиты которые умеют принимать данные из stdin: cat, grep, less, tail, head, wc.
Вот еще один пример, найдем все файлы, в которых есть буква «l«:
alex@deb-11:~$ ls apache2_2.4.53-1~deb11u1_amd64.deb date.log ls-out.txt rootCA.srl site.key test.txt crash id.txt rootCA.crt site.crt sysadminium.cnf timer.sh crash.c ls-error.txt rootCA.key site.csr testfolder ulimit-t.sh alex@deb-11:~$ ls | grep l date.log ls-error.txt ls-out.txt rootCA.srl testfolder ulimit-t.sh
Итог
Мы узнали про стандартные потоки ввода и вывода: stdin, stdout, stderr. Научились перенаправить stdout и stderr в файл и перенаправлять stdout одной команды на stdin другой.
В статье все примеры были проведены на Debian 11, но всё точно также будет работать и в Ubuntu 22.04.
Перенаправление ввода вывода 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 в файл ls-error.log c помощью первого символа перенаправления. Дальше в тот же самый файл будут направлены все ошибки. Второй метод проще:
Также можно использовать добавление вместо перезаписи:
Стандартный ввод из файла
Большинство программ, кроме сервисов, получают данные для своей работы через стандартный ввод. По умолчанию стандартный ввод ожидает данных от клавиатуры. Но вы можете заставить программу читать данные из файла с помощью оператора «:
Вы также можете сразу же перенаправить вывод тоже в файл. Например, пересортируем список:
Таким образом, мы в одной команде перенаправляем ввод вывод linux.
Использование тоннелей
Можно работать не только с файлами, но и перенаправлять вывод одной команды в качестве ввода другой. Это очень полезно для выполнения сложных операций. Например, выведем пять недавно измененных файлов:
С помощью утилиты xargs вы можете комбинировать команды таким образом, чтобы стандартный ввод передавался в параметры. Например, скопируем один файл в несколько папок:
echo test/ tmp/ | xargs -n 1 cp -v testfile.sh
Здесь параметр -n 1 задает, что для одной команды нужно подставлять только один параметр, а опция -v в cp позволяет выводить подробную информацию о перемещениях. Еще одна, полезная в таких случаях команда — это tee. Она читает данные из стандартного ввода и записывает в стандартный вывод или файлы. Например:
echo «Тест работы tee» | tee file1
В сочетании с другими командами все это может использоваться для создания сложных инструкций из нескольких команд.
Выводы
В этой статье мы рассмотрели основы перенаправления потоков ввода вывода Linux. Теперь вы знаете как перенаправить вывод в файл linux или вывод из файла. Это очень просто и удобно. Если у вас остались вопросы, спрашивайте в комментариях!
Обнаружили ошибку в тексте? Сообщите мне об этом. Выделите текст с ошибкой и нажмите Ctrl+Enter.