łącz wyjście z dwóch poleceń w bash


81

Czy można połączyć dane wyjściowe z tych dwóch poleceń?

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

Żadne polecenie nie kończy się, więc nie jestem pewien, jak to zrobić.


3
Jeśli programy się nie kończą, prawdopodobnie zapisują dane wyjściowe w sposób ciągły? Co chcesz zrobić z ich produkcją? Linie przeplotu, ...? Dlaczego chcesz to zrobić?
— vonbrand

2
Polecenie node nie wyświetla zbyt wiele, ale nadal musi zostać uruchomione. Python wysyła wszystkie żądania, chcę uchwycić oba i oglądać je oba w tym samym oknie powłoki.
— chovy

Odpowiedzi:


108

Możesz połączyć dwa polecenia, grupując je za pomocą { }:

{ command1 & command2; }

do tej pory, można przekierować grupę do pliku (ostatni ;przed }jest obowiązkowe):

{ command1 & command2; } > new_file

jeśli chcesz oddzielić STDOUTi STDERRdwa pliki:

{ command1 & command2; } > STDOUT_file 2> STDERR_file

3
Nie ma znaczenia, że ​​ich programy się nie kończą. „tail -f” też nie „kończy”, ale nadal działa i łączy wyniki obu programów. Działa również dla więcej niż dwóch poleceń. ^ c, aby wyjść zabija tylko jedno z pogrupowanych poleceń. Musisz jednak zabić drugiego przeciwnika ręcznie.
— SuperMagic

5
Wygląda na to brakuje ci ostatni ;przed }, to jest obowiązkowe!
— Gilles Quenot,

2
Uwaga: to nie zachowuje całych linii! Otrzymasz niewiarygodne wyniki, gdy linie zostaną częściowo podzielone i zmieszane między sobą. Możesz spróbować tego, dzięki { yes {1..20} & yes {1..20}; } | grep -v '^1 2 3'czemu idealnie nic nie wydrukujesz, jeśli linie nie zostaną złamane.
— antak

8
Wolałbym użyć &&zamiast &! command1 & command2- to uruchamia polecenie 1 w tle i natychmiast uruchamia polecenie 2, tym samym uruchamiając oba polecenia równolegle i psując dane wyjściowe. command1 && command2- uruchamia to polecenie 1 (na pierwszym planie), a następnie, jeśli polecenie 1 się powiedzie, uruchamia polecenie 2.
— DUzun,

1
@DUzun OP powiedział, że żadne polecenie nie kończy się, więc przy twoim rozwiązaniu drugie polecenie nigdy się nie uruchomi
— Zoey Hewll

50

Mówiąc bardziej ogólnie, można użyć grupowania podpowłoki lub grupowania poleceń i przekierować dane wyjściowe całej grupy naraz.

Kod:

( command1 ; command2 ; command3 ) | cat

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

Główna różnica między nimi polega na tym, że pierwszy dzieli proces potomny, podczas gdy drugi działa w kontekście głównej powłoki. Może to mieć konsekwencje w zakresie ustawiania i używania zmiennych i innych ustawień środowiska, a także wydajności.

Nie zapominaj, że nawias zamykający w grupowaniu poleceń (i funkcjach) musi być oddzielony od treści średnikiem lub znakiem nowej linii. Wynika to z faktu, że "}"tak naprawdę jest to samo polecenie (słowo kluczowe) i musi być traktowane jak jedno.


2
Przekierowanie z ( )działa również dobrze.
— muru

