需要工具:

    1.mysql 8.0

    2.python 3.11.0

        库(gunicorn(uvicorn),pymysql, supervisor, pipenv  2020.11.15,django-simpleui,django-ckeditor,pillow, paho-mqtt,cryptography requests[获取每次一句,可以不要,后期去掉这功能]),graphviz,django-widget-tweaks, django-simple-captcha, django-humanize, user-agents

    3.django 5.2

    3.nginx 1.16.1

搭建环境:

    centos 8


01 搭建mysql  

点击查看

02 搭建虚拟环境

点击查看

03 django部署代码

14.部署代码

接下来开始准备部署代码,让我们的博客应用在服务上跑起来,这和在本地开发时的过程是一模一样的。不过为了将应用部署到服务器上,我们首先要对项目做一点配置,打开 settings.py,找到 ALLOWED_HOSTS,将其修改为:

blog/settings.py
 
ALLOWED_HOSTS = ['127.0.0.1', 'localhost ', '.yys534640040.club']

或者
ALLOWED_HOSTS = ['*',]

指定了 ALLOWED_HOSTS 的值后,django 将只允许通过指定的域名访问我们的应用,比如这里只允许通过 127.0.0.1,localhost 以及 zmrenwu.com 和其任意子域名(域名前加一个点表示允许访问该域名下的子域名)访问(即 HTTP 报文头部中 Host 的值必须是以上指定的域名,通常你在浏览器输入域名访问网站时,Host 的值就会被设置为网站的域名),这样可以避免 HTTP Host 头攻击。

django 项目中会有一些 CSS、JavaScript 等静态文件,为了能够方便地让 Nginx 处理这些静态文件的请求,我们把项目中的全部静态文件收集到一个统一的目录下,这个目录通常位于 django 项目的根目录,并且命名为 static。为了完成这些任务,需要在项目的配置文件里做一些必要的配置:

blog/settings.py
# 其他配置...
STATIC_URL = '/static/'
# 加入下面的配置
STATIC_ROOT = os.path.join(BASE_DIR, "/home/blog/static/")  # 为centosstatic所在文件夹,如果设置/static/使用 collectstatic命令可能保存centos根目录

STATIC_ROOT 即指定静态文件的收集路径,这里指定为 BASE_DIR(项目根目录,在 settings.py 文件起始处定义)下的 static 文件夹。

把win10的数据库复制centos上

mysqldump yys -u root -p密码  | mysql -h 175.24.115.96 yys -u root -p密码

 

安装所需要的库

pip intall pymysql
pip intall django-simpleui
pip intall django-ckeditor
pip intall pillow

然后创建一下数据库:

python manage.py makemigrations
python manage.py migrate

启动开发服务器:

[root@VM_0_6_centos blog]# python manage.py runserver 0.0.0.0:8000

这里我们启动开发服务器时指定了服务器运行的 ip 和端口,这将允许通过公网 ip 的 8000 端口访问我们的博客。访问 ip:8000,可以看到访问成功(其中 ip 为你服务器的公网 ip)。

 

04 搭建Gunicorn

 

pipenv install uvicorn
pipenv run uvicorn --workers 2 --host 127.0.0.1 --port 8000 blog.asgi:application

下面是 Gunicorn

django 官方文档强调使用 runserver 开启的开发服务器仅用于开发测试,不建议用于生产环境。所以我们使用流行的 Gunicorn 来启动可以用于线上环境的服务器。

首先进入到项目根目录,安装 Gunicorn:

pipenv install gunicorn

由于我们在服务端修改安装了 gunicorn,代码中 Pipfile 文件和 Pipfile.lock 文件会被更新:

回到线上服务器,在项目根目录,执行下面的命令启动服务:

pipenv run gunicorn blog.wsgi -w 2 -k gthread -b 0.0.0.0:8000  

来解释一下各个参数的含义。

