问题
I have a batch file that executes a java application. I'm trying to modify it so that whenever an exception occurs, it'll write the STDERR out to a file.
It looks something like this:
start java something.jar method %1 %2 2>> log.txt
Is there a way I can write the arguments %1 and %2 to the log.txt file as well? I don't want to write it to the log file everytime this batch file gets called, only when an exception occurs.
I tried searching for a way to redirect STDERR into a variable, but I couldn't figure it out. Ideally I'd like the log file to look something like:
Batch file called with parameters:
- "first arg"
- "second arg"
Exception:
java.io.exception etc...
------------------------------------
Batch file called with parameters:
- "first arg"
- "second arg"
Exception:
java.io.exception etc...
回答1:
Something like this might work:
javastart.cmd
@echo off
set params=%*
for /f "delims=" %%e in ('java something.jar method %1 %2 ^>nul') do (
echo Batch file called with parameters:>>log.txt
echo - Args[]: %*>>log.txt
echo - Arg[1]: %1>>log.txt
echo - Arg[2]: %2>>log.txt
echo Exception: %%e
)
I am not a java programmer myself, I cannot test this output/situation but:
1: %* means every parameters, from 1st to last (even %12 although it's not directly available.. ) whatever the formating. Might be better to use this than delimit those. In the even of bad spacing/quoting, you would have the full parameters too. I added a line in the log, to show the full line then the parameters. You can see where the problem was if it's a matter of bad arguments.
2: sending the stdout to null (^>nul) will only keep the stderr output, set into %%e
3: Whatever is in the do part will only happen is the for test statement actually has anything as an output, i.e. if %%e is set.
With those being said, you have to test the script and see if the exception is actually sent to stderr or, like some other softwares, to stdout even if an error occured.
I hope this helps.
回答2:
The only working solution I see would be to redirect stderr to a temporary file
java blah.jar %1 %2 2>stderr
and afterwards looking whether something has been written to the file and writing to the log in that case.
for %%i in (stderr) do if %%~zi GTR 0 (
echo Parameters: %1 %2 >>log.txt
type stderr >> log.txt
)
If the batches aren't run in sequence but rather simultaneously you need to find something to uniquify the temp variable:
set file=%time::=%
set /a file=file
set file=%file%%random%
java blah.jar %1 %2 2>stderr_%file%
for %%i in (stderr) do if %%~zi GTR 0 (
echo Parameters: %1 %2 >>log.txt
type stderr >> log.txt
)
This will avoid clashes between multiple running batches. However, you are currently not using anything to lock writing to your log file and things may appear out of place when other things get written to it (with other batches you might get interleaving in the echo
and type
commands or, when you're redirecting output of java to that file as well, then it may get mixed up with regular output of the java program:
Parameters: foo bar Some regular output Parameters: foo2 bar2 More output NullPointerException at Blah: What we really wanted to have right after the parameters IOException at Blah: This exception belongs to the parameters foo2 bar2
You can use another file as semaphore for writing to the log to avoid the batch outputs getting mixed: create the file [copy nul file
] when you want to write to the log, delete it afterwards and before you attempt to create it check whether it is actually there and wait until it disappears. You can't do anything about the stdout log being mixed into the file, though, except you use that temp file approach for stdout as well (and simply type
the stdout log to log.txt
when the Java program finished, but, again with using the semaphore.
回答3:
I don't get exactly what you are asking, but here's some info that may help...
You can redirect stderr separately from stdout in a .cmd or .bat file. To redirect stderr, use something like this:
MyCommand.exe > command.stdout.txt 2> command.stderr.txt
Then, you can check the command.stderr.txt for content, and if any is present, concatenate it to the command.stdout.txt into your log file. Or you could concat it in any case. If you like you could also echo the command that you ran, into the final log file.
You can also check for the exit code in a batch file, using the %ERRORLEVEL% env var. Exe files are expected to set ERRORLEVEL in case of an error. I don't know if java.exe does this. It should, if it is a good citizen on Windows. This might be an alternative way of finding out if the Java app exited with an error condition. But this is no guarantee that stderr got nothing. For example, a Java app might print out an exception and stack trace, and then exit with code 0, which indicates success. In which case stderr would have gunk in it, but ERRORLEVEL would be zero.
EDIT: s/ERROR_LEVEL/ERRORLEVEL
回答4:
How about something like this (untested):
@echo off
@echo Batch file called with parameters: >> log.txt
@echo - %1 >> log.txt
@echo - %2 >> log.txt
start java something.jar method %1 %2 2>> log.txt
回答5:
Try using ERRORLEVEL
java something.jar method %1 %2 2>> log.txt
IF %ERRORLEVEL% NEQ 0 GOTO Error
Error:
@ECHO There was an error
@ECHO Arg 1: %1 >> log.txt
@ECHO Arg 2: %2 >> log.txt
回答6:
A batch file like this should do the trick.
start_prog.cmd
CALL :Start_Prog arg1 arg2
GOTO :EOF
:Start_Prog
something.py %1 %2 2>&1 1>nul | "C:\Python26\python.exe" format_output.py %1 %2 >>log.txt
GOTO :EOF
Here I'm passing stderr via a pipe and passing arguments as arguments. The output is then appended to a log.txt file.
Throw away stdout
1>nul
Redirect stderr to stdout
2>&1
Pipe the stderr into a script to format the output, and pass arguments as arguments.
| "C:\Python26\python.exe" format_output.py %1 %2
Append output to a "log.txt".
>>log.txt
On my system I need to call python.exe otherwise the pipe doesn't work.
Here are the two files I used "something.py" and "format_output.py".
something.py
import sys
print >>sys.stdout, " ".join(sys.argv[1:])
print >>sys.stderr, "java.io.exception etc..."
format_output.py
import sys
print "Batch file called with parameters:"
for arg in sys.argv[1:]:
print '- "{0}"'.format(arg)
print "Exception:"
for line in sys.stdin:
print line
And finaly here's the output.
log.txt
Batch file called with parameters:
- "arg1"
- "arg2"
Exception:
java.io.exception etc...
The only thing missing is that something is always written to the "log.txt" file.
To tidy this up further I would move writing the log file into "format_output.py".
You could then add a check to see if the stderr from your program is blank.
来源:https://stackoverflow.com/questions/918619/redirect-batch-stderr-to-file