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

CompTIABeginner
Практиковаться сейчас

Введение

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

В ходе выполнения упражнений вы будете использовать оператор > для записи вывода команды в файл с перезаписью существующего содержимого и оператор >> для добавления данных в конец файла без их потери. Вы также научитесь перенаправлять сообщения об ошибках с помощью 2> и узнаете, как объединить стандартный вывод и стандартные ошибки в один файл. Наконец, вы воспользуетесь командой tee для одновременного отображения вывода на экране и его сохранения в файл, а также попрактикуетесь в перенаправлении стандартного ввода с помощью оператора <, чтобы команда считывала данные из файла, а не с клавиатуры.

Перенаправление стандартного вывода с помощью оператора >

На этом этапе вы научитесь перенаправлять стандартный вывод команды. В оболочке Linux большинство команд генерируют определенные данные. По умолчанию этот поток, называемый «стандартным выводом» (Standard Output или stdout), отображается на экране терминала. Однако вы можете направить этот поток в файл, используя оператор >. Это полезно для сохранения результатов работы программ, создания лог-файлов или генерации отчетов.

Для начала выполним простую команду и увидим её результат в терминале.

echo "Hello from LabEx"

Вы должны увидеть следующий текст прямо в терминале:

Hello from LabEx

Теперь перенаправим этот вывод в файл. Мы используем оператор >, за которым следует имя файла. Это даст оболочке команду отправить результат работы echo в файл с именем hello.txt в текущем каталоге (~/project).

Выполните следующую команду:

echo "Hello from LabEx" > hello.txt

Обратите внимание, что на этот раз в терминале ничего не появилось. Это произошло потому, что вывод был отправлен в файл hello.txt. Вы можете проверить содержимое файла с помощью команды cat:

cat hello.txt

На экране отобразится текст, который был перенаправлен:

Hello from LabEx

Оператор > создаст файл, если он не существует. Будьте осторожны: если файл уже существует, оператор > полностью перезапишет его содержимое без какого-либо предупреждения. Давайте проверим это на практике.

Сначала выведем список файлов в текущем каталоге и сохраним его в новый файл file_list.txt.

ls -l > file_list.txt

Теперь просмотрите содержимое file_list.txt:

cat file_list.txt

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

total 4
-rw-rw-r-- 1 labex labex  0 Jun 25 14:56 file_list.txt
-rw-rw-r-- 1 labex labex 17 Jun 25 14:56 hello.txt

Теперь выполним другую команду и перенаправим её вывод в тот же файл file_list.txt.

echo "This is new content." > file_list.txt

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

cat file_list.txt

Теперь содержимое файла выглядит так:

This is new content.

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

Добавление данных в стандартный вывод с помощью оператора >>

На этом этапе вы научитесь добавлять данные в конец файла, сохраняя его текущее содержимое. Ранее вы видели, что оператор > перезаписывает целевой файл. Чтобы избежать этого, используйте оператор добавления >>. Этот оператор незаменим для таких задач, как ведение журналов (логов), куда новые записи должны добавляться со временем.

Начнем с создания файла с начальным текстом. Назовем его greetings.txt.

echo "Hello, this is the first line." > greetings.txt

Проверьте содержимое:

cat greetings.txt

Вывод должен быть таким:

Hello, this is the first line.

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

echo "This is the second line, appended." >> greetings.txt

Снова проверьте содержимое greetings.txt.

cat greetings.txt

На этот раз вы увидите, что новая строка добавилась после исходного текста:

Hello, this is the first line.
This is the second line, appended.

Оператор >> идеально подходит для создания лог-файлов. Давайте создадим простой файл журнала activity.log и добавим в него метку времени с помощью команды date.

date > activity.log

Теперь добавим еще одну метку времени в тот же файл.

date >> activity.log

Просмотрите итоговый файл activity.log, чтобы увидеть обе записи.

cat activity.log

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

Wed Jun 25 14:56:53 CST 2025
Wed Jun 25 14:56:56 CST 2025

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

Перенаправление стандартного потока ошибок с помощью оператора 2>

