Rejestrowanie danych wyjściowych demona za pomocą Upstart

34

Mam niestandardowego demona zarządzanego przez upstart na moim serwerze Ubuntu. Działa idealnie, z wyjątkiem tego, że muszę przechwycić (zalogować) dane wyjściowe demona. Strona oficjalna strofy mówi, że mogę używać console logged, aby to zrobić, ale co to plik dziennika?

Przeczytałem również, że nieconsole logged jest to już ważna zwrotka . Obecnie używam 0.3.9 (Hardy), ale za kilka miesięcy zaktualizuję do 0.6.x (Lucid). Jeśli console loggedw rzeczywistości nie będzie działać z późniejszymi wersjami, czego użyć zamiast tego?

Alex Reisner
źródło
1
Czy możesz po prostu zaktualizować niestandardowego demona, aby wysyłał dane wyjściowe do syslog lub do pliku dziennika określonego w pliku konfiguracyjnym demona?
Zoredache

Odpowiedzi:

35

Ten fragment kodu potokuje dane wyjściowe usługi do programu rejestrującego, jednocześnie umożliwiając wykonanie procesu usługi (zastępując w ten sposób proces powłoki), aby upstart nie pomylił się. Dba również o to, aby proces rejestrowania był ponownie wyświetlany dla init, więc nie jest to potomek twojej usługi i pozwala uniknąć pozostawiania cruft w systemie plików, nawet jeśli trzeba tymczasowo utworzyć fifo.

script
  mkfifo /tmp/myservice-log-fifo
  ( logger -t myservice </tmp/myservice-log-fifo & )
  exec >/tmp/myservice-log-fifo
  rm /tmp/myservice-log-fifo
  exec myservice 2>/dev/null
end script

Oto jak to działa:

  1. mkfifo /tmp/myservice-log-fifopo prostu tworzy specjalny plik fifo (aka o nazwie potok). Wpisz man 7 fifowięcej informacji.
  2. ( logger ... </tmp/myservice-log-fifo & ) rozpoczyna odczyt rejestratora z fifo, w tle. Pareny powodują, że proces rejestrujący zostaje ponownie rozpoznany jako init, a nie pozostaje potomkiem bieżącego procesu powłoki.
  3. exec >/tmp/myservice-log-fifoprzekierowuje standardowe wyjście powłoki do fifo. Teraz mamy otwarty deskryptor pliku dla tego fifo i tak naprawdę nie potrzebujemy już wpisu systemu plików ...
  4. rm /tmp/myservice-log-fifo więc go usuniemy.
  5. exec myservice 2>/dev/nullpo prostu uruchamia usługę w zwykły sposób. Stdout już jedzie do FIFO, a to się nie zmieni, gdy nowy program się uruchomi.

