объединить вывод двух команд в bash


81

Можно ли объединить вывод этих двух команд?

node ~/projects/trunk/index.js 
python ~/projects/trunk/run.py run

Ни одна из команд не завершается, поэтому я не уверен, как это сделать.


3
Если программы не заканчивают, предположительно, они записывают вывод непрерывно? Что вы хотите сделать с их выходом? Чередование строк, ...? почему ты хочешь сделать это?
vonbrand

2
Команда узла не выводит много, но все равно должна быть запущена. Python один выводит все запросы, я хочу захватить оба и посмотреть их в одном окне оболочки.
Чови

Ответы:


108

Вы можете объединить две команды, сгруппировав их с { }:

{ command1 & command2; }

пока что вы можете перенаправить группу в файл (последний ;перед }обязательным):

{ command1 & command2; } > new_file

если вы хотите разделить STDOUTи STDERRна два файла:

{ command1 & command2; } > STDOUT_file 2> STDERR_file

3
Не важно, что они программы не заканчивают. 'tail -f' также не «завершает», но это все еще работает и объединяет результаты обеих программ. Работает для более чем двух команд. ^ c, чтобы выйти, убивает только одну из сгруппированных команд. Вы должны будете убить другого вручную.
SuperMagic

5
Похоже , у вас не хватает последнего ;перед тем }, это обязательно!
Жиль Квено

2
Имейте в виду: это не сохраняет целые строки! Вы получите ненадежные результаты, так как линии разделены частично и перепутаны между собой. Вы можете попробовать это, в { yes {1..20} & yes {1..20}; } | grep -v '^1 2 3'идеале, ничего не печатать, если строки не разбиты.
Антак

8
Я бы предпочел использовать &&вместо &! command1 & command2- это запускает команду 1 в фоновом режиме и немедленно запускает команду 2, таким образом выполняя обе команды параллельно и портя вывод. command1 && command2- при этом запускается команда 1 (на переднем плане), а затем, если команда 1 выполнена, запускается команда 2.
июня

1
@DUzun OP сказал, что ни одна из команд не завершается, поэтому с вашим решением вторая команда никогда не запустится
Зои Хьюлл,

50

В более общем смысле можно использовать либо подоболочку, либо группирование команд и перенаправить вывод всей группы сразу.

Код:

( command1 ; command2 ; command3 ) | cat

{ command1 ; command2 ; command3 ; } > outfile.txt

Основное различие между ними состоит в том, что первый разделяет дочерний процесс, а второй работает в контексте основной оболочки. Это может иметь последствия в отношении настройки и использования переменных и других параметров среды, а также производительности.

Не забывайте, что закрывающая скобка в группировании команд (и функций) должна быть отделена от содержимого точкой с запятой или новой строкой. Это потому, что "}"на самом деле это отдельная команда (ключевое слово), и должна рассматриваться как одна.


2
Перенаправление с ( )работает тоже отлично.
Муру