`-w 2 表示启动 2 个 worker 用于处理请求(一个 worker 可以理解为一个进程),通常将 worker 数目设置为 CPU 核心数的 2-4 倍。

-k gthread 指定每个 worker 处理请求的方式,根据大家的实践,指定为 gthread 的异步模式能获取比较高的性能,因此我们采用这种模式。

-b 0.0.0.0:8000,将服务绑定到 8000 端口,运行通过公网 ip 和 8000 端口访问应用。

访问 ip:8000(ip 为你服务器的公网 ip),应用成功访问了,但是我们看到样式完全乱了。别急,这不是 bug!此前我们使用 django 自带的开发服务器,它会自动帮我们处理静态样式文件,但是 Gunicorn 并不会帮我们这么做。因为处理静态文件并不是 Gunicorn 所擅长的事,应该将它交给更加专业的服务应用来做,比如 Nginx。

 

 *如果为未找到Gunicorn命令可以添加环境变量

①找gunicorn路径

如果不启动,加入环境变量

find / -name gunicorn

/usr/local/sbin/python-3.7/bin/gunicorn  

 ②

vim ~/.bash_profile

添加一行

PATH=$PATH:$HOME/bin:/usr/local/sbin/python-3.7/bin

source ~/.bash_profile

 

 Uvicorn

ASGI既然是基于WSGI扩展开发的,那么使用的方法和WSGI类似,我们同样需要一个application对象,然后使用应用服务器把这个对象启动起来,就像使用Gunicorn/UWsgi启动WSGI一样,这样我们使用Uvicorn,Uvicorn是基于uvloop和httptools的ASGI服务器,它理论上是Python中最高性能的框架了,我们首先下载它

pip install uvicorn
  • 1

对于一个典型的Django项目,调用Uvicorn如下所示

uvicorn myproject.asgi:application

 

05  搭建 Nginx 服务器

 

Nginx (engine x) 是一个高性能的 HTTP 和反向代理 web 服务器,它的功能非常多,这里我们主要用它来处理静态文件以及将非静态文件的请求反向代理给 Gunicorn。

当我们访问一个博客文章详情页面时,服务器会接收到下面两种请求:

显示文章的详情信息,这些信息通常保存在数据库里,因此需要调用数据库获取数据。
图片、css、js 等存在服务器某个文件夹下的静态文件。
对于前一种请求,博客文章的数据需要借助 django 从数据库中获取,Nginx 处理不了,它就会把这个请求转发给 运行在 Gunicorn 服务中的 django 应用,让 django 去处理。而对于后一种静态文件的请求,只需要去这些静态文件所在的文件夹获取,Nginx 就会代为处理,不再麻烦 django。

用 django 去获取静态文件是很耗时的,但 Nginx 可以很高效地处理,这就是我们要使用 Nginx 的原因。

首先安装 Nginx:

sudo yum install epel-release -y

sudo yum install nginx -y

 

运行下面的命令启动 Nginx 服务:

sudo systemctl start nginx

访问ip地址(不是域名)就可以看到welcom页面

 

Nginx 的配置位于 /etc/nginx/nginx.conf 文件中,你可以打开这个文件看看里面的内容,下面是一些关键性的配置:

vim /etc/nginx/nginx.conf

编辑nginx.conf

user root;
...
http {
    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;
    client_max_body_size 20m;
 
    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;
 
        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;
 
        location / {
        }
    }
}

 首先是这个 user 配置,用于指定 Nginx 进程运行时的用户和组(分别为第一个和第二个参数),为了防止可能的权限问题,我们改成当前系统用户(我的用户名是 root,所属组 root,记得改成你自己服务器中运行的用户和组,修改完后记得保存文件内容):

client_max_body_size 20m;

在http{}段中加入 client_max_body_size 20m; 20m为允许最大上传的大小。默认是1兆的

user root;

 

然后在 http 配置下有一个 server 模块,server 模块用于配置一个虚拟服务,使这个虚拟服务监听指定的端口和域名。你可以配置多个 server,这样就会启动多个虚拟服务,用于监听不同端口,或者是同一个端口,但是不同的域名,这样你就可以在同一服务器部署多个 web 应用了。

这个 server 的配置我们下面会详细讲解,再来看看 server 下的 include,include 会将指定路径中配置文件包含进来,这样便于配置的模块化管理,例如我们可以把不同 web 应用的配置放到 /etc/nginx/conf.d/ 目录下,这样 nginx 会把这个目录下所有以 .conf 结尾的文件内容包含到 nginx.conf 的配置中来,而无需把所有配置都堆到 nginx.conf 中,使得配置文件十分臃肿。

我们来配置博客应用,上面说了,为了模块化管理,我们将配置写到 /etc/nginx/conf.d/ 目录下。先在服务器的 conf.d 目录下新建一个配置文件,我把它叫做 yys.conf。写入下面的配置内容:

vim /etc/nginx/conf.d/yys.conf 

  ip也可以127.0.0.0.0:8000, proxy_set_header x-forwarded-for $remote_addr;可以获取用户ip,

server {
    charset utf-8;
    server_name yys534640040.club;

    location /static {
        alias /home/blog/static;
    }

    location / {
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header x-forwarded-for $remote_addr;
    }

    #listen 443 ssl; # managed by Certbot
    #ssl_certificate /etc/letsencrypt/live/yys534640040.club/fullchain.pem; # managed by Certbot
    #ssl_certificate_key /etc/letsencrypt/live/yys534640040.club/privkey.pem; # managed by Certbot
    #include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    #ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}


#server {
  #  if ($host = yys534640040.club) {
#        return 301 https://$host$request_uri;
#    } # managed by Certbot
#

 #   listen 80;
#    server_name yys534640040.club;
#    return 404; # managed by Certbot

#
#}  

 

首先我们配置了一个虚拟服务,编码方式为 utf-8,监听于 80 端口。

服务的域名为 yys534640040.club,所以来自这个域名的请求都会被这个服务所处理。

所有URL 匹配 /static 的请求均由 Nginx 处理,alias 指明了静态文件的存放目录,这样 Nginx 就可以在这个目录下找到请求的文件返回给客户端。

其它请求转发给运行在本机 8000 端口的应用程序处理,我们会在这个端口启动 Gunicorn 用于处理 Nginx 转发过来的请求。

配置ssl证书ngix

首先申请证书,服务器第一次申请要填写域名

使用 Certbot 向 Let's Encrypt 免费申请 HTTPS 证书

生成pem路径

vim /etc/nginx/conf.d/yys.conf 

第一个server就是主配置,默认监听443端口,主域名是http://yys534640040.club,打开了https访问

第二个server主是是监听80端口,主要是把非https的两个域名重定向到https的主域名。

第三个是把https的不带www的域名重定向到主域名,这样其他域名通过301重定向到主域名,就都可以访问了。

server {
    charset utf-8;
    server_name yys534640040.club;

    location /static {
        alias /home/blog/static;
    }

    location / {
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header x-forwarded-for $remote_addr;
    }


    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/yys534640040.club/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/yys534640040.club/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}
server {
    listen 80;
    server_name yys534640040.club,www.yys534640040.club;
    return 301 https://yys534640040.club$request_uri;
   }
   server {
    listen 443;
    server_name yys534640040.club;
    return 301 https://yys534640040.club$request_uri;
  }


server {
    if ($host = yys534640040.club) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    server_name yys534640040.club;
    listen 80;
    return 404; # managed by Certbot
}

重启 nginx 使得配置生效:

sudo systemctl restart nginx

启动若报错

Job for nginx.service failed because the control process exited with error code. See “systemctl stat


启动nginx服务时如果遇到这个错误 Job for nginx.service failed because the control process exited with error code. See “systemctl stat 可能原因如下:

1.nginx配置文件有错误
运行下面命令查看修改

nginx -t

2.已经启动nginx或者配置文件中的端口号被占用
检查端口是否被占用

 

netstat -tnlp


如果端口已经被占用,自己权衡一下是换个端口还是把占用端口的进程杀掉

检查nginx是否已经启动
 

ps -aux | grep nginx


如果已经启动使用下面命令干掉即可

pkill -9 nginx


 

关闭 DEBUG 模式,收集静态文件
开发环境下,django 为了调试方便,会将 settings.py 文件中的 DEBUG 选项配置为 True,这样如果程序运行出错,调试信息将一览无余,这在开发时很方便,但部署到线上就会带来巨大安全隐患,所以我们把 DEBUG 选项设置为 False,关闭调试模式,在本地将 settings.py 中的 DEBUG 为:

DEBUG=False
线上服务器更新最新的代码,然后运行命令收集静态文件到之前配置的 STATIC_ROOT 目录下:

pipenv run python manage.py collectstatic

然后使用 uvicorn启动服务。

 

pipenv run uvicorn blog.asgi:application


现在,访问配置的域名 yys534640040.club(改成你自己在 Nginx 中配置的域名),可以看到博客成功部署!

 

06 配置supervisor

1、安装supervisor

supervisor4.0.0已支持python3,目前最新版4.2.0了,需使用pip安装

sudo pip install supervisor

2、软连接,使其正常执行命令

sudo ln -s /usr/local/bin/supervisord /usr/bin/supervisord

sudo ln -s /usr/local/bin/supervisorctl /usr/bin/supervisorctl

3、产生设置

依次执行
#创建supervisor,若存在请忽略
sudo mkdir /etc/supervisor 
#创建conf.d,若存在请忽略
sudo mkdir /etc/supervisor/conf.d
#添加设置
sudo echo_supervisord_conf > /etc/supervisor/supervisord.conf

注意:若上条不行回到supervisord.conf用cho_supervisord_conf > supervisord.conf

4、修改设置

sudo vim /etc/supervisor/supervisord.conf

#在[supervisord]将末尾的[include]部分改为:files = /etc/supervisor/conf.d/*.conf 读取用户配置

文件夹:/etc/supervisor/supervisord.conf
[include]
files = /etc/supervisor/conf.d/*.ini

5、设置开机自启

sudo vim /usr/lib/systemd/system/supervisord.service

#添加以下内容并保存

[Unit]

Description=Supervisor daemon

[Service]

Type=forking

ExecStart=/usr/bin/supervisord -c /etc/supervisor/supervisord.conf #读取配置

ExecStop=/usr/bin/supervisorctl shutdown

ExecReload=/usr/bin/supervisorctl reload

KillMode=process

Restart=on-failure

RestartSec=42s

[Install]

WantedBy=multi-user.target

5、使用systemctl执行相关命令

sudo systemctl start supervisord #启动 Supervisor 服务

sudo systemctl stop supervisord #停止 Supervisor 服务

sudo systemctl restart supervisord #重启 Supervisor 服务

sudo systemctl status supervisord #查看 Supervisor 服务状态

sudo systemctl enable supervisord #设置 Supervisor 服务开机自启动

sudo systemctl disable supervisord #关闭 Supervisor 服务开机自启动

6、配置gunicorn

 

  ip也可以127.0.0.0.0:8000

# 路径 /etc/supervisor/conf.d/blog.ini  不写入配置

# 配置内容
[program:blog]
# celery命令的绝对路径
command=pipenv run gunicorn blog.wsgi -w 2 -k gthread -b 127.0.0.1:8000  
# 项目路径
directory=/home/blog
user=root #创建该项目用户
# 日志文件路径
stdout_logfile=/var/log/myweb/celery.log
# 自动重启
autorestart=true
# 如果设置为true,进程则会把标准错误输出到supervisord后台的标准输出文件描述符
redirect_stderr=true

第一要创建日志文件夹

mkdir /var/log/myweb

uvicorn可以改成pipenv run uvicorn --workers 2 --host 127.0.0.1 --port 8000 blog.asgi:application

 

7.启动supervisor

supervisord -c /etc/supervisor/supervisord.conf

 

supervisorctl -c /etc/supervisor/supervisord.conf

​​​​​​

成功的提示是

[root@VM_0_6_centos ~]# supervisorctl -c /etc/supervisor/supervisord.conf
blog                             RUNNING   pid 21081, uptime 0:16:31

如果uptime时间总是更新不超过10秒,需要重启服务器了

失败提示:若上面出错:ProtocolError: <ProtocolError for 127.0.0.1/RPC2: 401 Unauthorized>

ps -ef | grep supervisord

 根据列表进程杀死id,

kill -9 <processID>

然后执行第7步

 8.最后执行更新

supervisor> update

查看状态 

supervisor> status

blog                             RUNNING   pid 21081, uptime 0:37:51

浏览器输入域名,可以看到服务已经正常启动了。

注意:如果修改.py后缀文件:重启gunicorn进程才会生效,有两种方法重启

方法一:(推荐)

supervisorctl reload

 

注意:如果出现报错

[root@VM_0_6_centos conf.d]# supervisorctl reload
error: <class 'FileNotFoundError'>, [Errno 2] No such file or directory: file: /usr/local/sbin/python-3.7/lib/python3.7/site-packages/supervisor/xmlrpc.py line: 560

有可能是supervisor已经启动,不正常关闭导致的

<解决办法

寻找masterpid

​​​​​​​pstree -ap|grep gunicorn

[root@VM_0_6_centos conf.d]# pstree -ap|grep gunicorn
  |-gunicorn,
8610 /usr/local/sbin/python-3.7/bin/gunicorn blog.wsgi -w 2 -k gthread -b 127.0.0.1:8000
  |   |-gunicorn,4672 /usr/local/sbin/python-3.7/bin/gunicorn blog.wsgi -w 2 -k gthread -b 127.0.0.1:8000
  |   |   `-{gunicorn},4786
  |   `-gunicorn,4673 /usr/local/sbin/python-3.7/bin/gunicorn blog.wsgi -w 2 -k gthread -b 127.0.0.1:8000
  |       `-{gunicorn},4799
  |   |       |-grep,6030 --color=auto gunicorn

