前言
以下是后文将会用到的东西,请提前参阅与准备
项目源地址(golang开发的)
psutil的详细介绍
windoes+celery易错点
django+celery配合实现定时任务
1、新建项目
1.1 创建子应用host并且设置本地化
1)新建django项目
2)启动子应用host
python manage.py startapp host
3)子应用注册
4)改中文
1.2 数据库表的创建和超级用户的创建
1)数据迁移文件生成与迁移
python manage.py makemigrations
python manage.py migrate
2)生成超级用户
python manage.py createsuperuser
1.3 git 管理项目(requirement.txt,README.md,.gitignore)
生成.gitignore
git init
git add *
git commit -m "...."
pip freeze
pip freeze > requirements.txt
生成.gitignore
git init:
requirements.txt
1.4 配置gitee,上传到gitee托管
1)新建仓库
2)复制链接
3)编辑README.md 文件
# sysinfo
## 简介
sysinfo 使用 Python Django 框架和 psutil 开发的一个中文版 Linux 服务器信息查看应用,可查看的信息包括系统、CPU、内存、硬盘、进程、网络、登录用户等,同时可查看并导出部分数据的图表。
4)远程连接仓库,第一次使用强制上传
git remote add origin https://gitee.com/xxxx/sysinfo.git
git push --set-upstream origin master -f
2、搭建sysinfo框架
2.1 主路由urls
#sysinfo/urls.py ##主urls
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('host.urls')),
]
2.2 子路由配置
路由 | 视图函数 | 前端模板 |
---|---|---|
/ | views.index | index.html |
/user/ | views.user | user.html |
/cpu/ | views.cpu | cpu.html |
/memory/ | views.memory | memory.html |
/disk/ | views.disk | disk.html |
/network/ | views.network | network.html |
/process/ | views.process | process.html |
# host/urls.py app对应的urls,为了关联视图函数
from django.contrib import admin
from django.urls import path, include
from .views import *
urlpatterns = [
path('', index, name='index'),
path('user/', user, name='user'),
path('cpu/', cpu, name='cpu'),
path('memory/', memory, name='memory'),
path('disk/', disk, name='disk'),
path('network/', network, name='network'),
path('process/', process, name='process'),
]
2.3 视图函数配置
#host/views.py 视图函数
from django.shortcuts import render
# Create your views here.
def index(request):
pass
return render(request, 'host/index.html', locals())
def user(request):
pass
return render(request, 'host/user.html', locals())
def cpu(request):
pass
return render(request, 'host/cpu.html', locals())
def memory(request):
pass
return render(request, 'host/memory.html', locals())
def disk(request):
pass
return render(request, 'host/disk.html', locals())
def network(request):
pass
return render(request, 'host/network.html', locals())
def process(request):
pass
return render(request, 'host/process.html', locals())
##模板都是新建的,没有内容
2.4 新建html模版
2.5 上传至gitee
git add *
git commit -m "sysinfo框架"
git push
3、主页信息的配置index
3.1 配置文件
- 基模板就相当于一个框架,别的模板导入之后,只需要修改基模板中可以修改的部分即可
psutil模块详解
<!-- 基模板 -->
<!-- templates/host/base.html -->
<!DOCTYPE html>
<html {% block html_attribs %}{% endblock html_attribs %}>
<head>
{% block head %} <!-- 这里面可以自定义head 和title -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %} {% endblock title %}</title>
<link rel="stylesheet" type="text/css" href="/static/css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="/static/css/my-style.css">
<script src="/static/js/jquery-3.1.1.min.js"></script>
{% endblock head %}
</head>
<body>
<div class="sysinfo">
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/">Sys Info</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">系统</a></li>
<li><a href="/cpu/">CPU</a></li>
<li><a href="/memory/">内存</a></li>
<li><a href="/disk/">硬盘</a></li>
<li><a href="/network/">网络</a></li>
<li><a href="/process/">进程</a></li>
<li><a href="/user/">用户</a></li>
</ul>
</div>
</div>
</div>
<div class="container">
{% block content %}{% endblock %} <--! 自定义内容 -->
</div>
</div>
</body>
</html>
<!-- index.html -->
{% extends 'host/base.html' %} <!-- 导入基模板 -->
{% block title %}Sys Info{% endblock %}
{% block content %}
<div class="page-header">
<h1>系统信息</h1>
</div>
<div>
<table class="table table-bordered">
<tr>
<td>主机名</td>
<td>{{ sys_name }}</td>
</tr>
<tr>
<td>内核名称</td>
<td>{{ kernel_name }}</td>
</tr>
<tr>
<td>发行版本号</td>
<td>{{ kernel_no }}</td>
</tr>
<tr>
<td>内核版本</td>
<td>{{ kernel_version }}</td>
</tr>
<tr>
<td>系统架构</td>
<td>{{ sys_framework }}</td>
</tr>
<tr>
<td>现在时间</td>
<td>{{ now_time }}</td>
</tr>
<tr>
<td>开机时间</td>
<td>{{ boot_time }}</td>
</tr>
<tr>
<td>运行时间</td>
<td>{{ up_time }}</td>
</tr>
</table>
</div>
{% endblock %}
1 安装psutil模块
(venv) E:\pycharm pro\sysinfo> pip install --index-url http://pypi.douban.com/simple/ psutil --trusted-host pypi.douban.com
或者:pip install psutil
2 host/views.py ##视图函数新增内容
from datetime import datetime
from django.shortcuts import render
import psutil ##导入psutil模块
import os, platform
# Create your views here.
def index(request):
"""
sys_name
kernel_name
kernel_no
kernel_version
sys_framework
now_time
boot_time
up_time
"""
try:
info = os.uname() ##linux系统是os.uname
except Exception as e:
info = platform.uname() ##windows系统是platform.uname
sys_name = info.node ##window和linux执行查询命令显示的参数
kernel_name = info.system
kernel_no = info.release
kernel_version = info.version
sys_framework = info.machine
boot_time = datetime.fromtimestamp(psutil.boot_time())
now_time = datetime.now()
print(boot_time, now_time)
up_time = now_time - boot_time
return render(request, 'host/index.html', locals())
3 sysinfo/settings新增内容 声明使用的是static文件夹内容。
STATICFILES_DIRS = [
BASE_DIR / "static",
]
STATIC_URL = '/static/'
3.2 启动服务器访问
配置完成启动服务器
(venv) D:\pycharm pro\sysinfo>python manage.py runserver
3.3 上传gitee
git add *
git commit -m "index首页展示"
git push
4、用户登录界面显示
4.1 user登陆界面的文件配置
##host/views.py 增加内容
def user(request):
users = psutil.users()
return render(request, 'host/user.html', locals())
#templatetags/timefilter.py 新建包
"""
自定义过滤器实现的方法:
https://docs.djangoproject.com/zh-hans/3.1/howto/custom-template-tags/
"""
from django import template
from datetime import datetime
register = template.Library()
@register.filter(name='timefmt') ##俩种方法,这里使用的是装饰器的方法。
def timefmt(value):
"""将时间戳转换成datetime类型的时间"""
return datetime.fromtimestamp(value)
## templates/user.html
{% extends 'host/base.html' %} <!-- 继承基本模板 -->
{% load timefilter %} <!--加载自定义过滤器 -->
{% block title %} 用户信息 {% endblock %}
{% block content %}
<div class="page-header">
<h1>登录用户</h1>
</div>
<div>
<table class="table table-bordered">
<tr> <!-- tr行 , td 列 -->
<td>用户名</td>
<td>登录主机</td>
<td>终端</td>
<td>登录时间</td>
</tr>
{% for user in users %} <!-- 循环用户并获取信息 -->
<tr>
<td>{{ user.name }}</td>
<td>{{ user.terminal }}</td>
<td>{{ user.host }}</td>
<td>{{ user.started | timefmt }}</td> <!--使用过滤器,可以是内置过滤器,也可以是自定义过滤器 -->
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
4.2 测试结果
4.3 上传gitee
5、cpu信息的展示
5.1 文件配置,cpu信息
#templatetags/timefilter.py
"""
自定义过滤器实现的方法:
https://docs.djangoproject.com/zh-hans/3.1/howto/custom-template-tags/
"""
from django import template
from datetime import datetime
register = template.Library()
@register.filter(name='timefmt')
def timefmt(value):
"""将时间戳转换成datetime类型的时间"""
return datetime.fromtimestamp(value)
@register.filter(name='cpu_val_fmt') ##添加的自定义过滤器
def cpu_val_fmt(value):
return round(value/1000, 2)
<!-- cpu页面展示-->
{% extends 'host/base.html' %}
{% load timefilter %}
{% block title %} cpu信息 {% endblock %}
{% block content %}
<div class="page-header">
<a {% if not chart %}id="display"{% endif %} href="/cpu/">CPU 信息</a>
<a {% if chart == 'line' %}id="display"{% endif %} href="/cpu/">CPU
折线图</a>
<a {% if chart == 'pie' %}id="display"{% endif %} href="/cpu/">CPU 饼图</a>
</div>
<div>
<div id="cpu_info">
<table class="table table-bordered">
<tr>
<td>物理 CPU 核心数</td>
<td>{{ physical_core_num }}</td>
</tr>
<tr>
<td>逻辑 CPU 核心数</td>
<td>{{ logical_core_num }}</td>
</tr>
<tr>
<td>最近 1 分钟平均负载</td>
<td>{{ load_avg.0 }}</td>
</tr>
<tr>
<td>最近 5 分钟平均负载</td>
<td>{{ load_avg.1 }}</td>
</tr>
<tr>
<td>最近 15 分钟平均负载</td>
<td>{{ load_avg.2 }}</td>
</tr>
<tr>
<td>用户</td>
<td>{{ cpu_time_percent.user }} %</td>
</tr>
<tr>
<td>系统</td>
<td>{{ cpu_time_percent.system }} %</td>
</tr>
<tr>
<td>空闲</td>
<td>{{ cpu_time_percent.idle }} %</td>
</tr>
{% if cpu_time_percent.nice %}
<tr>
<td>nice</td>
<td>{{ cpu_time_percent.nice }} %</td>
</tr>
{% endif %}
{% if cpu_time_percent.iowait %}
<tr>
<td>iowait</td>
<td>{{ cpu_time_percent.iowait }} %</td>
</tr>
{% endif %}
{% if else_percent %}
<tr>
<td>其他</td>
<td>{{ else_percent }} %</td>
</tr>
{% endif %}
{% if cpu_freq %}
<tr>
<td>正在运行频率</td>
<td>{{ cpu_freq.current | cpu_val_fmt }} GHz</td>
</tr>
<tr>
<td>最低运行频率</td>
<td>{{ cpu_freq.min | cpu_val_fmt }} GHz</td>
</tr>
<tr>
<td>最高运行频率</td>
<td>{{ cpu_freq.max | cpu_val_fmt }} GHz</td>
</tr>
{% endif %}
</table>
</div>
{% endblock %}
##views下cpu的视图函数
def cpu(request):
logical_core_num = psutil.cpu_count() #
physical_core_num = psutil.cpu_count(logical=False)
try:
load_avg = os.getloadavg()
except Exception as e:
load_avg = ['', '', '']
cpu_time_percent = psutil.cpu_times_percent()
else_percent = 0.0
for i in range(5):
else_percent += cpu_time_percent[i]
try:
cpu_freq = psutil.cpu_freq()
except AttributeError:
cpu_freq = None
return render(request, 'host/cpu.html', locals())
5.2 测试结果
5.3 CPU饼状图
- echarts绘制饼图
- echart官网
文件配置
##host/urls
from django.contrib import admin
from django.urls import path, include
from .views import *
urlpatterns = [
path('', index, name='index'),
path('user/', user, name='user'),
path('cpu/', cpu, name='cpu'),
path('cpu/<str:chart>/', cpu, name='cpu'), #指定名字
path('memory/', memory, name='memory'),
path('disk/', disk, name='disk'),
path('network/', network, name='network'),
]
##host/views
def cpu(request, chart=None):
logical_core_num = psutil.cpu_count() #
physical_core_num = psutil.cpu_count(logical=False)
try:
load_avg = os.getloadavg()
except Exception as e:
load_avg = ['', '', '']
cpu_time_percent = psutil.cpu_times_percent()
else_percent = 0.0
for i in range(3, 5):
else_percent += cpu_time_percent[i]
try:
cpu_freq = psutil.cpu_freq()
except AttributeError:
cpu_freq = None
if chart == 'line':
return render(request, 'host/cpu-line.html', locals())
elif chart == 'pie':
return render(request, 'host/cpu-pie.html', locals())
return render(request, 'host/cpu.html', locals())
##host/modules.py ##此处的modules是为了之后的折线图做准备的
from django.db import models
# 定时任务定期扫描并存储。
class UserCpuPercent(models.Model):
create_time = models.DateTimeField(auto_now_add=True, verbose_name="扫描时间")
user_percent = models.FloatField(verbose_name="用户CPU占用百分比")
##配置了modules文件需要重新生成数据库迁移文件
(venv) D:\pycharm pro\sysinfo>python manage.py makemigrations
(venv) D:\pycharm pro\sysinfo>python manage.py migrate
<!-- templates/base.html-->
<!DOCTYPE html>
<html {% block html_attribs %}{% endblock html_attribs %}>
<head>
{% block head %}
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %} {% endblock title %}</title>
<link rel="stylesheet" type="text/css" href="/static/css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="/static/css/my-style.css">
<script src="/static/js/jquery-3.1.1.min.js"></script>
<script src="https://lib.baomitu.com/echarts/5.0.2/echarts.min.js"></script> <!-- 使用的是在线的js模板 -->
{% endblock head %}
</head>
<body>
<div class="sysinfo">
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/">Sys Info</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">系统</a></li>
<li><a href="/cpu/">CPU</a></li>
<li><a href="/memory/">内存</a></li>
<li><a href="/disk/">硬盘</a></li>
<li><a href="/network/">网络</a></li>
<li><a href="/process/">进程</a></li>
<li><a href="/user/">用户</a></li>
</ul>
</div>
</div>
</div>
<div class="container">
{% block content %}{% endblock %}
</div>
</div>
</body>
</html>
<!-- templates/cpu.html -->
{% extends 'host/base.html' %}
{% load timefilter %}
{% block title %} cpu信息 {% endblock %}
{% block content %}
{% include 'host/cpu-header.html' %}
<div>
<div id="cpu_info">
<table class="table table-bordered">
<tr>
<td>物理 CPU 核心数</td>
<td>{{ physical_core_num }}</td>
</tr>
<tr>
<td>逻辑 CPU 核心数</td>
<td>{{ logical_core_num }}</td>
</tr>
<tr>
<td>最近 1 分钟平均负载</td>
<td>{{ load_avg.0 }}</td>
</tr>
<tr>
<td>最近 5 分钟平均负载</td>
<td>{{ load_avg.1 }}</td>
</tr>
<tr>
<td>最近 15 分钟平均负载</td>
<td>{{ load_avg.2 }}</td>
</tr>
<tr>
<td>用户</td>
<td>{{ cpu_time_percent.user }} %</td>
</tr>
<tr>
<td>系统</td>
<td>{{ cpu_time_percent.system }} %</td>
</tr>
<tr>
<td>空闲</td>
<td>{{ cpu_time_percent.idle }} %</td>
</tr>
{% if cpu_time_percent.nice %}
<tr>
<td>nice</td>
<td>{{ cpu_time_percent.nice }} %</td>
</tr>
{% endif %}
{% if cpu_time_percent.iowait %}
<tr>
<td>iowait</td>
<td>{{ cpu_time_percent.iowait }} %</td>
</tr>
{% endif %}
{% if else_percent %}
<tr>
<td>其他</td>
<td>{{ else_percent }} %</td>
</tr>
{% endif %}
{% if cpu_freq %}
<tr>
<td>正在运行频率</td>
<td>{{ cpu_freq.current | cpu_val_fmt }} GHz</td>
</tr>
<tr>
<td>最低运行频率</td>
<td>{{ cpu_freq.min | cpu_val_fmt }} GHz</td>
</tr>
<tr>
<td>最高运行频率</td>
<td>{{ cpu_freq.max | cpu_val_fmt }} GHz</td>
</tr>
{% endif %}
</table>
</div>
</div>
{% endblock %}
<!-- templates/cpu-pie.html -->
{% extends 'host/base.html' %}
{% load timefilter %}
{% block title %} cpu信息 {% endblock %}
{% block content %}
{% include 'host/cpu-header.html' %}
<div>
<div id="main" style="width: 80%;height:400px;"></div>
</div>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
option = {
tooltip: {
trigger: 'item'
},
legend: {
top: '5%',
left: 'center'
},
series: [
{
name: 'CPU占用百分比分类',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: '#fff',
borderWidth: 2
},
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: '40',
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: [
{value: {{ cpu_time_percent.user }}, name: '用户'},
{value: {{ cpu_time_percent.system }}, name: '系统'},
{value: {{ cpu_time_percent.idle }}, name: '空闲'},
]
}
]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
{% endblock %}
5.5 测试
5.6 git提交
git add *
git commit -m "基于echart的饼状图实现"
git push
6、celery定时任务和异步任务
- Celery 是一个简单、灵活且可靠的,处理大量消息的分布式系统。大白话理解处理异步任务和定时任务
的工具。
工作原理如下图:
6.1 需要用到的安装包
#requirement.txt文件
amqp==5.0.5
asgiref==3.3.1
billiard==3.6.3.0
celery==5.0.5
click==7.1.2
click-didyoumean==0.0.3
click-plugins==1.1.1
click-repl==0.1.6
Django==3.1.7
django-celery-beat==2.2.0
django-celery-results==2.0.1
django-timezone-field==4.1.1
dnspython==1.16.0
eventlet==0.30.2
greenlet==1.0.0
importlib-metadata==3.7.2
kombu==5.0.2
prompt-toolkit==3.0.17
psutil==5.8.0
python-crontab==2.5.1
python-dateutil==2.8.1
pytz==2021.1
redis==3.5.3
six==1.15.0
sqlparse==0.4.1
typing-extensions==3.7.4.3
vine==5.0.0
wcwidth==0.2.5
zipp==3.4.1
6.2 安装redis
6.3 配置定时任务
(venv) E:\sysinfo>pip install celery
(venv) E:\sysinfo>pip install django-celery-beat
#sysinfo/celery.py
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
# 设置django环境
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sysinfo.settings')
app = Celery('sysinfo')
# 使用CELERY_ 作为前缀,在settings中写配置
app.config_from_object('django.conf:settings', namespace='CELERY')
# 发现任务文件每个app下的task.py
app.autodiscover_tasks()
#sysinfo/__init__.py
from __future__ import absolute_import, unicode_literals
from .celery import app as celery_app
__all__ = ['celery_app'] #将app展示出来,不然访问不到定时任务
#sysinfo/settings.py 文件内容,celery configure,必须安装redis
CELERY_BROKER_URL = 'redis://127.0.0.1:6379/0' # Broker配置,使用Redis作为消息中间件
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/1' # BACKEND配置,这里使用redis
CELERY_RESULT_SERIALIZER = 'json' # 结果序列化方案
6.4 启动worker
(venv) E:\sysinfo>pip install eventlet
(venv) E:\sysinfo>pip install redis
(venv) E:\sysinfo>pip install django-celery-beat
(venv) E:\sysinfo>Celery -A sysinfo worker -l info -P eventlet
#安装包之后执行这条命令,连接数据库成功。worker启动成功
6.5 编写定时任务
#host/tasks.py ##用于定时任务
import psutil
from celery import shared_task
from host.models import UserCpuPercent
@shared_task() ##装饰器共享任务
def scan_cpu_info():
percent = UserCpuPercent( user_percent=psutil.cpu_times_percent().user) ##获取用户占用cpu百分比
percent.save()
6.6 使用定时任务
(venv) E:\sysinfo>pip install django-celery-beat
6.6.1 注册app
#sysinfo/settings.py 文件内容,注册app
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_celery_beat',
'host',
]
6.6.2 数据库变更
(venv) E:\sysinfo>python manage.py makemigrations
(venv) E:\sysinfo>python manage.py migrate
6.6.3 后端访问
6.6.4 查看sql数据库是否有数据
此时没有任务
6.6.4 分别启动woker和beta
celery -A sysinfo beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler #启动beta 调度器使用数据库
Celery -A sysinfo worker -l info -P eventlet #启动woker,之前启动过了就不需要了。
##此时sql数据库仍然没有任何信息(实际操作)
Celery -A sysinfo worker-l info -P eventlet#这时多线程的方式,换成单线程
Celery -A sysinfo worker -l info --pool=solo ##使用这条命令
celery -A sysinfo beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler #启动beta 调度器使用数据库
6.7 上传gitee
git add *
git commit -m "add corntab task"
git push
6.8 更新requirements.txt
(venv) E:\sysinfo>pip freeze > requirements.txt
7. 配置cpu折线图
7.1 配置
#host/views.py
def cpu(request, chart=None):
logical_core_num = psutil.cpu_count() #
physical_core_num = psutil.cpu_count(logical=False)
try:
load_avg = os.getloadavg()
except Exception as e:
load_avg = ['', '', '']
cpu_time_percent = psutil.cpu_times_percent()
else_percent = 0.0
for i in range(3, 5):
else_percent += cpu_time_percent[i]
try:
cpu_freq = psutil.cpu_freq()
except AttributeError:
cpu_freq = None
if chart == 'line':
datas = UserCpuPercent.objects.order_by('-id')[:30] ##折线图显示最新30条记录
return render(request, 'host/cpu-line.html', locals())
elif chart == 'pie':
return render(request, 'host/cpu-pie.html', locals())
return render(request, 'host/cpu.html', locals())
<!-- templates/cpu-line.html -->
{% extends 'host/base.html' %}
{% load timefilter %}
{% block title %} cpu信息 {% endblock %}
{% block content %}
{% include 'host/cpu-header.html' %}
<div>
<div id="main" style="width: 80%;height:400px;"></div>
</div>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
{#首先,声明两个 javascript 的数组#}
var series_data = [];
var xAxis_data = [];
{#使用循环,依次将数据库需要展示的数据添加到刚才声明的数组中#}
{% for data in datas %}
{#series_data.push({{ data.user_percent }})#}
{#xAxis_data.push({{ data.create_time }})#}
series_data.push({{ data.user_percent }})
{#注意这里的双引号#}
xAxis_data.push("{{ data.create_time}}")
{% endfor %}
option = {
xAxis: {
type: 'category',
data: xAxis_data
},
yAxis: {
type: 'value'
},
series: [{
data: series_data,
type: 'line',
smooth: true
}]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
{% endblock %}
7.2 测试
7.3 git提交
git add *
git commit -m "config cpu-line.html"
git push