How to capture stderr on Windows/DOS? - windows

I want to capture the errors from a script into a file instead of to the screen.
In *nix, this is done with stderr redirection, usually
echo "Error" 2> errorfile.log
How do I do it in a CMD script under Windows?

For example:
PSKILL NOTEPAD >output.txt 2>&1
This will direct stdout and stderr to a file name output.txt.
See Underused features of Windows batch files for more details.

That should work in Win32, too.
If you have already redirected stdout, and want stderr redirected to the same file, you must use the 2>& special form, rather than just specifying the same file twice. Otherwise you'll get a "file busy" error.

Related

cmd.exe: After redirecting stdout and stderr to a file, it still prints lines to the console window

I have executed a .bat file under cmd.exe in Windows 10, and redirected the standard output and standard error to a file:
C:\MyFolder> Foo.bat 2>&1 1>x.txt
But it still prints some lines to the console window, and those lines are not written to the file.
How is that possible? On what output are these lines, which print to the console window?
How to redirect those lines to the file?
The correct way to redirect stdout (1) and stderr (2) into the same file is to redirect them in this exact order:
C:\MyFolder> Foo.bat 1>x.txt 2>&1
This applies to Windows cmd.exe, but also to Linux bash shell.
In your version (in the wrong order) stderr is not redirected to the file, and gets printed in the console window. So most probably the lines, which appeared in the console window were printed to stderr.
Another way a program (probably called by Foo.bat) can bypass the file, is writing directly to the console's active screen buffer with Console Handle CONOUT$. This cannot be redirected to a file.

Copy script output to file

I have a series of bash scripts that echo a lot of data to stdout and occasionally to stderr. There is a main bash script which then imports and/or invokes many other bash scripts.
I'm trying to implement something that will capture the output from not just the parent script, but all children scripts. I need to capture both stdout and stderr so that any issues from compilation, etc... get captured in this log file.
I'm aware of tee and of course the normal stdout redirect >... but these don't seem to work without either adding these commands to each line of every script, both parent and children. There's several thousand lines in these scripts, so adding a redirect to each line would be impractical, even using sed.
I've seen suggestions such as: Redirect stderr and stdout in a Bash script
But these require editing every line in the scripts. Forcing my users to install screen is also impractical.
UPDATE:
Forgot to mention I want the output to still display on the console as well as write to the log. The scripts take several hours to run, and the user needs to know something is happening...
You can use yourmainscript 2>&1 | tee log which will capture stdout and stderr from all imported/invoked scripts in yourmainscript while also showing it on screen.
Inside yourmainscript, you can get the same effect using:
echo "Redirecting the rest of script output to 'log'"
exec > >(tee log) 2>&1
rest of your code
To redirect just a certain section:
echo "Redirecting the next commands"
{
cmd1
cmd2
} > >(tee log) 2>&1
echo "Continuing as normal"

Duplicating stderr compilation output into separate file

I have a project, which builds by using make, and I want to add possibility
to analyze overall state of warning messages.
My idea is change make rules in order to duplicate stderr compilation output into separate file during full rebuild. Means each time make all will be done, all output will be printed in console and in addition stderr output will be duplicating into separate file.
This warning report file will be added into repository, so that I will have possibility to compare warnings existing in repository and local warnings.
The question is how to DUPLICATE (not redirect) stderr output into separate file? Means how I should change all target in Makefile?
I know how to redirect stderr output (make all 2>warning_report.txt), but it is not
what I need. Warning messages should be both in main console output and in warning file.
I use Windows 7 as work environment but I had no any deal with Windows command line or batch files before.
Thanks in advance.
Edited:
In my case final solution looks like below:
make all 3>&1 1>&2- 2>&3- | tee.bat warning_report.txt
In this case script tee.bat, which is written in JScript for Windows, I took from link specified by PA (thanks).
What about swapping, I took it from here and here.
I don't know about windows but you can do it using tee command in Linux. tee is used to redirect STDOUT to file as well as console so you can take its advantage and check if you can solve your problem.
make all 2>&1 1>stdout.log | tee stderr.log
redirect STDERR to STDOUT, redirect STDOUT to stdout.log and all the STDERR is copied to stderr.log ans echoed on the console as well.
But the solution is not complete yet. The STDOUT is not printed on the console but only copied to the stdout.log. Try playing around the commands you will get the solution .
I just re-read your question and decided I would try to answer it.
Here's a snippet made to export stderr and display it.
#echo off
if exist stderr.error del stderr.error
this_is_not_a_command 2>stderr.error
if exist stderr.error type stderr.error & del stderr.error
This would export stderr to a file and then display the contents of that file.
Hope that helps.

Continue capturing output after redirection

Okay, here's a toughie-- I'm capturing the output of cmd.exe just fine, reading from the pipe, yadda yadda yadda, but then a line in the cmd.exe batch file has the audacity to do:
dir err.txt >zz
.. that is, it's redirecting the output of the dir command, which is an internal command inside cmd.exe.
Problem is, this breaks my capturing of output! I can't get anything from cmd.exe after that point.
Apparently to redirect standard output, it closes it, or somehow breaks it, and makes a new stdout to redirect the output. And it never restores the old stdout handle.
Any ideas of how to track this output?
If you are allowed to modify the batch file, you may replace the inner redirection by a TEE command.
There are several ports to Windows (just google "windows command tee").
From Wikipedia:
In computing, tee is a command in various command-line interpreters (shells)
such as Unix shells, 4DOS/4NT and Windows PowerShell, which displays or pipes
the output of a command and copies it into a file or a variable
you should call dir err.txt in a separate process. try call dir err.txt >zz

trying to capture javac output in bash shell

I'm trying to redirect the java compiler output to a file.
I thought it's supposed to be:
javac file.java > log.txt
or something. Instead, I see all the output on the terminal and nothing in log.txt!
Also, if I want to log errors too, do I do
javac file.java 2>&1 > log.txt
?
javac file.java 2> log.txt
The reason is that you have two output file descriptors instead of one. The usual one is stdout, which you can redirect with > and it's supposed to be used for resulting output. The second one, stderr, is meant for human readable output like warnings, errors, current status etc., this one is redirected with 2>.
Your second line, using 2>&1, redirects stderr to stdout and finally stdout into log.txt.
Have you tried
javac -Xstdout log.txt file.java
This will send compiler errors to a log file instead of stderr.

Resources