Jak przekierować i dołączyć stdout i stderr do pliku za pomocą Bash?


1533

Aby przekierować standardowe wyjście do obciętego pliku w Bash, wiem, że używam:

cmd > file.txt

Aby przekierować standardowe wyjście w Bash, dołączając do pliku, wiem, że używam:

cmd >> file.txt

Aby przekierować zarówno stdout, jak i stderr do pliku obciętego, wiem, że używam:

cmd &> file.txt

Jak przekierować dołączanie stdout i stderr do pliku? cmd &>> file.txtnie działało dla mnie.


37
Chciałbym zauważyć, że &> outfile jest specyficznym kodem Bash (i innymi) i nie jest przenośny. Droga do przenośności (podobna do dołączanych odpowiedzi) zawsze była i nadal jest> outfile 2> & 1
— TheBonsai

Odpowiedzi:


1996
cmd >>file.txt 2>&1

Bash wykonuje przekierowania od lewej do prawej w następujący sposób:

  1. >>file.txt: Otwórz file.txtw trybie dołączania i przekieruj stdouttam.
  2. 2>&1: Przekieruj stderrdo „dokąd stdoutobecnie zmierza” . W tym przypadku jest to plik otwarty w trybie dołączania. Innymi słowy, &1ponownie wykorzystuje deskryptor pliku, który jest stdoutobecnie używany.

33
działa świetnie! ale czy istnieje sposób, aby to zrozumieć, czy powinienem traktować to jak atomowy konstrukt?
— flybywire

181
To proste przekierowanie, instrukcje przekierowania są oceniane, jak zawsze, od lewej do prawej. >> plik: czerwony. STDOUT do pliku (tryb dołączania) (skrót od 1 >> plik) 2> i 1: Czerwony. STDERR na „gdzie odchodzi stdout”. Zwróć uwagę, że interpretacja „przekierowuje STDERR na STDOUT” jest nieprawidłowa.
— TheBonsai

31
Mówi „dołącz wyjście (stdout, deskryptor pliku 1) do pliku.txt i wyślij stderr (deskryptor pliku 2) w to samo miejsce co fd1”.
— Wstrzymano do odwołania.

2
@TheBonsai jednak co, jeśli muszę przekierować STDERR do innego pliku, ale dołączam? czy to możliwe?
— arod

41
jeśli to zrobisz cmd >>file1 2>>file2, powinieneś osiągnąć to, co chcesz.
— Woodrow Douglass,

367

Można to zrobić na dwa sposoby, w zależności od wersji Bash.

Klasyczny i przenośny ( Bash pre-4 ) sposób to:

cmd >> outfile 2>&1

Nieprzenośnej sposób, wychodząc z Bash 4 jest

cmd &>> outfile

(analogowy do &> outfile)

Aby uzyskać dobry styl kodowania, powinieneś

  • zdecyduj, czy przenośność jest problemem (użyj klasycznego sposobu)
  • zdecyduj, czy przenośność nawet na Bash wcześniejszą niż 4 stanowi problem (użyj klasycznego sposobu)
  • bez względu na to, jakiej składni używasz, nie zmieniaj jej w tym samym skrypcie (zamieszanie!)

Jeśli skrypt zaczyna się już od #!/bin/sh(bez względu na to, czy jest to zamierzone czy nie), to rozwiązanie Bash 4 i ogólnie dowolny kod specyficzny dla Bash nie jest dobrym rozwiązaniem.

Pamiętaj też, że Bash 4 &>>jest po prostu krótszą składnią - nie wprowadza żadnych nowych funkcji ani nic podobnego.

Składnia jest (oprócz innej składni przekierowania) opisana tutaj: http://bash-hackers.org/wiki/doku.php/syntax/redirection#appending_redirected_output_and_error_output


8
Wolę & >>, ponieważ jest to zgodne z &> i >>. Łatwiej jest również przeczytać „dołącz dane wyjściowe i błędy do tego pliku” niż „wyślij błędy do danych wyjściowych, dołącz dane wyjściowe do tego pliku”. Uwaga, podczas gdy Linux zazwyczaj ma aktualną wersję bash, OS X, w momencie pisania, wciąż wymaga bash 4 do ręcznej instalacji przez homebrew itp.
— mikemaccana

Bardziej mi się podoba, ponieważ jest krótszy i zawiera tylko dwa miejsca na linię, więc co na przykład zrobiłby zsh z „& >>”?
— Phillipp,

Należy również zauważyć, że w zadaniu cron musisz użyć składni sprzed 4, nawet jeśli twój system ma Bash 4.
— hyperknot

5
@zsero cron wcale nie używa bash ... używa sh. Możesz zmienić domyślną powłokę, dodając SHELL=/bin/bashdo crontab -epliku.
— Ray Foss,

89

W Bash możesz również jawnie określić swoje przekierowania do różnych plików:

cmd >log.out 2>log_error.out

