HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>В каждом языке есть свой способ напечатать результат на экран.</p>
1 <p>В каждом языке есть свой способ напечатать результат на экран.</p>
2 <p>Javascript:</p>
2 <p>Javascript:</p>
3 <p>PHP:</p>
3 <p>PHP:</p>
4 <p>Python:</p>
4 <p>Python:</p>
5 <p>Java:</p>
5 <p>Java:</p>
6 <p>Ruby:</p>
6 <p>Ruby:</p>
7 <p>Несмотря на разнообразие языков и способов печати, с точки зрения операционной системы все программы работают абсолютно идентично. При старте любой программы операционная система связывает с ней три потока:</p>
7 <p>Несмотря на разнообразие языков и способов печати, с точки зрения операционной системы все программы работают абсолютно идентично. При старте любой программы операционная система связывает с ней три потока:</p>
8 <ul><li><strong>STDIN</strong>(Standard Input)</li>
8 <ul><li><strong>STDIN</strong>(Standard Input)</li>
9 <li><strong>STDOUT</strong>(Standard Output)</li>
9 <li><strong>STDOUT</strong>(Standard Output)</li>
10 <li><strong>STDERR</strong>(Standard Error)</li>
10 <li><strong>STDERR</strong>(Standard Error)</li>
11 </ul><p>Для языка программирования эти потоки выглядят как файлы, и взаимодействие с ними происходит как с файлами. В этом уроке мы изучим, как работают потоки на базовом уровне.</p>
11 </ul><p>Для языка программирования эти потоки выглядят как файлы, и взаимодействие с ними происходит как с файлами. В этом уроке мы изучим, как работают потоки на базовом уровне.</p>
12 <p>Начнем с потока STDOUT. Он отвечает за вывод на экран. Во время каждой печати на экран в программе на любом языке происходят следующие два шага:</p>
12 <p>Начнем с потока STDOUT. Он отвечает за вывод на экран. Во время каждой печати на экран в программе на любом языке происходят следующие два шага:</p>
13 <ul><li>Функция печати записывает данные в поток STDOUT с помощью функции write</li>
13 <ul><li>Функция печати записывает данные в поток STDOUT с помощью функции write</li>
14 <li>Операционная система решает, куда вывести результат. По умолчанию вывод происходит на экран терминала</li>
14 <li>Операционная система решает, куда вывести результат. По умолчанию вывод происходит на экран терминала</li>
15 </ul><p>Чтобы хорошо понять эту тему, нужно подробно изучить устройство операционных систем, в частности подсистемы, отвечающей за процессы и файловую систему. Но мы попробуем кратко рассказать самое важное для понимания.</p>
15 </ul><p>Чтобы хорошо понять эту тему, нужно подробно изучить устройство операционных систем, в частности подсистемы, отвечающей за процессы и файловую систему. Но мы попробуем кратко рассказать самое важное для понимания.</p>
16 <p>В двух словах, языки программирования не взаимодействуют с монитором и железом в целом. За взаимодействие с железом целиком и полностью отвечает операционная система. Программы могут только лишь попросить операционную систему выполнить ту или иную задачу.</p>
16 <p>В двух словах, языки программирования не взаимодействуют с монитором и железом в целом. За взаимодействие с железом целиком и полностью отвечает операционная система. Программы могут только лишь попросить операционную систему выполнить ту или иную задачу.</p>
17 <p>При таком разделении реализация языков программирования сильно упрощается. Достаточно знать про существование STDOUT и уметь писать в этот поток, а дальше все сделает операционная система.</p>
17 <p>При таком разделении реализация языков программирования сильно упрощается. Достаточно знать про существование STDOUT и уметь писать в этот поток, а дальше все сделает операционная система.</p>
18 <p>Именно благодаря такому разделению и потокам, можно написать программу на одном компьютере и без проблем запустить ее на другом компьютере с другой конфигурацией и монитором.</p>
18 <p>Именно благодаря такому разделению и потокам, можно написать программу на одном компьютере и без проблем запустить ее на другом компьютере с другой конфигурацией и монитором.</p>
19 <p>Самое удивительное начинается дальше. Операционные системы позволяют подменять потоки при старте системы, что открывает интересные возможности.</p>
19 <p>Самое удивительное начинается дальше. Операционные системы позволяют подменять потоки при старте системы, что открывает интересные возможности.</p>
20 <p>Например, вывод любой команды в bash можно не выводить на экран, а записать в файл:</p>
20 <p>Например, вывод любой команды в bash можно не выводить на экран, а записать в файл:</p>
21 <p>Запустив эту команду, вы не увидите на экране ничего нового. Зато в текущей директории появится файл<em>output</em>:</p>
21 <p>Запустив эту команду, вы не увидите на экране ничего нового. Зато в текущей директории появится файл<em>output</em>:</p>
22 <p>Операция, которую мы сделали выше, называется<strong>перенаправление потоков</strong>.</p>
22 <p>Операция, которую мы сделали выше, называется<strong>перенаправление потоков</strong>.</p>
23 <p>Символ &gt; означает, что нужно взять вывод из команды слева и отправить его в файл, указанный справа. Этот символ &gt; всегда<strong>перезаписывает</strong>файл.</p>
23 <p>Символ &gt; означает, что нужно взять вывод из команды слева и отправить его в файл, указанный справа. Этот символ &gt; всегда<strong>перезаписывает</strong>файл.</p>
24 <p>Такое перенаправление работает с абсолютно любой командой, которая выводит результаты своей работы в консоль:</p>
24 <p>Такое перенаправление работает с абсолютно любой командой, которая выводит результаты своей работы в консоль:</p>
25 <p>Если нужно не перезаписывать, а<strong>добавлять</strong>, то используйте &gt;&gt;.</p>
25 <p>Если нужно не перезаписывать, а<strong>добавлять</strong>, то используйте &gt;&gt;.</p>
26 <p>Для экспериментов с выводом удобно использовать встроенную команду echo. Она принимает на вход строчку и выдает ее в STDOUT, который уже можно перенаправлять:</p>
26 <p>Для экспериментов с выводом удобно использовать встроенную команду echo. Она принимает на вход строчку и выдает ее в STDOUT, который уже можно перенаправлять:</p>
27 <p>Кроме стандартного вывода, с каждым процессом ассоциируются два дополнительных потока:</p>
27 <p>Кроме стандартного вывода, с каждым процессом ассоциируются два дополнительных потока:</p>
28 <ul><li>STDERR - вывод ошибок</li>
28 <ul><li>STDERR - вывод ошибок</li>
29 <li>STDIN - стандартный ввод</li>
29 <li>STDIN - стандартный ввод</li>
30 </ul><p>STDIN работает в обратную сторону: через него программа может получать данные на вход.</p>
30 </ul><p>STDIN работает в обратную сторону: через него программа может получать данные на вход.</p>
31 <p>В *nix-системах встроена утилита wc (сокращение от<em>word count</em>). Она умеет считать количество слов, строк или символов в файле. Когда мы говорим о файле, то в *nix-системах это почти всегда означает, что данные можно передать и в стандартный поток ввода:</p>
31 <p>В *nix-системах встроена утилита wc (сокращение от<em>word count</em>). Она умеет считать количество слов, строк или символов в файле. Когда мы говорим о файле, то в *nix-системах это почти всегда означает, что данные можно передать и в стандартный поток ввода:</p>
32 <p>Выглядит довольно логично - стрелка меняет свое направление в другую сторону и содержимое файла отправляется в поток STDIN запускаемой программы wc.</p>
32 <p>Выглядит довольно логично - стрелка меняет свое направление в другую сторону и содержимое файла отправляется в поток STDIN запускаемой программы wc.</p>
33 <p>Теперь объединим перенаправление ввода и вывода:</p>
33 <p>Теперь объединим перенаправление ввода и вывода:</p>
34 <p>Кстати, таким же способом можно отправить вывод на печать, но мы оставим эту возможность на самостоятельное изучение.</p>
34 <p>Кстати, таким же способом можно отправить вывод на печать, но мы оставим эту возможность на самостоятельное изучение.</p>
35 <p>Последний вопрос связан с тем, зачем нужен поток STDERR.</p>
35 <p>Последний вопрос связан с тем, зачем нужен поток STDERR.</p>
36 <p>Поток STDERR позволяет отделить нормальный вывод программы от возникающих ошибок.</p>
36 <p>Поток STDERR позволяет отделить нормальный вывод программы от возникающих ошибок.</p>
37 <p>Как и STDOUT, он по умолчанию выводит информацию на экран. Такой подход удобен при ведении логов, для реагирования и отладки.</p>
37 <p>Как и STDOUT, он по умолчанию выводит информацию на экран. Такой подход удобен при ведении логов, для реагирования и отладки.</p>
38 <p>Будьте осторожны, потому что перенаправление вывода в файл перенаправляет только STDOUT. Убедиться в этом очень просто.</p>
38 <p>Будьте осторожны, потому что перенаправление вывода в файл перенаправляет только STDOUT. Убедиться в этом очень просто.</p>
39 <p>Если попробовать отобразить содержимое несуществующей директории, то команда ls выдаст ошибку:</p>
39 <p>Если попробовать отобразить содержимое несуществующей директории, то команда ls выдаст ошибку:</p>
40 <p>Теперь попробуем перенаправить вывод в файл<em>output</em>:</p>
40 <p>Теперь попробуем перенаправить вывод в файл<em>output</em>:</p>
41 <p>Перенаправление есть, но сообщение вывелось на экран. Это произошло именно по той причине, что STDERR остался привязан к экрану, а внутри файла<em>output</em>- пустота. Решить эту задачу можно несколькими способами.</p>
41 <p>Перенаправление есть, но сообщение вывелось на экран. Это произошло именно по той причине, что STDERR остался привязан к экрану, а внутри файла<em>output</em>- пустота. Решить эту задачу можно несколькими способами.</p>
42 <h3>Перенаправление STDERR в STDOUT</h3>
42 <h3>Перенаправление STDERR в STDOUT</h3>
43 <p>В unix-системах за каждым потоком закреплен определенный номер, который называется<a>файловым дескриптором</a>. С помощью него можно получить доступ к потокам ввода и вывода.</p>
43 <p>В unix-системах за каждым потоком закреплен определенный номер, который называется<a>файловым дескриптором</a>. С помощью него можно получить доступ к потокам ввода и вывода.</p>
44 <p>Существуют следующие стандартные потоки ввода и вывода:</p>
44 <p>Существуют следующие стандартные потоки ввода и вывода:</p>
45 <ul><li>STDIN - 0</li>
45 <ul><li>STDIN - 0</li>
46 <li>STDOUT - 1</li>
46 <li>STDOUT - 1</li>
47 <li>STDERR - 2</li>
47 <li>STDERR - 2</li>
48 </ul><p>Первый способ - перенаправить STDERR в STDOUT или отправить оба потока в файл.</p>
48 </ul><p>Первый способ - перенаправить STDERR в STDOUT или отправить оба потока в файл.</p>
49 <p>Часто стандартный поток ошибок объединяют со стандартным потоком вывода, чтобы можно было обрабатывать ошибки и результат выполнения вместе:</p>
49 <p>Часто стандартный поток ошибок объединяют со стандартным потоком вывода, чтобы можно было обрабатывать ошибки и результат выполнения вместе:</p>
50 <p>В примере выше обратите внимание на &amp; после символа перенаправления &gt;. По правилам синтаксиса символ &amp; нужно ставить, чтобы указать поток, в который осуществляется перенаправление.</p>
50 <p>В примере выше обратите внимание на &amp; после символа перенаправления &gt;. По правилам синтаксиса символ &amp; нужно ставить, чтобы указать поток, в который осуществляется перенаправление.</p>
51 <p>В примере ниже 2&gt;&amp;1 написано перед &gt; output. Это не будет работать, потому что когда интерпретатор прочитает 2&gt;&amp;1, он еще не будет знать, куда перенаправлен стандартный поток вывода. Поэтому потоки ошибок и вывода не будут объединены:</p>
51 <p>В примере ниже 2&gt;&amp;1 написано перед &gt; output. Это не будет работать, потому что когда интерпретатор прочитает 2&gt;&amp;1, он еще не будет знать, куда перенаправлен стандартный поток вывода. Поэтому потоки ошибок и вывода не будут объединены:</p>
52 <p>Перенаправление потока STDERR бывает полезно само по себе, без вывода в файл:</p>
52 <p>Перенаправление потока STDERR бывает полезно само по себе, без вывода в файл:</p>
53 <h2>Перенаправление конкретного потока в файл</h2>
53 <h2>Перенаправление конкретного потока в файл</h2>
54 <p>Чтобы перенаправить конкретный поток, нужно указать его номер перед &gt;:</p>
54 <p>Чтобы перенаправить конкретный поток, нужно указать его номер перед &gt;:</p>
55 <h2>Перенаправление обоих потоков в файл</h2>
55 <h2>Перенаправление обоих потоков в файл</h2>
56 <p>Этот вариант используется чаще всего. Он помогает проводить отладку и подсказывает, почему вообще возникла та или иная ошибка:</p>
56 <p>Этот вариант используется чаще всего. Он помогает проводить отладку и подсказывает, почему вообще возникла та или иная ошибка:</p>
57  
57