退出Gunicorn任务

kill -9 8610

然后再启动supervisor

supervisord -c /etc/supervisor/supervisord.conf

 

方法二:用reload

1.输入supervisorctl -c /etc/supervisor/supervisord.conf

supervisorctl -c /etc/supervisor/supervisord.conf

[root@VM_0_6_centos ~]# supervisorctl -c /etc/supervisor/supervisord.conf
blog                             RUNNING   pid 21081, uptime 3 days, 0:14:51

2.输入reload

reload

supervisor> reload
Really restart the remote supervisord process y/N? y

3.确定y

y

方法三:找进程

出现报错情况,可以使用error: <class 'FileNotFoundError'>, [Errno 2] No such file or directory: file: /usr/local/sbin/python-3.7/lib/python3.7/site-packages/supervisor/xmlrpc.py line: 560

1. 寻找masterpid

pstree -ap|grep gunicorn

得到如下的结果。

[root@VM_0_6_centos ~]# pstree -ap|grep gunicorn
  |           |-grep,23963 --color=auto gunicorn
  |   `-
gunicorn,21081 /usr/local/sbin/python-3.7/bin/gunicorn blog.wsgi -w 2 -k gthread -b 127.0.0.1:8000
  |       |-gunicorn,23208 /usr/local/sbin/python-3.7/bin/gunicorn blog.wsgi -w 2 -k gthread -b 127.0.0.1:8000
  |       |   `-{gunicorn},23329
  |       `-gunicorn,23209 /usr/local/sbin/python-3.7/bin/gunicorn blog.wsgi -w 2 -k gthread -b 127.0.0.1:8000
  |           `-{gunicorn},23746

