Jak upewnić się, że aplikacja działa w systemie Linux

83

Próbuję upewnić się, że skrypt nadal działa na serwerze deweloperskim. Zestawia statystyki i udostępnia usługę sieciową, więc ma trwać, ale kilka razy dziennie umiera z nieznanych powodów. Kiedy zauważymy, po prostu uruchamiamy go ponownie, ale jest to ból z tyłu, a niektórzy użytkownicy nie mają pozwolenia (lub know-how), aby go uruchomić.

Programista we mnie chce poświęcić kilka godzin na zgłębienie problemu, ale zapracowana osoba we mnie uważa, że ​​musi istnieć łatwy sposób na wykrycie, czy aplikacja nie działa, i ponowne jej uruchomienie.

Wiem, że mogłyby cron-skryptu ps przez grep:

ps -A | grep appname

Ale znowu, to kolejna godzina mojego życia zmarnowana na zrobienie czegoś, co już musi istnieć ... Czy nie ma gotowej aplikacji, do której mogę przekazać plik wykonywalny (opcjonalnie z argumentami) i która będzie utrzymywać proces w nieskończoność?

Na wypadek, gdyby miało to jakiekolwiek znaczenie, jest to Ubuntu.

Oli
źródło
1
Zależy to od tego, czy statystyki są tracone, gdy skrypt nie działa, ale myślę, że programista w tobie ma rację - powinieneś dowiedzieć się więcej o tym, dlaczego skrypt nie działa w nieskończoność.
Jonathan Leffler
1
Jest to bardziej narzędzie usługowe na żądanie niż coś, co nieustannie analizuje liczby. Jeśli ulegnie awarii przed zapisaniem danych, nic nie zostanie utracone; po prostu zakończy pracę przy następnym uruchomieniu.
Oli,
Pytanie zostało odebrane przy standardowym lub najlepszym sposobem na podtrzymanie procesu rozpoczętego przez skrypt init.d . Rozwiązania obejmują użycie systemd i /etc/inittab.
koppor

Odpowiedzi:

37

Uwaga: Upstart jest w trybie konserwacji i został porzucony przez Ubuntu, który używa systemd. Należy zajrzeć do podręcznika systemd, aby dowiedzieć się, jak pisać definicję usługi.

Ponieważ używasz Ubuntu, możesz być zainteresowany Upstart , który zastąpił tradycyjny init sysV . Jedną z kluczowych cech jest to, że może ponownie uruchomić usługę, jeśli nieoczekiwanie umrze. Fedora przeszła na początek, a Debian jest w fazie eksperymentalnej, więc warto się temu przyjrzeć.

Może to być jednak przesada w tej sytuacji, ponieważ implementacja skryptu cron zajmie 2 minuty.

#!/bin/bash
if [[ ! `pidof -s yourapp` ]]; then
    invoke-rc.d yourapp start
fi
JimB
źródło
Muszę zauważyć, że konfiguracja upstartu do zarządzania twoją usługą i utrzymania jej działania jest dość prosta (piszesz mały plik konfiguracyjny). To rozwiązanie jest znacznie czystsze, prostsze i lepsze niż jakikolwiek inny „prosty” monitoring oparty na skryptach cron / shell.
thor
@thor - (uwaga, to jest z 2008 roku, kiedy upstart był nowy, a dokumentacja była trudniejsza do zdobycia). Zgadzam się, „prosty” skrypt cron służył tylko do zilustrowania, że ​​skrypt nie musi być skomplikowany, aby wykonać to zadanie.
JimB,
Widzę. I tak zagłosowałem za Twoją odpowiedź, umieszczając mój komentarz
thor
86

Użyłem prostego skryptu z cronem, aby upewnić się, że program działa. Jeśli tak nie jest, uruchomi go. To może nie być idealne rozwiązanie, którego szukasz, ale jest proste i działa dość dobrze.

#!/bin/bash
#make-run.sh
#make sure a process is always running.

export DISPLAY=:0 #needed if you are running a simple gui app.

process=YourProcessName
makerun="/usr/bin/program"

if ps ax | grep -v grep | grep $process > /dev/null
then
    exit
else
    $makerun &
fi

exit

Następnie dodawaj zadanie crona co minutę lub co 5 minut.

Chris Wendt
źródło
2
To genialne. Przetrwa ponowne uruchomienie i nic do zainstalowania.
Ian Purton,
Użyłem tego osobiście, ponieważ instalacja nie wymaga uprawnień roota.
JohnMudd,
Co by process namesię stało, gdybym chciał, aby skrypt w Pythonie działał?
Użytkownik
@User Użyj, ps ax | grep XXXaby wyświetlić tylko swój proces, wtedy XXX będzie tym.
strongwillow
11
Jako jedna linijka crona, uruchamiaj raz na minutę:* * * * * ps aux|grep -v grep|grep -q YourProcessName || /usr/bin/program &
ACK_stoverflow,
43

