Поиск по сайту:

Полноте, люди, сквернить несказанными яствами тело (Овидий).

Ввод, вывод и перенаправление ошибок в Linux8 мин для чтения

FavoriteLoadingДобавить в избранное
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Загрузка...
5 мая 2020
Ввод, вывод и перенаправление ошибок в Linux
Если вы знакомы с основными командами Linux, вам также следует изучить концепцию перенаправления ввода-вывода.

Вы уже знаете, как работает команда в Linux. Она принимает вход и дает вам выход. Здесь есть несколько игроков. Позвольте нам рассказать вам о них.

 

Stdin, stdout и stderr

Когда вы запускаете команду Linux, в ней играют роль три потока данных:

  • Стандартный ввод ( stdin ) является источником входных данных. По умолчанию стандартный ввод – это любой текст, введенный с клавиатуры. Идентификатор потока равен 0.
  • Стандартный вывод ( stdout ) является результатом команды. По умолчанию он отображается на экране. Идентификатор потока равен 1.
  • Стандартная ошибка ( stderr ) – это сообщение об ошибке (если есть), генерируемое командами. По умолчанию stderr также отображается на экране. Идентификатор потока равен 2.

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

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

В Linux также существует такая концепция перенаправления, при которой вы можете перенаправить stdin, stdout и stderr из обычного места назначения в другой файл или команду (или даже на периферийные устройства, такие как принтеры).

Позвольте нам показать, как работает перенаправление и как вы можете его использовать.

 

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

Первой и самой простой формой перенаправления является перенаправление вывода, также называемое перенаправлением stdout.

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

andreyex@destroyer:~$ ls
appstxt  new.txt  static-ip.txt

 

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

command > file

 

Например, позвольте нам сохранить вывод команды ls в файл с именем output.txt:

andreyex@destroyer:~$ ls > output.txt

Выходной файл создается заранее

Как вы думаете, каким должно быть содержимое этого выходного файла? Позвольте нам использовать команду cat, чтобы показать вам сюрприз:

andreyex@destroyer:~$ cat output.txt 
appstxt
new.txt
output.txt
static-ip.txt

 

Вы заметили, что включение output.txt существует ? Мы сознательно выбрали этот пример, чтобы показать вам это.

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

Читать  Как запустить одновременно несколько команд в Linux

 

Добавить вместо удаления

Одна из часто игнорируемых проблем заключается в том, что если вы перенаправляете файл, который уже существует, оболочка сначала удалит ( замкнет ) файл. Это означает, что существующее содержимое выходного файла будет удалено и заменено выводом команды.

Вы можете добавить вместо перезаписи, используя >> синтаксис перенаправления.

command >> file

 

Совет
Вы можете запретить забивание в текущем сеансе оболочки, используя: set -C

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

 

Перенаправление канала

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

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

command 1 | command 2

 

Позвольте нам показать вам практический пример. Скажем, вы хотите посчитать количество видимых файлов в текущем каталоге. Вы можете использовать ls -1 (это цифра один, а не буква L) для отображения файлов в текущем каталоге:

andreyex@destroyer:~$ ls -1
appstxt
new.txt
output.txt
static-ip.txt

 

Вы, наверное, уже знаете, что команда wc используется для подсчета количества строк в файле . Если вы объедините обе эти команды с конвейером, вот что вы получите:

andreyex@destroyer:~$ ls -1 | wc -l
4

 

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

Вы увидите результат последней команды в конвейере. Это очевидно, потому что вывод предыдущей команды (команд) подается на следующую команду (команды) вместо перехода на экран.

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

command_1 | command_2 | command_3 | command_4

Помните, что stdout/stdin это кусок данных, а не имена файлов

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

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

find . -type f -name "*.txt" | mv destination_directory

 

Читать  Использование команды Basename в Bash Scripts

Вот почему вы часто будете видеть команду find, используемую в сопряжении с командой exec или xargs. Эти специальные команды «преобразуют текст с кучей имен файлов в имя файла», которые могут быть переданы в качестве аргумента.

find . -type f -name "*.txt" | xargs -t -I{} mv {} ../new_dir

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

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

command < file

 

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

Возьмите это к примеру:

head < filename.txt

 

Приведенная выше команда могла быть просто заголовком filename.txt (без <).

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

tr a-z A-Z < filename.txt

 

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

Например, многие люди используют приведенный выше пример с cat, а затем используют tr на нем. Честно говоря, здесь нет необходимости использовать cat.

