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이 설치되어(버전 측면에서 또는 사용된 컴파일 옵션 측면에서) 신호 처리 동작이 달라진 것으로 의심됩니다.

관련 정보