Вам нужен инструмент автоматизации сборки , из которых существует множество . Даже если вы ограничитесь достойными инструментами для создания программ на C ++, которые работают как в Solaris, так и в Windows, вероятно, есть сотни вариантов. Классическим независимым от языка средством автоматизации сборки в мире Unix и Windows является make .Существует общее мнение, что можно добиться большего, но нет единого мнения о том, кто на самом деле добился большего.
Инструменты автоматизации сборки просто выполняют серию инструкций для создания результирующих двоичных файлов и других продуктов из исходного кода. Похоже, вам, вероятно, нужен инструмент непрерывной интеграции , который мог бы делать такие вещи, как извлечение из svn (возможно, автоматически в ловушке фиксации), вызов make, вызов тестовых скриптов, загрузку полученного продукта и результат теста куда-нибудь , отправьте уведомление, когда сборка будет завершена, и покажите какую-то панель с историей сборок.
Не существует де-факто стандартного инструмента непрерывной интеграции, не говоря уже о «лучшем». Просмотрите список Википедии, выберите несколько наиболее подходящих и потратьте несколько минут на просмотр их документации. Затем выберите один и настройте его. Если у вас нет других требований, о которых вы не упомянули, большинство из этих продуктов должно подойти.
Ваша первая команда,
( echo foo >&2 ) 2> >(sed 's/^/stderr: /') | sed 's/^/stdout: /'
в упрощенной форме (использование временного файла для хранения данных, созданныхecho
):
{ echo foo 2>file >&2; sed 's/^/stderr: /' file; } | sed 's/^/stdout: /'
То есть первый sed
считывает то, что выдается при стандартной ошибке, из echo
и записывает в стандартный вывод, а второй sed
читает и модифицирует это.
Ваша вторая команда,
( echo foo >&2 ) 2> >(sed 's/^/stderr: /') > >(sed 's/^/stdout: /')
в упрощенной форме,
echo foo 2>file >&2; sed 's/^/stderr: /' file; sed 's/^/stdout: /' </dev/null
Здесь sed
, который получает стандартный вывод ошибки, производит вывод, в то время как другой sed
, который получает стандартный вывод, (который ничего не дает ), не производит никакого вывода (, поскольку он не t не получает никаких входных данных, и поскольку он не вставлял и не добавлял никаких данных ).
Другой способ формулировки:
Первая команда:
( echo foo >&2 ) 2>file
sed 's/^/stderr: /' file | sed 's/^/stdout: /'
Вторая команда:
( echo foo >&2 ) 2>file >otherfile
sed 's/^/stderr: /' file
sed 's/^/stdout: /' otherfile
Короче говоря, второй sed
во второй команде никогда ничего не читает. В частности, он не считывает вывод первой команды sed
, как в первой команде.
Используя чрезвычайно упрощенные символы, первая команда выглядит примерно так
utility-writing-to-stderr 2> >(something1) | something2
где something1
пишет в стандартный вывод, который считывается something2
.
Вторая команда, использующая те же обозначения,
utility-writing-to-stderr 2> >(something1) >(something2)
т.е. something1
и something2
даже не связаны друг с другом, и something2
никак не может прочесть, что something1
производит. Кроме того, поскольку utility-writing-to-stderr
ничего не производит в своем стандартном потоке вывода, something2
не будет ничего читать из своего стандартного ввода.
>
работает с ( echo foo >&2 )
, а |
работает с >(sed 's/^/stderr: /')
из-за порядка перенаправления в оболочках. НАПРИМЕР.
$ ( echo foo >&2 ) 2> >(sed 's/^/stderr: /' > >(sed 's/^/stdout: /') )
stdout: stderr: foo
или
$ ( echo foo >&2 ) 2> >(sed 's/^/stderr: /') | cat > >(sed 's/^/stdout: /')
stdout: stderr: foo
vs явные примеры порядок в вопросе
$ ( ( echo foo >&2 ) > >(sed 's/^/stdout: /') ) 2> >(sed 's/^/stderr: /')
stderr: foo
или
$ ( ( echo foo >&2 ) | sed 's/^/stdout: /' ) 2> >(sed 's/^/stderr: /')
stderr: foo
Эти две команды не эквивалентны.
Команда (1):
( one ) 2> >(two) | three
Отправляет вывод (std )из two
вthree
(Подробнее о stderr ниже ).
Команда (2):
( one ) 2> >(two) > >(three)
Отправляет вывод (std )из one
вthree
(stderr переходит вtwo
).
Болезненная деталь:
Команда 1:( one ) 2> >(two) | three
three
запущена(sed 's/^/stdout: /'
)в ожидании ввода на стандартный ввод. 2
(stderr
)на stdin
из two
. one
(echo foo >&2
). foo
наstderr
(ничего на стандартный вывод ). foo
перенаправляется с(stderr
изone
)на(stdin
из two
). sed 's/^/stderr: /'
)two
(stderr: foo
)отправляется на стандартный вывод two
. two
проходит по каналу к three
. three
, которая ожидала ввода с самого начала, получает вывод. stdout:
. stdout: stderr: foo
отправляется на tty. Команда 2:(один )2> > (два )> > (три)
>
)создается первым. three
запускается в ожидании ввода наstdin
только(>()
). three
получает только стандартный вывод из one
. two
запускается в ожидании ввода. two
получает(только)стандартный вывод one
. one
с его stderr
. one
выполняется, отправляя foo
наstderr
(изone
).foo
переходит вtwo
two
изменяет полученную строку на stderr: foo
и отправляет ее на tty . three
получает пустой ввод из стандартного вывода one
. three
ничего не печатает (, так как нет строки для обработки ). Поймите, что эта команда:
printf '' | sed 's/^/initial: /'
не имеет вывода (и нет способа заставить его работать ).
Изменение порядка :Команда 3:(один )> > (три )2> > (два)
Направляет вывод two
на three
(, а не на деталь tty
), оставленную в качестве упражнения.
Я проголосовал за очень четкий -урезанный ответ @Kusalananda, но осмелюсь (с опозданием )добавить это к его ответу, как небольшую иллюстрацию замены процессов в действии:
Ваше второе предложение будет работать с небольшим типографским изменением (и сравнительно большим изменением его ошибочной логики):
$ ( echo foo >&2 ) 2> >(sed 's/^/stderr: /') > >(sed 's/^/stdout: /')
stderr: foo # for the well explained reason above
Но:
v vv
$ ( (echo foo >&2) 2> >(sed 's/^/stderr: /') )> >(sed 's/^/stdout: /')
stdout: stderr: foo
Поскольку добавление ( )>
, как показано на рисунке (или >( )
, оба работают нормально, )на самом деле позволяет вам создать файл с помощью подстановки процесса, чьи выходные данные могут быть перенаправлены в качестве входных на >(sed 's/^/stdout: /')
.
Я подумал о том, чтобы добавить это, чтобы проиллюстрировать, как подстановка процесса может быть встроена в подстановку другого процесса. Для удобочитаемости я бы не продвигал его к большему количеству уровней встраивания. Но если по какой-либо причине вам нужно избежать трубы и связанной с ней оболочки , это хорошее решение.