Ubuntu

程序所有權在 GCP Ubuntu 18.04LTS 上自動更改為 init 程序

  • March 6, 2019

我們最近將開發基礎架構從我們自己的執行 Ubuntu 12.04 的舊機器轉移到執行 Ubuntu 18.04 的 Google Cloud 實例。

開發人員通常會啟動一些螢幕並在這些螢幕中執行 django 伺服器。

例如,可以創建一個螢幕screen -S webserver_5552並在螢幕內執行其 django 開發應用程序python manage.py runserver 0.0.0.0:5552

ctrl+a d在我們之前的機器screen -r xxxx.webserver_5552上,我們可以分離螢幕(

然而,在 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

因此,當我重新連接螢幕時,我預計問題不會存在。但是,當我重新連接螢幕時:boom,程序被殺死了!

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 程序由於某種原因被殺死。

不確定那一步會發生什麼?請注意,如果我在短時間內啟動伺服器,分離並重新連接螢幕,則不會觸發問題,它只會在一段時間後發生。

我找到了根本原因。

重新連接螢幕時,SIGWINCH 信號被發送到父 django 程序。該過程不處理它,只是崩潰,使孩子成為孤兒。

然後可以通過調整術語大小或使用kill -28 PID.

我不確定為什麼它只發生在 GCP 實例上,但環境中可能存在一些不同(python 版本?),無論如何,這給了我更多關於在哪裡找到解決方案的線索。

編輯:

經過一段時間的搜尋,根本原因來自我們readline在其原始碼中導入的 django 依賴項之一。

python readline 是對gnureadline庫的綁定,似乎信號處理gnureadline干擾了在 python/django 中完成的處理。

考慮到它只發生在 GCP 機器上,而不是我們以前的機器上,我懷疑我們 GCP 機器上安裝的 gnureadline 是不同的(無論是在版本方面,還是在使用的編譯選項方面),導致不同的信號處理行為。

引用自:https://unix.stackexchange.com/questions/503495