【Python】以邮件的方式定时发送一天的股票分析报告

news2024/9/22 11:06:09

【Python】以邮件的方式定时发送一天的股票分析报告

文章目录

  • 【Python】以邮件的方式定时发送一天的股票分析报告
    • 1、Python发送邮件
      • 1)`EmailSender`封装
      • 2)可能存在的问题
    • 2、jinja2动态渲染html页面
    • 3、阿里云OSS搭建图床
      • 1)Python上传图片到OSS中
      • 2)使用`PicGo`上传图片到OSS中
      • 3)图片链接访问报错解决
    • 4、APScheduler定时任务
      • 1)APScheduler四个组件
      • 2)配置scheduler调度器

假设我现在的需求是:

假设我已经实现了对某只股票的分时/日/周/月K线,以及对应指标(RSI,BOLL,OBV,MACD)的绘制。

在这里插入图片描述

如果我想让系统每天在股市结束后,给我发送关于几只自选股票的分析报告,我可以通过如下方式实现:

  • 1)让系统对今天几只股票的分时/日/周/月K线以及对应指标进行计算和绘制;

  • 2)绘制的图片自动上传到阿里云OSS中,并返回关于已上传图片的url链接;

  • 3)根据给定的html模板,利用Jinja2工具包,将今天的股票绘制结果动态渲染到html

  • 4)系统将生成的html文件以邮件的形式发送到指定的收件人中;

这里分成4个模块,依次对邮件发送、html模板渲染、图床搭建、定时任务进行介绍,这里并没有给出实现这个需求的完整代码。

1、Python发送邮件

参考资料:

  • 简单三步,用 Python 发邮件_程序员王饱饱的博客-CSDN博客_python 发送邮件

  • Python SMTP发送邮件 | 菜鸟教程

1)EmailSender封装

封装好的邮件发送类EmailSender代码如下:包括文本内容、带txtpdf、图片和html的附件发送。

  • MIMEMultipart可以允许带附件;

  • 如果想添加一个txt或者html文本附件,用MIMEText封装;

  • 如果想添加一个pdf文本附件, 用MIMEApplication封装,参考# 【Mail小技巧】如何使用Python优雅的发送带有pdf附件的电子邮件;

  • 如果想添加一个照片附件,用MIMEImage封装;

# 参考 https://blog.csdn.net/weixin_55154866/article/details/128098092
# 参考 https://www.runoob.com/python/python-email.html
# 参考 https://blog.csdn.net/YP_FlowerSky/article/details/124451913
import smtplib
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
import pdfplumber
from pathlib import Path