AKTUALIZACJA: set -e nie jest potrzebna, ponieważ Upstart domyślnie uruchamia skrypty z tą opcją (patrz http://upstart.ubuntu.com/cookbook/#develop-scripts-using-bin-sh )

Keith Rarick
źródło
świetna odpowiedź i nie pozostawia nigdzie plików fifo.
Ash Berlin-Taylor
Co to jest set -e?
Peter Mounce
1
set -eWywołuje skrypt natychmiast opuścić jeśli komenda nie powiedzie się. Bez tej linii skrypt kontynuowałby uruchamianie kolejnych poleceń bezużytecznie (i prawdopodobnie niebezpiecznie).
Keith Rarick
1
Aby zalogować stderr i stdout, dodaj linię exec 2>&1powyżej rmlinii i usuń ją 2>/dev/nullz ostatniej linii.
itsadok
31

W przypadku najnowszych wersji Ubuntu (12.04+) po prostu użyj

console log

A wyjście demona (STDOUT & STDERR) zostanie dołączone do /var/log/upstart/<service>.log

http://upstart.ubuntu.com/cookbook/#console-log

Willem
źródło
2
Byłoby to czyste i miłe, ale niestety nie działa na CentOS 6.x, który wciąż zawiera starą wersję upstart, która tego nie obsługuje.
Cristian Măgherușan-Stanciu
11

Jeśli korzystasz z console output pokoju , a następnie rurę wyjściową do skryptu logger(interfejs poleceń powłoki do syslog (moduł dziennika System 3)), a następnie, że praca będzie.

Na przykład

console output
exec /my/script | logger

zaloguje się do /var/log/messages

Na przykład

console output
exec /my/script | logger -t my-script

zaloguje się /var/log/messagesi otaguje każdą wiadomośćmy-script

logger --help dla opcji użycia rejestratora.

(Jestem na Amazon Linux AMI, który jest oparty na Centos 5.x; YMMV)

Peter Mounce
źródło
4
Okazuje się, że to nie jest dobre rozwiązanie. upstart zatrzaskuje się na PID logger, a nie w procesie, którym faktycznie chcesz zarządzać.
Peter Mounce
10

Nie udało mi się mkfifopodstępem pracować zadowalająco; Wygląda na to, że nie przechwycił stderr, a próby przekierowania spowodowały, że Upstart zwolnił za kaucją bez błędów.

Ma również niefortunny efekt uboczny, sprawiając, że loggerproces zostaje zawieszony jako dziecko init, więc informacja o tym, kto „jest właścicielem” programu rejestrującego, zostaje utracona, a każdy, kto nie jest świadomy tego, mkfifomoże założyć, że jest to ryzykowny proces, który można zabić.

Zamiast tego otrzymałem następujące rozwiązanie, które rozwiązuje wszystkie te problemy. Powoduje, logger że staje się procesem potomnym, zachowując usługę jako proces root. Niestety wymaga wykonania bash, ale po prostu wygląda na brudne.

script
  # ... setup commands here, e.g. environment, cd, ...
  exec bash <<EOT
    exec 1> >(logger -t myservice) 2>&1
    exec myservice
EOT
end script

Wykorzystuje sztuczkę, która przekierowuje stdout i stderr do polecenia. Ponieważ wykonujemy usługę wewnątrz bashpolecenia, ma to efekt uboczny polegający na zastąpieniu powłoki i magicznym uczynieniu basha procesem potomnym usługi, jak pokazano ps aufxw:

myservice 
 \_ bash -c exec 1> >(logger -t myservice) 2>&1 && exec myservice
    \_ logger -t myservice

Z jakiegoś powodu powyższe polecenie musi być spakowane w bash -c. Zakładam, że dzieje się tak, ponieważ Upstart udaje, że uruchamia twój skrypt przez Bash, ale tak naprawdę nie jest. Jeśli ktoś może zasugerować sposób na uniknięcie dodatkowej powłoki bash, byłoby to niesamowite.

Alexander Staubo
źródło
1
Tak! Tak się cieszę, że to znalazłem. Wygląda lepiej niż wariant mkfifo iw moim przypadku nie musiałem tracić exec bash -l << EOF.
thom_nic
6

To brzydkie, ale jak dotąd najlepsze, jakie znalazłem

exec / path / to / server >> /tmp/upstart.log 2> & 1

Jorge Vargas
źródło
2
Rozwiązanie nie jest dobre, jeśli chodzi o rotację dziennika, ponieważ aplikacja loguje się bezpośrednio do pliku. Logowanie przez syslog pozwala uniknąć powiązanych problemów.
Mark Stosberg
3

Możesz także przekierować dane wyjściowe do syslog, np

exec $SERVER 2>&1 | logger -t myservice -p local0.info

Jednak potok może spowodować, że upstart pomyli PID procesu rejestrowania z PID demona.

Nikratio
źródło
Demon mylący PID jest w rzeczywistości bezużytecznym demonem, ponieważ powinien obserwować proces, a następnie go odrodzić. Masz pomysł, jak upewnić się, że oglądany jest odpowiedni PID?
Johann Philipp Strathausen,
Myślę (ale nie próbowałem), że będziesz chciał expect forklub expect daemonzwrotkę. Albo możesz catumieścić plik pid w komunikacie dziennika inaczej, tak myślę.
Peter Mounce
1

Inną alternatywą jest użycie trójnika, takiego jak:

exec $SERVER 2>&1 | tee /dev/stderr | logger -t myservice

aby uzyskać zarówno plik początkowy, jak i dane wyjściowe syslog

perl
źródło