jak przekierować dane wyjściowe do wielu plików dziennika

52

Jak przekierować standardowe wyjście do wielu plików dziennika? Następujące nie działa:

some_command 1> output_log_1 output_log_2 2>&1
dubler
źródło
6
Dzięki zshmożesz użyć some_command >output_log_1 >output_log_2.
jofel

Odpowiedzi:

70

Zobacz man tee:

NAZWA: tee - odczyt ze standardowego wejścia i zapis do standardowego wyjścia i plików

SKŁADNIA: tee [OPCJA] ... [PLIK] ...

Odpowiednio:

echo test | tee file1 file2 file3
akond
źródło
czy można przekierować stderr w więcej niż jednym pliku?
fromnaboo
Tak, można tego dokonać poprzez przekierowanie: znajdź / nazwa testu 2> i 1 | tee plik1 plik2 plik3
Akond
@akond, cmd 2>&1 | tee log1 log2 próbowałem wykonać jak wyżej, ale muszę nacisnąć ctrl-c, aby przekierować go do drugiego pliku dziennika. również wyjście jest drukowane na konsoli. Chcę, aby dane wyjściowe polecenia były przekierowywane do dzienników, ale nie do konsoli. każda pomoc jest doceniana.
doubleledecker
@doubledecker teePolecenie zapisuje stdindo pliku (ów), a także do stdout. Jeśli nie chcesz, aby dane wyjściowe pojawiały się na terminalu, musisz przekierować do tego, /dev/nullco zwykle.
Minix,
4
Możliwe jest również dołączanie do wielu plików:echo test | tee --append file1 file2
user1364368
13

Załóżmy, że dane wyjściowe są generowane z funkcji cmd():

cmd() {
    echo hello world!
}

Aby przekierować wyjście z cmddwóch plików, ale nie do konsoli, możesz użyć:

cmd | tee file1 file2 >/dev/null

Będzie to działać dla wielu plików, biorąc pod uwagę wszelkie źródła danych przesyłane do tee:

echo "foobarbaz" | tee file1 file2 file3 file4 > /dev/null

Będzie to również działać:

echo $(cmd) | tee file1 file2 >/dev/null

Bez /dev/nullprzekierowania tee wyśle ​​wyjście na standardowe wyjście oprócz podanych plików.

Na przykład, jeśli uruchomisz to z konsoli, zobaczysz tam wyjście. Uruchom z crontab, na wyjściu pojawi się komunikat o stanie, który zostanie wysłany do Ciebie (patrz również odpowiedź Gillesa tutaj https://unix.stackexchange.com/a/100833/3998 ).

To działało dla mnie w bash na Ubuntu 12.04 i zostało zweryfikowane w Ubuntu 14.04 przy użyciu GNU bash 4.3.11 (1), więc powinno działać na każdej najnowszej wersji bash GNU.

KP MacGregor
źródło
@doubledecker - wygląda na to, że spełnia twoje warunki, więc może zostać zaakceptowany jako odpowiedź. Również +1, gdy testowałem to pod GNU bash ( version 4.3.11(1)-release (i686-pc-linux-gnu)) w Ubuntu 14.04.
belacqua
9

To stary post, ale właśnie go znalazłem ...

Zamiast przekierowywać dane wyjściowe > /dev/null, możesz przekierować je do ostatniego pliku:

echo "foobarbaz" | tee file1 > file2

Lub do dołączenia wyniku:

echo "foobarbaz" | tee -a file1 >> file2
James gotuje
źródło
to mniej więcej to, co powiedziała inna odpowiedź (z wyjątkiem -a tee)
Archemar
To jest odpowiednie rozwiązanie.
71GA
5

Jak @jofel wspomniał w komentarzu pod odpowiedzią, można to zrobić natywnie w zsh:

echo foobar >file1 >file2 >file3

lub z rozszerzeniem nawiasu klamrowego:

echo foobar >file{1..3}

Wewnętrznie działa to bardzo podobnie do teeodpowiedzi podanych powyżej. Powłoka łączy stdout polecenia z procesem, który potokuje do wielu plików; w związku z tym, nie ma żadnych istotnych zaletą techniczną robi to w ten sposób (ale to ma wyglądać naprawdę dobrze). Więcej informacji znajdziesz w zshinstrukcji obsługi .

strugee
źródło
2

Nie można jednak skomentować innego sposobu wyrażenia

echo "foobarbaz" | tee file1 file2 file3 file4 file5 file6 file7 file8 > /dev/null

Można to uprościć w przypadku wielu plików.

echo "foobarbaz" | tee file{1..8} > /dev/null
użytkownik149146
źródło
2
Czym to się naprawdę różni od innych już udzielonych odpowiedzi? Zwłaszcza, że kilka osób może chcieć dosłowne file1przez file8co ich nazwami i są to prawdopodobnie tylko przykładowe zastępcze dla nazw plików
Eric Renouf
1
Prawdopodobnie lub nie, to jest dokładnie to rozwiązanie, którego potrzebowałem i pomyślałem, że może pomóc komuś innemu.
user149146