Windows stderr and stdout

/* steve jansen */

// another day in paradise hacking code and more

Windows Batch Scripting: Stdin, Stdout, Stderr

DOS, like Unix/Linux, uses the three universal “files” for keyboard input, printing text on the screen, and the printing errors on the screen. The “Standard In” file, known as stdin, contains the input to the program/script. The “Standard Out” file, known as stdout, is used to write output for display on the screen. Finally, the “Standard Err” file, known as stderr, contains any error messages for display on the screen.

File Numbers

Each of these three standard files, otherwise known as the standard streams, are referernced using the numbers 0, 1, and 2. Stdin is file 0, stdout is file 1, and stderr is file 2.

Redirection

A very common task in batch files is sending the output of a program to a log file. The > operator sends, or redirects, stdout or stderr to another file. For example, you can write a listing of the current directory to a text file:

The > operator will overwrite the contents of temp.txt with stdout from the DIR command. The >> operator is a slight variant that appends the output to a target file, rather than overwriting the target file.

A common technique is to use > to create/overwrite a log file, then use >> subsequently to append to the log file.

By default, the > and >> operators redirect stdout. You can redirect stderr by using the file number 2 in front of the operator:

You can even combine the stdout and stderr streams using the file number and the & prefix:

This is useful if you want to write both stdout and stderr to a single log file.

To use the contents of a file as the input to a program, instead of typing the input from the keyboard, use the operator.

Suppressing Program Output

The pseudofile NUL is used to discard any output from a program. Here is an example of emulating the Unix command sleep by calling ping against the loopback address. We redirect stdout to the NUL device to avoid printing the output on the command prompt screen.

Redirecting Program Output As Input to Another Program

Let’s say you want to chain together the output of one program as input to another. This is known as “piping” output to another program, and not suprisingly we use the pipe character | to get the job done. We’ll sort the output of the DIR commmand.

A Cool Party Trick

You can quickly create a new text file, say maybe a batch script, from just the command line by redirecting the command prompt’s own stdin, called CON , to a text file. When you are done typing, hit CTRL+Z , which sends the end-of-file (EOF) character.

There are a number of other special files on DOS that you can redirect, however, most are a bit dated like like LPT1 for parallel portt printers or COM1 for serial devices like modems.

Posted by Steve Jansen Mar 1 st , 2013 batch, scripting, shell, windows

Читайте также:  Windows os configuration msi что это

Comments

Hi, I’m Steve. I’m a software developer loving life in Charlotte, NC, an (ISC) 2 CSSLP and an avid fan of Crossfit.

And, no, I’m not Steve Jansen the British jazz drummer, though that does sound like a sweet career.

Guides

Recent Posts

Social Stuff

  • @steve-jansen on GitHub
  • @steve-jansen on StackOverflow
  • @steve-jansen ProTips on Coderwall
  • @steve-jansen on Microsft Connect
  • @steve-jansen on ASP.NET User Voice
  • Subscribe via RSS

Copyright © 2015 — Steve Jansen — Powered by Octopress

stdin, stdout, stderr stdin, stdout, stderr

Синтаксис Syntax

Remarks Remarks

Это стандартные потоки для ввода, вывода и вывода ошибок. These are standard streams for input, output, and error output.

По умолчанию стандартный ввод — чтение с клавиатуры, в то время как стандартный вывод и стандартный вывод ошибок печатаются на экране. By default, standard input is read from the keyboard, while standard output and standard error are printed to the screen.

Следующие указатели потока доступны для получения стандартных потоков: The following stream pointers are available to access the standard streams:

Указатель Pointer Поток Stream
stdin Стандартный ввод Standard input
stdout Стандартные выходные данные Standard output
stderr Стандартная ошибка Standard error

Эти указатели можно использовать в качестве аргументов для функций. These pointers can be used as arguments to functions. Некоторые функции, например getchar и putchar, используют stdin и stdout автоматически. Some functions, such as getchar and putchar, use stdin and stdout automatically.

Эти указатели являются константами, и им не могут быть присвоены новые значения. These pointers are constants, and cannot be assigned new values. Функцию freopen можно использовать, чтобы перенаправить потоки в файлы на диске или на другие устройства. The freopen function can be used to redirect the streams to disk files or to other devices. Операционная система позволяет перенаправлять стандартный ввод и вывод программы на командном уровне. The operating system allows you to redirect a program’s standard input and output at the command level.

Стандартные потоки вывода (stdout) Windows

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

Есть 3 файловых дескриптора: stdin — стандартный ввод, stdout — стандартный вывод и stderr — стандартный поток ошибок. В скриптах 1 означает stdout , а 2 — stderr .

Практически это означает, что для программ, которые используют стандартные входные и выходные устройства, операционная система позволяет:

  • перенаправлять stdout в файл
  • перенаправлять stderr в файл
  • перенаправлять stdout в stderr
  • перенаправлять stderr в stdout
  • перенаправлять stderr и stdout в файл
  • перенаправлять stderr и stdout в stdout
  • перенаправлять stderr и stdout в stderr
  • перенаправление stderr и stdout по конвейеру

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

А теперь примеры:

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

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

2. Перенаправление стандартного потока программы в файл с до записью содержимого лога

Тоже самое, но при прерывание пинга и начале нового, старое содержимое лога не затрется, а новое дописывается в конец

3. Перенаправление потока ошибок программы в фаил с заменой содержимого

при этом, стандартный поток программы пойдет на экран, а ошибки будут записаны в лог, с заменой содержимого.

4. То же самое, но с до записью содержимого лога.