2
}wcale nie jest poleceniem. To zastrzeżone słowo. To samo dotyczy {. I zazwyczaj pisać takie listy tak: { command1;command2;} > outfile.txt. Możesz dodać spacje po średnikach, ale nie jest to konieczne. Konieczne { jest jednak miejsce po .
— Wildcard

1
Uwaga: to nie zachowuje całych linii! Otrzymasz niewiarygodne wyniki, gdy linie zostaną częściowo podzielone i zmieszane między sobą. Możesz spróbować tego, dzięki ( yes {1..20} & yes {1..20}; ) | grep -v '^1 2 3'czemu idealnie nic nie wydrukujesz, jeśli linie nie zostaną złamane. (H / t do @antak).
— Ole Tange

3
Czasami chcesz uruchomić polecenie 2 tylko wtedy, gdy polecenie 1 ( command1 && command2 && command3 ) | cat
— powiodło się

Wolę okrągłe nawiasy, ()jak w nawiasach klamrowych, {}które działają jako postęp w tle, a następnie musisz poradzić sobie z tym. Również potok do kota `| cat` jest lepszą alternatywą niż `> / dev / stdout`
— DarkMukke,

2

Skończyło się na tym, inne sugestie nie zadziałały, ponieważ 2. polecenie zostało zabite lub nigdy nie zostało wykonane.

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
Uwaga: może to powodować błędy we / wy, jeśli dwa procesy spróbują zapisać do pliku „w tym samym czasie”.
— Djizeus

2
mogę określić 2 różne pliki dziennika i zrobić, tail -f *.logchociaż nigdy nie widziałem tego jako problemu z 2 różnymi procesami zapisującymi do tego samego pliku dziennika.
— chovy

@chovy: czy możesz napisać swój problem jako pytanie tutaj ... jest to przydatne
— Abdennour TOUMI

1
Uwaga: to nie zachowuje całych linii! Otrzymasz niewiarygodne wyniki, gdy linie zostaną częściowo podzielone i zmieszane między sobą. Możesz tego spróbować za pomocą polecenia1 = yes {1..20}polecenie2 = yes {1..20}i potokować połączone wyjście, przez | grep -v '^1 2 3'które idealnie nic nie wydrukujemy, jeśli linie nie zostaną podzielone. (H / t do @antak).
— Ole Tange,

Ponadto dysk może być zapełniony, jeśli ilość danych jest duża.
— Ole Tange

2

Spróbuj tego:

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

1
co robi „wklej”?
— chovy

@chovy, patrz tutaj: techrepublic.com/article/… Nie jestem pewien, czy to zadziała w tym kontekście.
— FixMaker

Nie sądzę, aby wklejanie było tutaj właściwe, ponieważ ma to na celu umieszczenie kolumn obok siebie
— Bernhard

@Bernhard rzeczywiście. Ale nie zostało to określone w wymaganiach
— frogstarr78

@ frogstarr78 Myślę, że jest bardzo mało prawdopodobne, że tego właśnie chce, ale masz rację, nie jest to określone.
— Bernhard

1

Większość dotychczasowych rozwiązań źle radzi sobie z problemem częściowej linii. Załóżmy przez chwilę, że programami są:

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

Podczas uruchamiania tych równolegle chcesz, aby wynik zawierał pełne linie as, po których następują pełne linie bs. Czego nie chce to as i bs mieszania w tej samej linii ( tr -s abzastępuje powtarzając as przy pojedynczym a, więc łatwiej jest zobaczyć, co się dzieje):

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

Jeśli zamiast tego użyjesz GNU Parallel, uzyskasz ładne, czyste pełne linie z as lub bs, ale nigdy nie mieszane:

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

Nowsze wersje GNU Parallel unikają nawet zapełniania dysku: powyższe może działać wiecznie.


0

Ponieważ już korzystasz node, możesz spróbować spróbować jednocześnie

Uruchom wiele poleceń jednocześnie. Jak, npm run watch-js & npm run watch-lessale lepiej.


0

W specjalnym przypadku łączenia wielu danych wyjściowych poleceń BASH w jednym wierszu, oto przepis na uruchamianie każdego polecenia po kolei, usuwając wszelkie znaki nowej linii między ich wyjściami.

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

Jako przykład ze świata rzeczywistego poniższy kod osadzi komunikat ASCII między dwoma stałymi ciągami bajtów (w tym przypadku tworząc polecenie drukowania)

#   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

(Uwaga: ta metoda działa tylko wtedy, gdy polecenia kończą się. Aby połączyć standardowe wyjście z poleceń, które się nie kończą, zobacz inne odpowiedzi.)


(1) Pokaż (oczekiwany) wynik drugiego polecenia. (2) Pokaż, w jaki sposób OP wykorzystałby tę technikę do rozwiązania swojego problemu.
— Scott

1) Wyjście drugiego polecenia nie jest ascii binarne, więc nie byłoby użyteczne jego pokazywanie. 2) OP prawdopodobnie rozwiązał swój konkretny problem między 2013 r. A teraz. To pytanie jest teraz skutecznie odniesieniem do łączenia standardowego polecenia wielu poleceń Bash, więc uważam, że technika łączenia ich w jednym wierszu jest użytecznym „przepisem”, o którym należy wspomnieć tutaj (ponieważ przybyłem tutaj, aby go znaleźć i nie mogłem znaleźć to).
— Łukasz
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.