Python子进程 - 用Ctrl-C关闭Django服务器和Docker容器,返回终端

问题描述 投票:0回答:3

我正在试图找出如何正确关闭我的脚本,该脚本应该启动在docker容器中运行的Django服务器(boot2docker,在Mac OS X上)。这是相关的代码块:

try:
    init_code = subprocess.check_output('./initdocker.sh', shell=True)
    subprocess.call('./startdockerdjango.sh', shell=True)
except subprocess.CalledProcessError:
    try:
        subprocess.call('./startdockerdjango.sh', shell=True)
    except KeyboardInterrupt:
        return

其中startdockerdjango.sh负责设置docker需要的环境变量并启动服务器。整个脚本应该知道是否要进行首次设置和初始化,或者只是启动容器和服务器;捕获CalledProcessError意味着第一次设置已经完成,并且容器和服务器可以刚刚启动。启动工作正常,但当用户按Ctrl-C停止服务器时,服务器正常停止,但显然启动服务器的进程仍在继续。如果我按回车键,那么我可以回到正常的终端命令提示符。如果我执行任何类型的shell命令,比如ls,那么它将被执行然后我可以返回终端。我想更改代码,以便在用户按下Ctrl-C时,服务器和运行服务器的容器将正常停止,然后停止进程并退出整个脚本。如何才能做到这一点?我不想只是在KeyboardInterrupt上杀死或终止进程,因为那时服务器和容器将无法正常停止但会被突然终止。

更新:我最近根据Padraic Cunningham的评论尝试了以下内容:

try:
    init_code = subprocess.check_output('./initdocker.sh', shell=True)
    subprocess.call('./startdockerdjango.sh', shell=True)
except subprocess.CalledProcessError:
    try:
        startproc = subprocess.Popen('./startdockerdjango.sh')
    except KeyboardInterrupt:
        startproc.send_signal(SIGTERM)
        startproc.wait()
        return

这是我尝试将一个术语发送到服务器以便正常关闭然后使用wait()等待进程(startproc)完成。然而,这导致容器和服务器突然终止,这是我试图阻止的。如果我尝试使用SIGINT,会发生同样的事情。如果有的话,我在第二种方法中做错了什么?我仍然想要和以前一样的整体事情,即只有一个Ctrl-C结束容器和服务器,然后退出脚本。

python django docker
3个回答
0
投票

您可能想要使用Popen创建流程。它可以让您更好地控制如何管理子进程。

env = {"MY_ENV_VAR": "some value"}
proc = subprocess.Popen("./dockerdjango.sh", env=env)
try:
    proc.wait()
except KeyboardInterupt:
    proc.terminate() # on linux this gives the a chance to clean up,
    # or even ignore the signal entirely
    # use proc.send_signal(...) and the module signal to send other signals.
    # or proc.kill() if you wish to be kill the process immediately.

如果在python中设置环境变量,它也会导致需要杀死的子进程更少。


0
投票

最后,让脚本知道要么做第一次初始化还是服务器+容器启动是不值得的。相反,该脚本将尝试首次设置,然后将告诉用户在成功安装后执行docker-compose up。对于我的具体情况,这是一个更好的解决方案,而不是试图找出如何让Ctrl-C正确关闭服务器然后退出脚本。


0
投票

要重置django服务器子进程,请在终端中执行:

$ sudo lsof -i tcp:8080
$ sudo lsof -i tcp:8080|awk '{print $2}'|cut -d/ -f 1|xargs kill
© www.soinside.com 2019 - 2024. All rights reserved.