将批处理 stderr 重定向到文件

发布于 2024-07-23 04:37:10 字数 589 浏览 14 评论 0原文

我有一个执行 java 应用程序的批处理文件。 我正在尝试修改它,以便每当发生异常时,它都会将 STDERR 写入文件。

它看起来像这样:

start java something.jar method %1 %2 2>> log.txt

有没有办法将参数 %1 和 %2 也写入 log.txt 文件? 我不想每次调用该批处理文件时都将其写入日志文件,只有在发生异常时才将其写入日志文件。

我尝试寻找一种将 STDERR 重定向到变量的方法,但我无法弄清楚。 理想情况下,我希望日志文件看起来像:

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...

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...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

百合的盛世恋 2024-07-30 04:37:10

我看到的唯一可行的解​​决方案是将 stderr 重定向到临时文件

java blah.jar %1 %2 2>stderr

,然后查看是否已将某些内容写入该文件并在这种情况下写入日志。

for %%i in (stderr) do if %%~zi GTR 0 (
    echo Parameters: %1 %2 >>log.txt
    type stderr >> log.txt
)

如果批次不是按顺序运行而是同时运行,您需要找到一些东西来唯一化临时变量:

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
)

这将避免多个运行批次之间的冲突。 但是,您当前没有使用任何东西来锁定对日志文件的写入,并且当其他内容写入日志文件时,事情可能会显得不合适(对于其他批次,您可能会在 echo中交错>type 命令,或者,当您将 java 的输出也重定向到该文件时,它可能会与 java 程序的常规输出混淆:

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

您可以使用另一个文件作为信号量来写入日志避免批处理输出混合:当您想要写入日志时创建文件 [copy nul file],然后将其删除,然后在尝试创建它之前检查它是否确实存在并等待但是,您无法对混合到文件中的 stdout 日志执行任何操作,除非您也对 stdout 使用临时文件方法(并且只需将 stdout 日志键入log.txt 当 Java 程序完成时,但是再次使用信号量。

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.

枯寂 2024-07-30 04:37:10

我不明白你在问什么,但这里有一些信息可能会有所帮助...

你可以在 .cmd 或 .bat 文件中将 stderr 与 stdout 分开重定向。 要重定向 stderr,请使用如下内容:

MyCommand.exe > command.stdout.txt  2> command.stderr.txt

然后,您可以检查 command.stderr.txt 中的内容,如果存在,请将其与 command.stdout.txt 连接到日志文件中。 或者你可以在任何情况下连接它。 如果您愿意,还可以将您运行的命令回显到最终日志文件中。

您还可以使用 %ERRORLEVEL% 环境变量检查批处理文件中的退出代码。 Exe 文件预计会在出现错误时设置 ERRORLEVEL。 我不知道java.exe是否执行此操作。 如果它是 Windows 上的好公民,那么应该如此。 这可能是查明 Java 应用程序是否因错误情况退出的另一种方法。 但这并不能保证 stderr 一无所获。 例如,Java 应用程序可能会打印出异常和堆栈跟踪,然后以代码 0 退出,这表示成功。 在这种情况下,stderr 中会有垃圾,但 ERRORLEVEL 将为零。

编辑:s/ERROR_LEVEL/ERRORLEVEL

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

情归归情 2024-07-30 04:37:10

像这样的东西可能会起作用:

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
)

我自己不是 java 程序员,我无法测试此输出/情况,但是:

1: %* > 表示每个参数,从第一个到最后一个(甚至 %12,尽管它不能直接可用..),无论格式如何。 使用它可能比划定它们更好。 即使间距/引用不好,您也将拥有完整的参数。 我在日志中添加了一行,以显示完整的行,然后显示参数。 如果争论不顺利,你就能看出问题出在哪里。

2: 将 stdout 发送到 null (^>nul) 将仅保留 stderr 输出,设置为 %%e

3: 无论是什么仅当 for 测试语句实际上有任何内容作为输出时,即 %%e 设置时,才会发生 do 部分中的情况。

话虽如此,您必须测试脚本并查看异常是否确实发送到 stderr,或者像其他一些软件一样发送到 stdout,即使发生错误也是如此。

我希望这有帮助。

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.

伪装你 2024-07-30 04:37:10

像这样的事情怎么样(未经测试):

@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

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
那支青花 2024-07-30 04:37:10

尝试使用 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

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
喜爱纠缠 2024-07-30 04:37:10

像这样的批处理文件应该可以解决问题。

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

在这里,我通过管道传递 stderr 并将参数作为参数传递。 然后输出将附加到 log.txt 文件中。

丢弃 stdout

1>nul

将 stderr 重定向到 stdout 将

2>&1

stderr 通过管道传输到脚本中以格式化输出,并将参数作为参数传递。

| "C:\Python26\python.exe" format_output.py %1 %2

将输出附加到“log.txt”

>>log.txt

在我的系统上,我需要调用 python.exe,否则管道将无法工作。

这是我使用的两个文件“something.py”“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

最后这是输出。

log.txt

Batch file called with parameters:
- "arg1"
- "arg2"
Exception:
java.io.exception etc...

唯一缺少的是总是将某些内容写入“log.txt” 文件中。

为了进一步整理这个问题,我将把日志文件写入“format_output.py”。

然后,您可以添加一个检查来查看程序中的 stderr 是否为空。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文