web-dev-qa-db-ja.com

Upstartがプロセスの間違ったPIDを追跡-再スポーンしない

私はもともとStackOverflowでこの質問をしました。その後、これはおそらくより良い場所であることに気づきました。

Delay_jobプロセスを監視するためのbluepillセットアップがあります。 (RailsアプリケーションのRuby)

Ubuntu 12.10。を使用する.

Ubuntuのupstartを使用してbluepillサービス自体を開始および監視しています。私のスタートアップ構成は以下です(/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

expect forkの代わりにexpect daemonを試してみました。また、expect...行を完全に削除しようとしました。

マシンが起動すると、bluepillは正常に起動します。

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

BluepillプロセスのPIDはここでは1154です。ただし、upstartは間違ったPIDを追跡しているようです。存在しないPIDを追跡しています。

$ initctl status bluepill
bluepill start/running, process 990

Bluepillプロセスを開始したSudoプロセスのPIDを追跡していると思います。

これは、kill -9を使用してbluepillを強制的に強制終了した場合、bluepillプロセスが再生成されないようにするためです。

さらに、誤ったPIDが追跡されているため、リブート/シャットダウンがハングするだけで、毎回マシンをハードリセットする必要があります。

ここで何が問題になりますか?

UPDATE

この問題は、Ubuntu 14.04.2では今日(2015年5月3日)のままです。

問題は、Sudoを使用しているためではありません。私はもうSudoを使用していません。更新されたupstartの構成は次のとおりです。

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

マシンが起動すると、プログラムは正常にロードされます。ただし、上記のように、upstartは引き続き間違ったPIDを追跡します。

コメントに記載されている回避策により、ハングの問題が解決する場合があります。しかし、私はそれを試していません。

11
Anjan

かなり遅れていますが、これが他のユーザーの助けになることを願っています。

Upstartには、誤ったforkスタンザをupstart構成で指定すると、initctlが間違ったPIDを追跡する可能性のあるバグが文書化されています。 https://bugs.launchpad.net/upstart/+bug/406397

何が起こるかというと、upstartはforkスタンザをチェックし、制御されているプログラムの「真の」PIDを選択する前にチェックするフォークプロセスの数を決定します。 expect forkまたはexpect daemonを指定しても、プログラムが十分な回数フォークしない場合、startがハングします。一方、プロセスの分岐が多すぎる場合、initctlは間違ったPIDを追跡します。理論的には、これを pstart cookbookのセクション に文書化する必要がありますが、この状況でわかるように、強制終了されるべきではないプロセスに関連付けられたPIDがあります。

これの意味はバグトラッカーのコメントで説明されていますが、ここで要約します:initctlに加えて、デーモンプロセスを停止できず、文書化されていない/違法な状態に陥る<service> start/killed, process <pid>そのPIDに属することは停止し(通常は停止します)、PIDはシステムによる再利用のために解放されます。

initctl stop <service>またはservice <service> stopを発行すると、initctlは次回PIDが表示されたときにそのPIDを強制終了します。これは、この間違いを犯した後に再起動しない場合、将来的にはデーモンではないにもかかわらず、その[PID]を使用する次のプロセスがinitctlによって即座に強制終了されることを意味します。 catのように単純なものでも、ffmpegのように複雑なものでもかまいません。また、何らかの日常的な操作の途中でソフトウェアパッケージがクラッシュした理由を理解するのは困難です。

したがって、問題は、デーモンプロセスが実際に作成するフォークの数に間違ったexpectオプションを指定したことです。彼らは、この問題に対処するアップスタートのリライトがあると言いますが、アップスタート1.8(最新のUbuntu 13.04/January 2014)の時点で、この問題はまだ存在しています。

expect daemonを使用し、この問題で終わったため、expect forkを試すことをお勧めします。

編集:これはUbuntu BASH互換のスクリプトです( Wade Fitzpatrickによるオリジナル Ubuntu sleepを使用するように変更され、利用可能なプロセスIDアドレス空間が使い果たされるまでプロセスを生成します。 0で、「スタック」PIDまで進みます。その後、プロセスはPID initctlがハングアップしたときに生成され、initctlはプロセスを強制終了してリセットします。

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

提供された例の場合:

$ initctl status bluepill
bluepill start/running, process 990

私の簡単な解決策は次のとおりです。

# 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

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

これが役立つことを願っています。何が起こっているかは、他の回答で説明されています。

5
Szymon Jeż

pstart user level job または setuidスタンザを使用 を実行している場合を除き、ジョブはrootとして実行されています。

Upstartはすでにrootとして実行されているので、なぜexecスタンザでSudoを使用する必要があるのですか?

Sudoスタンザでsuまたはexecを使用すると、ここで説明したのと同じ問題が発生します。

通常、アイテム1 OR両方の1と2が発生します。

  1. upstartは誤ったPIDに従います
  2. プロセスを停止しようとするとupstartがハングする

もちろん、expectスタンザに正しいフォーク数を反映させる必要があります。

YMMV、しかし私にとって:

  • execスタンザで正しい数のフォークを指定してSudoまたはsuを使用すると、通常、上記の状況1になります。
  • execにSudo/suを使用せずに)指定された誤った数のフォークは、上記の状況1および2になります。
0
user12345