简体   繁体   English

在Flask的后台运行进程

[英]Running A Process In the Background In Flask

I am making a webapp in python and flask which will email & tweet to the webmaster when the moment his website goes down. 我正在用python和flask创建一个webapp,当他的网站关闭时,它会通过电子邮件和tweet通知网站管理员。 I am thinking of running an infinite while loop which waits for 10 minutes and then send a request to the website to be checked and checks if the returned response is 200. The problem is that were in the script can I insert this loop? 我正在考虑运行一个无限的while循环,该循环等待10分钟,然后将请求发送到要检查的网站,并检查返回的响应是否为200。问题在于脚本中是否可以插入此循环? Any suggestions about how I can achieve this? 关于如何实现此目标的任何建议?

Soldier, tell me when you are dead 士兵,你死后告诉我

Trying to report a problem from dying app is not the most reliable method. 尝试从即将死机的应用程序报告问题不是最可靠的方法。

Use external process to watch the app 使用外部流程观看应用

You shall have some external independent app, monitoring your app. 您将拥有一些外部独立应用程序,以监视您的应用程序。

If you live in pure Python environment, you may write a script, which will check if accessing some app url succeeds and if not, it would alert someone. 如果您生活在纯Python环境中,则可以编写脚本,该脚本将检查是否成功访问某些应用程序URL,否则,将向某人发出警报。 For alerting, you may try eg logbook with log records being sent by e-mail (see MailHandler or GMailHandler ). 对于警报,您可以尝试例如通过电子邮件发送日志记录的logbook (请参阅MailHandlerGMailHandler )。

In production environment it would be best to run some monitoring app like Nagios and simply check by check_http 在生产环境中,最好运行某些监视应用程序(如Nagios)并只需通过check_http检查

Sample checking script using Logbook 使用Logbook的示例检查脚本

For better readibility, the content is split to more parts, real script is in one file called monitor_url.py 为了提高可读性,将内容分为更多部分,真实的脚本位于一个名为monitor_url.py文件中

monitor_url.py : Docstring, imports and MAIL_TEMPLATE monitor_url.py :文档字符串,导入和MAIL_TEMPLATE

Docstring explains usage and is finally used by command line parser docopt Docstring解释了用法,最后由命令行解析器docopt

Imports are mostly logbook related 进口大多与logbook有关

"""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 function performing the checks monitor_url.py :执行检查的main功能

This script is looping in while and performs once a minute a check. 此脚本中循环while ,进行一分钟一次的检查。 If a problem is detected, or status code has changed, GMailHandler is configured to send e-mail. 如果检测到问题或状态代码已更改,则将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 final if __name__ ... montior_url.py if __name__ ... montior_url.py最终if __name__ ...

This part actually parses command line parameters and calls the main 这部分实际上是解析命令行参数并调用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"]))

Call it 称它为

Try to call it without parameters: 尝试不带参数调用它:

$ python monitor_url.py 

Usage: monitor_url.py [options] ... monitor_url.py -h 用法:monitor_url.py [选项] ... monitor_url.py -h

To get full help, use -h 要获得完整的帮助,请使用-h

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

Use it for real monitoring, here used for monitoring http://localhost:8000 使用它进行实际监视,这里用于监视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

Check logfile created in local folder. 检查在本地文件夹中创建的日志文件。

Check your gmail inbox (if there is nothing, you have to play with the password). 检查您的gmail收件箱(如果没有,则必须使用密码进行播放)。

Conclusions 结论

Twitter notification is also possible with logbook , but is not shown here. 使用logbook也可以进行Twitter通知,但此处未显示。

To run the script, Python 2.7 is expected and you shall install some packages: 要运行该脚本,应使用Python 2.7,并且应安装一些软件包:

$ pip install logbook jinja2 requests

Managing notification from such a script is not easy. 从这样的脚本管理通知并不容易。 Consider this script of beta quality in this regard. 考虑一下这方面的beta质量脚本。

Usage of solutions like Nagios seems to be more appropriate for this purpose. 使用Nagios之类的解决方案似乎更适合此目的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM