python - 在 Flask 中后台运行进程

标签 python flask

我正在用 python 和 Flask 制作一个网络应用程序,当网站管理员的网站出现故障时,它会通过电子邮件和推文发送给网站管理员。我正在考虑运行一个无限 while 循环,等待 10 分钟,然后向要检查的网站发送请求,并检查返回的响应是否为 200。问题是在脚本中我可以插入这个循环吗?关于如何实现这一目标有什么建议吗?

最佳答案

士兵,你死后告诉我

尝试报告死机应用程序的问题并不是最可靠的方法。

使用外部进程观看应用

您应该有一些外部独立应用程序来监控您的应用程序。

如果你生活在纯Python环境中,你可以编写一个脚本,它会检查访问某个应用程序的url是否成功,如果不成功,它会提醒某人。对于警报,您可以尝试例如日志,包含通过电子邮件发送的日志记录(请参阅 MailHandlerGMailHandler )。

在生产环境中,最好运行一些监控应用程序,例如 Nagios只需通过 check_http 进行检查

使用日志检查脚本示例

为了更好的可读性,内容被分成更多部分,真正的脚本位于一个名为 monitor_url.py

的文件中

monitor_url.py:文档字符串、导入和 MAIL_TEMPLATE

Docstring解释了用法,最终被命令行解析器使用docopt

进口主要与日志相关

"""monitor_url.py - check GET access to a url, notify by GMail about problems
Usage:
    monitor_url.py   [options] <url> <from> <pswd> <to>...
    monitor_url.py -h

Options:
  -L, --logfile <logfile>    Name of logfile to write to [default: monitor_url.log].
  -N, --archives <archives>  Number of daily logs to keep, use 0 for unlimited [default: 0]

The check is performed once a minute and does HTTP GET request to <url>.
If there is a problem, it sends an e-mail using GMail account.
There is a limit of 6 e-mails, which can be sent per hour.
"""
import time
from logbook import Logger, GMailHandler, StderrHandler, NestedSetup, TimedRotatingFileHandler, Processor
from logbook.more import JinjaFormatter
from datetime import timedelta
import requests
from requests.exceptions import ConnectionError

MAIL_TEMPL = """Subject: {{ record.level_name }} on {{ record.extra.url }}

{{ record.message }}

Url: {{ record.extra.url }}
{% if record.exc_info %}
Exception: {{ record.formatted_exception }}
{% else %}
Status: {{ record.extra.req.status_code }}
Reason: {{ record.extra.req.reason }}
{% endif %}
"""

monitor_url.py:执行检查的main函数

该脚本在 while 中循环,每分钟执行一次检查。 如果检测到问题或状态代码已更改,GMailHandler 将配置为发送电子邮件。

def main(url, e_from, pswd, e_to, logfile, archives):
    log = Logger("httpWatcher")
    def inject_req(record):
        record.extra.url = url
        record.extra.req = req
    processor = Processor(inject_req)
    gmail_handler = GMailHandler(e_from, pswd, e_to,
        level="WARNING", record_limit=6, record_delta=timedelta(hours=1), bubble=True)
    gmail_handler.formatter = JinjaFormatter(MAIL_TEMPL)

    setup = NestedSetup([StderrHandler(),
        TimedRotatingFileHandler(logfile, bubble=True),
        gmail_handler,
        processor])

    with setup.applicationbound():
        last_status = 200
        while True:
            try:
                req = requests.get(url)
                if req.status_code != last_status:
                    log.warn("url was reached, status has changed")
                if req.ok:
                    log.info("url was reached, status OK")
                else:
                    log.error("Problem to reach the url")
                last_status = req.status_code
            except ConnectionError:
                req = None
                log.exception("Unable to connect")
                last_status = 0
            time.sleep(6)

montior_url.py 最终if __name__ ...

这部分实际上是解析命令行参数并调用main

if __name__ == "__main__":
    from docopt import docopt
    args = docopt(__doc__)
    print args
    main(args["<url>"], args["<from>"], args["<pswd>"], args["<to>"], args["--logfile"],
            int(args["--archives"]))

调用它

尝试不带参数调用它:

$ python monitor_url.py 

用法: Monitor_url.py [选项] ... Monitor_url.py -h

要获得完整帮助,请使用-h

$ python monitor_url.py -h
...the help is the same as script docstring...

用于真正的监控,这里用于监控http://localhost:8000

$ python monitor_url.py -L mylog.log -N 2 http://localhost:8000 <yourmail>@gmail.com xxxpasswordxxx notified.person@example.com
{'--archives': '2',
 '--logfile': 'mylog.log',
 '-h': False,
 '<from>': 'your.mail@gmail.com',
 '<pswd>': 'xxxxxxx',
 '<to>': ['notified.person@example.com'],
 '<url>': 'http://localhost:8000'}
[2014-06-09 19:41] INFO: httpWatcher: url was reached, status OK
[2014-06-09 19:41] ERROR: httpWatcher: Unable to connect
Traceback (most recent call last):
....(shortened)...
    raise ConnectionError(e, request=request)
ConnectionError: HTTPConnectionPool(host='localhost', port=8000): Max retries exceeded with url: / (Caused by <class 'socket.error'>: [Errno 111] Connection refused)
[2014-06-09 19:41] WARNING: httpWatcher: url was reached, status has changed
[2014-06-09 19:41] INFO: httpWatcher: url was reached, status OK

检查本地文件夹中创建的日志文件。

检查你的gmail收件箱(如果没有任何内容,你就得玩密码了)。

结论

Twitter 通知也可以通过日志 实现,但此处未显示。

要运行该脚本,需要 Python 2.7,并且您应安装一些软件包:

$ pip install logbook jinja2 requests

管理来自这样的脚本的通知并不容易。在这方面考虑这个测试质量的脚本。

使用 Nagios 等解决方案似乎更适合此目的。

关于python - 在 Flask 中后台运行进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24115650/

相关文章:

python - 使用 requests 库将 CURL 请求转换为 Python

python - 从被比较的两个字典之一的键创建一个新字典,Python

python - Flask App with Gunicorn on Nginx 服务器 POST 错误

python - flask-login 从不注销

javascript - 从 PostgreSQL JSONField 到 Django 模板中的 JSON 对象

Python 字符串转换

python - Python Flask 中 ssl_context 选项的区别

python - 从蓝图中更改 jinja_env

python - 使用flask-zodb的LockError

python - 为什么这个 Python boolean 比较返回一个三元组?