Процесс убийства в Docker покинуть поток ядра - PullRequest
0 голосов
/ 22 декабря 2019

Я экспериментирую с Docker и решил большинство своих проблем, но не могу сдвинуться с места с этим.

У меня есть приложение на python, которое периодически включает vpn (через клиент openvpn) внутри докера, делает что-то и потом делает

os.system("pkill -f openvpn")
#os.system("killall openvpn")

Я пробовал оба, и оба прекрасно работают напросто автономная система, но в докере они оставляют позади потоки ядра (?) каждый раз, когда демон openvpn убит.

Клиент Openvpn вызывается так внутри скрипта:

os.system("/usr/sbin/openvpn --daemon --config " + config_file)

Нокаждый раз, когда его убитый пс получает еще один [openvpn]

/app # ps auxf
PID   USER     TIME  COMMAND
    1 root      0:01 python app.py
    9 root      0:00 [openvpn]
   10 root      0:00 [openvpn]
   16 root      0:00 sh
   41 root      0:00 [openvpn]
   42 root      0:00 [openvpn]
   57 root      0:00 [openvpn]
   58 root      0:00 [openvpn]
   75 root      0:00 [openvpn]
   76 root      0:00 [openvpn]
   89 root      0:00 [openvpn]
   90 root      0:00 [openvpn]
  106 root      0:00 [openvpn]
  107 root      0:00 [openvpn]
  123 root      0:00 [openvpn]
  124 root      0:00 [openvpn]
  137 root      0:00 [openvpn]
  138 root      0:00 /usr/sbin/openvpn --daemon --config /etc/openvpn/VPNarea/Poland-Warsaw.ovpn
  145 root      0:00 ps auxf

Почему это происходит? Или как это предотвратить?

1 Ответ

0 голосов
/ 23 декабря 2019

Вы пропускаете процессы зомби.

Когда вы запускаете в контейнере Docker, ваш процесс имеет идентификатор процесса 1. Это означает, что если что-то внутри контейнера будет убито, а его родитель исчезнет (например,поскольку он сделал двойной ответвление, чтобы стать процессом-демоном), ваш процесс становится его новым родителем, и вы несете ответственность за wait (2) его. Когда вы этого не делаете, вы получаете зомби-процессы, подобные этому.

Один немедленный ответ может быть на os.waitpid(-1, 0) после того, как вы выполните команду "kill". Это заставит вас ждать следующего, что выйдет, и выполнить необходимую очистку.

Хотя было бы чище не пытаться выполнить эту очистку настолько косвенно. Вместо того, чтобы запускать подпроцесс в качестве демона и пытаться очистить его позже, вы можете использовать subprocess.Popen() для создания процесса. Вы можете запустить процесс "на переднем плане", но не блокировать его завершение в процессе Python. Это будет выглядеть примерно так:

vpn = subprocess.Popen(["/usr/sbin/openvpn", "--config", config_file])
...
vpn.kill()
vpn.wait()

Если вы можете разделить вещи так, чтобы эти два элемента работали в отдельных контейнерах, что было бы еще лучше;тогда вы можете избежать этой проблемы управления.

(... что происходит, когда config_file = "/dev/null; cat /etc/shadow"? Попробуйте избегать использования команд строковой формы, таких как os.system(), если это вообще возможно.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...