Что такое stdin, stdout и stderr в Linux?
Опубликовано: 2022-01-29
stdin
, stdout
и stderr
— это три потока данных, которые создаются при запуске команды Linux. Вы можете использовать их, чтобы узнать, передаются ли ваши сценарии по конвейеру или перенаправляются. Мы покажем вам, как это сделать.
Потоки соединяют две точки
Как только вы начнете знакомиться с Linux и Unix-подобными операционными системами, вы столкнетесь с терминами stdin
, stdout
и stederr
. Это три стандартных потока, которые устанавливаются при выполнении команды Linux. В вычислениях поток — это то, что может передавать данные. В случае этих потоков эти данные являются текстовыми.
Потоки данных, как и потоки воды, имеют два конца. У них есть исток и отток. Какую бы команду Linux вы ни использовали, она обеспечивает один конец каждого потока. Другой конец определяется оболочкой, запустившей команду. Этот конец будет подключен к окну терминала, подключен к каналу или перенаправлен в файл или другую команду в соответствии с командной строкой, которая запустила команду.
Стандартные потоки Linux
В Linux stdin
является стандартным входным потоком. Это принимает текст в качестве входных данных. Текстовый вывод из команды в оболочку доставляется через поток stdout
(стандартный вывод). Сообщения об ошибках от команды отправляются через поток stderr
(стандартная ошибка).
Итак, вы можете видеть, что есть два потока вывода, stdout
и stderr
, и один поток ввода, stdin
. Поскольку сообщения об ошибках и обычный вывод имеют собственный канал для переноса в окно терминала, их можно обрабатывать независимо друг от друга.
Потоки обрабатываются как файлы
Потоки в Linux, как и почти все остальное, обрабатываются так, как если бы они были файлами. Вы можете читать текст из файла и записывать текст в файл. Оба этих действия включают поток данных. Таким образом, концепция обработки потока данных в виде файла не так уж и натянута.
Каждому файлу, связанному с процессом, присваивается уникальный номер для его идентификации. Это известно как файловый дескриптор. Всякий раз, когда требуется выполнить действие над файлом, файловый дескриптор используется для идентификации файла.
Эти значения всегда используются для stdin
, stdout,
и stderr
:
- 0 : стандартный ввод
- 1 : стандартный вывод
- 2 : стандартный вывод
Реакция на каналы и редиректы
Чтобы облегчить чье-то введение в предмет, распространенным приемом является преподавание упрощенной версии темы. Например, в случае с грамматикой нам говорят, что действует правило «I перед E, кроме как после C». Но на самом деле исключений из этого правила больше, чем случаев, которые ему подчиняются.
Аналогичным образом, говоря о stdin
, stdout
и stderr
, удобно изложить общепринятую аксиому, согласно которой процесс не знает и не заботится о том, где заканчиваются его три стандартных потока. Должен ли процесс заботиться о том, идет ли его вывод на терминал или перенаправляется в файл? Может ли он даже сказать, поступает ли его ввод с клавиатуры или передается ему из другого процесса?
На самом деле процесс знает — или, по крайней мере, может узнать, если решит проверить, — и может соответствующим образом изменить свое поведение, если автор программного обеспечения решит добавить эту функциональность.
Мы можем легко увидеть это изменение в поведении. Попробуйте эти две команды:
лс
лс | Кот
Команда ls
ведет себя иначе, если ее вывод ( stdout
) передается другой команде. Это ls
, который переключается на вывод в один столбец, а не преобразование, выполняемое cat
. И ls
делает то же самое, если его вывод перенаправляется:
лс > захват.txt
захват кошки.txt
Перенаправление stdout и stderr
Есть преимущество в том, что сообщения об ошибках доставляются выделенным потоком. Это означает, что мы можем перенаправить вывод команды ( stdout
) в файл и по-прежнему видеть любые сообщения об ошибках ( stderr
) в окне терминала. При необходимости вы можете реагировать на ошибки по мере их возникновения. Это также не позволяет сообщениям об ошибках загрязнять файл, в который был перенаправлен stdout
.
Введите следующий текст в редактор и сохраните его в файл с именем error.sh.
#!/бин/баш echo "О попытке доступа к несуществующему файлу" кошка плохое имя-файла.txt
Сделайте скрипт исполняемым с помощью этой команды:
chmod +x error.sh
Первая строка скрипта выводит текст в окно терминала через поток stdout
. Вторая строка пытается получить доступ к несуществующему файлу. Это сгенерирует сообщение об ошибке, которое будет доставлено через stderr
.
Запустите скрипт с помощью этой команды:
./ошибка.ш
Мы видим, что оба потока вывода, stdout
и stderr
, отображаются в окнах терминала.
Попробуем перенаправить вывод в файл:
./error.sh > захват.txt
Сообщение об ошибке, которое доставляется через stderr
, по-прежнему отправляется в окно терминала. Мы можем проверить содержимое файла, чтобы увидеть, перешел ли вывод stdout
в файл.
захват кошки.txt
Вывод из стандартного stdin
был перенаправлен в файл, как и ожидалось.
Символ перенаправления >
по умолчанию работает со стандартным stdout
. Вы можете использовать один из числовых файловых дескрипторов, чтобы указать, какой стандартный поток вывода вы хотите перенаправить.
Чтобы явно перенаправить stdout
, используйте эту инструкцию перенаправления:
1>
Чтобы явно перенаправить stderr
, используйте эту инструкцию перенаправления:
2>
Давайте снова попробуем наш тест, и на этот раз мы будем использовать 2>
:
./error.sh 2> захват.txt
Сообщение об ошибке перенаправляется, и echo
-сообщение stdout
отправляется в окно терминала:
Давайте посмотрим, что находится в файле capture.txt.
захват кошки.txt
Сообщение stderr
находится в файле capture.txt, как и ожидалось.
Перенаправление как stdout, так и stderr
Конечно, если мы можем перенаправить либо stdout
, либо stderr
в файл независимо друг от друга, мы должны иметь возможность перенаправить их оба одновременно, в два разных файла?
Да мы можем. Эта команда направит stdout
в файл с именем Capture.txt, а stderr
— в файл с именем error.txt.
./error.sh 1> Capture.txt 2> error.txt
Поскольку оба потока вывода — стандартный вывод и стандартная ошибка — перенаправляются в файлы, вывод в окне терминала не отображается. Мы возвращаемся к приглашению командной строки, как будто ничего не произошло.
Проверим содержимое каждого файла:
захват кошки.txt
ошибка кота.txt
Перенаправление stdout и stderr в один и тот же файл
Это здорово, у нас есть каждый из стандартных выходных потоков, идущих в свой собственный выделенный файл. Единственная другая комбинация, которую мы можем сделать, это отправить и stdout
, и stderr
в один и тот же файл.