Monit jest do tego idealny :)

Możesz napisać proste pliki konfiguracyjne, które każą monitowi obserwować np. Port TCP, plik PID itp

monit uruchomi polecenie, które podasz, gdy monitorowany przez niego proces jest niedostępny / zużywa zbyt dużo pamięci / zbyt długo wiąże procesor / etc. Pojawi się również powiadomienie e-mail z informacją o tym, co się stało i czy może coś z tym zrobić.

Używamy go, aby utrzymać działanie naszych witryn internetowych, jednocześnie dając nam wczesne ostrzeżenie, gdy coś jest nie tak.

- Twój wierny pracownik, Monit

Gareth
źródło
19
Jak utrzymujesz działanie Monit?
JohnMudd,
2
Ten jest dość trudny do nauczenia. Chcę tylko zrestartować skrypt (zamiast usługi) i czytałem jego dokumentację godzinami, ale nie mogłem tego rozgryźć.
Tyler Long
21

Jeśli używasz dystrybucji opartej na systemd, takiej jak Fedora i ostatnie wydania Ubuntu, możesz użyć funkcji „Restart” systemd dla usług. Może być skonfigurowany jako usługa systemowa lub jako usługa użytkownika, jeśli musi być zarządzany i uruchamiany jako konkretny użytkownik, co jest bardziej prawdopodobne w konkretnej sytuacji OP.

Opcja Restart trwa jeden no , on-success, on-failure, on-abnormal, on-watchdog, on-abort, lub always.

Aby uruchomić go jako użytkownik, po prostu umieść plik podobny do poniższego w ~/.config/systemd/user/something.service:

[Unit]
Description=Something

[Service]
ExecStart=/path/to/something
Restart=on-failure

[Install]
WantedBy=graphical.target

następnie:

systemctl --user daemon-reload
systemctl --user [status|start|stop|restart] something

Żadne uprawnienia roota / modyfikacja plików systemowych nie są potrzebne, żadne zadania cron nie są potrzebne, nic do zainstalowania, elastyczny jak diabli (zobacz wszystkie powiązane opcje usług w dokumentacji).

Zobacz także https://wiki.archlinux.org/index.php/Systemd/User, aby uzyskać więcej informacji na temat korzystania z instancji systemd na użytkownika.

Ramana
źródło
Świetna odpowiedź, ale ~ / .config / systemd / user / something.service było dla mnie trochę niejednoznaczne. Czy część „użytkownik” to dosłownie „użytkownik” czy na przykład „twoja nazwa użytkownika”? Jeśli jest to „twoja nazwa użytkownika”, wydaje mi się to zbyteczne, ponieważ tworzysz ten plik w swoim katalogu domowym. Edycja: wygląda na to, że to dosłownie „użytkownik”
fivedogit
8

Użyłem z crona "killall -0 nazwa programu || /etc/init.d/programname start". kill spowoduje błąd, jeśli proces nie istnieje. Jeśli istnieje, dostarczy zerowy sygnał do procesu (który jądro zignoruje i nie będzie zawracać sobie głowy przekazywaniem).

Ten idiom jest łatwy do zapamiętania (IMHO). Zwykle używam tego, gdy wciąż próbuję odkryć, dlaczego sama usługa zawodzi. IMHO program nie powinien po prostu zniknąć niespodziewanie :)


źródło
7

Umieść swój bieg w pętli - więc kiedy kończy się, działa ponownie ... while (true) {uruchom moją aplikację ..}

Klathzazt
źródło
4
Jeśli skrypt umiera z nieznanych przyczyn, prawdopodobnie anuluje również skrypt pętli, nie?
Gareth
4
Jestem z Garath, jeśli jest to system zabijający długo działające procesy, to sugerowana pętla - która uruchomiłaby się przed aplikacją - zostanie najpierw zabita.
ekerner,
2
Odpowiadając na twoje dwie uwagi: Nie, jeśli skrypt umiera z nieznanych przyczyn, skrypt pętli pozostaje nienaruszony, ponieważ jest uruchamiany w oddzielnym procesie - ale tak, jeśli system losowo zabija długo działające procesy, nadal byłby to problem - jednak wątpię, że tak jest. Reszta systemu nie została zgłoszona jako zagrożona i jest pełna innych długotrwałych procesów, które również zostałyby ponownie uruchomione (wspomniano tylko, że ten jeden skrypt ma problem).
Klathzazt
4

Z jakiegoś powodu nie mogłem sprawić , by rozwiązanie Chrisa Wendta działało, i było to trudne do debugowania. Ten jest prawie taki sam, ale łatwiejszy do debugowania, wyklucza bash z dopasowywania wzorców. Do debugowania wystarczy uruchomić: bash ./root/makerun-mysql.sh. W poniższym przykładzie z mysql-server po prostu zamień wartości zmiennych dla processi makerundla twojego procesu.

  • Utwórz skrypt BASH taki jak ten ( nano /root/makerun-mysql.sh):