На этом этапе вы научитесь управлять сообщениями об ошибках. Помимо стандартного вывода (stdout), команды генерируют другой тип данных, называемый «стандартным потоком ошибок» (Standard Error или stderr). Это отдельный поток, предназначенный специально для диагностических сообщений. По умолчанию и stdout, и stderr выводятся в терминал, но операторы перенаправления, которые вы изучили ранее (> и >>), влияют только на stdout.

Чтобы перенаправить stderr, необходимо указать его дескриптор файла — цифру 2. Оператор > на самом деле является сокращением для 1>, где 1 — это дескриптор stdout. Таким образом, для перенаправления ошибок используется 2>.

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

ls non_existent_file

Команда завершится неудачей и выведет сообщение об ошибке в терминал:

ls: cannot access 'non_existent_file': No such file or directory

Теперь попробуем перенаправить это с помощью обычного оператора >.

ls non_existent_file > output.txt

Заметьте, что сообщение об ошибке все равно появилось в терминале. Оператор > его не перехватил. Если вы проверите файл output.txt, он окажется пустым.

cat output.txt

Команда не создала данных в стандартном выводе, была зафиксирована только ошибка.

Теперь правильно перенаправим поток ошибок в файл error.log, используя 2>.

ls non_existent_file 2> error.log

На этот раз в терминале ничего не появилось. Ошибка была успешно перенаправлена. Вы можете просмотреть содержимое error.log, чтобы увидеть перехваченное сообщение.

cat error.log

Выводом будет сообщение об ошибке от команды ls:

ls: cannot access 'non_existent_file': No such file or directory

Так же, как >> дополняет стандартный вывод, вы можете использовать 2>> для добавления сообщений об ошибках в конец файла. Попробуем обратиться к еще одному несуществующему файлу и дописать ошибку в наш error.log.

ls another_fake_file 2>> error.log

Теперь снова проверьте содержимое error.log.

cat error.log

Вы увидите, что новое сообщение об ошибке добавилось в конец файла.

ls: cannot access 'non_existent_file': No such file or directory
ls: cannot access 'another_fake_file': No such file or directory

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

Перенаправление stdout и stderr в один файл

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

Воспользуемся командой, которая генерирует оба потока. Мы попытаемся вывести информацию о существующем файле (/etc/passwd) и о несуществующем (non_existent_file).

ls -l /etc/passwd non_existent_file

В терминале вы увидите два типа строк. Первая — это стандартная ошибка, вторая — стандартный вывод.

ls: cannot access 'non_existent_file': No such file or directory
-rw-r--r-- 1 root root 1916 Jul 18  2024 /etc/passwd

Если вы попытаетесь перенаправить это, используя только > для stdout, сообщение об ошибке все равно останется на экране.

ls -l /etc/passwd non_existent_file > output_only.txt

Вывод в терминале:

ls: cannot access 'non_existent_file': No such file or directory

А файл output_only.txt будет содержать только стандартный вывод:

cat output_only.txt
-rw-r--r-- 1 root root 1916 Jul 18  2024 /etc/passwd

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

Попробуем. Перенаправим весь вывод в файл combined.log.

ls -l /etc/passwd non_existent_file &> combined.log

На этот раз в терминал ничего не выводится. Весь результат сохранен в combined.log. Посмотрим его содержимое:

cat combined.log

Вы увидите, что файл содержит и данные, и ошибку:

ls: cannot access 'non_existent_file': No such file or directory
-rw-r--r-- 1 root root 1916 Jul 18  2024 /etc/passwd

Существует также более традиционный, но чуть более сложный синтаксис для достижения того же результата: > file 2>&1. Разберем его по частям:

  • > file: перенаправляет стандартный вывод (дескриптор 1) в file.
  • 2>&1: перенаправляет стандартный поток ошибок (дескриптор 2) туда же, куда направлен стандартный вывод (дескриптор 1). Поскольку stdout уже идет в file, stderr отправляется туда же.

Попробуем этот метод, сохранив результат в combined_traditional.log.

ls -l /etc/passwd non_existent_file > combined_traditional.log 2>&1

