2014-01-31 4 views
1

В частности, я пишу скрипт, чтобы упростить компиляцию и запуск моего кода на C++. Легко сказать, удалось ли компиляции сбой, но я также хочу добавить состояние, в котором оно «скомпилировано с предупреждениями».Bash capture stderr в переменную без перенаправления

$out # to avoid an "ambiguous redirect" 
g++ -Wall -Wextra $1 2> out 

if [ $? == 0 ] 
then 

     # this is supposed to test the length of the output string 
     # unless there are errors, $out should be length 0 
    if [ ${#out} == 0 ] 
    then 
     # print "Successful" 
    else 
     # print "Completed with Warnings" 
    fi 

else 
    # print "Failed" 
fi 

Как это, проверка провал случае работает нормально, но $out не всегда пустая строка, хотя STDERR больше не отображать на экране, $out фактически никогда не установлено. Если возможно, мне также хотелось бы, чтобы stderr продолжал идти на экран.

Надеюсь, что я сказал, имеет смысл. Приветствия.

ответ

0

Для захвата в переменной и отображения на экране, используйте tee:

out=$(g++ -Wall -Wextra "$1" 2>&1 >dev/null | tee /dev/stderr) 

Это выбрасывает стандартный вывод g++ и перенаправляет стандартные ошибки в стандартный вывод. Этот вывод передается по каналу на tee, который записывает его в указанный файл (/dev/stderr, чтобы сообщения возвращались к исходной стандартной ошибке) и стандартный вывод, который фиксируется в переменной out.

+0

, который улавливает в' $ out', которая была моей главной проблемой , хотя он, похоже, не позволяет '$? 'получить статус выхода' g ++ ', я предполагаю, что это потому, что после компиляции он запускает' tee'. Как еще я могу получить этот статус? – Dustin

+0

Массив 'PIPESTATUS' будет хранить статус выхода каждой команды в последнем конвейере переднего плана, поэтому после этого назначения' $ {PIPESTATUS [0]} 'должен содержать статус выхода' g ++ '. – chepner

+0

'PIPESTATUS' всегда, кажется, содержит одиночный 0, независимо от статуса выхода' g ++ '. – Dustin

0
g++ -Wall -Wextra $1 2> out 

Это перенаправляет поток ошибок в файл с именем out, а не переменная с именем $out.

Если вы хотите запустить gcc и посмотреть stdout и stderr на экране, а также сохранить вывод stderr, вы можете использовать именованный канал (FIFO). Это немного круглая, но это выполнило бы работу.

mkfifo stderr.fifo 
gcc -Wall -o /dev/null /tmp/warn.c 2> stderr.fifo & 
tee stderr.log <stderr.fifo>&2 
rm -f stderr.fifo 
wait 

После выполнения этих команд, предупреждения будут доступны в stderr.log. Воспользовавшись тем, что wait будет возвращать код выхода gcc «s, вы могли бы сделать что-то вроде:

if wait; then 
    if [[ -s stderr.log ]]; then 
     # print "Completed with Warnings" 
    else 
     # print "Successful" 
    fi 
else 
    # print "Failed" 
fi 

Аннотированный:

# Created a named pipe. If one process writes to the pipe, another process can 
# read from it to see what was written. 
mkfifo stderr.fifo 

# Run gcc and redirect its stderr to the pipe. Do it in the background so we can 
# read from the pipe in the foreground. 
gcc -Wall -o /dev/null /tmp/warn.c 2> stderr.fifo & 

# Read from the pipe and write its contents both to the screen (stdout) and to 
# the named file (stderr.log). 
tee stderr.log <stderr.fifo>&2 

# Clean up. 
rm -f stderr.fifo 

# Wait for gcc to finish and retrieve its exit code. `$?` will be gcc's exit code. 
wait 
Смежные вопросы