class EmailSender:
    def __init__(self,mail_host,mail_user,mail_pass,sender):
        '''
        @param mail_host 设置登录及服务器信息,比如网易邮箱是smtp.163.com; type=str
        @param mail_user 邮箱用户名; type=str
        @param mail_pass 邮箱授权码; type=str
        @param sender 邮件发送方邮箱地址; type=str
        '''
        self.mail_host = mail_host
        self.mail_user = mail_user
        self.mail_pass = mail_pass
        self.sender = sender

    '''初始化一封邮件'''
    def init_email(self,receivers,content,subject):
        '''
        @param receivers 接收方邮箱集合,适合群发; type=list
        @param content 文本内容;type=str
        @param subject 主题; type=str
        '''
        # 参考 https://blog.csdn.net/YP_FlowerSky/article/details/124451913
        self.receivers = receivers
        # 添加一个MIMEmultipart类,处理正文及附件
        self.message = MIMEMultipart()    #MIMEMultipart可以允许带附件
        self.message['From'] = self.sender  #发送方邮箱地址
        self.message['To'] = ','.join(receivers)   #接收方邮箱地址, 将['1046474088@qq.com','2802428220@qq.com']处理成'1046474088@qq.com,2802428220@qq.com'的str
        self.message['Subject'] = subject
        self.message.attach(MIMEText(content,'plain', 'utf-8')) # 文本内容 (plain文本格式,utf-8编码)

    '''为邮件添加附件'''
    def email_wrapper(self,filePath,fileType="text"):
        '''
        @param filePath 文件路径; type=str
        @param fileType 文件类型,可选 ['text','html','image'];  type=str
        '''
        if(fileType == 'text'):
            suffix = filePath.split(".")[-1]
            # 添加一个pdf文本附件, 用MIMEApplication封装 参考 https://blog.csdn.net/popboy29/article/details/126396549
            if (suffix == 'pdf'):
                with open(filePath, "rb") as f:
                    pdf_attach = MIMEApplication(f.read(), _subtype="pdf")
                    #如果出现邮件发送成功,但邮箱接收到的附件变为bin格式的情况时,检查add_header是否出错 参考https://blog.csdn.net/hxchuadian/article/details/125773738
                    pdf_attach.add_header('Content-Disposition', 'attachment', filename=str(Path(filePath).name))
                    self.message.attach(pdf_attach)
            else:
                #添加一个txt文本附件,用MIMEText封装
                with open(filePath,'r')as h:
                    content2 = h.read()
                #设置txt参数
                text_attach = MIMEText(content2,'plain','utf-8')
                #附件设置内容类型,方便起见,设置为二进制流
                text_attach['Content-Type'] = 'application/octet-stream'
                #设置附件头,添加文件名
                text_attach['Content-Disposition'] = f'attachment;filename="{filePath}"'
                self.message.attach(text_attach)

        if (fileType == 'html'):
            # 推荐使用html格式的正文内容,这样比较灵活,可以附加图片地址,调整格式等
            with open(filePath,'r') as f:
                # 设置html格式参数
                html_attach = MIMEText(f.read(), 'base64', 'gb2312')  # 将html文件以附件的形式发送
                html_attach['Content-Type'] = 'application/octet-stream'
                html_attach.add_header('Content-Disposition', 'attachment',filename=str(Path(filePath).name))  # filename是指下载的附件的命名
                self.message.attach(html_attach)

        if (fileType == 'image'):
            # 添加照片附件,用MIMEImage封装
            with open(filePath, 'rb') as fp:
                picture_attach = MIMEImage(fp.read())
                # 与txt文件设置相似
                picture_attach['Content-Type'] = 'application/octet-stream'
                picture_attach['Content-Disposition'] = f'attachment;filename="{filePath}"'
            # 将内容附加到邮件主体中
            self.message.attach(picture_attach)

    #登录并发送
    def sendEmail(self):
        try:
            smtpObj = smtplib.SMTP()
            smtpObj.connect(self.mail_host, 25)
            smtpObj.login(self.mail_user, self.mail_pass)
            smtpObj.sendmail(
                self.sender, self.receivers, self.message.as_string())  #receivers群发, receivers是一个列表['1046474088@qq.com','2802428220@qq.com']
            print('success')
            smtpObj.quit()
        except smtplib.SMTPException as e:
            print('error', e)

2)可能存在的问题

参考

  • 如果出现list‘ object has no attribute ‘encode‘_list' object has no attribute 'encode,主要原因是self.message['To']赋值有误,要想实现群发,需要将['1046474088@qq.com','2802428220@qq.com']处理成'1046474088@qq.com,2802428220@qq.com'str类型

    参考Selenium /Python 配置QQ邮箱后台自动发送邮件unittest//发送多人邮件报错: ‘list‘ object has no attribute ‘encode‘_list’ object has no attribute 'encode

  • 如果出现邮件发送成功,但邮箱接收到的附件变为bin格式的情况时,检查add_header是否出错。可参考Python 发送邮件时图片附件变为bin格式的解决方案

2、jinja2动态渲染html页面

参考Python之jinja2模板引擎生成HTML_宗而研之的博客-CSDN博客_python 生成html

html模板如下:

<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<html align='left'>
  <body>
    <h1>{{today}}股票分析报告</h1>
    <table>
      {% for stock in stocks %}
      <tr align='center'>
          <td>{{ stock.code }}</td>
          <td>{{ stock.codeName }}</td>
          <td><a href="{{stock.minute_kline_path}}">分时K线图</a> </td>
          <td><a href="{{stock.daily_kline_path}}">日K线图</a> </td>
          <td><a href="{{stock.week_kline_path}}">周K线图</a> </td>
          <td><a href="{{stock.month_kline_path}}">月K线图</a> </td>
      </tr>
      {% endfor%}
    </table>
  </body>
</html>

python代码如下:

import datetime

from jinja2 import Environment, FileSystemLoader
import datetime

import sys
import os
from pathlib import Path
curPath = os.path.abspath(os.path.dirname(__file__))
rootPath = os.path.split(curPath)[0]
sys.path.append(rootPath)

imgDir = os.path.join(rootPath,"html_task/temp/")

def generate_html(today, stocks):
    env = Environment(loader=FileSystemLoader('./'))
    template = env.get_template('template.html')
    with open("result.html", 'w+') as fout:
        html_content = template.render(today=today,
                                       stocks=stocks)
        fout.write(html_content)


if __name__ == "__main__":
    today = datetime.datetime.now().strftime("%Y-%m-%d")
    stocks = []
    stock1_path = os.path.join(imgDir,"sh601728")
    stock2_path = os.path.join(imgDir,"sz000722")

    stock1 = {'code': 'sh601728', 'codeName': '中国电信',
              'minute_kline_path': stock1_path + "/" + "minute_K_line.png",
              'daily_kline_path': stock1_path + "/" + "daily_K_line.png",
              'week_kline_path': stock1_path + "/" + "week_K_line.png",
              "month_kline_path" : stock1_path + "/" + "month_K_line.png", }
    stock2 = {'code': 'sz000722', 'codeName': '湖南发展',
              'minute_kline_path': stock2_path + "/" + "minute_K_line.png",
              'daily_kline_path': stock2_path + "/" + "daily_K_line.png",
              'week_kline_path': stock2_path + "/" + "week_K_line.png",
              "month_kline_path" : stock2_path + "/" + "month_K_line.png", }
    stocks.append(stock1)
    stocks.append(stock2)
    generate_html(today, stocks)  #图片无法正常显示,会报错:Not allowed to load local resource
    # 图片无法正常显示 解决方法参考 http://www.kuazhi.com/post/319149.html

生成的html可视化效果如下:

在这里插入图片描述

但是存在一个问题 - 点击链接并不能正常下载或访问图片,主要原因是:浏览器出于安全方面的考虑,禁止网页访问本地文件,因为图片是存在项目目录下的,所以无法通过本地的url进行访问。(参考浏览器报错:Not allowed to load local resource 原因及解决办法_扭不开瓶盖的三水的博客-CSDN博客)

因此这里打算用图床返回的图片url链接来解决Not allowed to load local resource问题。

3、阿里云OSS搭建图床

参考

  • 阿里云 oss 服务 —— 上传图片,获取url

  • 阿里云OSS使用流程

  • 使用阿里云OSS搭建图床 - 简书

1)Python上传图片到OSS中

使用python将图片上传到阿里云OSS(挺便宜的,买了1年9 rmb的资源包)中,然后通过url链接访问图片。其中建议使用RAM用户ACCESS_KEY_IDACCESS_KEY_SECRETBUCKET_NAME是购买的OSS实例名称,ENDPOINT是这个OSS实例的地域节点,具体获取方式参考阿里云OSS使用流程

# 使用阿里云OSS + picGo搭建图床 参考 https://www.jianshu.com/p/111ce9603ea6l

# -*- coding: utf-8 -*-
import datetime
import oss2
import unittest

