Jak mogę w pełni zalogować wszystkie działania skryptów bash?

44

Chcę przechwycić WSZYSTKIE dane z dzienników, zarówno z komunikatami o błędach, z danych wyjściowych skryptu i przekierować je wszystkie do pliku dziennika.

Mam skrypt jak poniżej:

#!/bin/bash
(
echo " `date` : part 1 - start "
ssh -f admin@server.com 'bash /www/htdocs/server.com/scripts/part1.sh logout exit'
echo " `date` : sleep 120"
sleep 120
echo " `date` : part 2 - start"
ssh admin@server.com 'bash /www/htdocs/server.com/scripts/part2.sh logout exit'
echo " `date` : part 3 - start"
ssh admin@server.com 'bash /www/htdocs/server.com/scripts/part3.sh logout exit'
echo " `date` : END"
) | tee -a /home/scripts/cron/logs

Chcę zobaczyć wszystkie działania w pliku /home/scripts/cron/logs

Ale widzę tylko to, co wstawiłem po poleceniu echa.

Jak sprawdzić w dziennikach, czy polecenie SSH zakończyło się pomyślnie?

Muszę zebrać wszystkie dane z dzienników. Potrzebuję tego, aby monitorować wynik każdego polecenia w moim skrypcie, aby lepiej analizować, co się dzieje, gdy skrypt nie działa.

BlueMark
źródło
Aby to zrobić, możesz również użyć „skryptu”. Zobacz ten post: [tutaj] [1] [1]: stackoverflow.com/questions/5985060/…
xX0v0Xx
musisz być ostrożny z errexit - zauważyłem, że jest ignorowany lub błąd nie wychodzi ze skryptu np. jeśli masz coś takiego w skrypcie: polecenie || dosmthg gdy komenda nie skrypt nie wyjść natychmiast z zestawem errexit ale wystarczy uruchomić dosmthg i kontynuuje skryptu

Odpowiedzi:

67

Ogólnie na początku każdego skryptu umieszczam coś podobnego do następującego (zwłaszcza jeśli będzie działał jako demon):

#!/bin/bash
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>log.out 2>&1
# Everything below will go to the file 'log.out':

Wyjaśnienie:

  1. exec 3>&1 4>&2

    Zapisuje deskryptory plików, aby można je było przywrócić do tego, czym były przed przekierowaniem, lub wykorzystać je do wyprowadzenia tego, co było przed następnym przekierowaniem.

  2. trap 'exec 2>&4 1>&3' 0 1 2 3

    Przywróć deskryptory plików dla określonych sygnałów. Nie jest to na ogół konieczne, ponieważ należy je przywrócić po wyjściu podpowłoki.

  3. exec 1>log.out 2>&1

    Przekieruj stdoutdo pliku, log.outa następnie przekieruj stderrdo stdout. Pamiętaj, że kolejność jest ważna, gdy chcesz, aby trafiły do ​​tego samego pliku. stdout musi zostać przekierowany, zanim stderrzostanie przekierowany do stdout.

Odtąd, aby zobaczyć dane wyjściowe na konsoli (być może), możesz po prostu przekierować na &3. Na przykład,

echo "$(date) : part 1 - start" >&3

pójdzie tam, gdzie stdoutzostał skierowany, prawdopodobnie na konsolę, przed wykonaniem linii 3 powyżej.

