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.