Как использовать код возврата первой программы в командной строке конвейера

Я пишу простую программу, которая анализирует вывод компилятора и переформатирует любые сообщения об ошибках, чтобы используемая нами среда разработки (Visual Studio) могла их анализировать. Мы используем nmake для сборки, и он вызовет компилятор с помощью командной строки, подобной этой:

cc166.exe SOME_FLAGS_HERE MyCFile.c 2>&1 | TaskingVXToVisualReformat.exe

Теперь проблема в том, что код возврата компилятора, cc166, не передается обратно в nmake. Используется только код возврата моего переформатирования, что означает, что если я верну ноль из программы переформатирования, nmake продолжит сборку, а не прервет ее. Как я могу вернуть код возврата из компилятора (cc166.exe) в nmake?

Есть ли способ, которым моя программа переформатирования может прочитать код возврата компилятора и использовать его при определении собственного кода возврата? Преобразователь написан на C#.


person SNil    schedule 09.05.2011    source источник


Ответы (2)


Я бы поместил инструкции по компиляции в скрипт bash и воспользовался бы функцией pipefail:

Статус выхода конвейера — это статус выхода последней команды в конвейере, если не включен параметр pipefail. Если включен pipefail, статус возврата конвейера — это значение последней (самой правой) команды для выхода с ненулевым статусом или ноль, если все команды завершились успешно.

Давайте попробуем это с помощью простого теста:

$ cat bash_pipe.sh
#!/bin/bash
set -o pipefail
ls $1 2>&1 | perl -ne '{print;}'

Если мы запустим его с существующим файлом, код выхода будет 0 (передается через канал):

$ ./bash_pipe.sh bash_pipe.sh 
bash_pipe.sh
$ echo $?
0

С другой стороны, команда завершается ошибкой с несуществующим файлом:

./bash_pipe.sh inexistent
ls: cannot access inexistent: No such file or directory
echo $?
2

Итак, в вашем случае вам нужно поместить инструкции по компиляции в скрипт, например

$ cat compilation_script.sh
#!/bin/bash
set -o pipefail
cc166.exe SOME_FLAGS_HERE $1 2>&1 | TaskingVXToVisualReformat.exe

и вызовите его напрямую (если можете) или косвенно через

bash -c "compilation_script.sh MyCFile.c"

Примечание: опция pipefail была введена в bash версии 3.

person lafrecciablu    schedule 17.11.2014

Вы можете разделить одну команду на две и сохранить результаты компиляции во временном файле:

cc166.exe SOME_FLAGS_HERE MyCFile.c > CCRESULT.TXT 2>&1
if not errorlevel 1 TaskingVXToVisualReformat.exe < CCRESULT.TXT
person SlavaGu    schedule 09.05.2011
comment
Это не отвечает на вопрос. Если cc166 завершается успешно, то похоже, что окончательный код возврата также является успешным. Но если это не удается, то код возврата преобразователя по-прежнему используется: таким образом, cc166 завершается с ошибкой, а преобразователь завершается успешно, что дает общий результат успеха (в то время как он должен быть неудачным. Кроме того, это предполагает, что единственный сбой cc166 имеет возврат 1. - person Alexander Bird; 13.07.2011
comment
В оболочке Windows код возврата 0 — это успех, любое другое значение — сбой. Условие, если не уровень ошибки 1, на самом деле выполняется успешно, если первая команда вернула 0. К вашему сведению, в Windows, если уровень ошибки 1 означает, что код ошибки больше или равен 1 - person SlavaGu; 18.07.2011
comment
Кажется, я понимаю, о чем вы говорили, но что произойдет, если cc166 вернет 1 (или 2, 3 и т. д.) И TaskingVXToVisualReformat.exe вернет 0? не будет ли весь скрипт возвращать успех, несмотря на то, что cc166 на самом деле потерпел неудачу? - person Alexander Bird; 18.07.2011
comment
И я исправляюсь по поводу команды errorlevel. Спасибо. - person Alexander Bird; 18.07.2011