Mam plik bash, który muszę przekierować wszystkie dane wyjściowe do jednego pliku, dziennika debugowania, a także do terminala. Muszę przekierować stdout i stderr do debugowania i zarejestrować je dla wszystkich poleceń w skrypcie.
Nie chcę dodawać 2>&1 | tee -a $DEBUG
do każdego polecenia w pliku. Mógłbym z tym żyć | tee -a $DEBUG
.
Pamiętam, że był na to sposób z czymś takim exec 2>&1
.
Obecnie używam czegoś takiego:
#!/bin/bash
DEBUGLOG=/tmp/debug
exec 2>&1
somecommand | tee -a $DEBUGLOG
somecommand2 | tee -a $DEBUGLOG
somecommand3 | tee -a $DEBUGLOG
ale to nie działa. Czy ktoś ma rozwiązanie / może wyjaśnić przyczynę?
bash
io-redirection
Avi
źródło
źródło
|&
działa jako skrót2>&1 |
, jest co najmniej nieco wygodniejszy.Odpowiedzi:
Jeśli chodzi o rozwiązanie przekierowywania wielu poleceń jednocześnie:
Dlaczego oryginalne rozwiązanie nie działa: exec 2> i 1 przekieruje standardowe wyjście błędu na standardowe wyjście powłoki, która, jeśli uruchomisz skrypt z konsoli, będzie twoją konsolą. przekierowanie potoku dla poleceń przekieruje jedynie standardowe wyjście polecenia.
Z punktu widzenia
somecommand
standardowego wyjścia przechodzi do podłączonego potoku,tee
a standardowy błąd trafia do tego samego pliku / pseudopliku, co standardowy błąd powłoki, który przekierowuje się do standardowego wyjścia powłoki, którym będzie konsoli, jeśli uruchamiasz program z konsoli.Jedynym prawdziwym sposobem na wyjaśnienie tego jest zobaczenie, co się naprawdę dzieje:
Oryginalne środowisko twojej powłoki może wyglądać tak, jeśli uruchomisz ją z terminala:
Po przekierowaniu standardowego błędu do standardowego wyjścia (
exec 2>&1
), ... zasadniczo nic nie zmieniasz. Ale jeśli przekierujesz standardowe wyjście skryptu do pliku, uzyskasz takie środowisko:Następnie przekierowanie standardowego błędu powłoki na standardowe wyjście skończyłoby się tak:
Uruchomienie polecenia odziedziczy to środowisko. Jeśli uruchomisz polecenie i potokujesz je do tee, środowisko polecenia to:
Zatem standardowy błąd polecenia nadal dotyczy tego, co powłoka używa jako standardowego błędu.
Środowisko polecenia można zobaczyć, patrząc
/proc/[pid]/fd
: użyj,ls -l
aby wyświetlić także zawartość dowiązania symbolicznego.0
Plik tutaj jest standardowe wejście,1
to standardowe wyjście i2
jest błąd standardowy. Jeśli polecenie otworzy więcej plików (a większość programów tak robi), zobaczysz je również. Program może również wybrać przekierowanie lub zamknięcie swojego standardowego wejścia / wyjścia i ponowne użycie0
,1
oraz2
.źródło
Możesz użyć exec w następujący sposób na górze skryptu:
Na przykład:
Daje mi dane wyjściowe do pliku
$HOME/somefile.log
i terminala w następujący sposób:źródło
/bin/sh
skryptach (wiele osób błędnie używa składni bash w/bin/sh
skryptach)./dev/fd/62: Operation not supported
jakieś wskazówki?myscript
i uruchamiam./myscript > /dev/null
, nadal powinienem zobaczyć,bye
który pochodziecho bye >&2
.Zapisz stderr i stdout do pliku, wyświetl stderr na ekranie (na stdout)
Przydatne w przypadku cronów, dzięki czemu możesz otrzymywać błędy (i tylko błędy) pocztą
źródło