# 阿里云OSS使用流程 参考 https://zhuanlan.zhihu.com/p/567771838
ACCESS_KEY_ID = "LTAI5*****Hu6m"  #RAM账号access_key_id,如果没有用主账号登录工作台创建并授权,关于RAM角色参考 https://ram.console.aliyun.com/roles
ACCESS_KEY_SECRET = "mkit8YsLh*****TYmoh1QRzK"  #RAM账号access_key_secret
ENDPOINT = "oss-cn-shenzhen.aliyuncs.com"  #可以在bucket中获取地域节点endpoint 参考 https://zhuanlan.zhihu.com/p/567771838
BUCKET_NAME = "w*****i-20200401"

#参考 https://www.likecs.com/show-308529932.html#sc=900
class Oss:
    """
    oss存储类
    上传bytes流,返回状态码和url
    """
    def __init__(self, access_key_id=ACCESS_KEY_ID, access_key_secret=ACCESS_KEY_SECRET,
                 endpoint=ENDPOINT, bucket_name=BUCKET_NAME):
        # 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
        auth = oss2.Auth(access_key_id, access_key_secret)
        # Endpoint以杭州为例,其它Region请按实际情况填写。'http://oss-cn-hangzhou.aliyuncs.com'
        self.bucket = oss2.Bucket(auth, endpoint, bucket_name)

    def upload_bytes(self, file_bytes, image_name):
        """上传bytes文件"""
        result = self.bucket.put_object('{}'.format(image_name), file_bytes)

class OSSTest(unittest.TestCase):

    def test_oss_uploadFile(self):
        oss_obj = Oss()
        with open("temp/sh601728/minute_K_line.png","rb") as f:
            oss_obj.upload_bytes(f.read(),"minute_K_line.png")

    def test_oss_downloadFile(self):
        # 上传后,可以访问的 url 的组成
        photo_name = 'minute_K_line.png'
        domain = f'https://{BUCKET_NAME}.{ENDPOINT}/'
        url_photo = domain + photo_name
        print(url_photo)

        #访问该图片时可能会报错:You have no right to access this object because of bucket acl.
        # 解决方法:在bucket的权限控制中,将私有修改为公共读 参考 https://blog.csdn.net/zsy3757486/article/details/126938973

2)使用PicGo上传图片到OSS中

在官网[Releases · Molunerfinn/PicGo · GitHub](https://github.com/Molunerfinn/PicGo/releases)下载安装好PicGo之后,在图床配置中配置好阿里云OSS的ACCESS_KEY_IDACCESS_KEY_SECRETBUCKET_NAME存储区域地址后,即可实现图片上传,具体参考使用阿里云OSS搭建图床 - 简书

3)图片链接访问报错解决

正常情况下上传到图片可以通过如下链接访问:

https://{BUCKET_NAME}.{ENDPOINT}/photo_name   #photo_name是上传到图片名称

但是在测试图片url连接时可能会报错:You have no right to access this object because of bucket acl.

解决方法:bucket的权限控制中,将私有修改为公共读。参考【阿里云OSS】You have no right to access this object because of bucket acl._路遥叶子的博客-CSDN博客

4、APScheduler定时任务

参考

  • Python 定时任务的实现方式
  • BlockingScheduler与BackgroundScheduler区别
  • APScheduler 定时任务详解

APScheduler定时框架:终于找到了可以每天定时喊我起床的方式了

APScheduler是一个 Python 定时任务框架,使用起来十分方便。提供了基于日期、固定时间间隔以及 crontab 类型的任务,并且可以持久化任务、并以 daemon 方式运行应用

使用 APScheduler 需要安装

pip install apscheduler

首先来看一个周一到周五每天早上6点半喊我起床的例子

from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime
# 输出时间
def job():
    print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
# BlockingScheduler
scheduler = BlockingScheduler()
scheduler.add_job(job, 'cron', day_of_week='1-5', hour=6, minute=30)
scheduler.start()

1)APScheduler四个组件