Мы можем добиться этого с помощью следующей команды:
./error.sh > Capture.txt 2>&1
Давайте сломаем это.
- ./error.sh : запускает файл сценария error.sh.
- > Capture.txt : перенаправляет поток
stdout
в файл Capture.txt.>
является сокращением от1>
. - 2>&1 : здесь используется инструкция перенаправления &>. Эта инструкция позволяет указать оболочке, что один поток должен попасть в тот же пункт назначения, что и другой поток. В этом случае мы говорим «перенаправить поток 2,
stderr
, в тот же пункт назначения, на который перенаправляется поток 1,stdout
».
Видимого выхода нет. Это обнадеживает.
Давайте проверим файл capture.txt и посмотрим, что в нем.
захват кошки.txt
Потоки stdout
и stderr
были перенаправлены в один целевой файл.
Чтобы вывод потока был перенаправлен и молча удален, направьте вывод в /dev/null
.
Обнаружение перенаправления внутри скрипта
Мы обсудили, как команда может определить, перенаправляется ли какой-либо из потоков, и может соответствующим образом изменить свое поведение. Можем ли мы сделать это в наших собственных сценариях? Да мы можем. И это очень простая техника для понимания и использования.
Введите следующий текст в редактор и сохраните его как input.sh.
#!/бин/баш если [-т 0]; тогда echo stdin с клавиатуры еще echo stdin из канала или файла фи
Используйте следующую команду, чтобы сделать его исполняемым:
chmod +x input.sh
Умная часть - это тест в квадратных скобках. Параметр -t
(терминал) возвращает значение true (0), если файл, связанный с файловым дескриптором, завершается в окне терминала. Мы использовали файловый дескриптор 0 в качестве аргумента теста, который представляет стандартный stdin
.
Если stdin
подключен к окну терминала, тест будет верным. Если stdin
подключен к файлу или каналу, тест завершится ошибкой.
Мы можем использовать любой удобный текстовый файл для создания входных данных для скрипта. Здесь мы используем файл с именем dummy.txt.
./input.sh < фиктивный.txt
Выходные данные показывают, что сценарий распознает, что ввод осуществляется не с клавиатуры, а из файла. При желании вы можете соответствующим образом изменить поведение своего скрипта.
Это было с перенаправлением файлов, попробуем с пайпом.
манекен кота.txt | ./ввод.ш
Сценарий распознает, что его входные данные передаются в него. Или, точнее, он еще раз распознает, что поток stdin
не подключен к окну терминала.
Давайте запустим скрипт без пайпов и редиректов.
./ввод.ш
Поток stdin
подключается к окну терминала, и скрипт сообщает об этом соответствующим образом.
Чтобы проверить то же самое с выходным потоком, нам нужен новый скрипт. Введите следующее в редактор и сохраните его как output.sh.
#!/бин/баш если [-t 1 ]; тогда echo stdout переходит в окно терминала еще echo stdout перенаправляется или передается по каналу фи
Используйте следующую команду, чтобы сделать его исполняемым:
chmod +x input.sh
Единственное существенное изменение в этом скрипте — тест в квадратных скобках. Мы используем цифру 1 для представления дескриптора файла для stdout
.
Давайте попробуем. Мы будем передавать вывод через cat
.
./выход | Кот
Сценарий распознает, что его вывод не идет прямо в окно терминала.
Мы также можем протестировать скрипт, перенаправив вывод в файл.
./output.sh > захват.txt
Выхода в окно терминала нет, нас молча возвращают в командную строку. Как мы и ожидали.
Мы можем заглянуть внутрь файла capture.txt, чтобы увидеть, что было захвачено. Для этого используйте следующую команду.
кошка захват.sh
Опять же, простой тест в нашем сценарии обнаруживает, что поток stdout
не отправляется непосредственно в окно терминала.
Если мы запустим скрипт без каких-либо каналов или перенаправлений, он должен обнаружить, что стандартный stdout
доставляется непосредственно в окно терминала.
./output.sh
И это именно то, что мы видим.
Потоки Сознания
Зная, как определить, подключены ли ваши скрипты к окну терминала, каналу или перенаправляются, вы сможете соответствующим образом настроить их поведение.
Вывод журналов и диагностики может быть более или менее подробным, в зависимости от того, идет ли он на экран или в файл. Сообщения об ошибках могут записываться в файл, отличный от обычного вывода программы.
Как это обычно бывает, чем больше знаний, тем больше возможностей.
Команды Linux | ||
Файлы | tar · pv · cat · tac · chmod · grep · diff · sed · ar · man · pushd · popd · fsck · testdisk · seq · fd · pandoc · cd · $PATH · awk · join · jq · fold · uniq · journalctl · tail · stat · ls · fstab · echo · less · chgrp · chown · rev · look · strings · type · rename · zip · unzip · mount · umount · install · fdisk · mkfs · rm · rmdir · rsync · df · gpg · vi · nano · mkdir · du · ln · patch · convert · rclone · shred · srm | |
Процессы | alias · screen · top · nice · renice · progress · strace · systemd · tmux · chsh · history · at · batch · free · which · dmesg · chfn · usermod · ps · chroot · xargs · tty · pinky · lsof · vmstat · тайм-аут · стена · да · убить · спать · sudo · su · время · groupadd · usermod · группы · lshw · выключение · перезагрузка · halt · poweroff · passwd · lscpu · crontab · дата · bg · fg | |
Сеть | netstat · ping · traceroute · ip · ss · whois · fail2ban · bmon · dig · finger · nmap · ftp · curl · wget · who · whoami · w · iptables · ssh-keygen · ufw |
СВЯЗАННЫЕ С: Лучшие ноутбуки с Linux для разработчиков и энтузиастов