Dołączanie będzie:

cmd >>log.out 2>>log_error.out

6
Przekierowanie dwóch strumieni do tego samego pliku przy użyciu pierwszej opcji spowoduje, że pierwszy z nich zapisze „na górze” drugiego, zastępując część lub całość zawartości. Zamiast tego użyj polecenia cmd >> log.out 2> log.out .
— Orestis P.,

3
Dzięki za złapanie tego; masz rację, jeden zatkarze drugi. Jednak twoje polecenie też nie działa. Myślę, że jedynym sposobem na zapisanie tego samego pliku jest to, co podano wcześniej cmd >log.out 2>&1. Edytuję swoją odpowiedź, aby usunąć pierwszy przykład.
— Aaron R.,

65

W Bash 4 (oraz ZSH 4.3.11):

cmd &>>outfile

po wyjęciu z pudełka


2
@ all: to dobra odpowiedź, ponieważ działa z bash i jest krótka, więc edytowałem, aby upewnić się, że wyraźnie wspomina o bash.
— mikemaccana

10
@mikemaccana: Odpowiedź TheBonsai pokazuje rozwiązanie bash 4 od 2009 roku
— jfs

52

To powinno działać dobrze:

your_command 2>&1 | tee -a file.txt

Będzie przechowywać wszystkie dzienniki w pliku.txt, a także zrzucić je na terminal.


To poprawna odpowiedź, jeśli chcesz zobaczyć również wyjście w terminalu. Jednak nie było to pierwotnie zadawane pytanie.
— Mikko Rantalainen

25

Spróbuj tego

You_command 1>output.log  2>&1

Twoje użycie pliku &> x.file działa w bash4. Przepraszam za to : (

Oto kilka dodatkowych wskazówek.

0, 1, 2 ... 9 to deskryptory plików w bash.

0 oznacza stdin, 1 oznacza stdout, 2 oznacza stderror. 3 ~ 9 jest zapasowe na każde inne tymczasowe użycie.

Dowolny deskryptor pliku można przekierować do innego deskryptora lub pliku za pomocą operatora >lub >>(append).

Sposób użycia: < file_descriptor > > < nazwa_pliku | & file_descriptor >

Proszę odnieść się do http://www.tldp.org/LDP/abs/html/io-redirection.html


Twój przykład zrobi coś innego niż OP żądany: Przekieruje stderr You_commandna stdout i stdout You_commanddo pliku output.log. Dodatkowo nie zostanie dołączony do pliku, ale go zastąpi.
— pabouk

Prawidłowo: deskryptorem pliku mogą być dowolne wartości, które są większe niż 3 dla wszystkich innych plików.
— Itachi,

5
Twoja odpowiedź pokazuje najczęstszy błąd przekierowania wyjścia: przekierowanie STDERR do miejsca, w którym aktualnie wskazuje STDOUT, i dopiero po przekierowaniu STDOUT do pliku. Nie spowoduje to przekierowania STDERR do tego samego pliku. Kolejność przekierowań ma znaczenie.
— Jan Wikholm

1
oznacza to, że najpierw powinienem przekierować STDERROR do STDOUT, a następnie przekierować STDOUT do pliku. 1 > output.log 2>&1
— Quintus.Zhou,

1
@ Quintus.Zhou Yup. Twoja wersja przekierowuje błąd do wyjścia, a jednocześnie do pliku.
— Alex Yaroshevich

11

Dziwi mnie, że od prawie dziesięciu lat nikt jeszcze nie opublikował takiego podejścia:

Jeśli używasz starszych wersji bash, gdzie &>>nie jest dostępna, możesz także:

(cmd 2>&1) >> file.txt

Ten ikra podpowłoce, więc jest mniej wydajny niż tradycyjne podejście cmd >> file.txt 2>&1, a co za tym idzie nie będzie działać dla poleceń, które trzeba zmodyfikować bieżącej powłoki (np cd, pushd), ale takie podejście wydaje się bardziej naturalne i zrozumiałe dla mnie jest:

  1. Przekieruj stderr na standardowe wyjście.
  2. Przekieruj nowy standard dołączając do pliku.

Ponadto nawiasy usuwają niejednoznaczność kolejności, szczególnie jeśli zamiast tego chcesz połączyć stdout i stderr z innym poleceniem.


Ta implementacja powoduje uruchomienie jednego dodatkowego procesu. Korzystanie ze składni cmd >> file 2>&1działa we wszystkich powłokach i nie wymaga dodatkowego procesu do uruchomienia.
— Mikko Rantalainen

@MikkoRantalainen Już wyjaśniłem, że odradza się podpowłoka i jest mniej wydajna. Istotą tego podejścia jest to, że jeśli wydajność nie jest wielką sprawą (a rzadko tak jest), łatwiej jest zapamiętać ten sposób i trudniej się pomylić.
— jamesdlin
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.