APScheduler 四个组件分别为:触发器(trigger),作业存储(job store),执行器(executor),调度器(scheduler)

a、触发器(trigger)

包含调度逻辑,每一个作业有它自己的触发器,用于决定接下来哪一个作业会运行。除了他们自己初始配置意外,触发器完全是无状态的
APScheduler 有三种内建的 trigger:

date: 特定的时间点触发
interval: 固定时间间隔触发
cron: 在特定时间周期性地触发

b、作业存储(job store)

存储被调度的作业,默认的作业存储是简单地把作业保存在内存中,其他的作业存储是将作业保存在数据库中。一个作业的数据讲在保存在持久化作业存储时被序列化,并在加载时被反序列化。调度器不能分享同一个作业存储。
APScheduler 默认使用 MemoryJobStore,可以修改使用 DB 存储方案

c、执行器(executor)

处理作业的运行,他们通常通过在作业中提交制定的可调用对象到一个线程或者进城池来进行。当作业完成时,执行器将会通知调度器。
最常用的 executor 有两种:

ProcessPoolExecutor
ThreadPoolExecutor

d、调度器(scheduler)

通常在应用中只有一个调度器,应用的开发者通常不会直接处理作业存储、调度器和触发器,相反,调度器提供了处理这些的合适的接口。配置作业存储和执行器可以在调度器中完成,例如添加、修改和移除作业。

2)配置scheduler调度器

APScheduler提供了许多不同的方式来配置调度器,你可以使用一个配置字典或者作为参数关键字的方式传入。你也可以先创建调度器,再配置和添加作业,这样你可以在不同的环境中得到更大的灵活性。

下面来看一个简单的 BlockingScheduler 例子

from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime

def job():
    print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
# 定义BlockingScheduler
sched = BlockingScheduler()
sched.add_job(job, 'interval', seconds=5)
sched.start()

上述代码创建了一个 BlockingScheduler,并使用默认内存存储和默认执行器。(默认选项分别是 MemoryJobStoreThreadPoolExecutor,其中线程池的最大线程数为10)。配置完成后使用 start() 方法来启动。

如果要给job传参,可以在add_job中使用args参数,如果要给job设置指定id,可以使用id参数

rom datetime import datetime

from apscheduler.schedulers.blocking import BlockingScheduler


def func(name):
    now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    print(now + f" Hello world, {name}")


scheduler = BlockingScheduler()
scheduler.add_job(func, 'interval', seconds=3, args=["desire"], id="func")
scheduler.start()

移除job

  • 1)通过job的ID来调用remove_job方法
  • 2)通过在add_job()中得到的job实例调用remove()方法
  • 如果一个job完成了调度(例如他的触发器不会再被触发), 它会自动被移除

如果job_id不存在,remove_job会报错,可以用try - except来处理

# remove
job = scheduler.add_job(func, 'interval', seconds=3, args=["desire"], id="job_remove")
job.remove()

# remove_job
scheduler.add_job(func, 'interval', seconds=3, args=["desire"], id="job_remove")
scheduler.remove_job(job_id="job_remove")

终止调度器中的执行器

scheduler.shutdown()  #终止调度器中的任务存储器以及执行器
scheduler.shutdown(wait=False)

默认情况,会终止任务存储器以及执行器,然后等待所有目前执行的job完成后(自动终止),wait=False 此参数不会等待任何运行中的任务完成,直接终止。但是如果scheduler没有执行,shutdown()会报错。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/357237.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在Linux和Windows上安装sentinel-1.8.5

记录&#xff1a;380场景&#xff1a;在CentOS 7.9操作系统上&#xff0c;安装sentinel-1.8.5。在Windows上操作系统上&#xff0c;安装sentinel-1.8.5。Sentinel是面向分布式、多语言异构化服务架构的流量治理组件。版本&#xff1a;JDK 1.8 sentinel-1.8.5 CentOS 7.9官网地址…

开发板上搭建vsftpd服务器

1、交叉编译vstftp 下载vsftpd源码&#xff1a;vsftpd-3.0.2.tar.gz # tar –xzvf vsftpd-3.0.2.tar.gz # cd vsftpd-3.0.2 修改makefile文件&#xff1a; CC arm-linux-gnueabihf-gcc # make 将vsftpd文件放到/usr/bin/&…

说说Hibernate

当你在实战项目中需要用到SSH时, 如果你之前只用过Mybatis那自然是不能解决问题的, 因为在很多银行类金融类项目中你可能会使用到Hibernate, 那么关于Hibernate你应该要了解什么呢, 本篇文章就以学习Hibernate框架为目的, 巩固在工作中可能需要用到的这种ORM技术, 同时也欢迎家…

PVE硬件直通之强制IOMMU分组

文章目录检查是否直接支持IOMMU分组配置IOMMU分组不直接支持的需要更新内核参考检查是否直接支持IOMMU分组 下面 以SATA控制器为例&#xff0c;看pci设备是否可以直接支持IOMMU分组 /* 打印pci设备详细信息*/ lspci -vv /* 找到SATA controller 段落*/ 16:00.1 SATA controll…

设计模式:模板模式 CRTP设计习语

一、模板模式 1、模板模式 1&#xff09;定义 定义一个操作中的算法的骨架&#xff08;稳定&#xff09;&#xff0c;而将一些步骤延迟&#xff08;变化&#xff09;到子类中。Template Method使得子类可以不改变&#xff08;复用&#xff09;一个算法的结构即可重定义&…

tensorflow 学习笔记(二):神经网络的优化过程

前言&#xff1a; 学习跟随 如何原谅奋力过但无声的 tensorflow 笔记笔记。 本章主要讲解神经网络的优化过程&#xff1a;神经网络的优化方法&#xff0c;掌握学习率、激活函数、损失函数和正则化的使用&#xff0c;用 Python 语言写出 SGD、Momentum、Adagrad、RMSProp、Ada…

2023-02-18干活记录

MathBERT: 耗时&#xff1a;2-3hours(昨天和人聊天聊完了&#xff0c;今天九点才到实验室&#xff0c;呜呜呜一早上就看了个论文) 读论文&#xff1a;BERT-Based Embedding Model for Formula Retrieval Corpus Description&#xff1a; resource:from MSE;the formulas ex…

腾讯云——负载均衡CLB

负载均衡 CLB 提供四层&#xff08;TCP 协议/UDP 协议/TCP SSL 协议&#xff09;和七层&#xff08;HTTP 协议/HTTPS 协议&#xff09;负载均衡。您可以通过 CLB 将业务流量分发到多个后端服务器上&#xff0c;消除单点故障并保障业务可用性。CLB 自身采用集群部署&#xff0c;…

电子技术——共栅和共源共栅放大器的高频响应

电子技术——共栅和共源共栅放大器的高频响应 我们在之前学过无论是是CS放大器还是CE放大器&#xff0c;都可以看做是一个带通&#xff08;IC低通&#xff09;滤波器。在高频处的响应收到输入电容 CinC_{in}Cin​ 的限制&#xff08;主要是米勒效应&#xff09;。因此&#xff…

中南民族大学数字电路实验一

数字电路实验一基本逻辑门实验1.与非门实现与门2.与非门实现或门3.与非门实现或非门4.与非门实现异或门5.与非门实现与或门6.与非门实现与或非门实验报告结果分析基本逻辑门实验 一、实验目的 1&#xff0e;掌握 logisim 软件的使用方法&#xff1b; 2&#xff0e;学习基于该软…

基于蜣螂算法优化Kmeans图像分割-附代码

