当前位置: 首页 > news >正文

基于python netmiko去ssh备份网络设备配置

自己为了便利写出来的基于python netmiko去ssh备份网络设备配置,用过secureCRT的脚本去备份设备配置,但是它没有图形化界面,使用不方便,自己就重新用python开发了一个,同时用pyinstaller打包成可执行程序(这里就不说明怎么打包了,搜一下就出来了,不打包也行,看你的)。感觉netmiko这个包还是很强大,大部分的设备都支持,不支持的也可以找到相似的去实现,比如我这里迈普的设备就是这样。该项目需要对netmiko和pyqt5有一个基本的了解,才能根据本人所写的去实现自定义的需求,代码中也有相应的注释。控制线程个数本来是用线程池,但是pyinstaller打包后有些线程无法执行完成,不知道啥原因,用信号量代替就正常了。

以下是几个源代码和配置文件的简单说明:

  1. main.py,程序的入口
  2. main_ui.py,图形化界面代码,由qtdesigner生成并加以修改
  3. backup_cur.py,具体功能的逻辑代码
  4. 备份设备列表.txt,目前只支持华为、迈普、锐捷、锐捷AC的配置备份(其他类型的设备自己去实现就好,不难,已经有一个框架了),分别对应配置文件中的Huawei、Mypower、Ruijie、RuijieAC,配置文件每一个设备占用一行,每一行的字段包含设备类型、IP地址、设备名称,用空格分开。设备类型、IP地址对了就行,设备名称随便起,但不能是空。务必严格遵循配置文件的语法,否则可能无法备份配置。具体可参考下面的文件示例。
  5. 在还没有熟悉代码前,所有文件名称最好别变,否则无法使用。注意代码中的注释,程序不难。

以下是各个源文件和文件

目录

  • main.py,程序的入口
  • main_ui.py,图形化界面代码
  • backup_cur.py,具体功能的逻辑代码
  • 备份设备列表.txt

main.py,程序的入口

# @Time        : 2022/12/17
# @Author      : zhu
# @Description : 程序入口
from sys import argv, exit
from PyQt5.QtWidgets import QApplication, QMainWindow
from main_ui import UiMainWindow
from backup_cur import BackupCurif __name__ == '__main__':app = QApplication(argv)window = QMainWindow()ui = UiMainWindow(window)backup_cur = BackupCur(ui)  # 变量虽然不用但必须声明,否则不生效window.show()exit(app.exec_())

main_ui.py,图形化界面代码

# @Time        : 2022/12/17
# @Author      : zhu
# @Description : UI界面代码
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QActionclass UiMainWindow(object):"""由PyQt5 UI code generator 5.15.9生成"""def __init__(self, main_window):"""初始化:param main_window: QMainWindow类"""main_window.setObjectName('main_window')main_window.resize(1200, 800)main_window.setStyleSheet('QPushButton{background-color: rgb(0, 102, 179); color: rgb(255,255,255)}')self.central_widget = QtWidgets.QWidget(main_window)self.central_widget.setObjectName('central_widget')self.vertical_layout_3 = QtWidgets.QVBoxLayout(self.central_widget)self.vertical_layout_3.setObjectName('vertical_layout_3')self.stacked_widget = QtWidgets.QStackedWidget(self.central_widget)self.stacked_widget.setObjectName('stacked_widget')self.main_page = QtWidgets.QWidget()  # 主页self.main_page.setObjectName('main_page')self.horizontal_layout_2 = QtWidgets.QHBoxLayout(self.main_page)self.horizontal_layout_2.setObjectName('horizontal_layout_2')self.horizontal_layout_1 = QtWidgets.QHBoxLayout()self.horizontal_layout_1.setObjectName('horizontal_layout_1')self.label_1 = QtWidgets.QLabel(self.main_page)font = QtGui.QFont()font.setFamily('Agency FB')font.setPointSize(36)self.label_1.setFont(font)self.label_1.setAlignment(QtCore.Qt.AlignCenter)self.label_1.setWordWrap(True)self.label_1.setObjectName('label_1')self.horizontal_layout_1.addWidget(self.label_1)self.horizontal_layout_2.addLayout(self.horizontal_layout_1)self.stacked_widget.addWidget(self.main_page)self.backup_cur_page = QtWidgets.QWidget()  # 备份设备配置界面self.backup_cur_page.setObjectName('backup_cur_page')self.horizontal_layout_4 = QtWidgets.QHBoxLayout(self.backup_cur_page)self.horizontal_layout_4.setContentsMargins(0, 0, 0, 0)self.horizontal_layout_4.setObjectName('horizontal_layout_4')self.vertical_layout_2 = QtWidgets.QVBoxLayout()self.vertical_layout_2.setObjectName('vertical_layout_2')self.backup_cur_button = QtWidgets.QPushButton(self.backup_cur_page)self.backup_cur_button.setObjectName('backup_cur_button')self.vertical_layout_2.addWidget(self.backup_cur_button)self.horizontal_layout_4.addLayout(self.vertical_layout_2)self.backup_plain_text_edit = QtWidgets.QPlainTextEdit(self.backup_cur_page)self.backup_plain_text_edit.setLineWrapMode(QtWidgets.QPlainTextEdit.NoWrap)self.backup_plain_text_edit.setReadOnly(True)self.backup_plain_text_edit.setObjectName('backup_plain_text_edit')self.horizontal_layout_4.addWidget(self.backup_plain_text_edit)self.horizontal_layout_4.setStretch(0, 1)self.horizontal_layout_4.setStretch(1, 5)self.stacked_widget.addWidget(self.backup_cur_page)self.vertical_layout_3.addWidget(self.stacked_widget)  # 菜单栏main_window.setCentralWidget(self.central_widget)self.menu_bar = QtWidgets.QMenuBar(main_window)self.menu_bar.setGeometry(QtCore.QRect(0, 0, 1200, 26))self.menu_bar.setStyleSheet('QMenuBar::item::selected{background-color: rgb(0, 102, 179); color: rgb(255,255,255)}')self.menu_bar.setObjectName('menu_bar')self.main_menu = QAction()  # 跳过传统的方式创建菜单栏的菜单项,利用这种可以绑定点击出发时的要做的动作self.main_menu.setObjectName('main_menu')self.main_menu.triggered.connect(self.set_current_main)  # 按下首页菜单时设置栈布局当前界面为首页self.backup_cur_menu = QAction()self.backup_cur_menu.setObjectName('backup_cur_menu')self.backup_cur_menu.triggered.connect(self.set_current_backup_cur)  # 按下首页菜单时设置栈布局当前界面为备份设备配置main_window.setMenuBar(self.menu_bar)self.menu_bar.addAction(self.main_menu)self.menu_bar.addAction(self.backup_cur_menu)self.retranslate_ui(main_window)self.stacked_widget.setCurrentIndex(0)QtCore.QMetaObject.connectSlotsByName(main_window)def retranslate_ui(self, main_window) -> None:"""自定义字段设置:param main_window: QMainWindow类"""_translate = QtCore.QCoreApplication.translatemain_window.setWindowTitle(_translate('main_window', '备份设备配置'))self.label_1.setText(_translate('main_window', '未经允许不得擅自使用,否则后果自负'))self.backup_cur_button.setText(_translate('main_window', '开始备份'))self.main_menu.setText(_translate('main_window', '首页'))self.backup_cur_menu.setText(_translate('main_window', '备份设备配置'))def set_current_main(self):"""设置栈布局当前界面为首页"""self.stacked_widget.setCurrentIndex(0)def set_current_backup_cur(self):"""设置栈布局当前界面为备份设备配置"""self.stacked_widget.setCurrentIndex(1)

backup_cur.py,具体功能的逻辑代码

# @Time        : 2022/12/17
# @Author      : zhu
# @Description : 备份具体实现
# @update      : 使用pyqt制作图形化界面
import os
import datetime
import threading
import traceback
from socket import inet_pton, AF_INET, AF_INET6
from threading import Thread
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QMessageBox
from netmiko import ConnectHandler
from main_ui import UiMainWindowdef is_ip_address(ip: str) -> bool:"""判读给定的字符串是否是IPv4或IPv6地址:param ip: IP地址字符串"""try:inet_pton(AF_INET, ip)return Trueexcept:try:inet_pton(AF_INET6, ip)return Trueexcept:return Falseclass BackupCur(QObject):"""目前支持华为、迈普、锐捷、锐捷AC,对应配置文件中的Huawei、Mypower、Ruijie、RuijieAC,设备类型必须和以上说明的配置文件类型严格对上,否则无法备份。控制线程个数本来是用线程池,但是pyinstaller打包后有些线程无法执行完成,就使用信号量代替了"""BACKUP_DEVICE_FILE = './备份设备列表.txt'USERNAME = 'your_username'PASSWORD = 'your_password'SSH_PORT = 22SEM = threading.Semaphore(10)  # 信号量为10,这里限制线程的最大数量为10个MY_SIGNAL = pyqtSignal(list)  # 该信号用于向主线程传递信息更新UI界面,信息类型标识、信息体def __init__(self, ui_main_window: UiMainWindow):"""初始化:param ui_main_window: UiMainWindow类"""super().__init__(None)self.failed_count = 0  # 统计备份失败的设备个数self.ui = ui_main_windowself.thread = None  # 备份配置的子线程self.finished_device_count = 0  # 统计备份完成的设备数量self.backup_path = ''self.device_count = 0  # 备份设备总数self.ui = ui_main_windowself.ui.backup_cur_button.clicked.connect(self.confirm_backup)self.MY_SIGNAL.connect(self.my_slot)def confirm_backup(self) -> None:"""确认是否进行备份"""message_box = QMessageBox(QMessageBox.Question, '提示', '确认备份设备吗')  # 自定义提示对话框yes = message_box.addButton(message_box.tr('确定'), QMessageBox.YesRole)message_box.addButton(message_box.tr('取消'), QMessageBox.NoRole)message_box.exec_()if message_box.clickedButton() == yes:  # 选择确定self.finished_device_count = 0self.failed_count = 0Thread(target=self.start_backup).start()  # 生成子线程避免主线程卡顿def start_backup(self) -> None:"""开始进行备份"""self.MY_SIGNAL.emit([0])self.backup_path = './操作日志/' + datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S') + '/'if not os.path.isdir(self.backup_path):os.makedirs(self.backup_path)try:with open(self.BACKUP_DEVICE_FILE) as file:device_list = file.readlines()  # 按行读取文件self.device_count = len(device_list)for device in device_list:self.SEM.acquire()  # 获取信号量,保证最多只有10个线程同时运行self.thread = threading.Thread(target=self.worker, args=(device,))self.thread.start()except OSError:  # 文件打开失败self.MY_SIGNAL.emit([1])def worker(self, worker_device: str) -> None:"""备份设备的线程:param worker_device: 备份的设备信息列表,类型、IP、设备名"""device_fields = worker_device.split()for i in range(len(device_fields)):device_fields[i] = device_fields[i].replace('\n', '').replace('\r', '')try:if is_ip_address(device_fields[1]):device_type = device_fields[0]if device_type == 'Huawei':ssh_type = 'huawei'cmd = 'dis cur'else:ssh_type = 'ruijie_os'  # Ruijie MaipuRT RuijieACcmd = 'show run'connect_filed = {  # ssh各个字段'device_type': ssh_type,'host': device_fields[1],'username': self.USERNAME,'password': self.PASSWORD,'port': self.SSH_PORT,'session_log': self.backup_path + device_fields[2] + '(' + device_fields[1] + ').log'}device_name = device_fields[2]try:net_connect = ConnectHandler(**connect_filed)  # ssh连接if device_type == 'Huawei' or device_type == 'Ruijie':net_connect.send_command(command_string=cmd,read_timeout=20.0,strip_prompt=False,  # 输出结果包含设备提示strip_command=False)  # 输出结果包含输入的命令elif device_type == 'Mypower':net_connect.send_command(command_string='more off',expect_string=device_name + '#',strip_prompt=False,strip_command=False)net_connect.send_command(command_string=cmd,expect_string=device_name + '#')else:  # 锐捷ACnet_connect.send_command(command_string=cmd,expect_string=device_name + '#')net_connect.send_command(command_string='show ap-config running',expect_string=device_name + '#')net_connect.disconnect()except:traceback.print_exc()self.MY_SIGNAL.emit([3, device_name, device_fields[1]])except:  # 一般来说只会是由于配置文件的设备字段出错导致,数组越界self.MY_SIGNAL.emit([2, worker_device])finally:self.SEM.release()  # 释放信号量self.MY_SIGNAL.emit([4])def my_slot(self, args: list) -> None:"""槽函数,接收子线程信号并更改主界面UI:param args: 标识位、信息、设备名称、设备ip地址、未知设备"""if args[0] == 0:self.ui.backup_plain_text_edit.appendPlainText('正在备份设备配置,请稍后...')self.ui.backup_cur_button.setEnabled(False)  # 设置按钮不可用以及颜色为灰色self.ui.backup_cur_button.setStyleSheet('QPushButton{background-color: rgb(128, 128, 128); color: rgb(255,255,255)}')self.ui.backup_cur_button.repaint()  # 重新绘制按钮,否则样式可能不生效elif args[0] == 1:self.ui.backup_plain_text_edit.appendPlainText('打开文件' + os.path.abspath(self.BACKUP_DEVICE_FILE) + '出错,请检查配置文件是否存在!')self.ui.backup_cur_button.setEnabled(True)  # 备份完成恢复按钮为原样self.ui.backup_cur_button.setStyleSheet('QPushButton{background-color: rgb(1, 102, 179); color: rgb(255,255,255)}')self.ui.backup_cur_button.repaint()  # 重新绘制按钮,否则样式可能不生效elif args[0] == 2:self.failed_count += 1self.ui.backup_plain_text_edit.appendPlainText('未知设备(' + args[1] + ')备份配置失败')elif args[0] == 3:self.failed_count += 1self.ui.backup_plain_text_edit.appendPlainText(args[1] + '(IP地址:' + args[2] + ')' + '备份配置失败')elif args[0] == 4:self.finished_device_count += 1if self.finished_device_count == self.device_count:self.ui.backup_plain_text_edit.appendPlainText('备份设备完成!其中成功备份的设备为' + str(self.device_count - self.failed_count) +'台,失败的为' + str(self.failed_count) + '台')self.ui.backup_plain_text_edit.appendPlainText('可前往[' + os.path.abspath(self.backup_path) + ']查看备份结果')self.ui.backup_cur_button.setEnabled(True)  # 备份完成恢复按钮为原样self.ui.backup_cur_button.setStyleSheet('QPushButton{background-color: rgb(1, 102, 179); color: rgb(255,255,255)}')self.ui.backup_cur_button.repaint()  # 重新绘制按钮,否则样式可能不生效self.ui.backup_plain_text_edit.repaint()  # 重新绘制,否则样式可能不生效

