程序所有權在 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
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:55530
PID=20764 和 PPID=19638 的 django 程序(bash 程序)這個 django 程序創建了一個
/home/testing/appium_android/../env/bin/python manage.py runserver 0.0.0.0:55530
PID=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 是不同的(無論是在版本方面,還是在使用的編譯選項方面),導致不同的信號處理行為。