Jak mogę to osiągnąć?
cmd >> file1 2>&1 1>>file2
Oznacza to, że stdout i stderr powinny przekierowywać do jednego pliku (plik1) i tylko stdout (plik2) powinien przekierowywać do innego (oba w trybie dołączania)?
Problem polega na tym, że po przekierowaniu danych wyjściowych nie jest już dostępny dla następnego przekierowania. Możesz tee
potokować do podpowłoki, aby zachować dane wyjściowe dla drugiego przekierowania:
( cmd | tee -a file2 ) >> file1 2>&1
lub jeśli chcesz zobaczyć dane wyjściowe w terminalu:
( cmd | tee -a file2 ) 2>&1 | tee -a file1
Aby uniknąć dodania stderr pierwszego tee
do file1
, powinieneś przekierować stderr swojego polecenia do jakiegoś deskryptora pliku (np. 3), a następnie dodać to ponownie do stdout:
( 2>&3 cmd | tee -a file2 ) >> file1 3>&1
# or
( 2>&3 cmd | tee -a file2 ) 3>&1 | tee -a file1
(dzięki @ fra-san)
Z zsh
:
cmd >& out+err.log > out.log
W trybie dołączania:
cmd >>& out+err.log >> out.log
W zsh
i pod warunkiem, że mult_ios
opcja nie została wyłączona, gdy deskryptor pliku (tutaj 1) jest kilkakrotnie przekierowywany do zapisu, wówczas powłoka implementuje wbudowaną funkcję tee
kopiowania danych wyjściowych do wszystkich celów.
out+err
iout
tu na myśli. Nazwy plików Strumienie do przekierowania?cmd >& file1 > file2
Możesz: otagować stdout (używając sedera UNBUFFERED, tj .:)
sed -u ...
, aby stderr również przeszedł do stdout (nieoznaczony, ponieważ nie przeszedł przez tagowania sed), a tym samym móc rozróżnić 2 w wynikowym pliku logu.Następujące: jest powolny (można go poważnie zoptymalizować, używając na przykład skryptu perl zamiast while ...; do ...; zrobiono, na przykład, który będzie tworzył podpowłoki i polecenia w każdym wierszu!), Dziwne (wydaje się, że potrzebuję 2 {} etapów, aby w jednym zmienić nazwę stdout, a następnie w drugim dodać do niego „przewrócony” stderr), itd. Ale to jest: „ dowód koncepcji ”, który będzie próbował zachować porządek wyjścia jak najwięcej stdout i stderr:
źródło
ls unknown
), aby wydrukować coś na stderr?>&2 echo "error"
będzie dobrze. (2)tee
może dołączyć do wielu plików jednocześnie. (3) Dlaczego niecat
zamiast tegogrep "^"
? (4) twój skrypt zawiedzie, gdy zaczyna się wyjście stderr_stdout_
. (5) Dlaczego?ls loop
spowoduje to wyświetlenie zarówno wyjścia standardowego, jak i standardowego, mieszanego (alternatywnie), w kontrolowanej kolejności; tak, abyśmy mogli sprawdzić, czy zachowaliśmy porządkowanie standardowego standardowego standardu pomimo oznaczenia standardowego standardu 2): może gnu ogon, ale nie zwykły ogon (np. na aix.). 3): grep „^” pokazuje także obie nazwy plików. 4): można to zmienić za pomocą zmiennej. 5): zwinięty przykład działa na starych osesach (np. Stary aix), gdzie go przetestowałem (brak dostępnego perla).uniquetag="banaNa11F453355B28E1158D4E516A2D3EDF96B3450406
...)Jeśli kolejność danych wyjściowych musi być: stdout, to stderr ; nie ma rozwiązania tylko z przekierowaniem.
Stderr musi być zapisany w pliku tymczasowym
Opis:
Jedynym sposobem przekierowania jednego wyjścia (fd takiego jak stdout lub stderr) do dwóch plików jest odtworzenie go. Polecenie
tee
jest właściwym narzędziem do odtwarzania zawartości deskryptora pliku. Tak więc początkowym pomysłem posiadania jednego wyjścia na dwóch plikach byłoby użycie:To odtwarza standardowe wejście tee do obu plików (1 i 2), pozostawiając wyjście tee wciąż nieużywane. Ale musimy dołączyć (użyć
-a
) i potrzebujemy tylko jednej kopii. To rozwiązuje oba problemy:Aby dostarczyć
tee
stdout (ten do powtórzenia), musimy użyć stderr bezpośrednio z komendy. Jednym ze sposobów, jeśli kolejność nie jest ważna (kolejność wyjścia zostanie (najprawdopodobniej) zachowana w stanie wygenerowanym, w zależności od tego, co nastąpi jako pierwsze, zostanie zapisane najpierw). Zarówno:cmd 2>>file1 | tee -a file2 >>file1
cmd 2>>file1 > >( tee -a file2 >>file1 )
( cmd | tee -a file2 ) >> file1 2>&1
Opcja 2 działa tylko w niektórych powłokach. Opcja 3 korzysta z dodatkowej podpowłoki (wolniej), ale nazwy plików należy używać tylko raz.
Ale jeśli stdout musi być pierwszy (cokolwiek zostanie wygenerowane wyjście zamówienia), musimy zapisać stderr, aby dołączyć go do pliku na końcu (pierwsze opublikowane rozwiązanie).
źródło
sponge
:(cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err
W interesie różnorodności:
Jeśli twój system obsługuje
/dev/stderr
, tobędzie działać. Standardowe wyjście
cmd
jest wysyłane zarówno do standardowego, jak i standardowego potoku. Standardowy błądcmd
omijatee
i wychodzi ze stderr rurociągu.Więc
cmd
icmd
zmieszanego.W takim razie wystarczy wysłać te strumienie do odpowiednich plików.
Jak w przypadku prawie każdego takiego podejścia (w tym odpowiedzi Stéphane'a ),
file1
linie mogą być nieczynne.źródło