systemd 运行celery

However, the init.d script should still work in those Linux distributions as well since systemd provides the systemd-sysv compatiblity layer which generates services automatically from the init.d scripts we provide.

官网已经有了相关的教程http://docs.celeryproject.org/en/latest/userguide/daemonizing.html#usage-systemd, 但是在实际操作的时候发现按照教程来配置无法正常启动。会报错,于是把服务简化了一下,把配置和服务信息写到了一起。如果你也遇到这个问题可以尝试下面的简化脚本:

[Unit]
Description=Celery Service
After=network.target

[Service]
WorkingDirectory=/var/www/html
ExecStart=/usr/local/bin/celery -A proj worker --logfile=/var/log/celery/celery.log  --loglevel="INFO"

Restart=on-failure

#3秒后启动
RestartSec=3s

[Install]
WantedBy=multi-user.target

系统Ubuntu 18.04, systemd版本:

root@mars:/etc/systemd/system# systemctl --version
systemd 229
+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP 
+GCRYPT +GNUTLS +ACL +XZ -LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD -IDN

由apscheduler引发的django.db.utils.InternalError: (1054, u”Unknown column ‘rms.go_datetime’ in ‘field list'”)

apscheduler.scheduler:INFO 2019-03-01 10:22:53,849 Adding job tentatively -- it will be properly scheduled when the scheduler starts
apscheduler.scheduler:INFO 2019-03-01 10:22:53,849 Adding job tentatively -- it will be properly scheduled when the scheduler starts
Do first job!
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "F:\PyCharmProjects\B\venv\lib\site-packages\django\core\management\__init__.py", line 364, in execute_from_command_line
File "F:\PyCharmProjects\B\venv\lib\site-packages\django\utils\functional.py", line 35, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "F:\PyCharmProjects\B\venv\lib\site-packages\django\urls\resolvers.py", line 407, in url_patterns
patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
File "F:\PyCharmProjects\B\venv\lib\site-packages\django\utils\functional.py", line 35, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "F:\PyCharmProjects\B\venv\lib\site-packages\django\urls\resolvers.py", line 400, in urlconf_module
return import_module(self.urlconf_name)
File "C:\Python27\Lib\importlib\__init__.py", line 37, in import_module
__import__(name)
File "F:\PyCharmProjects\B\B\B\urls.py", line 433, in <module>
import td.jobs # NOQA @isort:skip
File "F:\PyCharmProjects\B\B\td\jobs.py", line 174, in <module>
deal_with_first_jobs()
File "F:\PyCharmProjects\B\B\td\jobs.py", line 88, in deal_with_first_jobs
send_wechat_mini_app_push_message(rmds)
File "F:\PyCharmProjects\B\B\td\push.py", line 201, in send_wechat_mini_app_push_message
for rmd in rmds:
File "F:\PyCharmProjects\B\venv\lib\site-packages\django\db\models\query.py", line 250, in __iter__
self._fetch_all()
File "F:\PyCharmProjects\B\venv\lib\site-packages\django\db\models\query.py", line 1121, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "F:\PyCharmProjects\B\venv\lib\site-packages\django\db\models\query.py", line 53, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch)
File "F:\PyCharmProjects\B\venv\lib\site-packages\django\db\models\sql\compiler.py", line 899, in execute_sql
raise original_exception
django.db.utils.InternalError: (1054, u"Unknown column 'rms.go_datetime' in 'field list'")

刚开始以为是代码写错了,后来发现并不是,出错的地方在jobs.py中所以其实并不是代码的问题,而是在jobs中为了能够在服务启动的时候发送上一次运行停止之后遗漏的任务导致的。所以如果使用了apscheduler可以尝试将jobs.py清空再次尝试。

Django APScheduler + uwsgi 定时任务重复运行

基于某些原因可能在开发的时候通过django的manage.py运行定时任务没有任何的问题,但是一旦到了线上环境通过nginx+uwsgi来运行就会发现定时任务不断的重复执行,并且基本都执行失败了。发生这个问题的原因在于uwsgi启动了多个进程来提供服务,于是每次启动的时候定时任务都会跟着再启动一次,于是有4个进程的话,对应的服务就会启动4次,除了第一次可能执行成功后面的基本都会挂掉。

要解决这个问题其实也不难,只要保证在第一次启动的时候添加定时任务并且执行,以后启动的进程不再处理定时任务即可。但是在这种条件下通过python的进程互斥其实貌似并不是非常好使,具体可以看这个:

uWSGI employs some tricks which disable the Global Interpreter Lock and with it, the use of threads which are vital to the operation of APScheduler. To fix this, you need to re-enable the GIL using the --enable-threads switch. See the uWSGI documentation for more details.

