Ulepszenie śledzenia niewłaściwy PID procesu - brak odradzania

11

Pierwotnie zadałem to pytanie na StackOverflow. Potem zdałem sobie sprawę, że jest to prawdopodobnie lepsze miejsce.

Mam konfigurację bluepill do monitorowania moich opóźnionych procesów. (Aplikacja Ruby On Rails)

Korzystanie z Ubuntu 12.10.

Uruchamiam i monitoruję samą usługę bluepill przy użyciu Ubuntu upstart. Moja konfiguracja upstart jest poniżej ( /etc/init/bluepill.conf).

description "Start up the bluepill service"

start on runlevel [2]
stop on runlevel [016]

expect daemon
exec sudo /home/deploy/.rvm/wrappers/<app_name>/bluepill load /home/deploy/websites/<app_name>/current/config/server/staging/delayed_job.bluepill

# Restart the process if it dies with a signal
# or exit code not given by the 'normal exit' stanza.
respawn

Próbowałem też z expect forkzamiast expect daemon. Próbowałem też expect...całkowicie usunąć linię.

Po uruchomieniu maszyny bluepill uruchamia się dobrze.

$ ps aux | grep blue
root      1154  0.6  0.8 206416 17372 ?        Sl   21:19   0:00 bluepilld: <app_name>

PID procesu bluepill wynosi tutaj 1154. Ale upstartwydaje się, że śledzi niewłaściwy PID. Śledzi PID, który nie istnieje.

$ initctl status bluepill
bluepill start/running, process 990

Myślę, że śledzi PID sudoprocesu, który rozpoczął proces bluepill.

Zapobiega to odrodzeniu się procesu bluepill, jeśli siłą zabiję go za pomocą kill -9.

Co więcej, myślę, że z powodu śledzenia niewłaściwego PID, restart / wyłączenie po prostu zawiesza się i muszę za każdym razem mocno resetować maszynę.

Co może być tutaj problemem?

AKTUALIZACJA :

Problem pozostaje na dzień dzisiejszy (3 maja 2015 r.) W systemie Ubuntu 14.04.2.

Problem nie wynika z używania sudo. Nie używam już sudo. Moja zaktualizowana konfiguracja upstart to:

description "Start up the bluepill service"

start on runlevel [2]
stop on runlevel [016]

# Restart the process if it dies with a signal
# or exit code not given by the 'normal exit' stanza.
respawn

# Give up if restart occurs 10 times in 90 seconds.
respawn limit 10 90

expect daemon

script
    shared_path=/home/deploy/websites/some_app/shared

    bluepill load $shared_path/config/delayed_job.bluepill
end script

Po uruchomieniu komputera program ładuje się dobrze. Ale upstart nadal śledzi niewłaściwy PID, jak opisano powyżej.

Obejście wspomniane w komentarzach może rozwiązać problem z zawieszaniem się. Jednak tego nie próbowałem.

Anjan
źródło
próbowałeś zobaczyć, co to jest proces 990? ps aux | grep 990powinien to zrobić, ale pstree 990może być bardziej pouczający.
Oli
Nie istnieje żaden proces o PID 990.
Anjan
2
jeśli chodzi o potrzebę ponownego uruchomienia komputera, aby wrócić do dobrego stanu - zobacz to miłe narzędzie: github.com/ion1/workaround-upstart-snafu
andersonbd1
i możesz przyspieszyć to narzędzie za pomocą tego polecenia: $ echo 3000 | sudo tee / proc / sys / kernel / pid_max
andersonbd1

Odpowiedzi:

8

Dość późno, ale mam nadzieję, że może to pomóc innym użytkownikom.

Istnieje udokumentowany błąd w fazie upstart, który może spowodować, że initctl będzie śledził niewłaściwy PID, jeśli podasz nieprawidłową forksekcję w konfiguracji upstart: https://bugs.launchpad.net/upstart/+bug/406397

Dzieje się tak, gdy upstart sprawdza forkzwrotkę i określa, ile rozwidlonych procesów powinien sprawdzić przed wybraniem „prawdziwego” PID kontrolowanego programu. Jeśli określisz expect forklub expect daemontwój program nie rozwidla wystarczającej liczby razy, startzawiesi się. Jeśli natomiast proces rozwidla się zbyt wiele razy, initctlwyśledzi zły PID. Teoretycznie powinien to zostać udokumentowany w tej części książki kucharskiej , ale jak widać w tej sytuacji, PID jest związany z zabitym procesem, kiedy nie powinien.

