GCP Ubuntu 18.04LTSでは、プロセス所有権が自動的にinitプロセスに変更されました。

GCP Ubuntu 18.04LTSでは、プロセス所有権が自動的にinitプロセスに変更されました。

最近、Ubuntu 12.04 を実行する従来のマシンから Ubuntu 18.04 を実行する Google Cloud インスタンスに開発インフラストラクチャを移行しました。

開発者は通常、いくつかの画面を起動し、これらの画面でdjangoサーバーを実行します。

たとえば、画面を作成し、screen -S webserver_5552画面内でdjango開発アプリケーションを実行できます。python manage.py runserver 0.0.0.0:5552

以前のコンピュータでは、screen(ctrl+a d)を切り離してscreen -r xxxx.webserver_5552後で返す()できました。 djangoサーバープロセスはまだここにあり、実行中であり、screenのbashプロセスによって所有されています。

しかし、Google Cloud マシンではこれが異なる動作をし、私たちを狂わせました。それでも画面を切り離すことができますが、後で戻ってくると、djangoプロセスはもはやbashプロセスに属しなくなります!代わりにinitプロセスが所有しています(ppidはpsから1に設定されています)。

通常、私たちはdjangoプロセスがシグナルを受け取り、所有権を変更する前にトレースバックを取得します。しかし、それが私たちが得るすべてであり、根本的な原因が何であるか、それを防ぐ方法を理解することはできません。

Traceback (most recent call last):
  File "manage.py", line 65, in <module>
    execute_from_command_line(sys.argv)
  File "/home/testing/env/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 367, in execute_from_command_line
    utility.execute()
  File "/home/testing/env/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 359, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/testing/env/local/lib/python2.7/site-packages/django/core/management/base.py", line 294, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/testing/env/local/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 58, in execute
    super(Command, self).execute(*args, **options)
  File "/home/testing/env/local/lib/python2.7/site-packages/django/core/management/base.py", line 345, in execute
    output = self.handle(*args, **options)
  File "/home/testing/env/local/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 97, in handle
    self.run(**options)
  File "/home/testing/env/local/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 106, in run
    autoreload.main(self.inner_run, None, options)
  File "/home/testing/env/local/lib/python2.7/site-packages/django/utils/autoreload.py", line 333, in main
    reloader(wrapped_main_func, args, kwargs)
  File "/home/testing/env/local/lib/python2.7/site-packages/django/utils/autoreload.py", line 304, in python_reloader
    exit_code = restart_with_reloader()
  File "/home/testing/env/local/lib/python2.7/site-packages/django/utils/autoreload.py", line 290, in restart_with_reloader
    exit_code = os.spawnve(os.P_WAIT, sys.executable, args, new_environ)
  File "/home/testing/odesk_android/../env/lib/python2.7/os.py", line 575, in spawnve
    return _spawnvef(mode, file, args, env, execve)
  File "/home/testing/odesk_android/../env/lib/python2.7/os.py", line 548, in _spawnvef
    wpid, sts = waitpid(pid, 0)
OSError: [Errno 4] Interrupted system call

これは特に迷惑な動作であり、根本的な原因を特定することはできません(Ubuntu、GCP、一部の不適切な設定などに起因するものか…?)。

編集する:

スプラッシュ画面とスプラッシュ画面でテストしました。

testing@whova-qa-01:/home/simon_ninon_whova_com$ ps -ejf | grep 55530
testing  20764 19638 20764 19638  4 00:12 pts/18   00:00:01 ../env/bin/python manage.py runserver 0.0.0.0:55530
testing  20769 20764 20764 19638 12 00:12 pts/18   00:00:04 /home/testing/appium_android/../env/bin/python manage.py runserver 0.0.0.0:55530

ご覧のとおり、../env/bin/python manage.py runserver 0.0.0.0:55530PID = 20764およびPPID = 19638でdjangoプロセス(bashプロセス)を開始しました。

このdjangoプロセスは、/home/testing/appium_android/../env/bin/python manage.py runserver 0.0.0.0:55530PID = 20769およびPPID = 20764(私が作成した元のプロセス)の子プロセスを作成しました。

今朝、もう一度コンピュータにログインすると画面を再接続する前に、すべてがまだ同じです。

simon_ninon_whova_com@whova-qa-01:~$ ps -ejf | grep 55530
simon_n+  9026  9011  9025  9011  0 09:09 pts/9    00:00:00 grep --color=auto 55530
testing  20764 19638 20764 19638  0 00:12 pts/18   00:00:01 ../env/bin/python manage.py runserver 0.0.0.0:55530
testing  20769 20764 20764 19638  2 00:12 pts/18   00:13:56 /home/testing/appium_android/../env/bin/python manage.py runserver 0.0.0.0:55530

そのため、画面を再接続すると問題が発生するとは予想されません。しかし、画面を再接続すると、ハム、プロセスが終了します!

testing@whova-qa-01:~$ ps -ejf | grep 55530
testing   9085  9031  9084  9011  0 09:10 pts/9    00:00:00 grep --color=auto 55530
testing  20769     1 20764 19638  2 00:12 pts/18   00:13:59 /home/testing/appium_android/../env/bin/python manage.py runserver 0.0.0.0:55530

ご覧のとおり、親プロセスは終了しますが、initプロセスが所有する子プロセスはまだ存在します。

興味深いことに、元のbashプロセスがまだ存在することを確認すると、次のような結果が得られます。

simon_ninon_whova_com@whova-qa-01:~$ ps aux | grep 19638
simon_n+  9315  0.0  0.0  14664  1016 pts/9    S+   09:16   0:00 grep --color=auto 19638
testing  19638  0.0  0.0  25360  7692 pts/18   Ss+  Feb27   0:00 /bin/bash

したがって、画面を再接続すると、bashプロセスが保存されるように見えますが、何らかの理由で親djangoプロセスが終了します。

この段階で何を期待すべきか分からないのですか?サーバーを起動してしばらく画面を切断して再接続すると、問題は発生せず、しばらくしてから発生します。

答え1

根本原因を見つけました。

画面が再接続されると、SIGWINCH 信号が親 django プロセスに送信されます。プロセスはそれを処理できず、衝突だけが発生し、子供は孤児になります。

その後、用語のサイズを変更するか、を使用して簡単に再起動できますkill -28 PID

なぜGCPインスタンスでのみ発生するのかはわかりませんが、環境(Pythonバージョン?)に何か他のものがある可能性があります。とにかく、これは解決策が見つかる場所についてのより多くの手がかりを提供します。

編集する:

しばらく検索した結果、根本的な原因はreadlineソースコードからdjangoの依存関係を取得したことでした。

python readlineはライブラリへのバインディングであり、信号処理がpython / djangoで実行される信号処理を妨げているようgnureadlineです。gnureadline

以前のシステムではなくGCPシステムでのみ発生することを考慮すると、GCPシステムに別のgnureadlineがインストールされ(バージョン側または使用されているコンパイルオプションの観点から)、信号処理の動作が異なると思われます。

関連情報