Перенаправить пакетный stderr в файл

У меня есть пакетный файл, который выполняет 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...

Ответ 1

Что-то вроде этого может работать:

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: % * означает все параметры, от 1-го до последнего (даже% 12, хотя он не доступен напрямую..) независимо от формы. Возможно, лучше использовать это, чем ограничивать их. В четном неправильном пробеле/​​цитировании у вас также будут полные параметры. Я добавил строку в журнал, чтобы показать полную строку, затем параметры. Вы можете видеть, где проблема, если это вопрос плохих аргументов.

2: отправка stdout в null (^ > nul) приведет к сохранению вывода stderr, установленному в %% e

3: Все, что находится в do, произойдет только в том, что тестовый оператор для фактически имеет что-то в качестве вывода, т.е. если %% e.

С учетом сказанного вам нужно протестировать script и посмотреть, действительно ли исключение отправлено в stderr или, как и другие программные средства, в stdout, даже если произошла ошибка.

Надеюсь, это поможет.

Ответ 2

Я не понимаю, что вы просите, но вот информация, которая может помочь...

Вы можете перенаправить stderr отдельно от stdout в файле .cmd или .bat. Чтобы перенаправить stderr, используйте что-то вроде этого:

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

Затем вы можете проверить файл command.stderr.txt для содержимого, и если он присутствует, объедините его в файл command.stdout.txt в файл журнала. Или вы могли бы это сделать в любом случае. Если вам нравится, вы также можете выполнить команду, которую вы запустили, в последний файл журнала.

Вы также можете проверить код выхода в пакетном файле, используя% ERRORLEVEL% env var. Ожидается, что файлы Exe установят ERRORLEVEL в случае ошибки. Я не знаю, делает ли это java.exe. Это должно быть, если это хороший гражданин в Windows. Это может быть альтернативный способ узнать, вышло ли приложение Java с условием ошибки. Но это не гарантирует, что stderr ничего не получит. Например, приложение Java может распечатывать трассировку исключения и стека, а затем выходить с кодом 0, что указывает на успех. В этом случае stderr будет иметь гнал в нем, но ERRORLEVEL будет равен нулю.

EDIT: s/ERROR_LEVEL/ERRORLEVEL

Ответ 3

Единственным рабочим решением, которое я вижу, было бы перенаправление 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 (и просто type журнал stdout до log.txt, когда программа Java закончила, но, снова с использованием семафора.

Ответ 4

Как насчет чего-то вроде этого (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

Попробуйте использовать 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

Такой командный файл должен делать трюк.

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 с script для форматирования вывода и передайте аргументы в качестве аргументов.

| "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 из вашей программы.