因为项目中用到了channels做websocket消息推送,所以以前那种nginx+uwsgi的模式行不通了~,channels推荐的是daphne服务器,所以Google了一下,都说是用nginx+uwsgi+daphne+supervisor这一套组合来部署。看了下网上的教程,七零八落的,好不容易才拼凑起来,所以才有自己总结一下的想法。
服务器:CentOS8.2 64位
开发平台: Python3.8.3
Web框架: Django3.0.8
数据库: MySQL 8.0
缓存数据库: Redis
使用Nginx代理,将http部分请求发送给uwsgi或者gunicorn进行处理,将websocket部分请求发送给daphne进行处理。uwsgi和daphhe均使用supervisord进行控制。
需要注意的是,由于Nginx无法识别http请求和websocket请求,需要通过路由来区分是哪种协议。我使用的方法是规定所有的websocket的路由均以/ws开头(如: ws://www.example/ws/table/table_id/),这样就可以让Nginx将所有以/ws开头的请求全部转发给daphne进行处理。
当然,这一切都是在服务器的一个虚拟环境中。
安装方法在我另一篇博客中: 如何在 CentOS 8 上安装 Python 3.8
如果嫌pip安装太慢,可以参考这篇文章:更换pip源到国内镜像
yum install nginx -y
systemctl enable nginx
systemctl start nginx
[[email protected] ~]# nginx -V
nginx version: nginx/1.14.1
built by gcc 8.2.1 20180905 (Red Hat 8.2.1-3) (GCC)
built with OpenSSL 1.1.1 FIPS 11 Sep 2018
TLS SNI support enabled
configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-debug --with-cc-opt='-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E'
firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --permanent --zone=public --add-service=https
firewall-cmd --reload
配置文件目录
主配置文件:/etc/nginx/nginx.conf
默认文件目录:/usr/share/nginx/html
错误日志:/var/log/nginx/error.log
访问日志:/var/log/nginx/access.log
参考我的这篇文章: CentOS 8 安装MySQL 8.0
参考我的这篇文章:CentOS 8安装Redis的两种方式
pip install virtualenvwrapper
接下来编辑.bashrc文件,这是重点
[root@ITCMDB ~]# vi ~/.bashrc
添加下面j几行
VIRTUALENVWRAPPER_PYTHON=/usr/bin/python # 指定virtualenvwrapper执行的python版本
export WORKON_HOME=$HOME/.virtualenvs # 指定虚拟环境存放目录,.virtualenvs目录名可自拟
VIRTUALENVWRAPPER_VIRTUALENV_ARGS='' # 添加virtualenvwrapper的参数,生成干净隔绝的环境
source /usr/local/bin/virtualenvwrapper.sh # virtualenvwrapper.sh所在目录
保存后,重载./bashrc文件
source ~/.bashrc
执行命令
mkvirtualenv kzitcmdb(虚拟环境名称)
就创建好了, 当然,还有许多命令选项,我这里就不多说了
irtualenv
# 安装
$ pip install virtualenv
# 激活虚拟环境
$ source my_project/bin/activate
# 退出虚拟环境
$ deactivate
# 输出当前依赖包
$ pip freeze > requirements.txt
# 安装依赖包
$ pip install -r requirements.txt
virtualenvwrapper
# 安装
$ pip install virtualenvwrapper
# 修改~/.zshrc
$ cat ~/.zshrc
if [ -f /usr/local/bin/virtualenvwrapper.sh ]; then
export WORKON_HOME=$HOME/virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
fi
# 创建虚拟环境,创建成功后 $WORKON_HOME 下会多出一个文件夹
$ mkvirtualenv my_prj
# 使用虚拟环境
$ workon my_prj
# 退出虚拟环境
$ deactivate
# 删除
$ rmvirtualenv my_prj
# 列出所有环境
$ lsvirtualenv
# 进入到当前虚拟环境中
$ cdvirtualenv
# 进入到当前虚拟环境的 site-packages 中
$ cdsitepackages
.gitignore
*.py[cod] # 将匹配 .pyc、.pyo 和 .pyd文件
__pycache__/ # 排除整个文件夹
将准备的requirements.txt上传到服务器
然后执行下面命令
[root@ITCMDB /]# workon led_dev
(led_dev) [root@ITCMDB /]# pip install -r requirements.txt
等待安装完成即可
/root/webapp
同时,将数据库上传到服务器
本例中,用navicat进行数据库的复制。
此时,可以通过python内置的服务器进行测试
(kzitcmdb) [root@ITCMDB wwwroot]# python manage.py runserver 0.0.0.0:9999
启动成功后,在浏览器进行测试。
在django的setting文件中,添加下面一行内容:
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
并在项目根目录下运行命令:
python manage.py collectstatic
完成后,重启nginx
我这里是把我的项目的nginx配置文件放在了项目文件夹中,便于管理
在这个目录下新建一个led.conf
[root@ITCMDB nginx]# pwd
/root/webapp/LED/conf/nginx/
编辑led.conf
upstream led {
server unix:///root/webapp/LED/conf/sock/server.sock fail_timeout=0;
}
upstream websocket {
server unix:///root/webapp/LED/conf/sock/websocket.sock fail_timeout=0;
}
log_format access_exp '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
server {
listen 8000;
server_name 192.168.12.156; # substitute your machine's IP address or FQDN
charset utf-8;
client_max_body_size 1024M;
location /media {
alias /root/webapp/LED/media/;
}
location /static {
alias /root/webapp/LED/static/;
}
access_log /root/webapp/LED/log/nginx/access.log access_exp;
error_log /root/webapp/LED/log/nginx/error.log;
open_log_file_cache max=10;
location / {
# gunicorn 配置
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header Host $http_host;
# proxy_redirect off;
# if (!-f $request_filename) {
# proxy_pass http://led;
# break;
#}
# uwsgi 配置
uwsgi_pass led;
include /root/webapp/LED/conf/uwsgi/uwsgi_params;
}
location /ftp {
alias /root/webapp/LED/media/file/; #目录文件服务器根目录
autoindex on; #允许nginx在浏览器以文件夹形式访问
autoindex_exact_size off; #显示文件大小
autoindex_localtime on; #显示文件时间
charset utf-8; # 避免中文乱码
}
location /push {
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_read_timeout 36000s;
proxy_send_timeout 36000s;
}
}
然后需要将led.conf软链接到/etc/nginx/conf.d/文件夹下,这样nginx才能加载到你的配置文件
ln -s /root/webapp/LED/conf/nginx/led.conf /etc/nginx/conf.d/
在Nginx和daphne以及uwsgi进行通信时,有http socket和file socket两种通信方式,推荐使用后一种file socket的方式, 也就是我用的这种。
我这里是把我的项目uwsgi的ini文件也放在了项目文件夹中,便于管理
在这个目录下新建一个led.ini
[root@ITCMDB uwsgi]# pwd
/root/webapp/LED/conf/uwsgi/
编辑led.ini
[uwsgi]
#使用nginx连接时使用
socket=/root/webapp/LED/conf/sock/server.sock
#直接做web服务器使用 python manage.py runserver ip:port
#http=0.0.0.0:8000
#项目目录
chdir=/root/webapp/LED
#项目中wsgi.py文件的目录,相对于项目目录
wsgi-file=LED/wsgi.py
#指定启动的工作进程数
processes=2
#指定工作进程中的线程数
threads=2
#指定在这些进程里有一个主进程
master=True
#保存启动之后主进程的pid
pidfile=/root/webapp/LED/conf/uwsgi/uwsgi.pid
#设置uwsgi后台运行,uwsgi.log保存日志信息
daemonize=/root/webapp/LED/log/uwsgi.log
#设置日志文件最大字节数
log-maxsize = 100000
#设置每个进程最大请求数
max-requests = 1000
#设置虚拟环境的路径
virtualenv=/root/.virtualenvs/led_dev
重点:nginx的配置文件中有一个uwsgi_params文件,在/etc/nginx/文件夹内,拷贝到这个文件夹
安装教程:CentOS安装Supervisor
使用教程: supervised使用教程
我的daphne和uwsgi都是用supervisor管理的
编辑/etc/supervisord.conf 解除注释并修改(文件末尾)
[include]
files = /root/webapp/LED/conf/supervisor/*.conf
在/root/webapp/LED/conf/supervisor/文件夹新建 daphne.conf、uwsgi.conf、celery_worker.conf文件,因为我还用了celery,所以多一个celery的配置。
daphne.conf
[program:led.daphne]
command=/root/.virtualenvs/led_dev/bin/daphne -u /root/webapp/LED/conf/sock/websocket.sock LED.asgi:application
directory=/root/webapp/LED
user=root
autostart=true ; 随着supervisord的启动而启动
autorestart=true ; 自动重启。。当然要选上了
startretries=10 ; 启动失败时的最多重试次数
exitcodes=0 ; 正常退出代码
stopsignal=KILL ; 用来杀死进程的信号
stopwaitsecs=10 ; 发送SIGKILL前的等待时间
redirect_stderr=true ; 重定向stderr到stdout
stdout_logfile_maxbytes=20MB
stdout_logfile_backups=20
redirect_stderr=true
stdout_logfile=/root/webapp/LED/log/supervisor/daphne.log
; 给每个进程命名,便于管理
process_name=daphne_led
; 默认为 false,如果设置为 true,当进程收到 stop 信号时,会自动将该信号发给该进$
stopasgroup=true ; send stop signal to the UNIX process
; 默认为 false,如果设置为 true,当进程收到 kill 信号时,会自动将该信号发给该进$
killasgroup=true ; SIGKILL the UNIX process group (def false)
uwsgi.conf
;[program:led.uwsgi]
;command=/root/.virtualenvs/led_dev/bin/uwsgi --ini /root/webapp/LED/conf/uwsgi/led.ini
;directory=/root/webapp/LED
;user=root
;autostart=true ; 随着supervisord的启动而启动
;autorestart=true ; 自动重启。。当然要选上了
;startretries=10 ; 启动失败时的最多重试次数
;exitcodes=0 ; 正常退出代码
;stopsignal=KILL ; 用来杀死进程的信号
;stopwaitsecs=10 ; 发送SIGKILL前的等待时间
;redirect_stderr=true ; 重定向stderr到stdout
;stdout_logfile_maxbytes=20MB
;stdout_logfile_backups=20
;stdout_logfile=/root/webapp/LED/log/supervisor/uwsgi.log
; 默认为 false,如果设置为 true,当进程收到 stop 信号时,会自动将该信号发给该进$
;stopasgroup=true ; send stop signal to the UNIX process
; 默认为 false,如果设置为 true,当进程收到 kill 信号时,会自动将该信号发给该进$
;killasgroup=true ; SIGKILL the UNIX process group (def false)
celery_worker.conf
[program:led.celery.worker]
command=/root/.virtualenvs/led_dev/bin/celery -A LED worker -B -l info ; 被监控的进程路径
directory=/root/webapp/LED
user=root
numprocs=1
autostart=true ; 随着supervisord的启动而启动
autorestart=true ; 自动重启。。当然要选上了
startretries=3 ; 启动失败时的最多重试次数
exitcodes=0 ; 正常退出代码
stopsignal=KILL ; 用来杀死进程的信号
stopwaitsecs=10 ; 发送SIGKILL前的等待时间
redirect_stderr=true ; 重定向stderr到stdout
stdout_logfile_maxbytes=20MB
stdout_logfile_backups=20
stdout_logfile=/root/webapp/LED/log/supervisor/celery.log
; 给每个进程命名,便于管理
process_name=celery_led
; 默认为 false,如果设置为 true,当进程收到 stop 信号时,会自动将该信号发给该进$
stopasgroup=true ; send stop signal to the UNIX process
; 默认为 false,如果设置为 true,当进程收到 kill 信号时,会自动将该信号发给该进$
killasgroup=true ; SIGKILL the UNIX process group (def false)
启动supervisor
supervisord -c /etc/supervisord.conf
gunicorn使用教程:
python之gunicorn的配置
gunicorn 使用教程
gunicorn + nginx:通过套接字或代理服务器
pip install gunicorn
pip install gevent # 因为我使用的是gevent方式启动gunicorn
import multiprocessing
import os
import sys
BASE_DIR = '/root/webapp/LED/'
sys.path.append(BASE_DIR)
LOG_DIR = os.path.join(BASE_DIR, 'log/gunicorn/')
if not os.path.exists(LOG_DIR):
os.makedirs(LOG_DIR)
# 监听地址和端口
# bind = "127.0.0.1:8001"
# 使用套接字
bind = "unix:/root/webapp/LED/conf/sock/server.sock"
# 以守护进程的形式后台运行
daemon = True
# 服务器中在pending状态的最大连接数,即client处于waiting的数目。超过这个数目, client连接会得到一个error。
# 建议值64-2048。
backlog = 512
# 超时
timeout = 30
# 调试状态
debug = False
# gunicorn要切换到的目的工作目录
chdir = BASE_DIR
# 工作进程类型(默认的是 sync 模式,还包括 eventlet, gevent, or tornado, gthread, gaiohttp)
worker_class = 'gevent'
# 工作进程数
workers = (multiprocessing.cpu_count()) + 1
# 客户端最大同时连接数。只适用于eventlet, gevent工作方式。
worker_connections = ((multiprocessing.cpu_count()) + 1) * 1000
# 指定每个工作进程开启的线程数
# threads = multiprocessing.cpu_count() * 2
# 日志
# 日志级别,这个日志级别指的是错误日志的级别(debug、info、warning、error、critical),而访问日志的级别无法设置
loglevel = 'info'
# 其每个选项的含义如下:
'''
h remote address
l '-'
u currently '-', may be user name in future releases
t date of the request
r status line (e.g. ``GET / HTTP/1.1``)
s status
b response length or '-'
f referer
a user agent
T request time in seconds
D request time in microseconds
L request time in decimal seconds
p process ID
'''
# 访问日志文件
accesslog = os.path.join(LOG_DIR, 'gunicorn.access.log')
# 错误日志文件
errorlog = os.path.join(LOG_DIR, 'gunicorn.error.log')
# pid 文件
pidfile = os.path.join(BASE_DIR, 'conf/gunicorn/led_gunicorn.pid')
# 进程名
proc_name = 'led.pid'
# 指定worker进程的运行用户名。
user = 'root'
# 更多配置请执行:gunicorn -h 进行查看
在/root/webapp/LED/conf/supervisor/文件夹新建 gunicorn.conf,注意: gunicorn.conf 和 uwsgi.conf部署的时候二选一就行了。到时候可以把另一个注释掉。
gunicorn.conf
[program:led.gunicorn]
command=/root/.virtualenvs/led_dev/bin/gunicorn LED.wsgi:application -c /root/webapp/LED/conf/gunicorn/gunicorn.conf.py --log-level=info
directory=/root/webapp/LED
user=root
autostart=true ; 随着supervisord的启动而启动
autorestart=true ; 自动重启。。当然要选上了
startretries=10 ; 启动失败时的最多重试次数
exitcodes=0 ; 正常退出代码
stopsignal=KILL ; 用来杀死进程的信号
stopwaitsecs=10 ; 发送SIGKILL前的等待时间
redirect_stderr=true ; 重定向stderr到stdout
stdout_logfile_maxbytes=20MB
stdout_logfile_backups=20
stdout_logfile=/root/webapp/LED/log/supervisor/gunicorn.log
; 给每个进程命名,便于管理
process_name=gunicorn_led
; 默认为 false,如果设置为 true,当进程收到 stop 信号时,会自动将该信号发给该进$
stopasgroup=true ; send stop signal to the UNIX process
; 默认为 false,如果设置为 true,当进程收到 kill 信号时,会自动将该信号发给该进$
killasgroup=true ; SIGKILL the UNIX process group (def false)
使用gunicorn的nginx配置:
led.conf
upstream led {
server unix:///root/webapp/LED/conf/sock/server.sock fail_timeout=0;
}
upstream websocket {
server unix:///root/webapp/LED/conf/sock/websocket.sock fail_timeout=0;
}
log_format access_exp '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
server {
listen 8000;
server_name 192.168.12.156; # substitute your machine's IP address or FQDN
charset utf-8;
client_max_body_size 1024M;
location /media {
alias /root/webapp/LED/media/;
}
location /static {
alias /root/webapp/LED/static/;
}
access_log /root/webapp/LED/log/nginx/access.log access_exp;
error_log /root/webapp/LED/log/nginx/error.log;
open_log_file_cache max=10;
location / {
# gunicorn 配置
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
if (!-f $request_filename) {
proxy_pass http://led;
break;
}
# uwsgi 配置
# uwsgi_pass led;
# include /root/webapp/LED/conf/uwsgi/uwsgi_params;
}
location /ftp {
alias /root/webapp/LED/media/file/; #目录文件服务器根目录
autoindex on; #允许nginx在浏览器以文件夹形式访问
autoindex_exact_size off; #显示文件大小
autoindex_localtime on; #显示文件时间
charset utf-8; # 避免中文乱码
}
location /push {
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_read_timeout 36000s;
proxy_send_timeout 36000s;
}
}
启动supervisor
supervisord -c /etc/supervisord.conf
启动nginx
systemctl start nginx.service
没报错的话就是可以了~
安装:
yum -y install logrotate crontabs
配置:
/root/webapp/LED/log/gunicorn/*.log {
su root root
nocompress
daily
copytruncate
create
notifempty
rotate 7
olddir /root/webapp/LED/log/gunicorn
missingok
dateext
postrotate
[ -e /root/webapp/LED/conf/gunicorn/led_gunicorn.pid ] && kill -USR1 $(cat /root/webapp/LED/conf/gunicorn/led_gunicorn.pid)
endscript
}
/root/webapp/LED/log/nginx/*.log {
su root root
nocompress
daily
copytruncate
create
notifempty
rotate 7
olddir /root/webapp/LED/log/nginx
missingok
dateext
postrotate
[ -e /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
endscript
}
sudo crontab -e
然后编辑:
# rotate nginx log erery day
0 0 * * * /usr/sbin/logrotate -f /root/webapp/LED/conf/logrotate/nginx-log-rotate
0 0 * * * /usr/sbin/logrotate -f /root/webapp/LED/conf/logrotate/gunicorn-log-rotate
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
},
'skip_static_requests': {
'()': 'django.utils.log.CallbackFilter',
'callback': skip_static_requests
},
},
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(process)d %(thread)d %(name)s:%(lineno)s %(funcName)s() %(message)s'
},
'verbose_sql': {
'format': '%(levelname)s %(asctime)s %(process)d %(thread)d %(name)s:%(lineno)s %(funcName)s() %(sql)s\n%(params)s\n%(duration)ss'
},
},
'handlers': {
'console': {
'level': 'DEBUG',
'filters': ['skip_static_requests'],
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
'console_error': {
'level': 'ERROR',
'filters': ['skip_static_requests'],
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
'console_sql': {
'level': 'WARNING',
'filters': ['skip_static_requests'],
'class': 'logging.StreamHandler',
'formatter': 'verbose_sql',
},
},
'loggers': {
'django': {
'handlers': ['console'],
'level': 'INFO',
'propagate': True,
},
'django.request': {
'handlers': ['console_error'],
'level': 'ERROR',
'propagate': False,
},
'django.db.backends': {
'handlers': ['console_sql'],
'level': 'WARNING',
'propagate': False,
},
'django.security': {
'handlers': ['console_error'],
'level': 'ERROR',
'propagate': False,
},
'daphne': {
'handlers': [
'console',
],
'level': 'INFO'
},
},
}
def skip_static_requests(record):
if isinstance(record.args, dict):
if record.args.get('path', None):
if record.args.get('path').startswith('/static/'):
return False
if record.args.get('path').startswith('/media/'):
return False
if record.args.get('path').startswith('/captcha/image/'):
return False
return True
按上面步骤一步步来的话,基本就可以部署成功了,记得部署之前要把项目的settings配置文件配置好。
Error: Another program is already listening on a port that one of our HTTP servers is configured to use. Shut this program down first before starting supervisord.
解决办法:
运行命令
unlink /tmp/supervisor.sock
open() "/etc/nginx/conf.d/led.conf" failed (13: Permission denied) in /etc/nginx/nginx.conf
或者是nginx静态资源文件无法访问,403 forbidden错误:
解决方法:
nginx: [error] invalid PID number "" in "/run/nginx.pid"
解决办法
需要先执行
nginx -c /etc/nginx/nginx.conf
nginx.conf文件的路径可以从nginx -t的返回中找到。
nginx -t
nginx -s reload
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
我们在连接mysql的时候,如果host是localhost, 就会使用Unix Domain Socket来连接, MySql默认的sock文件路径是/tmp/mysql.sock, 一些mysql 安装方法 将 mysql .sock放在/var/lib/mysql .sock或者其他的什么地方,你可以通过修改/etc/my.cnf文件来修正它(8.0的配置文件好像是在/etc/my.cnf.d/mysql-server.cnf),打开文件,可以看到如下的东东:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysql/mysqld.log
pid-file=/run/mysqld/mysqld.pid
1. 修改HOST
打开settings.py文件,找到DATABASES的HOST字段。
有两种修改方案:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'xxx',
'USER': 'root',
'PASSWORD': 'passwd',
'HOST':'127.0.0.1', # 或者 `/tmp/mysql.sock`
'PORT':'3306',
}
}
2. 修改mysql的sock文件路径
vi etc/my.cnf # 或者 /etc/my.cnf.d/mysql-server.cnf
将sock路径变更为/var/lib/mysql/mysql.sock
socket = /tmp/mysql.sock
重启MySql服务。
Centos机器上
systemctl restart mysqld.service
在这里我用的是软链接的方式,因为我不想修改这些默认的配置,毕竟小白一个…
mysql.sock 一般不是在 /tmp/mysql.sock 就是在 /var/lib/mysql/mysql.sock 这里,没有的话就用
ln -s /var/lib/mysql/mysql.sock /tmp/mysql.sock
或者是
ln -s /tmp/mysql.sock /var/lib/mysql/mysql.sock
3. 数据库连接指定sock路径
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'xxx',
'USER': 'root',
'PASSWORD': 'passwd',
'OPTIONS': {
"unix_socket": "/tmp/mysql.sock",
},
}
}