Monitoraggio iniziale PID errato del processo - non rigenerazione


11

Inizialmente avevo posto questa domanda su StackOverflow. Quindi ho capito che questo è probabilmente un posto migliore.

Ho impostato bluepill per monitorare i miei processi delayed_job. (Applicazione Ruby On Rails)

Usando Ubuntu 12.10.

Sto avviando e monitorando il servizio bluepill stesso usando Ubuntu upstart. La mia configurazione iniziale è sotto ( /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

Ho anche provato con expect forkinvece di expect daemon. Ho anche provato a rimuovere expect...completamente la linea.

Quando la macchina si avvia, bluepill si avvia correttamente.

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

Il PID del processo bluepill è 1154 qui. Ma upstartsembra seguire il PID sbagliato. Tiene traccia di un PID che non esiste.

$ initctl status bluepill
bluepill start/running, process 990

Penso che stia monitorando il PID del sudoprocesso che ha avviato il processo bluepill.

Questo impedisce al processo di bluepill di essere rigenerato se uccido con forza bluepill usando kill -9.

Inoltre, penso che a causa del PID errato che viene rintracciato, il riavvio / arresto si blocca e devo reimpostare la macchina ogni volta.

Quale potrebbe essere il problema qui?

AGGIORNAMENTO :

Il problema persiste ad oggi (3 maggio 2015) su Ubuntu 14.04.2.

Il problema non è dovuto all'uso di sudo. Non sto più usando sudo. La mia configurazione upstart aggiornata è questa:

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

Quando la macchina si avvia, il programma si carica bene. Ma upstart tiene ancora traccia del PID errato, come descritto sopra.

La soluzione alternativa menzionata nei commenti potrebbe risolvere il problema impiccagione. Non l'ho provato, però.


hai provato a vedere quale processo è 990? ps aux | grep 990dovrebbe farlo, ma pstree 990potrebbe essere più informativo.
Oli

Non esiste alcun processo con il PID di 990.
Anjan,

2
per quanto riguarda la necessità di riavviare per riavviare in un buono stato - vedi questo bel strumento: github.com/ion1/workaround-upstart-snafu
andersonbd1

e puoi velocizzare quello strumento con questo comando: $ echo 3000 | sudo tee / proc / sys / kernel / pid_max
andersonbd1

Risposte:


8

Abbastanza tardi, ma speriamo che questo possa essere di aiuto per gli altri utenti.

C'è un bug documentato in upstart che può far sì che initctl tenga traccia del PID errato se si specifica la forkstanza errata in una configurazione upstart: https://bugs.launchpad.net/upstart/+bug/406397

Quello che succede è che upstart controlla la forkstanza e determina quanti processi biforcuti dovrebbe controllare prima di scegliere il "vero" PID del programma che viene controllato. Se si specifica expect forko expect daemonma il programma non si biforca un numero sufficiente di volte, si startbloccherà. Se, d'altra parte, il tuo processo si biforca troppe volte, initctlseguirà il PID sbagliato. Teoricamente, dovrebbe essere documentato in questa sezione del ricettario iniziale , ma come puoi vedere in questa situazione c'è un PID associato al processo ucciso quando non dovrebbe esserci.

Le implicazioni di questo sono spiegate nei commenti su bugtracker, ma riassumerò qui: oltre a initctlnon essere in grado di fermare il processo daemon e di essere bloccato in uno stato non documentato / illegale <service> start/killed, process <pid>, se il processo appartenente a quel PID si interrompe (e di solito lo farà ), il PID viene liberato per essere riutilizzato dal sistema.

Se emetti initctl stop <service>o service <service> stop, initctlucciderà quel PID la prossima volta che appare. Ciò significa che, da qualche parte lungo la strada se non si riavvia dopo aver commesso questo errore, il prossimo processo per utilizzare quel PID verrà immediatamente ucciso initctlanche se non sarà il demone. Potrebbe essere qualcosa di semplice cato complesso come ffmpeg, e faresti fatica a capire perché il tuo pacchetto software si è schiantato durante un'operazione di routine.

Quindi, il problema è che hai specificato l' expectopzione sbagliata per il numero di fork che il tuo processo daemon fa effettivamente. Dicono che c'è una riscrittura iniziale che risolve questo problema, ma a partire dalla versione 1.8 (ultimo Ubuntu 13.04 / gennaio 2014) il problema è ancora presente.

Dato che hai usato expect daemone finito questo problema, ti consiglio di provare expect fork.

Modifica: ecco uno script compatibile con Ubuntu BASH ( originale di Wade Fitzpatrick modificato per usare Ubuntu sleep) che genera i processi fino a quando lo spazio dell'indirizzo ID processo disponibile è esaurito, a quel punto inizia da 0 e arriva fino allo "bloccato" PID. Viene quindi generato un processo quando il PID initctlviene bloccato, initctllo uccide e si ripristina.

#!/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

Questa risposta contiene alcune informazioni utili e interessanti, tuttavia non mi è chiaro come questa risposta risponda alla domanda iniziale, come menzionato da @Anjan "Ho anche provato a prevedere fork invece di prevedere il demone. Ho anche provato a rimuovere completamente la linea
user12345,

5

Per l'esempio fornito:

$ initctl status bluepill
bluepill start/running, process 990

una soluzione rapida per me è:

# 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

fonte: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=582745#37

Spero che questo possa esserti utile Quello che sta succedendo è spiegato nelle altre risposte.


Bel copione. Questo può richiedere un minuto o due. A rebootpotrebbe talvolta essere preferibile e risolve anche questo.
Peter Ilfrich,

0

A meno che non si stia eseguendo un lavoro a livello di utente Upstart o utilizzando la stanza setuid , il lavoro verrà eseguito come root.

Poiché Upstart è già in esecuzione come root, perché devi usare sudo nella tua execstanza?

L'uso sudoo sunella execstanza mi ha causato gli stessi problemi che descrivi qui.

In genere sperimenterò l'articolo 1 OPPURE sia 1 che 2:

  1. upstart segue il PID errato
  2. upstart si blocca quando provo a interrompere il processo

Naturalmente, inoltre, è necessario che la expectstanza rifletta il numero corretto di forchette.

YMMV, ma per me:

  • l'uso di sudo o su nella execstanza con il numero corretto di forcelle specificato generalmente determina la situazione 1 sopra.
  • il numero errato di forcelle specificato (con il nostro senza sudo / su in exec) comporta la situazione 1 E 2 sopra.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.