2
}не команда вообще. Это зарезервированное слово. То же самое и для {. Я обычно пишу такие списки , как так: { command1;command2;} > outfile.txt. Вы можете добавить пробелы после точки с запятой, но это не обязательно. Пространство после { является необходимым, хотя.
Wildcard

1
Имейте в виду: это не сохраняет целые строки! Вы получите ненадежные результаты, так как линии разделены частично и перепутаны между собой. Вы можете попробовать это, в ( yes {1..20} & yes {1..20}; ) | grep -v '^1 2 3'идеале, ничего не печатать, если строки не разбиты. (H / T в @antak).
Оле Танге

3
Иногда вы хотите запустить command2, только если command1 завершился успешно:( command1 && command2 && command3 ) | cat
DUzun

Я предпочитаю круглые скобки, так ()как с фигурными скобками {}это работает как фоновый прогресс, а затем вам придется иметь дело с выводом из этого. Также труба для кошки `| cat` - более хорошая альтернатива, чем `> / dev / stdout`
DarkMukke

2

Я закончил тем, что делал это, другие предложения не работали, поскольку 2-я команда была либо убита, либо никогда не выполнялась.

alias app () {
    nohup python ~/projects/trunk/run.py run 1>/tmp/log 2>&1 &
    echo $! > /tmp/api.pid
    nohup node ~/projects/trunk/index.js 1>/tmp/log 2>&1 &
    echo $! > /tmp/client.pid
    tail -f /tmp/log
}

1
Примечание: это может привести к ошибкам ввода-вывода, если два процесса пытаются выполнить запись в файл «одновременно».
Джизей

2
Можно указать 2 разных файла журнала и сделать, tail -f *.logхотя я никогда не видел это как проблему с двумя разными процессами, записывающими в один и тот же файл журнала.
Чови

@chovy: ты мог бы написать свою проблему как вопрос здесь ... это полезно
Abdennour TOUMI

1
Имейте в виду: это не сохраняет целые строки! Вы получите ненадежные результаты, так как линии разделены частично и перепутаны между собой. Вы можете попробовать это с помощью команды command1 = yes {1..20}command2 = yes {1..20}и передать объединенный вывод, | grep -v '^1 2 3'который в идеале не будет ничего печатать, если строки не разбиты. (H / T в @antak).
Оле Танге

Кроме того, ваш диск может заполниться, если объем данных большой.
Оле Танге

2

Попробуй это:

paste $(node ~/projects/trunk/index.js) $(python ~/projects/trunk/run.py run) > outputfile

1
что делает «вставить»?
Чови

@chovy, смотрите здесь: techrepublic.com/article/… Не уверен, что это будет работать в этом контексте.
FixMaker

Я не думаю, что вставка здесь уместна, так как она предназначена для размещения столбцов рядом друг с другом
Бернхард

@ Бернхард действительно. Но это не было указано в требовании
frogstarr78

@ frogstarr78 Я думаю, вряд ли это то, что он хочет, но вы правы, это не указано.
Бернхард

1

Большинство решений до сих пор плохо справляются с проблемой частичной линии. Предположим на секунду, что программы:

cmd1() {
    perl -e 'while(1) { print "a"x3000_000,"\n"}'
}
export -f cmd1
cmd2() {
    perl -e 'while(1) { print "b"x3000_000,"\n"}'
}
export -f cmd2

При параллельном запуске вы хотите, чтобы в выводе были полные строки as, а затем полные строки bs. То, что вам не нужно, это смешивание as и bs в одной строке ( tr -s abзамена повторяющихся as одной a, чтобы было легче увидеть, что происходит):

# This is bad - half lines are mixed
$ (cmd1 & cmd2 ) | tr -s ab
bababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa
ababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab

Если вместо этого вы используете GNU Parallel, вы получите хорошие чистые полные строки с as или bs, но никогда не будете смешаны:

$ parallel --line-buffer ::: cmd1 cmd2 | tr -s ab
a
a
b
b
b
b
a

Более новые версии GNU Parallel даже избегают заполнения вашего диска: вышеописанное может работать вечно.


0

Поскольку вы уже используете node, вы можете попробовать одновременно

Выполнить несколько команд одновременно. Нравится, npm run watch-js & npm run watch-lessно лучше.


0

Для особого случая объединения нескольких выходов команды BASH в одну строку приведен рецепт выполнения каждой команды по очереди, удаляя любые переводы строк между их выходами.

(echo 'ab' && echo 'cd' && echo 'ef') | tr -d '\n'
>>> abcdef

В качестве реального примера приведенный ниже код будет вставлять сообщение ASCII между двумя фиксированными строками байтов (в данном случае формируя команду печати).

#   hex prefix           encode a message as hex    hex suffix    | strip newline | hex to binary | (then, for example, send the binary over a TCP connection)
(echo '1b40' && echo "Test print #1" | xxd -p && echo '1d564103') | tr -d '\n'    | xxd -r -p     | nc -N 192.168.192.168 9100

(Примечание: этот метод работает, только если команды завершаются. Для объединения stdout из команд, которые не выходят, см. Другие ответы.)


(1) Пожалуйста, покажите (ожидаемый) результат вашей второй команды. (2) Пожалуйста, покажите, как ОП будет использовать эту технику для решения своей проблемы.
Скотт

1) Вывод второй команды не является двоичным, поэтому показывать его было бы бесполезно. 2) ОП, вероятно, решил свою конкретную проблему в период с 2013 года по настоящее время. Теперь этот вопрос фактически является справочным материалом по объединению стандартного вывода нескольких команд Bash, поэтому я считаю, что методика объединения их в одну строку является полезным «рецептом», о котором следует упомянуть здесь (поскольку я пришел сюда в поисках и не смог найти Это).
Люк
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.