cat filename.txt | tr a-z A-Z

Объединить перенаправления

Вы можете комбинировать перенаправление stdin, stdout и pipe в соответствии с вашими потребностями.

Например, приведенная ниже команда перечисляет все файлы .txt в текущем каталоге, а затем подсчитывает эти файлы .txt и сохраняет выходные данные в новый файл.

ls *.txt | wc -l > count.txt

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

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

andreyex@destroyer:~$ ls -l ffffff > output.txt
ls: cannot access 'ffffff': No such file or directory

 

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

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

Но как вы различаете stdout и stderr, когда они оба являются потоком выходных данных? По их идентификатору потока (также называется дескриптором файла).

Поток данных Идентификатор потока
stdin
stdout 1
stderr 2

 

По умолчанию, когда вы используете выходной символ перенаправления >, это фактически означает 1>. Словом, вы говорите, что здесь выводится поток данных с ID 1.

Когда вам нужно перенаправить stderr, вы используете его идентификатор как 2> или 2>>. Это означает, что перенаправление вывода для потока данных stderr (ID 2).

 

Примеры перенаправления Stderr

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

andreyex@destroyer:~$ ls fffff 2> error.txt
andreyex@destroyer:~$ cat error.txt 
ls: cannot access 'fffff': No such file or directory

 

Это было просто. Давайте сделаем это немного более сложным (и полезным):

andreyex@destroyer:~$ ls -l new.txt ffff > output.txt 2> error.txt 
andreyex@destroyer:~$ cat output.txt 
-rw-rw-r-- 1 andreyex andreyex 0 May  5 10:12 new.txt
andreyex@destroyer:~$ cat error.txt 
ls: cannot access 'ffff': No such file or directory

 

В приведенном выше примере команда ls пытается отобразить два файла. Для одного файла она получает успех, а для другого – ошибку. Поэтому мы перенаправили stdout в ouput.txt (с>), а stderr в error.txt (с 2>).

Вы также можете перенаправить как stdout, так и stderr в один и тот же файл. Есть способы сделать это.

В приведенном ниже примере мы сначала отправляем stderr (с 2 >>) в файл комбинированный .txt в режиме добавления. Затем стандартный вывод (с >>) отправляется в тот же файл в режиме добавления.

andreyex@destroyer:~$ ls -l new.txt fff 2>> combined.txt >> combined.txt 
andreyex@destroyer:~$ cat combined.txt 
ls: cannot access 'fff': No such file or directory
-rw-rw-r-- 1 andreyex andreyex 0 May  5 10:12 new.txt

 

Другой способ, и он является предпочтительным, состоит в том, чтобы использовать что-то вроде 2>&1. Что можно примерно перевести как «перенаправить stderr на тот же адрес, что и stdout».

Давайте возьмем предыдущий пример и на этот раз используем 2>&1 для перенаправления как stdout, так и stderr в один и тот же файл.

andreyex@destroyer:~$ ls -l new.txt fff > output.txt 2>&1
andreyex@destroyer:~$ cat output.txt 
ls: cannot access 'fff': No such file or directory
-rw-rw-r-- 1 andreyex andreyex 0 May  5 10:12 new.txt

 

Имейте в виду, что вы не можете использовать 2>>&1, думая об использовании его в режиме добавления. 2>&1 уже переходит в режим добавления.

Вы также можете сначала использовать 2>, а затем 1>&2, чтобы перенаправить стандартный вывод в тот же файл, что и стандартный вывод. По сути, это «>&», который перенаправляет один поток данных в другой.

 

Резюме

  • Есть три потока данных. Один вход, stdin (0) и два потока выходных данных stdout (1) и stderr (2).
  • Клавиатура является стандартным устройством ввода, а экран является устройством вывода по умолчанию.
  • Перенаправление вывода используется с > или >> (для режима добавления).
  • Перенаправление ввода используется с <.
  • Stderr может быть перенаправлен с помощью 2> или 2>>.
  • Stderr и stdout можно комбинировать, используя 2>&1.

Надеюсь, вам понравилось эта подробная статья по перенаправлению в Linux. Если у вас все еще есть сомнения или у вас есть предложения по улучшению этой статьи, сообщите нам об этом в разделе комментариев.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Читайте также

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам:

Заполните форму и наш менеджер перезвонит Вам в самое ближайшее время!

badge
Обратный звонок 1
Отправить
galka

Спасибо! Ваша заявка принята

close
galka

Спасибо! Ваша заявка принята

close