Konsekwencje tego wyjaśniono w komentarzach bugtrackera, ale streszczę tutaj: oprócz initctlniemożności zatrzymania procesu demona i utknięcia w nieudokumentowanym / nielegalnym stanie <service> start/killed, process <pid>, jeśli proces należący do tego PID zatrzyma się (i zwykle będzie ), następnie PID zostaje zwolniony do ponownego wykorzystania przez system.

Jeśli wydasz initctl stop <service>lub service <service> stop, initctlzabije ten PID następnym razem, gdy się pojawi. Oznacza to, że gdzieś w dalszej części drogi, jeśli nie zrestartujesz się po popełnieniu tego błędu, następny proces użycia tego PID zostanie natychmiast zabity, initctlnawet jeśli nie będzie to demon. Może to być coś tak prostego catlub tak złożonego, jak to ffmpeg, i trudno byłoby ustalić, dlaczego pakiet oprogramowania zawiesił się w trakcie rutynowej operacji.

Problem polega na tym, że podałeś niewłaściwą expectopcję liczby rozwidleń faktycznie wykonywanych przez proces demona. Mówią, że istnieje poprawka przepisująca, która rozwiązuje ten problem, ale od wersji 1.8 (najnowszy Ubuntu 13.04 / styczeń 2014) problem nadal występuje.

Ponieważ użyłeś expect daemontego problemu i skończyłeś go, zalecamy wypróbowanie expect fork.

Edycja: Oto skrypt kompatybilny z BASH Ubuntu ( oryginalny autorstwa Wade Fitzpatrick zmodyfikowany do używania Ubuntu sleep), który spawnuje procesy do wyczerpania dostępnej przestrzeni adresowej identyfikatora procesu, w którym to punkcie zaczyna się od 0 i przechodzi do „zablokowanego” PID Następnie odradza się proces, gdy PID initctljest rozłączany, initctlzabija go i resetuje.

#!/bin/bash

# usage: sh /tmp/upstart_fix.sh <pid>

sleep 0.001 &
firstPID=$!
#first lets exhaust the space
while (( $! >= $firstPID ))
do
    sleep 0.001 &
done

# [ will use testPID itself, we want to use the next pid
declare -i testPID
testPID=$(($1 - 1))
while (( $! < $testPID ))
do
    sleep 0.001 &
done

# fork a background process then die so init reaps its pid
sleep 3 &
echo "Init will reap PID=$!"
kill -9 $$
# EOF
Dakota
źródło
Ta odpowiedź zawiera kilka użytecznych i interesujących informacji, jednak nie jest dla mnie jasne, w jaki sposób ta odpowiedź odpowiada na początkowe pytanie, jak wspomniał @Anjan „Próbowałem również z oczekiwaniem fork zamiast demona expect. Próbowałem też całkowicie usunąć linię expect ... „
user12345
5

Na podany przykład:

$ initctl status bluepill
bluepill start/running, process 990

dla mnie szybkie rozwiązanie to:

# If upstart gets stuck for some job in stop/killed state
export PID=990
cd /usr/local/bin
wget https://raw.github.com/ion1/workaround-upstart-snafu/master/workaround-upstart-snafu
chmod +x workaround-upstart-snafu
./workaround-upstart-snafu $PID

źródło: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=582745#37

Mam nadzieję, że będzie to pomocne. To, co się dzieje, wyjaśniono w innych odpowiedziach.

Szymon Jeż
źródło
Niezły scenariusz. Może to potrwać minutę lub dwie. rebootMoże czasami być korzystne i rozwiązuje również ten.
Peter Ilfrich
0

Chyba że uruchamiasz zadanie na poziomie użytkownika Upstart lub używasz sekcji setuid - wtedy twoje zadanie działa jako root.

Skoro Upstart jest już uruchomiony jako root, dlaczego w ogóle musisz używać sudo exec?

Używanie sudolub suw execzwrotce spowodowało dla mnie te same problemy, które opisujesz tutaj.

Zazwyczaj doświadczam przedmiotu 1 LUB zarówno 1 ORAZ 2:

  1. upstart następuje po nieprawidłowym PID
  2. upstart zawiesza się, gdy próbuję zatrzymać proces

Oczywiście dodatkowo musisz mieć expectzwrotkę odzwierciedlającą prawidłową liczbę widelców.

YMMV, ale dla mnie:

  • użycie sudo lub su w execzwrotce z określoną liczbą widelców ogólnie skutkuje sytuacją 1 powyżej.
  • nieprawidłowa liczba podanych widelców (z naszym bez sudo / su w exec) powoduje sytuację 1 i 2 powyżej.
użytkownik12345
źródło