基于蜣螂优化Kmeans图像分割算法 - 附代码 文章目录基于蜣螂优化Kmeans图像分割算法 - 附代码1.Kmeans原理2.基于蜣螂算法的Kmeans聚类3.算法实验结果4.Matlab代码摘要&#xff1a;基于蜣螂优化Kmeans图像分割算法。1.Kmeans原理 K-Means算法是一种无监督分类算法&#xff0c;…

蚂蚁感冒---第五届蓝桥杯真题

目录 题目链接 题目描述 分析&#xff1a; 代码&#xff1a; y总综合​ 666 题目链接 1211. 蚂蚁感冒 - AcWing题库 题目描述 分析&#xff1a; y总真牛逼&#xff0c;掉头等价于穿过&#xff0c;以第一个点为分界点&#xff0c;分别判断 代码&#xff1a; &#xff08;自…

Java线程池的创建以及原理

一、为什么要使用线程池 在外面的日常开发中&#xff0c;也使用了不少池化技术&#xff0c;比如线程池、数据库连接池、HTTP连接池等等都是对这个思想的应用。 池化技术的思想主要是为了减少每次获取资源的消耗&#xff0c;提高对资源的利用率。 线程池提供了一种限制和管理资…

centos7系统-kubeadm安装k8s集群(v1.26版本)亲测有效,解决各种坑可供参考

文章目录硬件要求可省略的步骤配置虚拟机ip设置阿里镜像源各服务器初始化配置配置主节点的主机名称配置从节点的主机名称配置各节点的Host文件关闭各节点的防火墙关闭selinux永久禁用各节点的交换分区同步各节点的时间将桥接的IPv4流量传递到iptables的链&#xff08;三台都执行…

PHP面向对象01:面向对象基础

PHP面向对象01&#xff1a;面向对象基础一、关键字说明二、技术实现1. 定义类2. 类成员三、 访问修饰限定符1. public2. protected3. private4. 空修饰限定符四、类内部对象五、构造和析构1. 构造方法2. 析构方法六、范围解析操作符1. 访问类常量2. 静态成员3. self关键字七、类…

自动驾驶:时钟同步

文章目录 一、自动驾驶时间同步简介二、时间同步需要的服务1、PTP1.1 ptp4l三、UTC转换UNIX时间戳(timestamp)一、自动驾驶时间同步简介 二、时间同步需要的服务 1、PTP ptp4l -i mgbe3_0 -f /etc/automotive-slave.cfg & phc2sys -s mgbe3_0 -O 0

IDEA插件 RestfulTool插件——Restful服务开发辅助工具集

IDEA插件 RestfulTool插件——Restful服务开发辅助工具集 目录IDEA插件 RestfulTool插件——Restful服务开发辅助工具集1.插件介绍2.安装方式3.使用方法1.插件介绍 RestfulTool插件。一套 Restful 服务开发辅助工具集&#xff1a; 提供了一个 Services tree 的显示窗口 双击 …

Linux C/C++ 多线程TCP/UDP服务器 (监控系统状态)

Linux环境中实现并发TCP/IP服务器。多线程在解决方案中提供了并发性。由于并发性&#xff0c;它允许多个客户端同时连接到服务器并与服务器交互。 Linux多线程编程概述 许多应用程序同时处理多项杂务。服务器应用程序处理并发客户端&#xff1b;交互式应用程序通常在处理后台…

80211无线网络架构

无线网络架构物理组件BSS&#xff08;Basic Service Set&#xff09;基本服务集BSSID&#xff08;BSS Identification&#xff09;ssid&#xff08;Service Set Identification&#xff09;ESS&#xff08;Extended Service Set&#xff09;扩展服务集物理组件 无线网络包含四…

【C++学习】基础语法(三)

众所周知C语言是面向过程的编程语言&#xff0c;关注的是过程&#xff1b;解决问题前&#xff0c;需要分析求解的步骤&#xff0c;然后编辑函数逐步解决问题。C是基于面向对象的&#xff0c;关注的是对象&#xff0c;将一件事拆分成不同的对象&#xff0c;不同对象间交互解决问…