Also, assuming that you will run more than one worker process (as you typically would in production), you should also read the next section.

https://apscheduler.readthedocs.io/en/latest/faq.html#how-can-i-use-apscheduler-with-uwsgi

Continue Reading

django 主动抛出 403 异常

网上的做法基本都是下面的代码

return HttpResponseForbidden()

试了一下,效果一般,没有异常页面显示,最终显示的是浏览器的异常页面,如下图:

如果要想让服务器截获异常并且显示错误页可以用下面的方式:

id = request.GET.get('id', '')
timestamp = request.GET.get('timestamp', '')
accesskey = request.GET.get('accesskey', '')

if timestamp == '' or accesskey == '' or id == '':
    raise PermissionDenied

Continue Reading

ngix+uwsgi+django 以及阿里云rds数据库数据导入

网上关于如果通过nginx来运行django的文章还是蛮多的,但是有的地方写的可能不够细致,于是在实际操作的时候可能会出现一些问题,具体可以参考这个链接:https://www.cnblogs.com/frchen/p/5709533.html。但是实际在不熟的时候却发现uwsgi的配置文件貌似不怎么好用,于是去官网看了一下,近习惯了修改:

[uwsgi]
socket = 127.0.0.1:8001
chdir = /var/www/html/
wsgi-file = Project/wsgi.py
processes = 4
threads = 2
stats = 127.0.0.1:9191

#stats=%(chdir)/uwsgi/uwsgi.status

pidfile=uwsgi.pid

buffer-size = 65536

需要注意的一点是,这个chdir 是项目的根目录,也是工程文件的父目录,后面的wsgi-file则是工程目录和wsgi文件的结合路径,如果这个搞错了,后面的就直接跑不起来了。此时就可以通过uwsgi uwsgi.ini来启动服务了,但是如果此时通过浏览器直接去访问http://192.168.1.100:8001这个地址很有可能是失败的。要配置好nginx的代理之后通过nginx进行访问,nginx配置文件如下:

Continue Reading

如何绕过微信图片的防盗链

具体实现原来可以参考这个链接: https://www.zhihu.com/question/35044484

下面给个Django下的实现代码:

@csrf_exempt
def image_proxy(request):
    img = request.GET.get('img')
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36',
    }
    status = 0
    try:
        r = requests.get(
            img,
            headers=headers)
    except ConnectionError, ConnectTimeout:
        status = 1
    if status == 1:
        return ''
    response = HttpResponse(r.content, content_type='image/jpeg')
    return response

url.py

url(r'^spider-api/image-proxy/$', image_proxy),

访问方法,url:

http://127.0.0.1:8001/spider-api/image-proxy/?img=https://mmbiz.qpic.cn/mmbiz_png/WliaoSKPrpSPqGrhMmQK8MwKR6AZ7qDDy2JtSxRjk3ZUke41PUGP6RoaibzIgxw8ey5cejb5FzkplhgGd48oOxAg/640

django 1452, ‘Cannot add or update a child row: a foreign key constraint fails

网上这个问题搜索的概率非常高,但是实际上解决方法并不是非常完美,例如删除数据库重建什么的。由于刚开始的时候没有设计用户模块,中间添加的用户模块,此时数据库已经有很多数据了,如果删除数据重新创建是显然不可能的,于是搜索了一下,https://blog.csdn.net/qingche456/article/details/58153741 这个帖子中的方法确实能够解决问题,但是并不是十分完美,作为一个强迫症患者,一定要解决这个问题,而不是用这种投机取巧的办法。

我这里出现这个问题的原因在于,新建的用户表用户数量已经超过了原有的auth_user数据数量,所以外键已经无法获取到正确的用户id。原始的约束如下

ADD CONSTRAINT `django_admin_log_user_id_52fdd58701c5f563_fk_auth_user_id` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);

而我新创建的用户model为h4ckUser_hackuser,于是新创建的用户都会增加到h4ckUser_hackuser表中,而不是默认的auth_user表中。要解决这个问题就需要修改外键约束,我用phpmyadmin
后台发现无法修改这些数据。于是只好重建一个新表,然后将两个表名称替换。此时这个问题就完美解决了,新建的表注意将上面的代码改成
ADD CONSTRAINT `django_admin_log_user_id_52fdd58701c5f563_fk_auth_user_id` FOREIGN KEY (`user_id`) REFERENCES `h4ckUser_hackuser` (`id`);
此时在后台新建用户以及各种操作就完全没有问题了,日志系统也会正常进行记录。
另外如果migrate失败,可以尝试删除migration下最后生成的文件,同时对数据库中新增加的数据进行删除。然后重新直接make migraions和migrate,为了稳妥还是最好天前进行系统备份,例如快照系统和mysql备份。