很显然,21081就是Gunicorn的主进程。

2. 重启Gunicorn任务

按照官方的推荐方法,很容易执行命令:

kill -HUP 21081

执行上述命令后,再次执行“pstree -ap|grep gunicorn”,我们很容易发现,除了主进程,其他的Gunicorn进程都已经销毁,并新建了进程(进程ID发生了变化)。

 

3. 退出Gunicorn任务(若想退出,忽略此步)

kill -9 21081

supervisorctl 常用命令

supervisorctl status:查看所有进程的状态
supervisorctl stop :停止
supervisorctl start :启动
supervisorctl restart : 重启
supervisorctl update :配置文件修改后可以使用该命令加载新的配置
supervisorctl reload: 重新启动配置中的所有程序

额外扩展:如果supervisor没有成功,先用命令 1. 安装(命令行执行任务)
        

CentOS 系列系统: yum install screen
Ubuntu 系列系统: sudo apt-get install screen


2. 创建 screen 窗口
          

screen -S  name

           # name可以设置为ssh、ftp,用于标注该 screen 窗口用途
          # 示例:
     screen -S xiaoming[小明就是命名]
     注意,执行 screen -S name 之后系统会跳进一个新窗口,这个窗口就是我们创建的新进程(它来执行我们的命令)。
在这里面进行项目的启动即可。
3. 退出保存
就是完全退出exit, 不会进行session保存了。
CTRL-a+d , 用screen -r就可恢复到原来的工作状态了。