Снова в терминале пусто. Проверка содержимого файла дает тот же результат:

cat combined_traditional.log
ls: cannot access 'non_existent_file': No such file or directory
-rw-r--r-- 1 root root 1916 Jul 18  2024 /etc/passwd

Хотя &> короче и зачастую удобнее, вы часто будете встречать 2>&1 в старых скриптах, поэтому важно понимать, как это работает. Чтобы добавить оба потока в конец файла, можно использовать &>> или >> file 2>&1.

Использование tee для разделения вывода и перенаправление ввода с помощью <

На этом заключительном этапе вы изучите две дополняющие друг друга концепции: разделение вывода с помощью команды tee и передачу данных в команду из файла с помощью оператора <.

Разделение вывода с помощью tee

Иногда требуется сохранить вывод команды в файл и одновременно видеть его в терминале. Операторы > и >> перенаправляют данные исключительно в файл, скрывая их с экрана. Команда tee решает эту задачу, разделяя поток данных: она отправляет его и в файл, и в стандартный вывод (на ваш экран). Название команды происходит от Т-образного разветвителя в сантехнике (T-splitter), который разделяет поток на два пути.

Посмотрим на это в деле. Мы выведем список содержимого каталога /etc/ и используем tee, чтобы отобразить список на экране и сохранить его в файл etc_listing.txt.

ls /etc/ | tee etc_listing.txt

Вы увидите полный список каталогов в терминале. Одновременно с этим команда tee записала те же самые данные в etc_listing.txt. Вы можете это проверить:

cat etc_listing.txt

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

По умолчанию tee перезаписывает файл. Чтобы вместо этого добавить данные в конец, используйте опцию -a. Это очень полезно для ведения журналов. Создадим лог-файл и добавим в него две записи.

date | tee system_log.txt
echo "User labex performed a system check." | tee -a system_log.txt

Первая команда создает system_log.txt с текущей датой. Вторая команда, используя tee -a, добавляет новую строку, не удаляя дату. Проверим итоговый файл:

cat system_log.txt

Вывод покажет обе строки:

Wed Jun 25 14:56:53 CST 2025
User labex performed a system check.

Перенаправление стандартного ввода с помощью <

Теперь рассмотрим противоположность перенаправлению вывода: перенаправление стандартного ввода (stdin). Многие команды, такие как sort, wc или cat, могут считывать данные из stdin (обычно это ваша клавиатура). Оператор < позволяет указать команде брать данные из файла.

Сначала создадим простой файл со списком элементов. Назовем его items.txt.

echo "banana" > items.txt
echo "apple" >> items.txt
echo "cherry" >> items.txt

Теперь у нас есть файл items.txt с тремя неотсортированными строками. Команда sort умеет сортировать текст. Используем <, чтобы передать содержимое items.txt на вход команде sort.

sort < items.txt

Команда прочитает содержимое items.txt как входные данные, отсортирует их и выведет результат в стандартный вывод (терминал):

apple
banana
cherry

Функционально это похоже на запуск sort items.txt, но данный пример демонстрирует мощную концепцию перенаправления файла в стандартный ввод команды. Это становится критически важным при работе с инструментами, которые умеют читать только из stdin и не принимают имя файла в качестве аргумента.

В качестве последнего примера рассмотрим cat < items.txt. Это заставляет cat читать данные из items.txt, и, поскольку задача cat — выводить входные данные на выход, содержимое файла отобразится на экране.

cat < items.txt

На этом наше знакомство с основами перенаправления ввода-вывода в Linux завершено. Теперь у вас есть инструменты для управления тем, откуда команды получают данные и куда они их отправляют.

Резюме

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

Кроме того, в работе было показано, как объединять эти концепции, направляя и stdout, и stderr в один файл для ведения подробных журналов. Вы изучили команду tee как способ разделения потока, позволяющий сохранять данные в файл и одновременно видеть их в терминале. Наконец, вы научились перенаправлять стандартный ввод (stdin) с помощью оператора <, что дает командам возможность считывать данные из файлов вместо ввода с клавиатуры.