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ć.
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ć.
Odpowiedzi:
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ć STDOUT
i STDERR
dwa pliki:
{ command1 & command2; } > STDOUT_file 2> STDERR_file
;
przed }
, to jest obowiązkowe!
{ yes {1..20} & yes {1..20}; } | grep -v '^1 2 3'
czemu idealnie nic nie wydrukujesz, jeśli linie nie zostaną złamane.
&&
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.
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.
( )
działa również dobrze.
}
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 .
( 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).
( command1 && command2 && command3 ) | cat
()
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`
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
}
tail -f *.log
chociaż nigdy nie widziałem tego jako problemu z 2 różnymi procesami zapisującymi do tego samego pliku dziennika.
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).
Spróbuj tego:
paste $(node ~/projects/trunk/index.js) $(python ~/projects/trunk/run.py run) > outputfile
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 a
s, po których następują pełne linie b
s. Czego nie chce to a
s i b
s mieszania w tej samej linii ( tr -s ab
zastępuje powtarzając a
s 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 a
s lub b
s, 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.
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-less
ale lepiej.
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.)