Upstart suivi PID erroné du processus - non respawn

11

J'ai initialement posé cette question sur StackOverflow. Alors rendu compte que ce qui est probablement un meilleur endroit.

J'ai bluepill configuré pour surveiller mes processus de delayed_job. (Application Ruby On Rails)

En utilisant Ubuntu 12.10.

Je commence et le suivi du service bluepill lui - même à l' aide de Ubuntu upstart. Ma config est arriviste ci - dessous ( /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

J'ai aussi essayé avec au expect forklieu de expect daemon. J'ai aussi essayé d' enlever la expect...complètement ligne.

Lorsque la machine démarre, bluepill se met en marche bien.

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

Le PID du processus Bluepill est 1154 ici. Mais upstartsemble être suivi du PID erroné. Il est suivi d' un PID qui n'existe pas.

$ initctl status bluepill
bluepill start/running, process 990

Je pense que c'est le suivi du PID du sudoprocessus qui a lancé le processus Bluepill.

Cela empêche le processus Bluepill de réapparaître si je tue avec force Bluepill en utilisant kill -9.

De plus, je pense qu'en raison du mauvais PID suivi, le redémarrage / arrêt se bloque et je dois réinitialiser la machine à chaque fois.

Quel pourrait être le problème ici?

MISE À JOUR :

Le problème persiste à partir d'aujourd'hui (3 mai 2015) sur Ubuntu 14.04.2.

Le problème n'est pas dû à l'utilisation de sudo. Je n'utilise plus sudo. Ma configuration par défaut mise à jour est la suivante:

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

Lorsque la machine démarre, le programme se charge correctement. Mais upstart suit toujours le mauvais PID, comme décrit ci-dessus.

La solution de contournement mentionnée dans les commentaires peut résoudre le problème de suspension. Mais je ne l'ai pas essayé.

Anjan
la source
avez-vous essayé de regarder ce qu'est le 990? ps aux | grep 990devrait le faire mais pstree 990pourrait être plus informatif.
Oli
Aucun processus avec le PID de 990 n'existe.
Anjan
2
en ce qui concerne la nécessité de redémarrer pour revenir en bon état - voir ce bel outil: github.com/ion1/workaround-upstart-snafu
andersonbd1
et vous pouvez accélérer cet outil avec cette commande: $ echo 3000 | sudo tee / proc / sys / kernel / pid_max
andersonbd1

Réponses:

8

Assez tard, mais j'espère que cela peut aider d'autres utilisateurs.

Il existe un bogue documenté dans upstart qui peut entraîner initctl à suivre le mauvais PID si vous spécifiez la forkstrophe incorrecte dans une configuration upstart: https://bugs.launchpad.net/upstart/+bug/406397

Ce qui se passe, c'est que upstart vérifie la forkstrophe et détermine combien de processus fourchus il doit vérifier avant de choisir le "vrai" PID du programme contrôlé. Si vous spécifiez expect forkou expect daemonmais que votre programme ne se déroule pas un nombre suffisant de fois, startse bloquera. Si, en revanche, votre processus bifurque trop de fois, initctlsuivra le mauvais PID. Théoriquement, cela devrait être documenté dans cette section du livre de cuisine parvenu , mais comme vous pouvez le voir dans cette situation, il y a un PID associé au processus tué alors qu'il ne devrait pas y en avoir.

Les implications sont expliquées dans les commentaires de bugtracker, mais je vais résumer ici: en plus de initctlne pas être en mesure d'arrêter le processus démon et d' être coincé dans un état sans papier / illégal <service> start/killed, process <pid>, si le processus appartenant à qui arrête PID (et il sera généralement ), le PID est libéré pour une nouvelle utilisation par le système.

Si vous émettez initctl stop <service>ou service <service> stop, initctlva tuer ce PID la prochaine fois qu'il apparaît. Cela signifie que, quelque part sur la route si vous ne redémarrez pas après avoir fait cette erreur, le prochain processus d'utiliser cette PID sera immédiatement tué par initctlmême si ce ne sera pas le démon. Il pourrait être quelque chose d' aussi simple que catou aussi complexe que ffmpeg, et vous auriez du mal à comprendre pourquoi votre logiciel est écrasé au milieu d'une opération de routine.

Donc, la question est que vous avez spécifié la mauvaise expectoption pour le nombre de fourches votre processus démon fait réellement. Ils disent qu'il existe une réécriture parvenu qui résout ce problème, mais à partir de la mise à jour 1.8 (dernier Ubuntu 13.04 / janvier 2014), le problème est toujours présent.

Depuis que vous avez utilisé expect daemonet a fini avec cette question, je vous recommande d' essayer expect fork.

Edit: Voici un script compatible BASH Ubuntu ( originale Wade Fitzpatrick modifié pour utiliser Ubuntu sleep) que les processus de pontes jusqu'à ce que l'espace d'adressage de processus ID disponible est épuisé, à quel point il recommence à 0 et fait son chemin jusqu'à la « coincé » PID. Un processus est ensuite donné naissance au PID initctlest raccroché, et initctltue et remet à zéro.

#!/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
la source
Cette réponse contient des informations utiles et intéressantes, mais je ne sais pas comment cette réponse répond à la question initiale, comme @Anjan l'a mentionné "J'ai également essayé avec expect fork au lieu de expect daemon. J'ai également essayé de supprimer complètement la ligne expect .... "
user12345
5

Pour l'exemple fourni:

$ initctl status bluepill
bluepill start/running, process 990

une solution rapide pour moi est:

# 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

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

J'espère que cela vous sera utile. Ce qui se passe est expliqué dans les autres réponses.

Szymon Jeż
la source
Joli script. Cela peut prendre une minute ou deux. Un rebootpeut parfois être préférable et corrige également cela.
Peter Ilfrich
0

Sauf si vous exécutez un travail de niveau utilisateur Upstart ou utilisez la strophe setuid - votre travail s'exécute en tant que root.

Étant donné que Upstart fonctionne déjà en tant que root, pourquoi avez-vous besoin d'utiliser sudo dans votre execstrophe?

L'utilisation de sudoou sudans la execstrophe m'a causé les mêmes problèmes que ceux que vous décrivez ici.

En règle générale, je connais l'élément 1 OU les deux 1 ET 2:

  1. parvenu suit le PID incorrect
  2. parvenu se bloque lorsque j'essaie d'arrêter le processus

Bien sûr, vous devez également avoir la expectstrophe reflétant le nombre correct de fourches.

YMMV, mais pour moi:

  • l'utilisation de sudo ou su dans la execstrophe avec le nombre correct de fourches spécifié entraîne généralement la situation 1 ci-dessus.
  • un nombre incorrect de fourches spécifié (avec ou sans sudo / su dans exec) entraîne la situation 1 ET 2 ci-dessus.
user12345
la source