停止:
首先:[查看有哪些]

screen -ls

只有Detached可以进入

如果只有一个 screen 进程,命令行输入 screen -r -d 即可

如果有多个screen, 我们可以通过它的 PID 进入screen:

screen -r -d 1572

进入之后直接CTRL+C,终止就行:​​​​​​​  

 

07.获取免费证书

点击查看

 

​​​​​​​08.prim库也要复制

获取库路径

>>> import sys
>>> print(sys.path)

centos的plug路径是:/usr/local/sbin/python-3.7/lib/python3.7/site-packages/ckeditor/static/ckeditor/ckeditor/plugins

乌班图18.04路径  /usr/local/lib/python3.6/dist-packages/ckeditor/static/ckeditor/ckeditor/plugins

从win10电脑复制到centos 

scp -r C:\Users\yys53\OneDrive\python\install\Lib\site-packages\ckeditor\static\ckeditor\ckeditor\plugins\prism root@yys534640040.club:/root/.local/share/virtualenvs/blog-pKvyoTrr/lib/python3.6/site-packages/ckeditor/static/ckeditor/ckeditor/plugins
pipenv run python manage.py collectstatic

09.复制markdown

下载:

git clone https://gitee.com/yang_yongsheng/CKEditor-Markdown-Plugin.git

