Czy można przekierować gdzieś wszystkie wyniki skryptu powłoki Bourne'a, ale za pomocą poleceń powłoki w samym skrypcie?
Przekierowanie wyjścia pojedynczego polecenia jest łatwe, ale chcę czegoś takiego:
#!/bin/sh
if [ ! -t 0 ]; then
# redirect all of my output to a file here
fi
# rest of script...
Znaczenie: jeśli skrypt jest uruchamiany nieinteraktywnie (na przykład cron), zapisz dane wyjściowe wszystkiego do pliku. Jeśli uruchamiany jest interaktywnie z powłoki, pozwól, aby wyjście przechodziło na standardowe wyjście jak zwykle.
Chcę to zrobić dla skryptu normalnie uruchamianego przez okresowe narzędzie FreeBSD. Jest to część codziennego biegu, którego zwykle nie obchodzi mnie codziennie w wiadomości e-mail, więc nie wysyłam go. Jeśli jednak coś w tym konkretnym skrypcie zawiedzie, jest to dla mnie ważne i chciałbym móc przechwytywać i wysyłać pocztą e-mail wyniki tej części codziennych zadań.
Aktualizacja: odpowiedź Jozuego jest natychmiastowa, ale chciałem również zapisać i przywrócić stdout i stderr dookoła całego skryptu, co odbywa się w następujący sposób:
# save stdout and stderr to file descriptors 3 and 4, then redirect them to "foo"
exec 3>&1 4>&2 >foo 2>&1
# ...
# restore stdout and stderr
exec 1>&3 2>&4
exec 1>&3 2>&4 3>&- 4>&-
Odpowiedzi:
Odpowiedź na pytanie w formie zaktualizowanej.
Nawiasy klamrowe „{...}” zapewniają jednostkę przekierowania we / wy. Nawiasy klamrowe muszą pojawiać się tam, gdzie może pojawić się polecenie - w uproszczeniu, na początku linii lub po średniku. ( Tak, można to sprecyzować; jeśli chcesz się spierać, daj mi znać. )
Masz rację, że możesz zachować oryginalny stdout i stderr z pokazanymi przekierowaniami, ale zwykle ludzie, którzy muszą później utrzymać skrypt, łatwiej zrozumieć, co się dzieje, jeśli zakodujesz przekierowany kod, jak pokazano powyżej.
Odpowiednie sekcje podręcznika Bash to polecenia grupujące i przekierowanie we / wy . Odpowiednie odcinki opisie powłoki POSIX są Compound poleceń i I / O przekierowania . Bash ma kilka dodatkowych notacji, ale poza tym jest podobny do specyfikacji powłoki POSIX.
źródło
>>
. Niektórzy ludzie mają nawyk>
. Dołączanie jest zawsze bezpieczniejsze i bardziej zalecane niż przytłaczanie. Ktoś napisał aplikację, która używa standardowego polecenia kopiowania, aby wyeksportować niektóre dane do tego samego miejsca docelowego.Zazwyczaj umieszczamy jeden z nich na górze skryptu lub w jego pobliżu. Skrypty, które analizują wiersze poleceń, dokonają przekierowania po analizie.
Wyślij stdout do pliku
z stderr
dołącz do pliku zarówno stdout, jak i stderr
Jak wspomniał Jonathan Leffler w swoim komentarzu :
exec
ma dwie osobne prace. Pierwszym z nich jest zastąpienie aktualnie wykonywanej powłoki (skryptu) nowym programem. Drugi polega na zmianie przekierowań we / wy w bieżącej powłoce. Wyróżnia się to brakiem argumentuexec
.źródło
exec
ma dwa osobne zadania. Jednym z nich jest zastąpienie bieżącego skryptu innym poleceniem, przy użyciu tego samego procesu - określasz drugie polecenie jako argumentexec
(i możesz dostosowywać przekierowania we / wy podczas tej operacji ). Drugim zadaniem jest zmiana przekierowań we / wy w bieżącym skrypcie powłoki bez zastępowania go. Notacja ta wyróżnia się tym, że nie ma polecenia jako argumentuexec
. Zapis w tej odpowiedzi dotyczy wariantu „Tylko we / wy” - zmienia tylko przekierowanie i nie zastępuje uruchomionego skryptu. (set
Polecenie jest podobnie wielofunkcyjne).exec > >(tee -a "logs/logdata.log") 2>&1
drukuje dzienniki na ekranie, a także zapisuje je w plikuMożesz ustawić cały skrypt w taki sposób:
następnie na końcu skryptu:
Alternatywnie możesz zalogować wszystko do pliku dziennika przy każdym uruchomieniu i nadal wyprowadzać go na standardowe wyjście, po prostu wykonując:
źródło
Aby zapisać oryginalny stdout i stderr, możesz użyć:
Na przykład poniższy kod wypisze „walla1” i „walla2” do pliku dziennika (
a.txt
), „walla3” na standardowe wyjście, „walla4” na standardowe wyjście.źródło
exec 5>&1
iexec 6>&2
, używając notacji przekierowania wyjścia, niż notacji przekierowania wejścia dla wyjść. Unikasz tego, ponieważ kiedy skrypt jest uruchamiany z terminala, standardowe dane wejściowe są również zapisywalne, a zarówno standardowe dane wyjściowe, jak i standardowy błąd są czytelne na podstawie (czy też „wice”?) Historycznego dziwactwa: terminal jest otwarty dla odczyt i zapis oraz ten sam opis otwartego pliku jest używany dla wszystkich trzech standardowych deskryptorów plików we / wy.źródło