об'єднати вихід з двох команд в баш


81

Чи можливо поєднувати вихід з цих двох команд?

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

Жодна команда не виходить, тому я не впевнений, як це зробити.


3
Якщо програми не закінчуються, імовірно, вони записують вихід постійно? Що ви хочете робити з їх результатами? Переплетені лінії, ...? Чому ти хочеш це робити?
— vonbrand

2
Команда вузла не видає багато, але її все одно потрібно запустити. Пітон виводить усі запити, я хочу захопити обидва та спостерігати їх обоє в одному вікні оболонки.
— chovy

Відповіді:


108

Ви можете об'єднати дві команди, згрупувавши їх { }:

{ command1 & command2; }

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

{ command1 & command2; } > new_file

якщо ви хочете відокремити STDOUTі STDERRв двох файлах:

{ command1 & command2; } > STDOUT_file 2> STDERR_file

3
Неважливо, що вони не закінчують програми. "хвіст -f" також не "закінчується", але це все ще працює і поєднує результати обох програм. Працює і більше двох команд. ^ c для виходу вбиває лише одну з згрупованих команд. Однак вам доведеться вбити іншого вручну.
— SuperMagic

5
Здається, вам не вистачає останнього ;раніше }, це обов’язково!
— Жилль Кінот

2
Будьте попереджені: Це не зберігає цілі рядки! Ви отримаєте ненадійні результати, оскільки лінії розбиваються частиною і змішуються між собою. Ви можете спробувати це, якщо в { yes {1..20} & yes {1..20}; } | grep -v '^1 2 3'ідеалі нічого не буде надруковано, якщо рядки не порушені.
— антак

8
Я вважаю за краще використовувати &&замість &! command1 & command2- це запускає команду1 у фоновому режимі та запускає команду2 негайно, тим самим виконуючи обидві команди паралельно та змішуючи вихід. command1 && command2- це запускає command1 (на передньому плані), а потім, якщо команда1 вдалася, запускає command2.
— DUzun

1
@DUzun OP сказав, що жодна команда не завершується, тому з вашим рішенням друга команда ніколи не запуститься
— Zoey Hewll

50

Більш загально, можна використовувати або підзаголовки, або групування команд, і перенаправляти результати всієї групи відразу.

Код:

( command1 ; command2 ; command3 ) | cat

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

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

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


2
Перенаправлення від ( )роботи теж чудово.
— muru

2
}зовсім не команда. Це застережене слово. Те саме стосується {. Я зазвичай пишу такі списки , як так: { command1;command2;} > outfile.txt. Ви можете додавати пробіли після крапки з комою, але це не обов'язково. Простір після { є необхідним, хоча.
— Wildcard

1
Будьте попереджені: Це не зберігає цілі рядки! Ви отримаєте ненадійні результати, оскільки лінії розбиваються частиною і змішуються між собою. Ви можете спробувати це, якщо в ( yes {1..20} & yes {1..20}; ) | grep -v '^1 2 3'ідеалі нічого не буде надруковано, якщо рядки не порушені. (H / t до @antak).
— Оле Танге

3
Іноді хочеться запустити command2, лише якщо ( command1 && command2 && command3 ) | cat
— команда1 вдалася

Я віддаю перевагу круглим дужкам, так ()як з фігурними дужками {}він працює як фоновий прогрес, і тоді вам доведеться мати справу з результатами з цього. Також труба кішці `| 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

@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

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

@Bernhard дійсно. Але це не було вказано у req's
— 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) Вихід другої команди не є ascii бінарним, тому не було б корисним її показувати. 2) ОП, ймовірно, вирішила свою конкретну проблему між 2013 та тепер. Зараз це питання фактично є посиланням на комбінування складання декількох команд Bash, тому я вважаю, що техніка їх поєднання в одному рядку є корисним "рецептом", про який слід згадати тут (оскільки я прийшов сюди шукати його і не зміг знайти це).
— Лука
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.