#!/bin/bash
process="mysql"
makerun="/etc/init.d/mysql restart"
if ps ax | grep -v grep | grep -v bash | grep --quiet $process
then
    printf "Process '%s' is running.\n" "$process"
    exit
else
    printf "Starting process '%s' with command '%s'.\n" "$process" "$makerun"
    $makerun
fi
exit
  • Upewnij się, że jest wykonywalny, dodając odpowiednie uprawnienia do pliku (tj. chmod 700 /root/makerun-mysql.sh)

  • Następnie dodaj to do swojej tabeli crontab ( crontab -e):

# Keep processes running every 5 minutes
*/5 * * * * bash /root/makerun-mysql.sh
cjohansson
źródło
1
Zwróć uwagę, że w porównaniu z rozwiązaniem Chrisa Wendta skrypt nie jest tutaj uruchamiany jako zadanie w tle.
Mason
2

superviseNarzędzie zdaemontools byłaby moja preferencji - ale potem wszystko Dan J Bernstein pisze jest moim preferencji :)

http://cr.yp.to/daemontools/supervise.html

Musisz utworzyć określoną strukturę katalogów dla skryptu uruchamiania aplikacji, ale jest bardzo prosty w użyciu.

Asfand Qazi
źródło
1

przede wszystkim, jak uruchomić tę aplikację? Czy rozwidla się na tle? Czy to się zaczęło od nohup… itd.? Jeśli to drugie, sprawdź, dlaczego zginął w nohup.out, jeśli to pierwszy, build log.

Jeśli chodzi o twoje główne pytanie: możesz go cronować lub uruchomić inny proces w tle (nie jest to najlepszy wybór) i użyć pidof w skrypcie bashscript, dość łatwo:

if [ `pidof -s app` -eq 0 ]; then
    nohup app &
fi
gx.
źródło
1

Mógłbyś uczynić z tego usługę uruchamianą z inittab (chociaż niektóre Linuksy przeszły na coś nowszego w /etc/event.d). Te wbudowane systemy zapewniają, że usługa będzie działać bez pisania własnych skryptów lub instalowania czegoś nowego.

Paul Tomblin
źródło
1

To zadanie dla DMD (demona monitorującego demona). jest kilka w pobliżu; ale zwykle po prostu piszę skrypt, który sprawdza, czy demon działa, a jeśli nie, uruchamiam i umieszczam go w cronie, aby był uruchamiany co minutę.

Javier
źródło
1

Sprawdź ' nanny', do którego odwołuje się rozdział 9 (str. 197 lub około) „Unix Hater's Handbook” (jedno z kilku źródeł książki w formacie PDF).

Jonathan Leffler
źródło
1

Przyjemny, prosty sposób na zrobienie tego jest następujący:

  1. Napisz serwer, aby umarł, jeśli nie może nasłuchiwać na porcie, którego oczekuje
  2. Ustaw cronjob, aby co minutę uruchamiać serwer

Jeśli nie jest uruchomiony, rozpocznie się, a jeśli nie, nie. W każdym razie Twój serwer będzie zawsze działał.

Casey Rodarmor
źródło
0

Myślę, że lepszym rozwiązaniem jest również przetestowanie funkcji. Na przykład, jeśli trzeba było przetestować apache, nie wystarczy tylko sprawdzić, czy w systemach istnieją procesy „apache”.

Jeśli chcesz sprawdzić, czy apache jest OK, spróbuj pobrać prostą stronę internetową i sprawdź, czy na wyjściu znajduje się Twój unikalny kod.

Jeśli nie, zabij apache za pomocą -9, a następnie uruchom ponownie. I wyślij wiadomość do katalogu głównego (który jest przekierowanym adresem pocztowym do katalogu głównego firmy / serwera / projektu).

peterh - Przywróć Monikę
źródło
1
To prawda. Wiele rozwiązań monitorowania sugerowanych w innych odpowiedziach zapewnia monitorowanie protokołu.
Oli,
0

To jeszcze prostsze:

#!/bin/bash

export DISPLAY=:0

process=processname
makerun="/usr/bin/processname"

if ! pgrep $process > /dev/null
then
    $makerun &
fi

Musisz jednak pamiętać, aby nazwa procesu była niepowtarzalna.

Radosław Ganczarek
źródło
0

Można zainstalować drobiazgowe monitorowanie cronjob w następujący sposób:

crontab -l> crontab; echo -e '* * * * * export DISPLAY = ": 0.0" && dla aplikacji w "eiskaltdcpp-qt" "Transmission-gtk" "nicotine"; do ps aux | grep -v grep | grep "$ app"; done || "$ app" & '>> crontab; crontab crontab

Wadą jest to, że nazwy aplikacji, które wprowadzasz, muszą być znalezione w ps aux|grep "appname"danych wyjściowych i jednocześnie można je uruchomić przy użyciu tej nazwy:"appname" &

16851556
źródło