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


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.