从win10电脑复制到centos 

scp -r C:\Users\yys53\OneDrive\python\install\Lib\site-packages\ckeditor\static\ckeditor\ckeditor\plugins\markdown root@yys534640040.club:/root/.local/share/virtualenvs/blog-pKvyoTrr/lib/python3.6/site-packages/ckeditor/static/ckeditor/ckeditor/plugins
pipenv run python manage.py collectstatic

 


创建数据库用户

创建 django后台管理员

注意:服务器长期使用过几个月要重启一下,不然supervisor有问题

10.问题解决


2024年12月09日 服务器故障及解决过程

问题概述

2024年12月09日,我的服务器出现了无法访问的情况,具体表现为:

  • SSH 无法连接到服务器
  • 通过浏览器访问搭建的网站无法加载
  • 在重启服务器后检查 Supervisor 管理的进程时,发现 blog 服务一直处于 BACKOFF 状态,提示 Exited too quickly

重启服务器后,发现以下问题:

  1. MySQL 服务丢失
  2. Pipfile 乱码
  3. 数据库迁移问题
  4. SSL 证书丢失
  5. Supervisor 服务 blog 启动失败

问题1:MySQL 服务丢失

在检查日志时,我发现 MySQL 服务无法启动。通过检查发现,MySQL 数据库已经被删除或丢失。

解决方案

  • 重新安装 MySQL 8,按照 CentOS 8 的安装教程进行安装。具体步骤如下:

    1. 参考文章:CentOS 8 安装 MySQL 8

问题2:Pipfile 乱码

在检查项目依赖时,发现 Pipfile 文件中包含乱码,导致 pipenv 无法正常解析。

解决方案

  • 重新编写 Pipfile 文件,确保内容正确无误:

    [[source]]
    url = "https://pypi.org/simple"
    verify_ssl = true
    name = "pypi"
    
    [packages]
    
    [dev-packages]
    
    [requires]
    python_version = "3.6"

问题3:数据库迁移问题

由于之前数据库丢失,需要重新进行 Django 的迁移操作,特别是在数据库不存在的情况下。

解决方案

  1. 重新进行数据库迁移:

    python manage.py makemigrations
    python manage.py migrate
  2. 将旧数据库的 SQL 文件重新导入数据库中。

开启 Django Debug 模式

  • 开启 Django 的 Debug 模式,有助于排查问题。在 settings.py 文件中设置:

    DEBUG = True

问题4:SSL 证书丢失

在重启后,发现网站 SSL 证书丢失。需要重新导入 SSL 证书以保证网站的安全访问。

解决方案

  • 重新导入 SSL 证书,并在 Nginx 中配置。你可以使用 Certbot 或手动方式来导入 SSL 证书。