备份设备列表.txt

RuijieAC 192.168.0.1 RUIJIE_AC_1
Mypower 192.168.0.2 MAIPU_RT_1
Ruijie 192.168.0.3 RUIJIE_SW_1
Huawei 192.168.0.4 HUAWEI_RT_1

相关文章:

基于python netmiko去ssh备份网络设备配置

自己为了便利写出来的基于python netmiko去ssh备份网络设备配置,用过secureCRT的脚本去备份设备配置,但是它没有图形化界面,使用不方便,自己就重新用python开发了一个,同时用pyinstaller打包成可执行程序(这…...

【CCF BDCI 2023】多模态多方对话场景下的发言人识别 Baseline 0.71 Slover 部分

【CCF BDCI 2023】多模态多方对话场景下的发言人识别 Baseline 0.71 Slover 部分 概述Solver 在多模态发言人识别中的作用Solver 在多模态发言人识别中的重要性Solver 的工作原理 二次规划二次规划的基本形式二次规划的特点二次规划在多模态发言中的应用 (我的理解) 代码详解数…...

爬虫工作量由小到大的思维转变---<第十二章 Scrapy之sql存储与爬虫高效性的平衡艺术>

前言: (本文仅属于技术性探讨,不属于教文) 刚好,前阵子团队还在闲聊这个问题呢。你知道吗,在数据收集这个行当里,怎么存数据这问题就跟“先有鸡还是先有蓝”一样,没完没了的循环往复。老规矩,咱们先搞清楚我们的“鸡…...

修改Docker0和容器的地址

修改Docker0和容器的地址 1. 需求 默认服务器安装完Docker-ce后会给docker0分配172.17.0.1/16地址. 公司新接入一个网段正好与172.17.0.1/16冲突,此时访问这台服务器的容器时就会发生网络不可达. 2. 解决方法 修改/etc/docker/daemon.json 加入一个自定义网段 vim /etc/d…...

弹性网络优化算法

3.3、Elastic-Net算法使用 这是scikit-learn官网给出的弹性网络回归的,损失函数公式,注意,它用的矩阵表示,里面用到范数运算。 min ⁡ w 1 2 n samples ∣ ∣ X w − y ∣ ∣ 2 2 α ρ ∣ ∣ w ∣ ∣ 1 α ( 1 − ρ ) 2 ∣ ∣…...

[C语言]大小端及整形输出问题

假设在一个32位little endian 的机器上运行下面的程序&#xff0c;结果是多少 ? 1.1先看以下三个程序 #include <stdio.h> int main() {long long a 1, b 2, c 3;printf("%lld %lld %lld\n", a, b, c); // 1 2 3printf("%d %d %d %d %d %d\n&quo…...

C# 命令行参数解析库示例

写在前面 在日常开发中&#xff0c;我们经常会用到命令行参数&#xff0c;比如cmd下的各种指令&#xff1b;还有C#的控制台类型的项目&#xff0c;在默认入口Main函数中&#xff0c;那个args参数&#xff0c;就是有系统传入到程序进程的命令行参数&#xff1b;在传入的参数相对…...

2020 年网络安全应急响应分析报告

2020 年全年奇安信集团安服团队共参与和处置了全国范围内 660起网络安全应急响应事件。2020 年全年应急响应处置事件行业 TOP3 分别为:政府部门行业(146 起)医疗卫生行业(90 起)以及事业单位(61 起&#xff0c;事件处置数分别占应急处置所有行业的 22.1%、13.6%、9.2%。2020 年…...

Git----学习Git第一步基于 Windows 10 系统和 CentOS7 系统安装 Git

查看原文 文章目录 基于 Windows 10 系统安装 Git 客户端基于 CentOS7 系统安装部署 Git 基于 Windows 10 系统安装 Git 客户端 &#xff08;1&#xff09;打开 git官网 &#xff0c;点击【windows】 &#xff08;2&#xff09;根据自己的电脑选择安装&#xff0c;目前一般w…...

爬虫 scrapy ——scrapy shell调试及下载当当网数据(十一)

目录 一、scrapy shell 1.什么是scrapy shell&#xff1f; 2.安装 ipython 3.使用scrapy shell 二、当当网案例 1.在items.py中定义数据结构 2.在dang.py中解析数据 3.使用pipeline保存 4.多条管道的使用 5.多页下载 参考 一、scrapy shell 1.什么是scrapy shell&am…...

Linux驱动(中断、异步通知):红外对射,并在Qt StatusBus使用指示灯进行显示

本文工作&#xff1a; 1、Linux驱动与应用程序编写&#xff1a;使用了设备树、中断、异步通知知识点&#xff0c;实现了红外对射状态的异步信息提醒。 2、QT程序编写&#xff1a;自定义了一个“文本指示灯”类&#xff0c;并放置在QMainWidget的StatusBus中。 3、C与C混合编程与…...

echarts地图的常见用法:基本使用、区域颜色分级、水波动画、区域轮播、给地图添加背景图片和图标、3d地图、飞线图

前言 最近几天用echarts做中国地图&#xff0c;就把以前写的demo&#xff1a;在vue中实现中国地图 拿来用&#xff0c;结果到项目里直接报错了&#xff0c;后来发现是因为版本的问题&#xff0c;没办法只能从头进行踩坑了。以下内容基于vue3 和 echarts 5.32 基本使用 获取地…...

进程间通讯-管道

介绍 管道&#xff08;Pipe&#xff09;是操作系统提供的一种进程间通信&#xff08;IPC&#xff0c;Inter-Process Communication&#xff09;机制&#xff0c;它允许一个进程的输出直接作为另一个进程的输入。管道主要分为以下两种类型&#xff1a; 无名管道&#xff08;Unn…...

项目总结-自主HTTP实现

终于是写完了&#xff0c;花费了2周时间&#xff0c;一点一点看&#xff0c;还没有扩展&#xff0c;但是基本功能是已经实现了。利用的是Tcp为网络链接&#xff0c;在其上面又写了http的壳。没有使用epoll&#xff0c;多路转接难度比较高&#xff0c;以后有机会再写&#xff0c…...

Java语言+二维数组+非递归实现五子棋游戏

以前做过一个C语言版五子棋&#xff1a;&#xff23;语言&#xff0b;二维数组&#xff0b;非递归实现五子棋游戏 现在做一个Java语言版五子棋&#xff0c;规则如下&#xff1a; 1&#xff64;白子为O; 2&#xff64;黑子为&#xff1b; 3&#xff64;白子先手&#xff1b;…...

WordCloud—— 词云

【说明】文章内容来自《机器学习入门——基于sklearn》&#xff0c;用于学习记录。若有争议联系删除。 wordcloud 是python的第三方库&#xff0c;称为词云&#xff0c;也成文字云&#xff0c;可以根据文本中的词频以直观和艺术化的形式展示文本中词语的重要性。 依赖于pillow …...

linux网络----UDP编程

一、函数接口: 1.socket:创建一个用来网络通信的终端节点&#xff1b; 参数: type&#xff1a;套接字类型 SOCK_STREAM 流式套接字 TCP SOCK_DGRAM 数据报套接字 UDP SOCK_RAM 原始套接字 domain: 协议族 AF_INET protocal: 默认为0 2.s…...

[AI工具推荐]AiRestful智能API代码生成

智能API代码示例生成工具AiRestful 一、产品介绍二、如何使用1、第一步(必须):2、第二步(可选):3、第三步(智能生成): 三、如何集成到您的网站(应用)1、开始接入2、接入案例 四、注意点 一、产品介绍 AiRestful是一款基于智能AI的,帮助小白快速生成任意编程语言的API接口调用示…...

Elasticsearch 8.10.0同义词API用法详解,支持同义词热更新

Elasticsearch 的同义词功能非常强大,如果使用得当,可以显着提高搜索引擎的效果。使用同义词功能时的一个常见问题是更新同义词集。 同义词在搜索引擎领域用途 同义词在搜索引擎领域的用途可概括如下: 增强搜索的准确性——当用户输入一个关键词时,可能与他们实际意图相关…...

深度学习之模型权重

在深度学习中&#xff0c;模型的权重&#xff08;weights&#xff09;是指神经网络中的参数&#xff0c;这些参数用于调整和学习模型的行为&#xff0c;以便能够对输入数据进行有效的映射和提取有用的特征。深度学习模型通常由许多神经元和连接组成&#xff0c;而权重就是连接这…...

纯前端使用XLSX导出excel表格

1 单个sheet page.js(页面中的导出方法) import { exportExcel } from ../../../utils/exportExcel.js; leadOut() {const arr [{ id: 1, name: 张三, age: 14, sex: 男 },{ id: 2, name: 李四, age: 15, sex: 女 },{ id: 3, name: 王五, age: 16, sex: 男 },];const allR…...

将mjpg格式数转化成opencv Mat格式

该博客可以解决如下两个问题&#xff1a; 1、将mjpg格式数据转化成opencv Mat格式 2、v4l2_buffer 格式获取的mjpg格式数据转换成Mat格式。 要将 MJPEG 格式的数据转换为 OpenCV 的 Mat 格式&#xff0c;您可以使用 imdecode 函数。imdecode 函数可以将图像数据解码为 Mat 对象…...

【golang/g3n】3D游戏引擎G3N的windows安装与测试

目录 说在前面安装测试 说在前面 操作系统&#xff1a;win 11go version&#xff1a;go1.21.5 windows/amd64g3n版本&#xff1a;github.com/g3n/engine v0.2.0其他&#xff1a;找了下golang 3d相关的库&#xff0c;目前好像就这个比较活跃 安装 按照官方教程所说&#xff0c;…...

sap table 获取 valuation class MBEW 查表获取

参考 https://www.tcodesearch.com/sap-tables/search?qvaluationclass...

介绍一些操作系统—— Ubuntu 系统

介绍一些操作系统—— Ubuntu 系统 Ubuntu 系统 Ubuntu 是一个以桌面应用为主的 Linux 发行版操作系统&#xff0c;其名称来自非洲南部祖鲁语或豪萨语的“ubuntu"一词&#xff0c;意思是“人性”“我的存在是因为大家的存在"&#xff0c;是非洲传统的一种价值观。U…...

React中props 和 state异同初探

在 React 中&#xff0c;props 和 state 是两个非常重要的概念&#xff0c;它们决定了组件的行为和渲染方式。 Props props&#xff08;属性&#xff09;是父组件传递给子组件的数据。它们类似于函数的参数&#xff0c;可以在组件内部被访问和使用&#xff0c;但不能被修改。…...

spring-kakfa依赖管理之org/springframework/kafka/listener/CommonErrorHandler错误

问题&#xff1a; 整个项目使用spring-boot2.6.8版本&#xff0c;使用gradle构建&#xff0c;在common模块指定了implementation org.springframework.kafka:spring-kafka:2.6.8’这个工程也都能运行&#xff08;这正常发送kafka消息和接收消息&#xff09;&#xff0c;但是执行…...

基于go语言开发的海量用户及时通讯系统

文章目录 二十三、海量用户即时通讯系统1、项目开发前技术准备2.实现功能-显示客户端登录菜单3.实现功能-完成用户登录-1.完成客户端可以该长度值发送消息长度&#xff0c;服务器端可以正常接收到-2.完成客户端可以发送消息&#xff0c;服务器端可以接收到消息并根据客户端发送…...

19.Oracle 中count(1) 、count(*) 和count(列名) 函数的区别

count(1) and count(字段) 两者的主要区别是 count(1) 会统计表中的所有的记录数&#xff0c;包含字段为null 的记录。count(字段) 会统计该字段在表中出现的次数&#xff0c;忽略字段为null 的情况。 即不统计字段为null 的记录。 count(*) 和 count(1)和count(列名)区别 …...

C 库函数 - time()

描述 C 库函数 time_t time(time_t *seconds) 返回自纪元 Epoch&#xff08;1970-01-01 00:00:00 UTC&#xff09;起经过的时间&#xff0c;以秒为单位。如果 seconds 不为空&#xff0c;则返回值也存储在变量 seconds 中。 声明 下面是 time() 函数的声明。 time_t time(t…...

云南专业网站建设/外贸网站制作推广

算是狗年上班的最后一天吧&#xff0c;想想还是略略总结一下近半年来的概况。 这段时间比较懒得去总结更新发表新的博客&#xff0c;一来是生活和工作的琐碎让自己有些懈怠&#xff0c;二是对自己写的东西缺乏深度感到困扰&#xff0c;自己大概也带着些完美型人格吧。最近的工…...

芜湖有没有做网站的/原版百度

HDFS的写入过程 1&#xff09;客户端向namenode请求上传文件&#xff0c;namenode检查目标文件是否已存在&#xff0c;父目录是否存在。 2&#xff09;namenode返回是否可以上传。如果可以上传,客户端给上传文件做逻辑分块。 3&#xff09;客户端请求第一个 block上传到哪几…...

网站建设活动海报/成都seo排名

创造者的思维方式 我不知道人们是怎么回事&#xff0c;缺乏想象力还是怎么的&#xff0c;所以我跟其他人对话常常遇到类似的问题。 我&#xff1a;A其实不怎么好。 其他人&#xff1a;你说A不好&#xff0c;难道你要我用B&#xff1f; &#xff08;对于政治爱好者&#xff0c;如…...

做美甲批发的都上什么网站/关键词批量调词软件

标记说明Ag形语素 形容词性语素。形容词代码为a&#xff0c;语素代码&#xff47;前面置以A。a形容词 取英语形容词adjective的第1个字母。ad副形词 直接作状语的形容词。形容词代码a和副词代码d并在一起。an名形词 具有名词功能的形容词。形容词代码a和名词代码n并在一起。b区…...

给别人做网站挣钱吗/国际军事最新头条新闻

问题描述&#xff1a;网站前端用vue&#xff0c;后端用java mvctomcat服务器&#xff0c;数据库access。由于数据库为共享文件&#xff0c;可能被通过前端网页修改&#xff0c;也可能被手动修改&#xff0c;还可能被windows应用程序修改。通过前端网页修改时&#xff0c;页面可…...

java做购物网站/国外搜索引擎排名百鸣

这里列出一些基本的关于MVC路由规则的使用正则表达式的例子。/*Front*///限定id只能是数字&#xff0c; 长度为0&#xff5e;11routes.MapRoute("Archive","{user}/Archive/{id}",new { controller "Blog", action "Archive", user …...