如何让 uwsgi 以任何失败子进程的 return 代码退出
How to get uwsgi to exit with return code of any failed sub-process
我正在编写一些涉及 Python 应用程序 运行ning 在 uwsgi 下的集成测试。
为了测试这个方面,我正在 运行ning 一个 uwsgi 假脱机程序,它要求 master 进程是 运行ning.
如果 pytest 有一个失败的测试,它 return 是一个非零退出代码,这很好。
没有 master 进程,整个 uwsgi 进程也 returns 这个退出代码,所以我们的持续集成服务器做出适当的响应。
但是,当主进程处于 运行ning 状态时,它总是以零退出代码退出 - 无论测试是否失败。
我需要它传递子进程的第一个非零退出代码(如果有的话)。
注意:我对模拟这个并不感兴趣——我需要测试这个工作。
我创建了一个 Dockerized Minimal, Complete, and Verifiable Example 来说明我的问题:
Dockerfile:
FROM python:3.6.4-slim-stretch
WORKDIR /srv
RUN apt-get update \
&& apt-get install -y build-essential \
&& pip install uwsgi pytest
COPY test_app.py /srv/
CMD ['/bin/bash']
test_app.py:
import pytest
def test_this():
assert 1==0
鉴于目录中的上述 2 个文件,如果我 运行 在 uwsgi 没有主进程 下进行此失败测试,则以下显示 return 代码:
$ docker build -t=test .
$ docker run test uwsgi --chdir /srv --pyrun /usr/local/bin/pytest
...
============================= test session starts ==============================
platform linux -- Python 3.6.4, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: /srv, inifile:
collected 1 item
test_app.py F [100%]
=================================== FAILURES ===================================
__________________________________ test_this ___________________________________
def test_this():
> assert 1==0
E assert 1 == 0
test_app.py:4: AssertionError
=========================== 1 failed in 0.05 seconds ===========================
$ echo $?
1
注意:您可以看到此过程(最后一行)中的 return 代码按要求非零
现在,除了 运行ning uwsgi 与 master 进程没有任何变化,我们得到以下输出:
$ docker run test uwsgi --set master=true --chdir /srv --pyrun /usr/local/bin/pytest
...
============================= test session starts ==============================
platform linux -- Python 3.6.4, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: /srv, inifile:
collected 1 item
test_app.py F [100%]
=================================== FAILURES ===================================
__________________________________ test_this ___________________________________
def test_this():
> assert 1==0
E assert 1 == 0
test_app.py:4: AssertionError
=========================== 1 failed in 0.05 seconds ===========================
worker 1 buried after 0 seconds
goodbye to uWSGI.
$ echo $?
0
注意:这次来自此过程(最后一行)的 return 代码为零 - 即使测试失败
如何让 uwsgi 将失败进程的退出代码转发给 master?
这可行,但感觉有点 hacky。如果有更好的答案,我会很乐意接受。
我通过添加两个附加文件(以及对 Dockerfile 的一个小更新)完成了这项工作:
Dockerfile:
FROM python:3.6.4-slim-stretch
WORKDIR /srv
RUN apt-get update \
&& apt-get install -y build-essential \
&& pip install uwsgi pytest
COPY test_app.py test run_tests.py /srv/
CMD ['/bin/bash']
测试:
#!/bin/bash
uwsgi --set master=true --chdir /srv --pyrun /srv/run_tests.py
exit $(cat /tmp/test_results)
run_tests.py:
#!/usr/bin/python
import re
import subprocess
import sys
from pytest import main
def write_result(retcode):
path = r'/tmp/test_results'
with open(path, 'w') as f:
f.write(str(retcode))
def run():
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
retcode = 1
try:
retcode = main()
finally:
write_result(retcode)
sys.exit(retcode)
if __name__ == '__main__':
run()
它的工作方式是我将 pytest 程序复制并调整到 run_tests.py
,它将测试的 return 代码写到一个临时文件中。测试是 运行 通过 bash 脚本:test
,运行s uwsgi,运行s 测试,然后使用 return 测试代码。
结果现在看起来像:
$ docker build -t=test .
$ docker run test /srv/test
...
============================= test session starts ==============================
platform linux -- Python 3.6.4, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: /srv, inifile:
collected 1 item
test_app.py F [100%]
=================================== FAILURES ===================================
__________________________________ test_this ___________________________________
def test_this():
> assert 1==0
E assert 1 == 0
test_app.py:4: AssertionError
=========================== 1 failed in 0.05 seconds ===========================
worker 1 buried after 0 seconds
goodbye to uWSGI.
$ echo $?
1
我正在编写一些涉及 Python 应用程序 运行ning 在 uwsgi 下的集成测试。
为了测试这个方面,我正在 运行ning 一个 uwsgi 假脱机程序,它要求 master 进程是 运行ning.
如果 pytest 有一个失败的测试,它 return 是一个非零退出代码,这很好。
没有 master 进程,整个 uwsgi 进程也 returns 这个退出代码,所以我们的持续集成服务器做出适当的响应。
但是,当主进程处于 运行ning 状态时,它总是以零退出代码退出 - 无论测试是否失败。
我需要它传递子进程的第一个非零退出代码(如果有的话)。
注意:我对模拟这个并不感兴趣——我需要测试这个工作。
我创建了一个 Dockerized Minimal, Complete, and Verifiable Example 来说明我的问题:
Dockerfile:
FROM python:3.6.4-slim-stretch
WORKDIR /srv
RUN apt-get update \
&& apt-get install -y build-essential \
&& pip install uwsgi pytest
COPY test_app.py /srv/
CMD ['/bin/bash']
test_app.py:
import pytest
def test_this():
assert 1==0
鉴于目录中的上述 2 个文件,如果我 运行 在 uwsgi 没有主进程 下进行此失败测试,则以下显示 return 代码:
$ docker build -t=test .
$ docker run test uwsgi --chdir /srv --pyrun /usr/local/bin/pytest
...
============================= test session starts ==============================
platform linux -- Python 3.6.4, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: /srv, inifile:
collected 1 item
test_app.py F [100%]
=================================== FAILURES ===================================
__________________________________ test_this ___________________________________
def test_this():
> assert 1==0
E assert 1 == 0
test_app.py:4: AssertionError
=========================== 1 failed in 0.05 seconds ===========================
$ echo $?
1
注意:您可以看到此过程(最后一行)中的 return 代码按要求非零
现在,除了 运行ning uwsgi 与 master 进程没有任何变化,我们得到以下输出:
$ docker run test uwsgi --set master=true --chdir /srv --pyrun /usr/local/bin/pytest
...
============================= test session starts ==============================
platform linux -- Python 3.6.4, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: /srv, inifile:
collected 1 item
test_app.py F [100%]
=================================== FAILURES ===================================
__________________________________ test_this ___________________________________
def test_this():
> assert 1==0
E assert 1 == 0
test_app.py:4: AssertionError
=========================== 1 failed in 0.05 seconds ===========================
worker 1 buried after 0 seconds
goodbye to uWSGI.
$ echo $?
0
注意:这次来自此过程(最后一行)的 return 代码为零 - 即使测试失败
如何让 uwsgi 将失败进程的退出代码转发给 master?
这可行,但感觉有点 hacky。如果有更好的答案,我会很乐意接受。
我通过添加两个附加文件(以及对 Dockerfile 的一个小更新)完成了这项工作:
Dockerfile:
FROM python:3.6.4-slim-stretch
WORKDIR /srv
RUN apt-get update \
&& apt-get install -y build-essential \
&& pip install uwsgi pytest
COPY test_app.py test run_tests.py /srv/
CMD ['/bin/bash']
测试:
#!/bin/bash
uwsgi --set master=true --chdir /srv --pyrun /srv/run_tests.py
exit $(cat /tmp/test_results)
run_tests.py:
#!/usr/bin/python
import re
import subprocess
import sys
from pytest import main
def write_result(retcode):
path = r'/tmp/test_results'
with open(path, 'w') as f:
f.write(str(retcode))
def run():
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
retcode = 1
try:
retcode = main()
finally:
write_result(retcode)
sys.exit(retcode)
if __name__ == '__main__':
run()
它的工作方式是我将 pytest 程序复制并调整到 run_tests.py
,它将测试的 return 代码写到一个临时文件中。测试是 运行 通过 bash 脚本:test
,运行s uwsgi,运行s 测试,然后使用 return 测试代码。
结果现在看起来像:
$ docker build -t=test .
$ docker run test /srv/test
...
============================= test session starts ==============================
platform linux -- Python 3.6.4, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: /srv, inifile:
collected 1 item
test_app.py F [100%]
=================================== FAILURES ===================================
__________________________________ test_this ___________________________________
def test_this():
> assert 1==0
E assert 1 == 0
test_app.py:4: AssertionError
=========================== 1 failed in 0.05 seconds ===========================
worker 1 buried after 0 seconds
goodbye to uWSGI.
$ echo $?
1