问题5:Supervisor 服务 blog 启动失败

在使用 supervisord 管理项目时,发现 blog 服务的状态为 BACKOFF,并且日志显示:“Exited too quickly”。这意味着 blog 进程启动失败,Supervisor 反复尝试重启该服务,但无法成功。

解决方案

  1. 查看日志

    • 首先查看 Supervisor 日志,定位进程启动失败的原因。可以使用以下命令查看相关日志:
      sudo tail -f /var/log/supervisord.log
  2. 检查配置文件

    • 检查 /etc/supervisor/supervisord.conf 和项目配置文件(如 blog.conf)是否有误,特别是 command 字段中的启动命令是否正确。
  3. 确保依赖已安装

    • 确保所有依赖已正确安装并且环境配置正确。例如,如果使用 pipenv,可以确保在虚拟环境中安装所需的依赖:
      pipenv install
  4. 手动启动进程

    • 尝试手动启动服务,以检查是否有任何错误输出。例如,如果是使用 gunicorn 启动,可以执行以下命令:
      pipenv run gunicorn blog.wsgi:application -b 127.0.0.1:8000
    • 如果手动启动时有错误输出,解决这些错误后,再尝试重新启动 Supervisor 管理的服务。
  5. 检查数据库连接

    • 如果数据库没有连接或配置错误,可能会导致 Django 无法正常启动。确保数据库已正确连接,并且 DATABASES 配置项正确无误。
  6. 重新启动 Supervisor

    • 最后,重新启动 Supervisor 服务以应用更改:
      sudo supervisorctl reread
      sudo supervisorctl update
      sudo supervisorctl restart blog

总结

通过解决上述问题,我成功地恢复了服务器的正常运行。具体过程包括:

  1. 重新安装 MySQL:恢复数据库服务。
  2. 重新编写 Pipfile:解决 pipenv 解析错误。
  3. 进行数据库迁移:确保数据库状态一致。
  4. 重新导入 SSL 证书:恢复 HTTPS 安全访问。
  5. 修复 Supervisor 配置:确保 blog 服务能正确启动。

通过这些步骤,我成功地解决了服务器故障,并恢复了网站的正常访问。


11.dot画图graphviz

https://yys.zone/detail/?id=368

 

12.一直循环STARTING

[root@VM-8-9-opencloudos ~]# supervisorctl -c /etc/supervisor/supervisord.conf
blog RUNNING pid 910846, uptime 0:00:02
supervisor> stats
*** Unknown syntax: stats
supervisor> status
blog STARTING
supervisor> status
blog STARTING
supervisor> status
blog RUNNING pid 910900, uptime 0:00:02
supervisor> status
blog RUNNING pid 910900, uptime 0:00:04
supervisor> status
blog RUNNING pid 910900, uptime 0:00:05
supervisor> status
blog RUNNING pid 910900, uptime 0:00:06
supervisor> status
blog STARTING
supervisor> status
blog STARTING
supervisor> status
blog RUNNING pid 910929, uptime 0:00:02
supervisor> status
blog RUNNING pid 910929, uptime 0:00:03“
 

解决:重启腾讯云服务器,没找到其他办法 .

 

13. Django 的 CSRF 防护机制

 

403 Forbidden 关键的错误信息是这几行:

WARNING 2025-04-17 09:27:42,492 log 248 Forbidden (Origin checking failed - https://yys.zone does not match any trusted origins.): /writeblog/
WARNING 2025-04-17 09:33:07,159 log 248 Forbidden (Origin checking failed - https://yys.zone does not match any trusted origins.): /login/
WARNING 2025-04-17 09:33:20,117 log 248 Forbidden (Origin checking failed - https://yys.zone does not match any trusted origins.): /login/
WARNING 2025-04-17 09:33:53,864 log 248 Forbidden (Origin checking failed - https://yys.zone does not match any trusted origins.): /updateblog/

错误分析:

这个错误 Forbidden (Origin checking failed - https://yys.zone does not match any trusted origins.) 和之前单纯的 CSRF verification failed 不太一样,但它们都与 Django 的 CSRF 防护机制有关。

  • Origin checking failed: 这表示 Django 在进行 CSRF 检查时,不仅仅验证了 csrfmiddlewaretoken,还检查了 HTTP 请求头中的 Origin 或 Referer 字段。这个字段表明请求是从哪个域名发起的。
  • https://yys.zone does not match any trusted origins: 这明确指出了问题所在。你的浏览器发起的请求告诉服务器,这个请求来自 https://yys.zone 这个域名。但是,你的 Django 项目配置中,并没有把 https://yys.zone 列为“受信任的来源” (Trusted Origins)。
  • 发生在 /writeblog//login//updateblog/: 这些都是需要进行 POST 请求(提交数据)的页面,因此会触发 CSRF 检查,包括来源检查。

为什么会发生这种情况?

当你的 Django 应用部署在 HTTPS 环境下,或者通过反向代理(如 Nginx)访问时,浏览器在发送 POST、PUT、DELETE 等可能改变服务器状态的请求时,会带上 Origin 请求头。Django 的 CsrfViewMiddleware 会检查这个 Origin 是否在 settings.py 文件中定义的 CSRF_TRUSTED_ORIGINS 列表里。如果不在,即使 csrfmiddlewaretoken 是正确的,Django 也会为了安全起见拒绝这个请求。

解决方法:

你需要编辑你的 Django 项目的 settings.py 文件,将你的网站域名添加到 CSRF_TRUSTED_ORIGINS 设置中。

在你的 settings.py 文件里,找到(或者如果没有就添加) CSRF_TRUSTED_ORIGINS 配置项,并添加你的域名:

# settings.py

# ... 其他设置 ...

# 将你的网站域名(带协议 https://)添加到这个列表中
CSRF_TRUSTED_ORIGINS = [
    'https://yys.zone',
    # 如果你还有其他需要信任的域名或子域名,也加在这里
    # 例如: 'https://www.yys.zone'
]

# 如果你在本地开发也遇到了类似问题,可能需要添加本地地址
# CSRF_TRUSTED_ORIGINS = ['http://127.0.0.1:8000', 'http://localhost:8000', 'https://yys.zone']


# 确保你的 ALLOWED_HOSTS 也包含了你的域名
ALLOWED_HOSTS = ['yys.zone', 'www.yys.zone', 'localhost', '127.0.0.1'] # 根据你的实际情况配置

# ... 其他设置 ...

重要提示:

  1. 包含协议: 在 CSRF_TRUSTED_ORIGINS 中添加域名时,必须包含协议部分(http:// 或 https://)。根据你的日志,你的网站是 https://
  2. 重启服务: 修改 settings.py 文件后,必须重启你的 Django 应用服务(例如 Gunicorn, uWSGI, 或者开发服务器 runserver)才能让新的设置生效。
  3. ALLOWED_HOSTS: 顺便检查一下你的 ALLOWED_HOSTS 设置是否也包含了 yys.zone。虽然错误信息是关于 CSRF_TRUSTED_ORIGINS,但 ALLOWED_HOSTS 是基础,也需要正确配置。

修改并重启服务后,再次尝试提交写文章、登录等表单,应该就不会再报这个 Origin checking failed 的错误了。

至于 Not Found: /robots.txt 这个警告,通常是搜索引擎爬虫尝试访问你网站的 robots.txt 文件(用于告诉爬虫哪些页面可以爬取),如果这个文件不存在就会报 404 Not Found。这通常是无害的,与你的表单提交问题无关。

 

​​​​​​​14.删除指定缓存catch

  1. 打开终端,进入你的 Django 项目目录。

  2. 运行命令 python manage.py shell。这将启动一个 Python 交互式会话,并且已经加载了你的 Django 环境。

  3. 在 Shell 中执行以下 Python 代码:

    from django.core.cache import cache
    from django.conf import settings
    
    # 获取缓存键
    cache_key = settings.VERSIONS_CACHE_KEY
    
    # 删除缓存
    deleted = cache.delete(cache_key)
    
    # 打印结果
    if deleted:
        print(f"缓存键 '{cache_key}' 已成功删除。")
    else:
        print(f"缓存键 '{cache_key}' 在缓存中不存在或删除失败。")
    
    # 退出 shell
    # exit()

这种方式对于临时调试非常方便,不需要修改代码。