Что такое стандартные потоки stdin, stdout и stderr в Linux

Ответ

В Linux и других UNIX-подобных системах каждая программа при запуске получает три стандартных потока ввода-вывода. Это основной механизм для текстового взаимодействия между программами и терминалом.

  • stdin (standard input) — стандартный поток ввода. По умолчанию связан с клавиатурой. Имеет файловый дескриптор 0.
  • stdout (standard output) — стандартный поток вывода. Сюда направляется обычный вывод программы. По умолчанию связан с терминалом. Дескриптор 1.
  • stderr (standard error) — стандартный поток ошибок. Сюда направляются сообщения об ошибках и диагностическая информация. По умолчанию также связан с терминалом. Дескриптор 2.

Разделение stdout и stderr позволяет перенаправлять обычный вывод программы в файл, но при этом видеть ошибки в консоли.

Перенаправление потоков в Shell

Операторы командной строки позволяют управлять этими потоками:

# Записать вывод команды ls в файл output.txt (перенаправление stdout)
ls -l > output.txt

# Записать ошибки в error.log (перенаправление stderr)
find /root -name "*.py" 2> error.log

# Прочитать данные для команды sort из файла input.txt (перенаправление stdin)
sort < input.txt

# Передать stdout команды 'cat' на stdin команды 'grep' (конвейер)
cat /var/log/syslog | grep 'error'

Пример использования в Python

import sys

# Чтение всех данных из стандартного ввода
for line in sys.stdin:
    # Запись в стандартный вывод
    sys.stdout.write(f"Processed line: {line}")

# Запись ошибки в стандартный поток ошибок
sys.stderr.write("An error occurred!n")

Ответ 18+ 🔞

А, слушай, смотри, вот тебе тема про эти ваши потоки в Линуксе. Ну, там, в Юниксах всяких. Ты сидишь, такой, в терминале, и каждая запущенная программа — она как будто в трёхдверную квартиру заселяется, блядь. И у каждой двери свой номер и своё назначение, ёпта. Не перепутаешь — жить будешь, перепутаешь — пиздец.

Первая дверь, stdin — это, типа, входная. Дескриптор у неё 0, как у круглого дурака. По умолчанию туда стучатся с клавиатуры. Программа сидит, ждёт, когда ты ей что-то в рот положишь.

Вторая, stdout — дескриптор 1. Это нормальный выход, парадная дверь. Туда программа вываливает все свои результаты, всё, что она насчитала, нашла, нарисовала. По умолчанию — прямо в терминал, тебе на голову.

А третья, stderr — дескриптор 2. Это, блядь, чёрный ход, запасной выход на случай пожара. Туда летят все ошибки, предупреждения, крики "ой, всё!" и прочая диагностическая хуйня. И тоже, по умолчанию, в терминал. Зачем так? А затем, сука, чтобы можно было парадную дверь (stdout) заткнуть, направить в файл, а крики о помощи (stderr) всё равно были слышны. Хитро, да? Не, ну а как иначе?

Вот смотри, как этим в консоли рулить:

# Вывод команды ls запихнуть в файл output.txt (это stdout, дверь номер 1)
ls -l > output.txt

# А все ошибки от find — в отдельный файл error.log (это stderr, дверь номер 2)
find /root -name "*.py" 2> error.log

# Чтоб команда sort жрала данные не с клавиатуры, а из файла input.txt (это stdin, дверь 0)
sort < input.txt

# А это конвейер, классика жанра. Вывод cat'а засунуть прямо на вход grep'у.
cat /var/log/syslog | grep 'error'

Ну и на Питоне, для полного счастья, это выглядит как-то так:

import sys

# Читаем всё, что нам в stdin навалили
for line in sys.stdin:
    # И пишем обработанное в stdout
    sys.stdout.write(f"Processed line: {line}")

# А если пиздец случился — орём в stderr
sys.stderr.write("An error occurred!n")

Вот и вся магия, блядь. Три потока, три дескриптора. Главное — не перепутать, куда что лить, а то получится как у того немого Герасима: хотел в озеро, а получилось в рот мне чих-пых.