Перенаправление вывода ошибок 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

И все эти потоки можно перенаправлять, например можно пустить:

Читайте также:  Windows printer driver on linux

Про эти файлы можно почитать в официальном мануале здесь, или выполнив команду 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 create filesystem in file

Есть такой файл в 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 другой.

Читайте также:  Linux exit code last command

В статье все примеры были проведены на Debian 11, но всё точно также будет работать и в Ubuntu 22.04.

Источник

Оцените статью
Adblock
detector