5. Следующая конструкция позволяет перенаправить информацию между потоками (между стандартным потоком и потоком ошибок, или наоборот).

или с до записью лога

В данном примере стандартный поток ошибок пересылается в стандартный поток (конструкция 2>&1 ) а потом стандартный поток (уже с завернутым в него потоком ошибок) посылается в лог.

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

или с до записью лога

7. По аналогии с Linux системами в Windows можно перенаправить весь или часть вывода программы в виртуальное устройство, а проще говоря слить в мусор.

Таким устройством является nul, и делать перенаправление в него можно используя все выше представленные комбинации. Например

В Linux есть еще одна конструкция перенаправления, а именно &>/var/log/log.txt , она перенаправляет ВСЕ без исключения потоки программы в указанное место, по сути являясь более коротким и более грамотным аналогом конструкции >log.txt 1>&2 . Но к сожалению в Windows это не работает.

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

Он разделяет 3 вида вывода, вывод полезной информации, вывод служебной информации и вывод ошибок. Если перенаправить вывод так: > или >> или 1> или 1>> то по завершению запроса отобразится служебная информация о запросе, а вся полезная информация уйдет в лог (это именно то, что уходит по конвейеру | ).

А теперь сделаем заведомо ошибочный запрос, изменив протокол http на http3 не меняя вывода в лог. В итоге мы получим ошибку на экране.

Изменим вывод в лог на один из этих: 2> или 2>> ошибка ранее выводившаяся на экран, попала в лог, и на экране ничего не будет (служебной информации нет, так как запрос произведен не был).

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

И вывод был бы таким:

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

На данном скриншоте, конструкцией 2>&1 мы завернули поток ошибок в стандартный поток, а конструкцией > 5555.txt стандартный поток перенаправили в лог. Если вместо > 5555.txt использовать 2> 5555.txt , то есть перенаправить в лог стандартный поток ошибок, мы увидим весь вывод программы (и ошибки, и служебную информацию и полезный вывод) на экране. Конструкция 2>&1 имеет больший приоритет, а по ней уже все завернуто в стандартный поток.

Делать пример с заворотом стандартного потока в поток ошибок ( 1>&2 ) я не буду, ибо там все точно так же.

Is there a way to redirect ONLY stderr to stdout (not combine the two) so it can be piped to other programs?

I’m working in a Windows CMD.EXE environment and would like to change the output of stdout to match that of stderr so that I can pipe error messages to other programs without the intermediary of a file.

I’m aware of the 2>&1 notation, but that combines stdout and stderr into a single stream.

What I’m thinking of would be something like this:

But that combines stdout and stderr just like:

I realize that I could do.

But this does not have the flexibility and power of a program | find » » sort of notation. Doing this requires that program has finished with its output before that output can be processed.

2 Answers 2

CMD processes redirection from left to right. You want to first redirect 2 (stderr) to &1 (stdout), then redirect 1 (stdout) to something else. At this point stderr will still be redirected to the previous definition of stdout. The pipe will still work with the old definition of stdout (which now contains stderr).

If you don’t care about stdout then you can redirect to nul

If you want to capture stdout to a file then redirect to a file

If you still want to see stdout on the console, but you only want to pipe stderr to FIND, then you can redirect 1 to con:

Note that there is a subtle difference between the original definition of stdout and con:. For example, cls >con: does not clear the screen, it prints a funny character to the screen instead.

It is possible to truly swap stdout and stderr if you use a 3rd (initially unused) file handle. 1 and 3 will contain original definition of stderr, and 2 will contain original definition of stdout.

Actually there is an additional file handle defined every time a redirection is performed. The original definition is saved in the first available unused file handle. Assume there has not been any redirection prior to issuing the above command. 3>&2 does not save the original definition of 3 because 3 was not previously defined. But 2>&1 saves the original definition of stderr in 4 (3 has already been used), and 1>&2 saves the original definition of stdout in 5.

So technically, the explicit redirection of 3 is not needed to swap stderr and stdout

2>&1 saves stderr in 3 and 2 is redirected to &1 (stdout). 1>&3 saves stdout in 4 and 1 is redirected to &3 (stderr).

But the above will only work properly if you are positive that 3 has not already been defined prior to issuing the command. It is much safer to explicitly define 3 as in my prior code example.

Capture program stdout and stderr to separate variables

Is it possible to redirect stdout from an external program to a variable and stderr from external programs to another variable in one run?

A dull example however I am wondering if that is possible?

6 Answers 6

The easiest way to do this is to use a file for the stderr output, e.g.:

I would also use $LastExitCode to check for errors from native console EXE files.

One option is to combine the output of stdout and stderr into a single stream, then filter.

Data from stdout will be strings, while stderr produces System.Management.Automation.ErrorRecord objects.

You should be using Start-Process with -RedirectStandardError -RedirectStandardOutput options. This other post has a great example of how to do this (sampled from that post below):

This is also an alternative that I have used to redirect stdout and stderr of a command line while still showing the output during PowerShell execution:

It is just another possibility to supplement what was already given.

Keep in mind this may not always work depending upon how the script is invoked. I have had problems with -OutVariable and -ErrorVariable when invoked from a standard command line rather than a PowerShell command line like this:

An alternative that seems to work under most circumstances is this:

Unfortunately, you will lose output to the command line during execution of the script and would have to Write-Host $stdOutAndError after the command returns to make it «a part of the record» (like a part of a Jenkins batch file run). And unfortunately it doesn’t separate stdout and stderr.

Читайте также:  N 70fx драйвер для windows 10
Оцените статью