nicerobot
źródło
<< niceroot, dzięki! Dodałem te trzy linie (exec, trap, exec) na początku skryptu i jestem w stanie uzyskać zarówno stdout, jak i stderr. Ale jeden problem: widziałem „Wyciekły deskryptor pliku 3 (potok: XXX) na komendę some_” ... Daj mi znać, jak mogę uniknąć tych błędów. Używam sh w oparciu o busybox w niestandardowej płycie.
kumar
3
Świetne KungFu tutaj !!! - Jeszcze lepiej jest używać trap 'exec 2>&4 1>&3' 0 1 2 3 RETURN. Pseudo sigspec RETURN deskryptory plików przywracają za każdym razem, gdy funkcja powłoki lub skrypt są wykonywane przy pomocy. lub wbudowane źródła kończą wykonywanie. Z tego (i innych powodów) w moich skryptach dodaję jako ostatnie 2 wiersze: return& exit 0- Tylko moje 2 centy, wyrazy uznania dla ciebie @nicerobot!
DavAlPi
Istnieje wiele szczegółowych informacji na temat rejestrowania skryptów powłoki za pomocą globalnych zmiennych powłoki. Możemy emulować podobny rodzaj logowania w skrypcie powłoki: cubicrace.com/2016/03/efficient-logging-mechnism-in-shell.html Post zawiera szczegółowe informacje na temat wprowadzania poziomów dziennika, takich jak INFO, DEBUG, BŁĄD. Szczegóły śledzenia, takie jak wpis skryptu, wyjście skryptu, wejście funkcji, wyjście funkcji.
Piyush Chordia
Wyliczenie trapsygnałów wygląda nieco dziwnie. Zwykle też chcesz to uwzględnić 15.
tripleee
14

aby uzyskać wyjście ssh do twojego pliku dziennika, musisz przekierować stderrna stdout. możesz to zrobić, dołączając 2>&1po skrypcie bash.

To powinno wyglądać tak:

#!/bin/bash
(
...
) 2>&1 | tee ...

gdy to nie wyświetla wiadomości w odpowiedniej kolejności, spróbuj dodać kolejną podpowłokę:

#!/bin/bash
((
...
) 2>&1) | tee ...
chrześcijanin
źródło
1
To działa świetnie. W rzeczywistości możesz reżyserować stdout i stderr za pomocą:( ... ) |& tee output.log
Noam Manos
13

Kiedy czytam twoje pytanie, nie chcesz rejestrować danych wyjściowych, ale cała sekwencja poleceń, w którym to przypadku inne odpowiedzi ci nie pomogą.

Wywołaj skrypty powłoki z opcją -x, aby wyświetlić wszystko:

sh -x foo.sh

Zaloguj się do pliku, który chcesz:

sh -x foo.sh >> /home/scripts/cron/logs

Alex Holst
źródło
2
+1 za opcję -x
Coc
10

W bash możesz umieścić, set -xa następnie wydrukuje każde wykonane polecenie (i zmienne bash). Możesz to wyłączyć za pomocą set +x.

Jeśli chcesz być paranoikiem, możesz wpisać set -o errexitswój skrypt. Oznacza to, że skrypt zawiedzie i zatrzyma się, jeśli jedno polecenie zwróci niezerowy kod wyjścia, co jest standardowym sposobem uniksowym sygnalizującym, że coś poszło nie tak.

Jeśli chcesz uzyskać ładniejszy dzienników, należy spojrzeć tsw moreutilspakiecie debian / ubuntu. Poprzedzi każdą linię znacznikiem czasu i wydrukuje ją. Możesz więc zobaczyć, kiedy coś się działo.

Rory
źródło
1
„set -o errexit” musi być tym samym, co „set -e”
Ajith Antony
0

Zgodnie z tym, co powiedzieli inni, zestaw instrukcji jest dobrym źródłem. Włożyłem:

#!/usr/bin/env bash
exec 1> command.log 2>&1
set -x

Na górze skryptów chcę kontynuować, lub set -exjeśli powinien zakończyć się po błędzie.

dragon951
źródło
Jak to pomoże dziennikom ssh i pomyślnemu wykonaniu polecenia?
asktyagi
Testując za pomocą fałszywego skryptu OP, rejestruje każde polecenie i bez względu na wynik: limit czasu ssh, niepoprawna domena itp. Lub dla prawidłowego adresu ssh zapisuje polecenia w zdalnej powłoce. Jeśli potrzebujesz więcej informacji na temat logowania ssh ssh -vv?
dragon951